iPXE
rsa.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <byteswap.h>
28#include <stdint.h>
29#include <stdlib.h>
30#include <stdarg.h>
31#include <string.h>
32#include <strings.h>
33#include <errno.h>
34#include <ipxe/asn1.h>
35#include <ipxe/crypto.h>
36#include <ipxe/bigint.h>
37#include <ipxe/random_nz.h>
38#include <ipxe/rsa.h>
39
40/** @file
41 *
42 * RSA public-key cryptography
43 *
44 * RSA is documented in RFC 3447 and updated in RFC 8017.
45 */
46
47/* Disambiguate the various error causes */
48#define EACCES_VERIFY \
49 __einfo_error ( EINFO_EACCES_VERIFY )
50#define EINFO_EACCES_VERIFY \
51 __einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" )
52
53/** An RSA context */
55 /** Allocated memory */
56 void *dynamic;
57 /** Modulus */
59 /** Modulus size */
60 unsigned int size;
61 /** Modulus length */
62 size_t max_len;
63 /** Exponent */
65 /** Exponent size */
66 unsigned int exponent_size;
67 /** Input buffer */
69 /** Output buffer */
71 /** Temporary working space for modular exponentiation */
72 void *tmp;
73 /** Modulus MSB mask */
75};
76
77/**
78 * Encode digest
79 *
80 * @v context RSA context
81 * @v digest Digest algorithm
82 * @v value Digest value
83 * @v reference Reference encoded digest (or NULL)
84 * @v encoded Encoded digest
85 * @ret rc Return status code
86 */
87typedef int ( rsa_encode_t ) ( struct rsa_context *context,
88 struct digest_algorithm *digest,
89 const void *value, const void *reference,
90 void *encoded );
91
92/** Generate random data */
93int ( * rsa_get_random ) ( void *data, size_t len ) = get_random_nz;
94
95/**
96 * Identify RSA prefix
97 *
98 * @v digest Digest algorithm
99 * @ret prefix RSA prefix, or NULL
100 */
101static struct rsa_digestinfo_prefix *
104
106 if ( prefix->digest == digest )
107 return prefix;
108 }
109 return NULL;
110}
111
112/**
113 * Free RSA dynamic storage
114 *
115 * @v context RSA context
116 */
117static inline void rsa_free ( struct rsa_context *context ) {
118
119 zfree ( context->dynamic );
120}
121
122/**
123 * Allocate RSA dynamic storage
124 *
125 * @v context RSA context
126 * @v modulus_len Modulus length
127 * @v exponent_len Exponent length
128 * @ret rc Return status code
129 */
130static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
131 size_t exponent_len ) {
132 unsigned int size = bigint_required_size ( modulus_len );
133 unsigned int exponent_size = bigint_required_size ( exponent_len );
134 bigint_t ( size ) *modulus;
135 size_t tmp_len = bigint_mod_exp_tmp_len ( modulus );
136 struct {
137 bigint_t ( size ) modulus;
138 bigint_t ( exponent_size ) exponent;
139 bigint_t ( size ) input;
140 bigint_t ( size ) output;
141 uint8_t tmp[tmp_len];
142 } __attribute__ (( packed )) *dynamic;
143
144 /* Allocate dynamic storage */
145 dynamic = malloc ( sizeof ( *dynamic ) );
146 if ( ! dynamic )
147 return -ENOMEM;
148
149 /* Assign dynamic storage */
150 context->dynamic = dynamic;
151 context->modulus0 = &dynamic->modulus.element[0];
152 context->size = size;
153 context->max_len = modulus_len;
154 context->exponent0 = &dynamic->exponent.element[0];
155 context->exponent_size = exponent_size;
156 context->input0 = &dynamic->input.element[0];
157 context->output0 = &dynamic->output.element[0];
158 context->tmp = &dynamic->tmp;
159
160 return 0;
161}
162
163/**
164 * Parse RSA modulus and exponent
165 *
166 * @v modulus Modulus to fill in
167 * @v exponent Exponent to fill in
168 * @v raw ASN.1 cursor
169 * @ret rc Return status code
170 */
171static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
172 struct asn1_cursor *exponent,
173 const struct asn1_cursor *raw ) {
174 struct asn1_cursor cursor;
175 int is_private;
176 int rc;
177
178 /* Enter subjectPublicKeyInfo/privateKeyInfo/RSAPrivateKey */
179 memcpy ( &cursor, raw, sizeof ( cursor ) );
180 asn1_enter ( &cursor, ASN1_SEQUENCE );
181
182 /* Determine key format */
183 if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
184
185 /* Private key */
186 is_private = 1;
187
188 /* Skip version */
189 asn1_skip_any ( &cursor );
190
191 /* Enter privateKey, if present */
192 if ( asn1_check_algorithm ( &cursor, &rsa_encryption_algorithm,
193 NULL ) == 0 ) {
194
195 /* Skip privateKeyAlgorithm */
196 asn1_skip_any ( &cursor );
197
198 /* Enter privateKey */
199 asn1_enter ( &cursor, ASN1_OCTET_STRING );
200
201 /* Enter RSAPrivateKey */
202 asn1_enter ( &cursor, ASN1_SEQUENCE );
203
204 /* Skip version */
205 asn1_skip ( &cursor, ASN1_INTEGER );
206 }
207
208 } else {
209
210 /* Public key */
211 is_private = 0;
212
213 /* Skip algorithm */
214 asn1_skip ( &cursor, ASN1_SEQUENCE );
215
216 /* Enter subjectPublicKey */
217 asn1_enter_bits ( &cursor, NULL );
218
219 /* Enter RSAPublicKey */
220 asn1_enter ( &cursor, ASN1_SEQUENCE );
221 }
222
223 /* Extract modulus */
224 memcpy ( modulus, &cursor, sizeof ( *modulus ) );
225 if ( ( rc = asn1_enter_unsigned ( modulus ) ) != 0 )
226 return rc;
227 asn1_skip_any ( &cursor );
228
229 /* Skip public exponent, if applicable */
230 if ( is_private )
231 asn1_skip ( &cursor, ASN1_INTEGER );
232
233 /* Extract publicExponent/privateExponent */
234 memcpy ( exponent, &cursor, sizeof ( *exponent ) );
235 if ( ( rc = asn1_enter_unsigned ( exponent ) ) != 0 )
236 return rc;
237
238 return 0;
239}
240
241/**
242 * Initialise RSA cipher
243 *
244 * @v context RSA context
245 * @v key Key
246 * @ret rc Return status code
247 */
248static int rsa_init ( struct rsa_context *context,
249 const struct asn1_cursor *key ) {
250 struct asn1_cursor modulus;
251 struct asn1_cursor exponent;
252 uint8_t msb;
253 int rc;
254
255 /* Initialise context */
256 memset ( context, 0, sizeof ( *context ) );
257
258 /* Parse modulus and exponent */
259 if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, key ) ) != 0 ){
260 DBGC ( context, "RSA %p invalid modulus/exponent:\n", context );
261 DBGC_HDA ( context, 0, key->data, key->len );
262 goto err_parse;
263 }
264
265 DBGC ( context, "RSA %p modulus:\n", context );
266 DBGC_HDA ( context, 0, modulus.data, modulus.len );
267 DBGC ( context, "RSA %p exponent:\n", context );
268 DBGC_HDA ( context, 0, exponent.data, exponent.len );
269
270 /* Construct MSB mask */
271 msb = *( ( const uint8_t * ) modulus.data );
272 if ( ! msb ) {
273 DBGC ( context, "RSA %p invalid modulus MSB\n", context );
274 rc = -EINVAL;
275 goto err_msb;
276 }
277 context->mask = ( ( 1 << ( fls ( msb ) - 1 ) ) - 1 );
278
279 /* Allocate dynamic storage */
280 if ( ( rc = rsa_alloc ( context, modulus.len, exponent.len ) ) != 0 )
281 goto err_alloc;
282
283 /* Construct big integers */
284 bigint_init ( ( ( bigint_t ( context->size ) * ) context->modulus0 ),
285 modulus.data, modulus.len );
286 bigint_init ( ( ( bigint_t ( context->exponent_size ) * )
287 context->exponent0 ), exponent.data, exponent.len );
288
289 return 0;
290
291 rsa_free ( context );
292 err_alloc:
293 err_msb:
294 err_parse:
295 return rc;
296}
297
298/**
299 * Perform RSA cipher operation
300 *
301 * @v context RSA context
302 * @v in Input buffer
303 * @v out Output buffer
304 */
305static void rsa_cipher ( struct rsa_context *context,
306 const void *in, void *out ) {
307 bigint_t ( context->size ) *input = ( ( void * ) context->input0 );
308 bigint_t ( context->size ) *output = ( ( void * ) context->output0 );
309 bigint_t ( context->size ) *modulus = ( ( void * ) context->modulus0 );
310 bigint_t ( context->exponent_size ) *exponent =
311 ( ( void * ) context->exponent0 );
312
313 /* Initialise big integer */
314 bigint_init ( input, in, context->max_len );
315
316 /* Perform modular exponentiation */
317 bigint_mod_exp ( input, modulus, exponent, output, context->tmp );
318
319 /* Copy out result */
320 bigint_done ( output, out, context->max_len );
321}
322
323/**
324 * Encrypt using RSA PKCS#1
325 *
326 * @v pubkey Public-key algorithm
327 * @v key Key
328 * @v plaintext Plaintext
329 * @v ciphertext Ciphertext
330 * @ret ciphertext_len Length of ciphertext, or negative error
331 */
332static int rsa_pkcs1_encrypt ( struct pubkey_algorithm *pubkey __unused,
333 const struct asn1_cursor *key,
334 const struct asn1_cursor *plaintext,
335 struct asn1_builder *ciphertext ) {
336 struct rsa_context context;
337 void *temp;
338 uint8_t *encoded;
339 size_t min_len;
340 size_t pad_len;
341 int rc;
342
343 DBGC ( &context, "RSA %p encrypting:\n", &context );
344 DBGC_HDA ( &context, 0, plaintext->data, plaintext->len );
345
346 /* Initialise context */
347 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
348 goto err_init;
349
350 /* Calculate lengths */
351 min_len = ( 1 /* "0x00" */ + 1 /* "0x02" */ + 8 /* minimum padding */
352 + 1 /* "0x00" */ + plaintext->len );
353 if ( min_len > context.max_len ) {
354 DBGC ( &context, "RSA %p modulus too small for %zd-byte "
355 "plaintext\n", &context, plaintext->len );
356 goto err_sanity;
357 }
358 pad_len = ( 8 /* minimum padding */ + context.max_len - min_len );
359
360 /* Construct encoded message (using the big integer output
361 * buffer as temporary storage)
362 */
363 temp = context.output0;
364 encoded = temp;
365 encoded[0] = 0x00;
366 encoded[1] = 0x02;
367 if ( ( rc = rsa_get_random ( &encoded[2], pad_len ) ) != 0 ) {
368 DBGC ( &context, "RSA %p could not generate random data: %s\n",
369 &context, strerror ( rc ) );
370 goto err_random;
371 }
372 encoded[ 2 + pad_len ] = 0x00;
373 memcpy ( &encoded[ context.max_len - plaintext->len ],
374 plaintext->data, plaintext->len );
375 DBGC ( &context, "RSA %p encoded:\n", &context );
376 DBGC_HDA ( &context, 0, encoded, context.max_len );
377
378 /* Create space for ciphertext */
379 if ( ( rc = asn1_grow ( ciphertext, context.max_len ) ) != 0 )
380 goto err_grow;
381
382 /* Encipher the encoded message */
383 rsa_cipher ( &context, encoded, ciphertext->data );
384 DBGC ( &context, "RSA %p encrypted:\n", &context );
385 DBGC_HDA ( &context, 0, ciphertext->data, context.max_len );
386
387 /* Free context */
388 rsa_free ( &context );
389
390 return 0;
391
392 err_grow:
393 err_random:
394 err_sanity:
395 rsa_free ( &context );
396 err_init:
397 return rc;
398}
399
400/**
401 * Decrypt using RSA PKCS#1
402 *
403 * @v pubkey Public-key algorithm
404 * @v key Key
405 * @v ciphertext Ciphertext
406 * @v plaintext Plaintext
407 * @ret rc Return status code
408 */
409static int rsa_pkcs1_decrypt ( struct pubkey_algorithm *pubkey __unused,
410 const struct asn1_cursor *key,
411 const struct asn1_cursor *ciphertext,
412 struct asn1_builder *plaintext ) {
413 struct rsa_context context;
414 void *temp;
415 uint8_t *encoded;
416 uint8_t *end;
417 uint8_t *zero;
418 uint8_t *start;
419 size_t len;
420 int rc;
421
422 DBGC ( &context, "RSA %p decrypting:\n", &context );
423 DBGC_HDA ( &context, 0, ciphertext->data, ciphertext->len );
424
425 /* Initialise context */
426 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
427 goto err_init;
428
429 /* Sanity check */
430 if ( ciphertext->len != context.max_len ) {
431 DBGC ( &context, "RSA %p ciphertext incorrect length (%zd "
432 "bytes, should be %zd)\n",
433 &context, ciphertext->len, context.max_len );
434 rc = -ERANGE;
435 goto err_sanity;
436 }
437
438 /* Decipher the message (using the big integer input buffer as
439 * temporary storage)
440 */
441 temp = context.input0;
442 encoded = temp;
443 rsa_cipher ( &context, ciphertext->data, encoded );
444 DBGC ( &context, "RSA %p encoded:\n", &context );
445 DBGC_HDA ( &context, 0, encoded, context.max_len );
446
447 /* Parse the message */
448 end = ( encoded + context.max_len );
449 if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) ) {
450 rc = -EINVAL;
451 goto err_invalid;
452 }
453 zero = memchr ( &encoded[2], 0, ( end - &encoded[2] ) );
454 if ( ! zero ) {
455 DBGC ( &context, "RSA %p invalid decrypted message:\n",
456 &context );
457 DBGC_HDA ( &context, 0, encoded, context.max_len );
458 rc = -EINVAL;
459 goto err_invalid;
460 }
461 start = ( zero + 1 );
462 len = ( end - start );
463
464 /* Create space for plaintext */
465 if ( ( rc = asn1_grow ( plaintext, len ) ) != 0 )
466 goto err_grow;
467
468 /* Copy out message */
469 memcpy ( plaintext->data, start, len );
470 DBGC ( &context, "RSA %p decrypted:\n", &context );
471 DBGC_HDA ( &context, 0, plaintext->data, len );
472
473 /* Free context */
474 rsa_free ( &context );
475
476 return 0;
477
478 err_grow:
479 err_invalid:
480 err_sanity:
481 rsa_free ( &context );
482 err_init:
483 return rc;
484}
485
486/**
487 * Encode digest using RSA PKCS#1
488 *
489 * @v context RSA context
490 * @v digest Digest algorithm
491 * @v value Digest value
492 * @v reference Reference encoded digest (or NULL)
493 * @v encoded Encoded digest
494 * @ret rc Return status code
495 */
496static int rsa_pkcs1_encode ( struct rsa_context *context,
497 struct digest_algorithm *digest,
498 const void *value,
499 const void *reference __unused,
500 void *encoded ) {
502 size_t digest_len = digest->digestsize;
503 uint8_t *temp = encoded;
504 size_t digestinfo_len;
505 size_t min_len;
506 size_t pad_len;
507
508 /* Identify prefix */
510 if ( ! prefix ) {
511 DBGC ( context, "RSA %p has no prefix for %s\n",
512 context, digest->name );
513 return -ENOTSUP;
514 }
515 digestinfo_len = ( prefix->len + digest_len );
516
517 /* Sanity check */
518 min_len = ( 1 /* "0x00" */ + 1 /* "0x01" */ + 8 /* minimum padding */
519 + 1 /* "0x00" */ + digestinfo_len );
520 if ( min_len > context->max_len ) {
521 DBGC ( context, "RSA %p modulus too small for %s digest\n",
522 context, digest->name );
523 return -ERANGE;
524 }
525 DBGC ( context, "RSA %p encoding %s digest using PKCS#1:\n",
526 context, digest->name );
527 DBGC_HDA ( context, 0, value, digest_len );
528
529 /* Construct encoded message */
530 *(temp++) = 0x00;
531 *(temp++) = 0x01;
532 pad_len = ( 8 /* minimum padding */ + context->max_len - min_len );
533 memset ( temp, 0xff, pad_len );
534 temp += pad_len;
535 *(temp++) = 0x00;
536 memcpy ( temp, prefix->data, prefix->len );
537 temp += prefix->len;
538 memcpy ( temp, value, digest_len );
539 temp += digest_len;
540 assert ( temp == ( encoded + context->max_len ) );
541 DBGC ( context, "RSA %p encoded %s digest using PKCS#1:\n",
542 context, digest->name );
543 DBGC_HDA ( context, 0, encoded, context->max_len );
544
545 return 0;
546}
547
548/**
549 * Apply RSA PSS mask generation function
550 *
551 * @v digest Digest algorithm
552 * @v ctx Digest context buffer
553 * @v out Digest output buffer
554 * @v seed Mask seed
555 * @v xor XOR buffer
556 * @v len Length of XOR buffer
557 */
558static void rsa_xor_mask ( struct digest_algorithm *digest, void *ctx,
559 void *out, const void *seed, void *xor,
560 size_t len ) {
561 size_t digest_len = digest->digestsize;
562 const uint8_t *out_byte = out;
563 uint8_t *xor_byte = xor;
564 uint32_t counter = 0;
565 unsigned int i;
566
567 while ( len ) {
568
569 /* Generate output */
571 digest_update ( digest, ctx, seed, digest_len );
572 digest_update ( digest, ctx, &counter, sizeof ( counter ) );
574
575 /* XOR output into buffer */
576 for ( i = 0 ; len && ( i < digest_len ) ; i++, len-- )
577 *(xor_byte++) ^= out_byte[i];
578
579 /* Increment counter */
580 counter = htonl ( ntohl ( counter ) + 1 );
581 }
582}
583
584/**
585 * Encode digest using RSA PSS
586 *
587 * @v context RSA context
588 * @v digest Digest algorithm
589 * @v value Digest value
590 * @v reference Reference encoded digest (or NULL)
591 * @v encoded Encoded digest
592 * @ret rc Return status code
593 */
594static int rsa_pss_encode ( struct rsa_context *context,
595 struct digest_algorithm *digest,
596 const void *value, const void *reference,
597 void *encoded ) {
598 static uint8_t zero[8];
601 size_t digest_len = digest->digestsize;
602 size_t mask_len;
603 size_t pad_len;
604 size_t min_len;
605 void *hash;
606 void *salt;
607 uint8_t *msb;
608 uint8_t *head;
609 uint8_t *tail;
610 int rc;
611
612 /* Sanity check */
613 min_len = ( sizeof ( *head ) + digest_len /* salt */ +
614 digest_len /* hash */ + sizeof ( *tail ) );
615 if ( context->max_len < min_len ) {
616 DBGC ( context, "RSA %p %s formatted digest value too long "
617 "(%zd bytes, max %zd)\n", context, digest->name,
618 min_len, context->max_len );
619 return -ERANGE;
620 }
621 DBGC ( context, "RSA %p encoding %s digest using PSS:\n",
622 context, digest->name );
623 DBGC_HDA ( context, 0, value, digest_len );
624
625 /* Split message into component parts */
626 pad_len = ( context->max_len - min_len );
627 msb = encoded;
628 head = ( msb + pad_len );
629 salt = ( head + sizeof ( *head ) );
630 hash = ( salt + digest_len );
631 tail = ( hash + digest_len );
632 mask_len = ( pad_len + sizeof ( *head ) + digest_len /* salt */ );
633 assert ( tail == ( encoded + context->max_len - 1 ) );
634
635 /* Generate or construct salt as applicable */
636 if ( reference ) {
637 memcpy ( encoded, reference, context->max_len );
638 rsa_xor_mask ( digest, ctx, out, hash, encoded, mask_len );
639 } else {
640 if ( ( rc = rsa_get_random ( salt, digest_len ) ) != 0 ) {
641 DBGC ( context, "RSA %p could not generate random "
642 "salt: %s\n", context, strerror ( rc ) );
643 return rc;
644 }
645 }
646 DBGC ( context, "RSA %p salt:\n", context );
647 DBGC_HDA ( context, 0, salt, digest_len );
648
649 /* Construct intermediate digest */
651 digest_update ( digest, ctx, zero, sizeof ( zero ) );
652 digest_update ( digest, ctx, value, digest_len );
653 digest_update ( digest, ctx, salt, digest_len );
655
656 /* Construct message */
657 memset ( encoded, 0, pad_len );
658 *head = 0x01;
659 rsa_xor_mask ( digest, ctx, out, hash, encoded, mask_len );
660 *msb &= context->mask;
661 *tail = 0xbc;
662 DBGC ( context, "RSA %p encoded %s digest using PSS:\n",
663 context, digest->name );
664 DBGC_HDA ( context, 0, encoded, context->max_len );
665
666 return 0;
667}
668
669/**
670 * Sign digest value using RSA
671 *
672 * @v pubkey Public-key algorithm
673 * @v key Key
674 * @v digest Digest algorithm
675 * @v value Digest value
676 * @v signature Signature
677 * @ret rc Return status code
678 */
679static int rsa_sign ( struct pubkey_algorithm *pubkey,
680 const struct asn1_cursor *key,
681 struct digest_algorithm *digest, const void *value,
682 struct asn1_builder *signature ) {
683 rsa_encode_t *encode = pubkey->priv;
684 struct rsa_context context;
685 int rc;
686
687 DBGC ( &context, "RSA %p signing %s digest:\n",
688 &context, digest->name );
689 DBGC_HDA ( &context, 0, value, digest->digestsize );
690
691 /* Initialise context */
692 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
693 goto err_init;
694
695 /* Create space for encoded digest and signature */
696 if ( ( rc = asn1_grow ( signature, context.max_len ) ) != 0 )
697 goto err_grow;
698
699 /* Encode digest */
700 if ( ( rc = encode ( &context, digest, value, NULL,
701 signature->data ) ) != 0 )
702 goto err_encode;
703
704 /* Encipher the encoded digest */
705 rsa_cipher ( &context, signature->data, signature->data );
706 DBGC ( &context, "RSA %p signed %s digest:\n", &context, digest->name );
707 DBGC_HDA ( &context, 0, signature->data, signature->len );
708
709 /* Free context */
710 rsa_free ( &context );
711
712 return 0;
713
714 err_encode:
715 err_grow:
716 rsa_free ( &context );
717 err_init:
718 return rc;
719}
720
721/**
722 * Verify signed digest value using RSA
723 *
724 * @v pubkey Public-key algorithm
725 * @v key Key
726 * @v digest Digest algorithm
727 * @v value Digest value
728 * @v signature Signature
729 * @ret rc Return status code
730 */
731static int rsa_verify ( struct pubkey_algorithm *pubkey,
732 const struct asn1_cursor *key,
733 struct digest_algorithm *digest, const void *value,
734 const struct asn1_cursor *signature ) {
735 rsa_encode_t *encode = pubkey->priv;
736 struct rsa_context context;
737 void *temp;
738 void *expected;
739 void *actual;
740 int rc;
741
742 DBGC ( &context, "RSA %p verifying %s digest:\n",
743 &context, digest->name );
744 DBGC_HDA ( &context, 0, value, digest->digestsize );
745 DBGC_HDA ( &context, 0, signature->data, signature->len );
746
747 /* Initialise context */
748 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
749 goto err_init;
750
751 /* Sanity check */
752 if ( signature->len != context.max_len ) {
753 DBGC ( &context, "RSA %p signature incorrect length (%zd "
754 "bytes, should be %zd)\n",
755 &context, signature->len, context.max_len );
756 rc = -ERANGE;
757 goto err_sanity;
758 }
759
760 /* Decipher the signature (using the big integer input buffer
761 * as temporary storage)
762 */
763 temp = context.input0;
764 expected = temp;
765 rsa_cipher ( &context, signature->data, expected );
766 DBGC ( &context, "RSA %p deciphered signature:\n", &context );
767 DBGC_HDA ( &context, 0, expected, context.max_len );
768
769 /* Encode digest (using the big integer output buffer as
770 * temporary storage)
771 */
772 temp = context.output0;
773 actual = temp;
774 if ( ( rc = encode ( &context, digest, value, expected,
775 actual ) ) != 0 )
776 goto err_encode;
777
778 /* Verify the signature */
779 if ( memcmp ( actual, expected, context.max_len ) != 0 ) {
780 DBGC ( &context, "RSA %p signature verification failed\n",
781 &context );
782 rc = -EACCES_VERIFY;
783 goto err_verify;
784 }
785
786 /* Free context */
787 rsa_free ( &context );
788
789 DBGC ( &context, "RSA %p signature verified successfully\n", &context );
790 return 0;
791
792 err_verify:
793 err_encode:
794 err_sanity:
795 rsa_free ( &context );
796 err_init:
797 return rc;
798}
799
800/**
801 * Check for matching RSA public/private key pair
802 *
803 * @v pubkey Public-key algorithm
804 * @v private_key Private key
805 * @v public_key Public key
806 * @ret rc Return status code
807 */
808static int rsa_match ( struct pubkey_algorithm *pubkey __unused,
809 const struct asn1_cursor *private_key,
810 const struct asn1_cursor *public_key ) {
811 struct asn1_cursor private_modulus;
812 struct asn1_cursor private_exponent;
813 struct asn1_cursor public_modulus;
814 struct asn1_cursor public_exponent;
815 int rc;
816
817 /* Parse moduli and exponents */
818 if ( ( rc = rsa_parse_mod_exp ( &private_modulus, &private_exponent,
819 private_key ) ) != 0 )
820 return rc;
821 if ( ( rc = rsa_parse_mod_exp ( &public_modulus, &public_exponent,
822 public_key ) ) != 0 )
823 return rc;
824
825 /* Compare moduli */
826 if ( asn1_compare ( &private_modulus, &public_modulus ) != 0 )
827 return -ENOTTY;
828
829 return 0;
830}
831
832/** RSA public-key algorithm */
834 .name = "rsa",
835 .encrypt = rsa_pkcs1_encrypt,
836 .decrypt = rsa_pkcs1_decrypt,
837 .sign = rsa_sign,
838 .verify = rsa_verify,
839 .match = rsa_match,
840 .priv = rsa_pkcs1_encode,
841};
842
843/** RSA-PSS public-key algorithm */
845 .name = "rsa_pss",
846 .encrypt = pubkey_null_encrypt,
847 .decrypt = pubkey_null_decrypt,
848 .sign = rsa_sign,
849 .verify = rsa_verify,
850 .match = rsa_match,
851 .priv = rsa_pss_encode,
852};
853
854/* Drag in objects via rsa_algorithm */
856
857/* Drag in crypto configuration */
858REQUIRE_OBJECT ( config_crypto );
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 out[4]
Definition CIB_PRM.h:8
__be32 raw[7]
Definition CIB_PRM.h:0
__be32 in[4]
Definition CIB_PRM.h:7
u8 signature
CPU signature.
Definition CIB_PRM.h:7
union @162305117151260234136356364136041353210355154177 key
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
uint32_t bigint_element_t
Element of a big integer.
Definition bigint.h:15
int asn1_enter_unsigned(struct asn1_cursor *cursor)
Enter ASN.1 unsigned integer.
Definition asn1.c:439
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:360
int asn1_check_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm *expected, struct asn1_cursor *params)
Check ASN.1 OID-identified algorithm.
Definition asn1.c:775
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:986
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:239
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:301
int asn1_enter_bits(struct asn1_cursor *cursor, unsigned int *unused)
Enter ASN.1 bit string.
Definition asn1.c:381
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:528
ASN.1 encoding.
#define ASN1_INTEGER
ASN.1 integer.
Definition asn1.h:63
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:90
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition asn1.h:69
static unsigned int asn1_type(const struct asn1_cursor *cursor)
Extract ASN.1 type.
Definition asn1.h:486
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
int pubkey_null_decrypt(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key __unused, const struct asn1_cursor *ciphertext __unused, struct asn1_builder *plaintext __unused)
int pubkey_null_encrypt(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key __unused, const struct asn1_cursor *plaintext __unused, struct asn1_builder *ciphertext __unused)
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
uint32_t start
Starting offset.
Definition netvsc.h:1
uint16_t size
Buffer size.
Definition dwmac.h:3
uint8_t head
Head number.
Definition int13.h:23
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define REQUIRE_OBJECT(object)
Require an object.
Definition compiler.h:227
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ERANGE
Result too large.
Definition errno.h:640
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
Definition compiler.h:140
#define ntohl(value)
Definition byteswap.h:135
#define htonl(value)
Definition byteswap.h:134
#define __attribute__(x)
Definition compiler.h:10
Big integer support.
#define bigint_mod_exp(base, modulus, exponent, result, tmp)
Perform modular exponentiation of big integers.
Definition bigint.h:348
#define bigint_mod_exp_tmp_len(modulus)
Calculate temporary working space required for moduluar exponentiation.
Definition bigint.h:362
#define bigint_t(size)
Define a big-integer type.
Definition bigint.h:21
#define bigint_required_size(len)
Determine number of elements required for a big-integer type.
Definition bigint.h:32
#define bigint_done(value, out, len)
Finalise big integer.
Definition bigint.h:76
#define bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:63
Cryptographic API.
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:294
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:305
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:299
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
String functions.
#define fls(x)
Find last (i.e.
Definition strings.h:167
unsigned long tmp
Definition linux_pci.h:65
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:682
uint32_t end
Ending offset.
Definition netvsc.h:7
int get_random_nz(void *data, size_t len)
Get random non-zero bytes.
Definition random_nz.c:63
HMAC_DRBG algorithm.
#define EACCES_VERIFY
Definition rsa.c:48
static int rsa_pkcs1_encrypt(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key, const struct asn1_cursor *plaintext, struct asn1_builder *ciphertext)
Encrypt using RSA PKCS#1.
Definition rsa.c:332
static void rsa_free(struct rsa_context *context)
Free RSA dynamic storage.
Definition rsa.c:117
static int rsa_match(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *private_key, const struct asn1_cursor *public_key)
Check for matching RSA public/private key pair.
Definition rsa.c:808
static struct rsa_digestinfo_prefix * rsa_find_prefix(struct digest_algorithm *digest)
Identify RSA prefix.
Definition rsa.c:102
static int rsa_parse_mod_exp(struct asn1_cursor *modulus, struct asn1_cursor *exponent, const struct asn1_cursor *raw)
Parse RSA modulus and exponent.
Definition rsa.c:171
static void rsa_xor_mask(struct digest_algorithm *digest, void *ctx, void *out, const void *seed, void *xor, size_t len)
Apply RSA PSS mask generation function.
Definition rsa.c:558
struct pubkey_algorithm rsa_algorithm
RSA public-key algorithm.
Definition rsa.c:833
static int rsa_pkcs1_decrypt(struct pubkey_algorithm *pubkey __unused, const struct asn1_cursor *key, const struct asn1_cursor *ciphertext, struct asn1_builder *plaintext)
Decrypt using RSA PKCS#1.
Definition rsa.c:409
int(* rsa_get_random)(void *data, size_t len)
Generate random data.
Definition rsa.c:93
static int rsa_init(struct rsa_context *context, const struct asn1_cursor *key)
Initialise RSA cipher.
Definition rsa.c:248
static void rsa_cipher(struct rsa_context *context, const void *in, void *out)
Perform RSA cipher operation.
Definition rsa.c:305
static int rsa_sign(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, struct asn1_builder *signature)
Sign digest value using RSA.
Definition rsa.c:679
static int rsa_pkcs1_encode(struct rsa_context *context, struct digest_algorithm *digest, const void *value, const void *reference __unused, void *encoded)
Encode digest using RSA PKCS#1.
Definition rsa.c:496
static int rsa_alloc(struct rsa_context *context, size_t modulus_len, size_t exponent_len)
Allocate RSA dynamic storage.
Definition rsa.c:130
static int rsa_pss_encode(struct rsa_context *context, struct digest_algorithm *digest, const void *value, const void *reference, void *encoded)
Encode digest using RSA PSS.
Definition rsa.c:594
static int rsa_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Verify signed digest value using RSA.
Definition rsa.c:731
struct pubkey_algorithm rsa_pss_algorithm
RSA-PSS public-key algorithm.
Definition rsa.c:844
int rsa_encode_t(struct rsa_context *context, struct digest_algorithm *digest, const void *value, const void *reference, void *encoded)
Encode digest.
Definition rsa.c:87
RSA public-key cryptography.
#define RSA_DIGESTINFO_PREFIXES
RSA digestInfo prefix table.
Definition rsa.h:53
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
void * memchr(const void *src, int character, size_t len)
Find character within a memory region.
Definition string.c:136
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An ASN.1 object builder.
Definition asn1.h:29
void * data
Data.
Definition asn1.h:36
An ASN.1 object cursor.
Definition asn1.h:21
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
size_t ctxsize
Context size.
Definition crypto.h:23
const char * name
Algorithm name.
Definition crypto.h:21
A private key.
Definition privkey.h:17
A public key algorithm.
Definition crypto.h:142
void * priv
Algorithm private data.
Definition crypto.h:206
An RSA context.
Definition rsa.c:54
bigint_element_t * exponent0
Exponent.
Definition rsa.c:64
bigint_element_t * input0
Input buffer.
Definition rsa.c:68
void * dynamic
Allocated memory.
Definition rsa.c:56
void * tmp
Temporary working space for modular exponentiation.
Definition rsa.c:72
bigint_element_t * modulus0
Modulus.
Definition rsa.c:58
unsigned int exponent_size
Exponent size.
Definition rsa.c:66
uint8_t mask
Modulus MSB mask.
Definition rsa.c:74
bigint_element_t * output0
Output buffer.
Definition rsa.c:70
size_t max_len
Modulus length.
Definition rsa.c:62
unsigned int size
Modulus size.
Definition rsa.c:60
An RSA digestInfo prefix.
Definition rsa.h:43
struct digest_algorithm * digest
Digest algorithm.
Definition rsa.h:45
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
static u32 xor(u32 a, u32 b)
Definition tlan.h:457
char prefix[4]
Definition vmconsole.c:53