@@ -48,9 +48,9 @@ struct _OstreeSignEd25519
48
48
{
49
49
GObject parent ;
50
50
ed25519_state state ;
51
- guchar * secret_key ; /* malloc'd buffer of length OSTREE_SIGN_ED25519_SECKEY_SIZE */
52
- GList * public_keys ; /* malloc'd buffer of length OSTREE_SIGN_ED25519_PUBKEY_SIZE */
53
- GList * revoked_keys ; /* malloc'd buffer of length OSTREE_SIGN_ED25519_PUBKEY_SIZE */
51
+ GBytes * secret_key ;
52
+ GList * public_keys ; /* GBytes */
53
+ GList * revoked_keys ; /* GBytes */
54
54
};
55
55
56
56
static void ostree_sign_ed25519_iface_init (OstreeSignInterface * self );
@@ -96,15 +96,19 @@ _ostree_sign_ed25519_init (OstreeSignEd25519 *self)
96
96
#endif
97
97
}
98
98
99
+ #if defined(USE_LIBSODIUM )
100
+ // Strictly verify pubkey and signature lengths, as libsodium can
101
+ // only handle raw ed25519 public key and signatures.
99
102
static gboolean
100
103
validate_length (gsize found , gsize expected , GError * * error )
101
104
{
102
105
if (found == expected )
103
106
return TRUE;
104
107
return glnx_throw (
105
108
error , "Ill-formed input: expected %" G_GSIZE_FORMAT " bytes, got %" G_GSIZE_FORMAT " bytes" ,
106
- found , expected );
109
+ expected , found );
107
110
}
111
+ #endif
108
112
109
113
static gboolean
110
114
_ostree_sign_ed25519_is_initialized (OstreeSignEd25519 * self , GError * * error )
@@ -136,27 +140,43 @@ ostree_sign_ed25519_data (OstreeSign *self, GBytes *data, GBytes **signature,
136
140
if (sign -> secret_key == NULL )
137
141
return glnx_throw (error , "Not able to sign: secret key is not set" );
138
142
143
+ #if defined(USE_LIBSODIUM ) || defined(USE_OPENSSL )
144
+ gsize secret_key_size ;
145
+ const guint8 * secret_key_buf = g_bytes_get_data (sign -> secret_key , & secret_key_size );
146
+ #endif
147
+
139
148
unsigned long long sig_size = 0 ;
140
- g_autofree guchar * sig = g_malloc0 ( OSTREE_SIGN_ED25519_SIG_SIZE ) ;
149
+ g_autofree guchar * sig = NULL ;
141
150
142
151
#if defined(USE_LIBSODIUM )
152
+ sig = g_malloc0 (OSTREE_SIGN_ED25519_SIG_SIZE );
143
153
if (crypto_sign_detached (sig , & sig_size , g_bytes_get_data (data , NULL ), g_bytes_get_size (data ),
144
- sign -> secret_key ))
154
+ secret_key_buf ))
145
155
sig_size = 0 ;
146
156
#elif defined(USE_OPENSSL )
147
157
EVP_MD_CTX * ctx = EVP_MD_CTX_new ();
148
158
if (!ctx )
149
159
return glnx_throw (error , "openssl: failed to allocate context" );
150
- EVP_PKEY * pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519 , NULL , sign -> secret_key ,
151
- OSTREE_SIGN_ED25519_SEED_SIZE );
160
+
161
+ // Try PKCS8 encoded private key first.
162
+ const unsigned char * p = secret_key_buf ;
163
+ EVP_PKEY * pkey = d2i_AutoPrivateKey (NULL , & p , secret_key_size );
164
+
165
+ // Try raw ed25519 private key if the length matches.
166
+ if (pkey == NULL && secret_key_size == OSTREE_SIGN_ED25519_SECKEY_SIZE )
167
+ pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519 , NULL , secret_key_buf ,
168
+ OSTREE_SIGN_ED25519_SEED_SIZE );
169
+
152
170
if (!pkey )
153
171
{
154
172
EVP_MD_CTX_free (ctx );
155
- return glnx_throw (error , "openssl: Failed to initialize ed5519 key" );
173
+ return glnx_throw (error , "openssl: Failed to initialize ed25519 key" );
156
174
}
157
175
158
176
size_t len ;
159
177
if (EVP_DigestSignInit (ctx , NULL , NULL , NULL , pkey )
178
+ && EVP_DigestSign (ctx , NULL , & len , g_bytes_get_data (data , NULL ), g_bytes_get_size (data ))
179
+ && (sig = g_malloc0 (len )) != NULL
160
180
&& EVP_DigestSign (ctx , sig , & len , g_bytes_get_data (data , NULL ), g_bytes_get_size (data )))
161
181
sig_size = len ;
162
182
@@ -172,12 +192,6 @@ ostree_sign_ed25519_data (OstreeSign *self, GBytes *data, GBytes **signature,
172
192
return TRUE;
173
193
}
174
194
175
- static gint
176
- _compare_ed25519_keys (gconstpointer a , gconstpointer b )
177
- {
178
- return memcmp (a , b , OSTREE_SIGN_ED25519_PUBKEY_SIZE );
179
- }
180
-
181
195
gboolean
182
196
ostree_sign_ed25519_data_verify (OstreeSign * self , GBytes * data , GVariant * signatures ,
183
197
char * * out_success_message , GError * * error )
@@ -222,29 +236,27 @@ ostree_sign_ed25519_data_verify (OstreeSign *self, GBytes *data, GVariant *signa
222
236
g_autoptr (GVariant ) child = g_variant_get_child_value (signatures , i );
223
237
g_autoptr (GBytes ) signature = g_variant_get_data_as_bytes (child );
224
238
239
+ #if defined(USE_LIBSODIUM )
225
240
if (!validate_length (g_bytes_get_size (signature ), OSTREE_SIGN_ED25519_SIG_SIZE , error ))
226
241
return glnx_prefix_error (error , "Invalid signature" );
227
-
228
- g_autofree char * hex = g_malloc0 (OSTREE_SIGN_ED25519_PUBKEY_SIZE * 2 + 1 );
242
+ #endif
229
243
230
244
g_debug ("Read signature %d: %s" , (gint )i , g_variant_print (child , TRUE));
231
245
232
- for (GList * public_key = sign -> public_keys ; public_key != NULL ; public_key = public_key -> next )
246
+ for (GList * l = sign -> public_keys ; l != NULL ; l = l -> next )
233
247
{
248
+ GBytes * public_key = l -> data ;
234
249
/* TODO: use non-list for tons of revoked keys? */
235
- if (g_list_find_custom (sign -> revoked_keys , public_key -> data , _compare_ed25519_keys )
236
- != NULL )
250
+ if (g_list_find_custom (sign -> revoked_keys , public_key , g_bytes_compare ) != NULL )
237
251
{
238
- ot_bin2hex (hex , public_key -> data , OSTREE_SIGN_ED25519_PUBKEY_SIZE );
252
+ g_autofree char * hex = g_malloc0 (g_bytes_get_size (public_key ) * 2 + 1 );
253
+ ot_bin2hex (hex , g_bytes_get_data (public_key , NULL ), g_bytes_get_size (public_key ));
239
254
g_debug ("Skip revoked key '%s'" , hex );
240
255
continue ;
241
256
}
242
257
243
258
bool valid = false;
244
- // Wrap the pubkey in a GBytes as that's what this API wants
245
- g_autoptr (GBytes ) public_key_bytes
246
- = g_bytes_new_static (public_key -> data , OSTREE_SIGN_ED25519_PUBKEY_SIZE );
247
- if (!otcore_validate_ed25519_signature (data , public_key_bytes , signature , & valid , error ))
259
+ if (!otcore_validate_ed25519_signature (data , public_key , signature , & valid , error ))
248
260
return FALSE;
249
261
if (!valid )
250
262
{
@@ -254,14 +266,17 @@ ostree_sign_ed25519_data_verify (OstreeSign *self, GBytes *data, GVariant *signa
254
266
else
255
267
g_string_append (invalid_signatures , "; " );
256
268
n_invalid_signatures ++ ;
257
- ot_bin2hex (hex , public_key -> data , OSTREE_SIGN_ED25519_PUBKEY_SIZE );
269
+ g_autofree char * hex = g_malloc0 (g_bytes_get_size (public_key ) * 2 + 1 );
270
+ ot_bin2hex (hex , g_bytes_get_data (public_key , NULL ), g_bytes_get_size (public_key ));
258
271
g_string_append_printf (invalid_signatures , "key '%s'" , hex );
259
272
}
260
273
else
261
274
{
262
275
if (out_success_message )
263
276
{
264
- ot_bin2hex (hex , public_key -> data , OSTREE_SIGN_ED25519_PUBKEY_SIZE );
277
+ g_autofree char * hex = g_malloc0 (g_bytes_get_size (public_key ) * 2 + 1 );
278
+ ot_bin2hex (hex , g_bytes_get_data (public_key , NULL ),
279
+ g_bytes_get_size (public_key ));
265
280
* out_success_message = g_strdup_printf (
266
281
"ed25519: Signature verified successfully with key '%s'" , hex );
267
282
}
@@ -320,22 +335,23 @@ ostree_sign_ed25519_clear_keys (OstreeSign *self, GError **error)
320
335
/* Clear secret key */
321
336
if (sign -> secret_key != NULL )
322
337
{
323
- memset (sign -> secret_key , 0 , OSTREE_SIGN_ED25519_SECKEY_SIZE );
324
- g_free (sign -> secret_key );
338
+ gsize size ;
339
+ gpointer data = g_bytes_unref_to_data (sign -> secret_key , & size );
340
+ memset (data , 0 , size );
325
341
sign -> secret_key = NULL ;
326
342
}
327
343
328
344
/* Clear already loaded trusted keys */
329
345
if (sign -> public_keys != NULL )
330
346
{
331
- g_list_free_full (sign -> public_keys , g_free );
347
+ g_list_free_full (sign -> public_keys , ( GDestroyNotify ) g_bytes_unref );
332
348
sign -> public_keys = NULL ;
333
349
}
334
350
335
351
/* Clear already loaded revoked keys */
336
352
if (sign -> revoked_keys != NULL )
337
353
{
338
- g_list_free_full (sign -> revoked_keys , g_free );
354
+ g_list_free_full (sign -> revoked_keys , ( GDestroyNotify ) g_bytes_unref );
339
355
sign -> revoked_keys = NULL ;
340
356
}
341
357
@@ -374,10 +390,12 @@ ostree_sign_ed25519_set_sk (OstreeSign *self, GVariant *secret_key, GError **err
374
390
return glnx_throw (error , "Unknown ed25519 secret key type" );
375
391
}
376
392
393
+ #if defined(USE_LIBSODIUM )
377
394
if (!validate_length (n_elements , OSTREE_SIGN_ED25519_SECKEY_SIZE , error ))
378
395
return glnx_prefix_error (error , "Invalid ed25519 secret key" );
396
+ #endif
379
397
380
- sign -> secret_key = g_steal_pointer (& secret_key_buf );
398
+ sign -> secret_key = g_bytes_new_take ( g_steal_pointer (& secret_key_buf ), n_elements );
381
399
382
400
return TRUE;
383
401
}
@@ -429,17 +447,20 @@ ostree_sign_ed25519_add_pk (OstreeSign *self, GVariant *public_key, GError **err
429
447
return glnx_throw (error , "Unknown ed25519 public key type" );
430
448
}
431
449
450
+ #if defined(USE_LIBSODIUM )
432
451
if (!validate_length (n_elements , OSTREE_SIGN_ED25519_PUBKEY_SIZE , error ))
433
452
return glnx_prefix_error (error , "Invalid ed25519 public key" );
453
+ #endif
434
454
435
- g_autofree char * hex = g_malloc0 (OSTREE_SIGN_ED25519_PUBKEY_SIZE * 2 + 1 );
455
+ g_autofree char * hex = g_malloc0 (n_elements * 2 + 1 );
436
456
ot_bin2hex (hex , key , n_elements );
437
457
g_debug ("Read ed25519 public key = %s" , hex );
438
458
439
- if (g_list_find_custom (sign -> public_keys , key , _compare_ed25519_keys ) == NULL )
459
+ g_autoptr (GBytes ) key_bytes = g_bytes_new_static (key , n_elements );
460
+ if (g_list_find_custom (sign -> public_keys , key_bytes , g_bytes_compare ) == NULL )
440
461
{
441
- gpointer newkey = g_memdup2 (key , n_elements );
442
- sign -> public_keys = g_list_prepend (sign -> public_keys , newkey );
462
+ GBytes * new_key_bytes = g_bytes_new (key , n_elements );
463
+ sign -> public_keys = g_list_prepend (sign -> public_keys , new_key_bytes );
443
464
}
444
465
445
466
return TRUE;
@@ -460,17 +481,20 @@ _ed25519_add_revoked (OstreeSign *self, GVariant *revoked_key, GError **error)
460
481
gsize n_elements = 0 ;
461
482
g_autofree guint8 * key = g_base64_decode (rk_ascii , & n_elements );
462
483
484
+ #if defined(USE_LIBSODIUM )
463
485
if (!validate_length (n_elements , OSTREE_SIGN_ED25519_PUBKEY_SIZE , error ))
464
486
return glnx_prefix_error (error , "Incorrect ed25519 revoked key" );
487
+ #endif
465
488
466
- g_autofree char * hex = g_malloc0 (OSTREE_SIGN_ED25519_PUBKEY_SIZE * 2 + 1 );
489
+ g_autofree char * hex = g_malloc0 (n_elements * 2 + 1 );
467
490
ot_bin2hex (hex , key , n_elements );
468
491
g_debug ("Read ed25519 revoked key = %s" , hex );
469
492
470
- if (g_list_find_custom (sign -> revoked_keys , key , _compare_ed25519_keys ) == NULL )
493
+ g_autoptr (GBytes ) key_bytes = g_bytes_new_static (key , n_elements );
494
+ if (g_list_find_custom (sign -> revoked_keys , key , g_bytes_compare ) == NULL )
471
495
{
472
- gpointer newkey = g_memdup2 (key , n_elements );
473
- sign -> revoked_keys = g_list_prepend (sign -> revoked_keys , newkey );
496
+ GBytes * new_key_bytes = g_bytes_new (key , n_elements );
497
+ sign -> revoked_keys = g_list_prepend (sign -> revoked_keys , new_key_bytes );
474
498
}
475
499
476
500
return TRUE;
0 commit comments