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 * @ret canonical Input was in canonical form
305 */
306static int rsa_cipher ( struct rsa_context *context,
307 const void *in, void *out ) {
308 bigint_t ( context->size ) *input = ( ( void * ) context->input0 );
309 bigint_t ( context->size ) *output = ( ( void * ) context->output0 );
310 bigint_t ( context->size ) *modulus = ( ( void * ) context->modulus0 );
311 bigint_t ( context->exponent_size ) *exponent =
312 ( ( void * ) context->exponent0 );
313 int canonical;
314
315 /* Initialise big integer */
316 bigint_init ( input, in, context->max_len );
317 canonical = ( ! bigint_is_geq ( input, modulus ) );
318
319 /* Perform modular exponentiation */
320 bigint_mod_exp ( input, modulus, exponent, output, context->tmp );
321
322 /* Copy out result */
323 bigint_done ( output, out, context->max_len );
324
325 /* Check for canonical input */
326 return canonical;
327}
328
329/**
330 * Encrypt using RSA PKCS#1
331 *
332 * @v pubkey Public-key algorithm
333 * @v key Key
334 * @v plaintext Plaintext
335 * @v ciphertext Ciphertext
336 * @ret ciphertext_len Length of ciphertext, or negative error
337 */
338static int rsa_pkcs1_encrypt ( struct pubkey_algorithm *pubkey __unused,
339 const struct asn1_cursor *key,
340 const struct asn1_cursor *plaintext,
341 struct asn1_builder *ciphertext ) {
342 struct rsa_context context;
343 void *temp;
344 uint8_t *encoded;
345 size_t min_len;
346 size_t pad_len;
347 int canonical;
348 int rc;
349
350 DBGC ( &context, "RSA %p encrypting:\n", &context );
351 DBGC_HDA ( &context, 0, plaintext->data, plaintext->len );
352
353 /* Initialise context */
354 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
355 goto err_init;
356
357 /* Calculate lengths */
358 min_len = ( 1 /* "0x00" */ + 1 /* "0x02" */ + 8 /* minimum padding */
359 + 1 /* "0x00" */ + plaintext->len );
360 if ( min_len > context.max_len ) {
361 DBGC ( &context, "RSA %p modulus too small for %zd-byte "
362 "plaintext\n", &context, plaintext->len );
363 goto err_sanity;
364 }
365 pad_len = ( 8 /* minimum padding */ + context.max_len - min_len );
366
367 /* Construct encoded message (using the big integer output
368 * buffer as temporary storage)
369 */
370 temp = context.output0;
371 encoded = temp;
372 encoded[0] = 0x00;
373 encoded[1] = 0x02;
374 if ( ( rc = rsa_get_random ( &encoded[2], pad_len ) ) != 0 ) {
375 DBGC ( &context, "RSA %p could not generate random data: %s\n",
376 &context, strerror ( rc ) );
377 goto err_random;
378 }
379 encoded[ 2 + pad_len ] = 0x00;
380 memcpy ( &encoded[ context.max_len - plaintext->len ],
381 plaintext->data, plaintext->len );
382 DBGC ( &context, "RSA %p encoded:\n", &context );
383 DBGC_HDA ( &context, 0, encoded, context.max_len );
384
385 /* Create space for ciphertext */
386 if ( ( rc = asn1_grow ( ciphertext, context.max_len ) ) != 0 )
387 goto err_grow;
388
389 /* Encipher the encoded message */
390 canonical = rsa_cipher ( &context, encoded, ciphertext->data );
391 assert ( canonical );
392 DBGC ( &context, "RSA %p encrypted:\n", &context );
393 DBGC_HDA ( &context, 0, ciphertext->data, context.max_len );
394
395 /* Free context */
396 rsa_free ( &context );
397
398 return 0;
399
400 err_grow:
401 err_random:
402 err_sanity:
403 rsa_free ( &context );
404 err_init:
405 return rc;
406}
407
408/**
409 * Decrypt using RSA PKCS#1
410 *
411 * @v pubkey Public-key algorithm
412 * @v key Key
413 * @v ciphertext Ciphertext
414 * @v plaintext Plaintext
415 * @ret rc Return status code
416 */
417static int rsa_pkcs1_decrypt ( struct pubkey_algorithm *pubkey __unused,
418 const struct asn1_cursor *key,
419 const struct asn1_cursor *ciphertext,
420 struct asn1_builder *plaintext ) {
421 struct rsa_context context;
422 void *temp;
423 uint8_t *encoded;
424 uint8_t *end;
425 uint8_t *pad;
426 uint8_t *zero;
427 uint8_t *start;
428 size_t len;
429 int canonical;
430 int rc;
431
432 DBGC ( &context, "RSA %p decrypting:\n", &context );
433 DBGC_HDA ( &context, 0, ciphertext->data, ciphertext->len );
434
435 /* Initialise context */
436 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
437 goto err_init;
438
439 /* Sanity check */
440 if ( ciphertext->len != context.max_len ) {
441 DBGC ( &context, "RSA %p ciphertext incorrect length (%zd "
442 "bytes, should be %zd)\n",
443 &context, ciphertext->len, context.max_len );
444 rc = -ERANGE;
445 goto err_sanity;
446 }
447
448 /* Decipher the message (using the big integer input buffer as
449 * temporary storage)
450 */
451 temp = context.input0;
452 encoded = temp;
453 canonical = rsa_cipher ( &context, ciphertext->data, encoded );
454 DBGC ( &context, "RSA %p encoded:\n", &context );
455 DBGC_HDA ( &context, 0, encoded, context.max_len );
456 if ( ! canonical ) {
457 DBGC ( &context, "RSA %p ciphertext was not canonical\n",
458 &context );
459 rc = -EINVAL;
460 goto err_canonical;
461 }
462
463 /* Parse the message */
464 end = ( encoded + context.max_len );
465 if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) ) {
466 rc = -EINVAL;
467 goto err_invalid;
468 }
469 pad = &encoded[2];
470 zero = memchr ( pad, 0, ( end - pad ) );
471 if ( ( ! zero ) || ( ( zero - pad ) < 8 /* minimum padding */ ) ) {
472 DBGC ( &context, "RSA %p invalid decrypted message:\n",
473 &context );
474 DBGC_HDA ( &context, 0, encoded, context.max_len );
475 rc = -EINVAL;
476 goto err_invalid;
477 }
478 start = ( zero + 1 );
479 len = ( end - start );
480
481 /* Create space for plaintext */
482 if ( ( rc = asn1_grow ( plaintext, len ) ) != 0 )
483 goto err_grow;
484
485 /* Copy out message */
486 memcpy ( plaintext->data, start, len );
487 DBGC ( &context, "RSA %p decrypted:\n", &context );
488 DBGC_HDA ( &context, 0, plaintext->data, len );
489
490 /* Free context */
491 rsa_free ( &context );
492
493 return 0;
494
495 err_grow:
496 err_invalid:
497 err_canonical:
498 err_sanity:
499 rsa_free ( &context );
500 err_init:
501 return rc;
502}
503
504/**
505 * Encode digest using RSA PKCS#1
506 *
507 * @v context RSA context
508 * @v digest Digest algorithm
509 * @v value Digest value
510 * @v reference Reference encoded digest (or NULL)
511 * @v encoded Encoded digest
512 * @ret rc Return status code
513 */
514static int rsa_pkcs1_encode ( struct rsa_context *context,
515 struct digest_algorithm *digest,
516 const void *value,
517 const void *reference __unused,
518 void *encoded ) {
520 size_t digest_len = digest->digestsize;
521 uint8_t *temp = encoded;
522 size_t digestinfo_len;
523 size_t min_len;
524 size_t pad_len;
525
526 /* Identify prefix */
528 if ( ! prefix ) {
529 DBGC ( context, "RSA %p has no prefix for %s\n",
530 context, digest->name );
531 return -ENOTSUP;
532 }
533 digestinfo_len = ( prefix->len + digest_len );
534
535 /* Sanity check */
536 min_len = ( 1 /* "0x00" */ + 1 /* "0x01" */ + 8 /* minimum padding */
537 + 1 /* "0x00" */ + digestinfo_len );
538 if ( min_len > context->max_len ) {
539 DBGC ( context, "RSA %p modulus too small for %s digest\n",
540 context, digest->name );
541 return -ERANGE;
542 }
543 DBGC ( context, "RSA %p encoding %s digest using PKCS#1:\n",
544 context, digest->name );
545 DBGC_HDA ( context, 0, value, digest_len );
546
547 /* Construct encoded message */
548 *(temp++) = 0x00;
549 *(temp++) = 0x01;
550 pad_len = ( 8 /* minimum padding */ + context->max_len - min_len );
551 memset ( temp, 0xff, pad_len );
552 temp += pad_len;
553 *(temp++) = 0x00;
554 memcpy ( temp, prefix->data, prefix->len );
555 temp += prefix->len;
556 memcpy ( temp, value, digest_len );
557 temp += digest_len;
558 assert ( temp == ( encoded + context->max_len ) );
559 DBGC ( context, "RSA %p encoded %s digest using PKCS#1:\n",
560 context, digest->name );
561 DBGC_HDA ( context, 0, encoded, context->max_len );
562
563 return 0;
564}
565
566/**
567 * Apply RSA PSS mask generation function
568 *
569 * @v digest Digest algorithm
570 * @v ctx Digest context buffer
571 * @v out Digest output buffer
572 * @v seed Mask seed
573 * @v xor XOR buffer
574 * @v len Length of XOR buffer
575 */
576static void rsa_xor_mask ( struct digest_algorithm *digest, void *ctx,
577 void *out, const void *seed, void *xor,
578 size_t len ) {
579 size_t digest_len = digest->digestsize;
580 const uint8_t *out_byte = out;
581 uint8_t *xor_byte = xor;
582 uint32_t counter = 0;
583 unsigned int i;
584
585 while ( len ) {
586
587 /* Generate output */
589 digest_update ( digest, ctx, seed, digest_len );
590 digest_update ( digest, ctx, &counter, sizeof ( counter ) );
592
593 /* XOR output into buffer */
594 for ( i = 0 ; len && ( i < digest_len ) ; i++, len-- )
595 *(xor_byte++) ^= out_byte[i];
596
597 /* Increment counter */
598 counter = htonl ( ntohl ( counter ) + 1 );
599 }
600}
601
602/**
603 * Encode digest using RSA PSS
604 *
605 * @v context RSA context
606 * @v digest Digest algorithm
607 * @v value Digest value
608 * @v reference Reference encoded digest (or NULL)
609 * @v encoded Encoded digest
610 * @ret rc Return status code
611 */
612static int rsa_pss_encode ( struct rsa_context *context,
613 struct digest_algorithm *digest,
614 const void *value, const void *reference,
615 void *encoded ) {
616 static uint8_t zero[8];
619 size_t digest_len = digest->digestsize;
620 size_t mask_len;
621 size_t pad_len;
622 size_t min_len;
623 void *hash;
624 void *salt;
625 uint8_t *msb;
626 uint8_t *head;
627 uint8_t *tail;
628 int rc;
629
630 /* Sanity check */
631 min_len = ( sizeof ( *head ) + digest_len /* salt */ +
632 digest_len /* hash */ + sizeof ( *tail ) );
633 if ( context->max_len < min_len ) {
634 DBGC ( context, "RSA %p %s formatted digest value too long "
635 "(%zd bytes, max %zd)\n", context, digest->name,
636 min_len, context->max_len );
637 return -ERANGE;
638 }
639 DBGC ( context, "RSA %p encoding %s digest using PSS:\n",
640 context, digest->name );
641 DBGC_HDA ( context, 0, value, digest_len );
642
643 /* Split message into component parts */
644 pad_len = ( context->max_len - min_len );
645 msb = encoded;
646 head = ( msb + pad_len );
647 salt = ( head + sizeof ( *head ) );
648 hash = ( salt + digest_len );
649 tail = ( hash + digest_len );
650 mask_len = ( pad_len + sizeof ( *head ) + digest_len /* salt */ );
651 assert ( tail == ( encoded + context->max_len - 1 ) );
652
653 /* Generate or construct salt as applicable */
654 if ( reference ) {
655 memcpy ( encoded, reference, context->max_len );
656 rsa_xor_mask ( digest, ctx, out, hash, encoded, mask_len );
657 } else {
658 if ( ( rc = rsa_get_random ( salt, digest_len ) ) != 0 ) {
659 DBGC ( context, "RSA %p could not generate random "
660 "salt: %s\n", context, strerror ( rc ) );
661 return rc;
662 }
663 }
664 DBGC ( context, "RSA %p salt:\n", context );
665 DBGC_HDA ( context, 0, salt, digest_len );
666
667 /* Construct intermediate digest */
669 digest_update ( digest, ctx, zero, sizeof ( zero ) );
670 digest_update ( digest, ctx, value, digest_len );
671 digest_update ( digest, ctx, salt, digest_len );
673
674 /* Construct message */
675 memset ( encoded, 0, pad_len );
676 *head = 0x01;
677 rsa_xor_mask ( digest, ctx, out, hash, encoded, mask_len );
678 *msb &= context->mask;
679 *tail = 0xbc;
680 DBGC ( context, "RSA %p encoded %s digest using PSS:\n",
681 context, digest->name );
682 DBGC_HDA ( context, 0, encoded, context->max_len );
683
684 return 0;
685}
686
687/**
688 * Sign digest value using RSA
689 *
690 * @v pubkey Public-key algorithm
691 * @v key Key
692 * @v digest Digest algorithm
693 * @v value Digest value
694 * @v signature Signature
695 * @ret rc Return status code
696 */
697static int rsa_sign ( struct pubkey_algorithm *pubkey,
698 const struct asn1_cursor *key,
699 struct digest_algorithm *digest, const void *value,
700 struct asn1_builder *signature ) {
701 rsa_encode_t *encode = pubkey->priv;
702 struct rsa_context context;
703 int canonical;
704 int rc;
705
706 DBGC ( &context, "RSA %p signing %s digest:\n",
707 &context, digest->name );
708 DBGC_HDA ( &context, 0, value, digest->digestsize );
709
710 /* Initialise context */
711 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
712 goto err_init;
713
714 /* Create space for encoded digest and signature */
715 if ( ( rc = asn1_grow ( signature, context.max_len ) ) != 0 )
716 goto err_grow;
717
718 /* Encode digest */
719 if ( ( rc = encode ( &context, digest, value, NULL,
720 signature->data ) ) != 0 )
721 goto err_encode;
722
723 /* Encipher the encoded digest */
724 canonical = rsa_cipher ( &context, signature->data, signature->data );
725 assert ( canonical );
726 DBGC ( &context, "RSA %p signed %s digest:\n", &context, digest->name );
727 DBGC_HDA ( &context, 0, signature->data, signature->len );
728
729 /* Free context */
730 rsa_free ( &context );
731
732 return 0;
733
734 err_encode:
735 err_grow:
736 rsa_free ( &context );
737 err_init:
738 return rc;
739}
740
741/**
742 * Verify signed digest value using RSA
743 *
744 * @v pubkey Public-key algorithm
745 * @v key Key
746 * @v digest Digest algorithm
747 * @v value Digest value
748 * @v signature Signature
749 * @ret rc Return status code
750 */
751static int rsa_verify ( struct pubkey_algorithm *pubkey,
752 const struct asn1_cursor *key,
753 struct digest_algorithm *digest, const void *value,
754 const struct asn1_cursor *signature ) {
755 rsa_encode_t *encode = pubkey->priv;
756 struct rsa_context context;
757 void *temp;
758 void *expected;
759 void *actual;
760 int canonical;
761 int rc;
762
763 DBGC ( &context, "RSA %p verifying %s digest:\n",
764 &context, digest->name );
765 DBGC_HDA ( &context, 0, value, digest->digestsize );
766 DBGC_HDA ( &context, 0, signature->data, signature->len );
767
768 /* Initialise context */
769 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
770 goto err_init;
771
772 /* Sanity check */
773 if ( signature->len != context.max_len ) {
774 DBGC ( &context, "RSA %p signature incorrect length (%zd "
775 "bytes, should be %zd)\n",
776 &context, signature->len, context.max_len );
777 rc = -ERANGE;
778 goto err_sanity;
779 }
780
781 /* Decipher the signature (using the big integer input buffer
782 * as temporary storage)
783 */
784 temp = context.input0;
785 expected = temp;
786 canonical = rsa_cipher ( &context, signature->data, expected );
787 DBGC ( &context, "RSA %p deciphered signature:\n", &context );
788 DBGC_HDA ( &context, 0, expected, context.max_len );
789 if ( ! canonical ) {
790 DBGC ( &context, "RSA %p signature was not canonical\n",
791 &context );
792 rc = -ERANGE;
793 goto err_canonical;
794 }
795
796 /* Encode digest (using the big integer output buffer as
797 * temporary storage)
798 */
799 temp = context.output0;
800 actual = temp;
801 if ( ( rc = encode ( &context, digest, value, expected,
802 actual ) ) != 0 )
803 goto err_encode;
804
805 /* Verify the signature */
806 if ( memcmp ( actual, expected, context.max_len ) != 0 ) {
807 DBGC ( &context, "RSA %p signature verification failed\n",
808 &context );
809 rc = -EACCES_VERIFY;
810 goto err_verify;
811 }
812
813 /* Free context */
814 rsa_free ( &context );
815
816 DBGC ( &context, "RSA %p signature verified successfully\n", &context );
817 return 0;
818
819 err_verify:
820 err_encode:
821 err_canonical:
822 err_sanity:
823 rsa_free ( &context );
824 err_init:
825 return rc;
826}
827
828/**
829 * Check for matching RSA public/private key pair
830 *
831 * @v pubkey Public-key algorithm
832 * @v private_key Private key
833 * @v public_key Public key
834 * @ret rc Return status code
835 */
836static int rsa_match ( struct pubkey_algorithm *pubkey __unused,
837 const struct asn1_cursor *private_key,
838 const struct asn1_cursor *public_key ) {
839 struct asn1_cursor private_modulus;
840 struct asn1_cursor private_exponent;
841 struct asn1_cursor public_modulus;
842 struct asn1_cursor public_exponent;
843 int rc;
844
845 /* Parse moduli and exponents */
846 if ( ( rc = rsa_parse_mod_exp ( &private_modulus, &private_exponent,
847 private_key ) ) != 0 )
848 return rc;
849 if ( ( rc = rsa_parse_mod_exp ( &public_modulus, &public_exponent,
850 public_key ) ) != 0 )
851 return rc;
852
853 /* Compare moduli */
854 if ( asn1_compare ( &private_modulus, &public_modulus ) != 0 )
855 return -ENOTTY;
856
857 return 0;
858}
859
860/** RSA public-key algorithm */
862 .name = "rsa",
863 .encrypt = rsa_pkcs1_encrypt,
864 .decrypt = rsa_pkcs1_decrypt,
865 .sign = rsa_sign,
866 .verify = rsa_verify,
867 .match = rsa_match,
868 .priv = rsa_pkcs1_encode,
869};
870
871/** RSA-PSS public-key algorithm */
873 .name = "rsa_pss",
874 .encrypt = pubkey_null_encrypt,
875 .decrypt = pubkey_null_decrypt,
876 .sign = rsa_sign,
877 .verify = rsa_verify,
878 .match = rsa_match,
879 .priv = rsa_pss_encode,
880};
881
882/* Drag in objects via rsa_algorithm */
884
885/* Drag in crypto configuration */
886REQUIRE_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
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
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:459
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:382
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:813
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:1036
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:261
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:323
int asn1_enter_bits(struct asn1_cursor *cursor, unsigned int *unused)
Enter ASN.1 bit string.
Definition asn1.c:403
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:566
ASN.1 encoding.
#define ASN1_INTEGER
ASN.1 integer.
Definition asn1.h:63
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:93
#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:505
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
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:472
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ERANGE
Result too large.
Definition errno.h:683
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
#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_is_geq(value, reference)
Compare big integers.
Definition bigint.h:146
#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:677
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:738
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:338
static int rsa_cipher(struct rsa_context *context, const void *in, void *out)
Perform RSA cipher operation.
Definition rsa.c:306
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:836
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:576
struct pubkey_algorithm rsa_algorithm
RSA public-key algorithm.
Definition rsa.c:861
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:417
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 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:697
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:514
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:612
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:751
struct pubkey_algorithm rsa_pss_algorithm
RSA-PSS public-key algorithm.
Definition rsa.c:872
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