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/md5_sha1.h>
39#include <ipxe/rsa.h>
40
41/** @file
42 *
43 * RSA public-key cryptography
44 *
45 * RSA is documented in RFC 3447 and updated in RFC 8017.
46 */
47
48/* Disambiguate the various error causes */
49#define EACCES_VERIFY \
50 __einfo_error ( EINFO_EACCES_VERIFY )
51#define EINFO_EACCES_VERIFY \
52 __einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" )
53
54/** An RSA context */
56 /** Allocated memory */
57 void *dynamic;
58 /** Modulus */
60 /** Modulus size */
61 unsigned int size;
62 /** Modulus length */
63 size_t max_len;
64 /** Exponent */
66 /** Exponent size */
67 unsigned int exponent_size;
68 /** Input buffer */
70 /** Output buffer */
72 /** Temporary working space for modular exponentiation */
73 void *tmp;
74 /** Modulus MSB mask */
76};
77
78/**
79 * Encode digest
80 *
81 * @v context RSA context
82 * @v digest Digest algorithm
83 * @v value Digest value
84 * @v reference Reference encoded digest (or NULL)
85 * @v encoded Encoded digest
86 * @ret rc Return status code
87 */
88typedef int ( rsa_encode_t ) ( struct rsa_context *context,
89 struct digest_algorithm *digest,
90 const void *value, const void *reference,
91 void *encoded );
92
93/** Generate random data */
94int ( * rsa_get_random ) ( void *data, size_t len ) = get_random_nz;
95
96/**
97 * Identify RSA prefix
98 *
99 * @v digest Digest algorithm
100 * @ret prefix RSA prefix, or NULL
101 */
102static struct rsa_digestinfo_prefix *
105
107 if ( prefix->digest == digest )
108 return prefix;
109 }
110 return NULL;
111}
112
113/**
114 * Free RSA dynamic storage
115 *
116 * @v context RSA context
117 */
118static inline void rsa_free ( struct rsa_context *context ) {
119
120 zfree ( context->dynamic );
121}
122
123/**
124 * Allocate RSA dynamic storage
125 *
126 * @v context RSA context
127 * @v modulus_len Modulus length
128 * @v exponent_len Exponent length
129 * @ret rc Return status code
130 */
131static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
132 size_t exponent_len ) {
133 unsigned int size = bigint_required_size ( modulus_len );
134 unsigned int exponent_size = bigint_required_size ( exponent_len );
135 bigint_t ( size ) *modulus;
136 size_t tmp_len = bigint_mod_exp_tmp_len ( modulus );
137 struct {
138 bigint_t ( size ) modulus;
139 bigint_t ( exponent_size ) exponent;
140 bigint_t ( size ) input;
141 bigint_t ( size ) output;
142 uint8_t tmp[tmp_len];
143 } __attribute__ (( packed )) *dynamic;
144
145 /* Allocate dynamic storage */
146 dynamic = malloc ( sizeof ( *dynamic ) );
147 if ( ! dynamic )
148 return -ENOMEM;
149
150 /* Assign dynamic storage */
151 context->dynamic = dynamic;
152 context->modulus0 = &dynamic->modulus.element[0];
153 context->size = size;
154 context->max_len = modulus_len;
155 context->exponent0 = &dynamic->exponent.element[0];
156 context->exponent_size = exponent_size;
157 context->input0 = &dynamic->input.element[0];
158 context->output0 = &dynamic->output.element[0];
159 context->tmp = &dynamic->tmp;
160
161 return 0;
162}
163
164/**
165 * Parse RSA modulus and exponent
166 *
167 * @v modulus Modulus to fill in
168 * @v exponent Exponent to fill in
169 * @v raw ASN.1 cursor
170 * @ret rc Return status code
171 */
172static int rsa_parse_mod_exp ( struct asn1_cursor *modulus,
173 struct asn1_cursor *exponent,
174 const struct asn1_cursor *raw ) {
175 struct asn1_cursor cursor;
176 int is_private;
177 int rc;
178
179 /* Enter subjectPublicKeyInfo/privateKeyInfo/RSAPrivateKey */
180 memcpy ( &cursor, raw, sizeof ( cursor ) );
181 asn1_enter ( &cursor, ASN1_SEQUENCE );
182
183 /* Determine key format */
184 if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
185
186 /* Private key */
187 is_private = 1;
188
189 /* Skip version */
190 asn1_skip_any ( &cursor );
191
192 /* Enter privateKey, if present */
193 if ( asn1_check_algorithm ( &cursor, &rsa_encryption_algorithm,
194 NULL ) == 0 ) {
195
196 /* Skip privateKeyAlgorithm */
197 asn1_skip_any ( &cursor );
198
199 /* Enter privateKey */
200 asn1_enter ( &cursor, ASN1_OCTET_STRING );
201
202 /* Enter RSAPrivateKey */
203 asn1_enter ( &cursor, ASN1_SEQUENCE );
204
205 /* Skip version */
206 asn1_skip ( &cursor, ASN1_INTEGER );
207 }
208
209 } else {
210
211 /* Public key */
212 is_private = 0;
213
214 /* Skip algorithm */
215 asn1_skip ( &cursor, ASN1_SEQUENCE );
216
217 /* Enter subjectPublicKey */
218 asn1_enter_bits ( &cursor, NULL );
219
220 /* Enter RSAPublicKey */
221 asn1_enter ( &cursor, ASN1_SEQUENCE );
222 }
223
224 /* Extract modulus */
225 memcpy ( modulus, &cursor, sizeof ( *modulus ) );
226 if ( ( rc = asn1_enter_unsigned ( modulus ) ) != 0 )
227 return rc;
228 asn1_skip_any ( &cursor );
229
230 /* Skip public exponent, if applicable */
231 if ( is_private )
232 asn1_skip ( &cursor, ASN1_INTEGER );
233
234 /* Extract publicExponent/privateExponent */
235 memcpy ( exponent, &cursor, sizeof ( *exponent ) );
236 if ( ( rc = asn1_enter_unsigned ( exponent ) ) != 0 )
237 return rc;
238
239 return 0;
240}
241
242/**
243 * Initialise RSA cipher
244 *
245 * @v context RSA context
246 * @v key Key
247 * @ret rc Return status code
248 */
249static int rsa_init ( struct rsa_context *context,
250 const struct asn1_cursor *key ) {
251 struct asn1_cursor modulus;
252 struct asn1_cursor exponent;
253 uint8_t msb;
254 int rc;
255
256 /* Initialise context */
257 memset ( context, 0, sizeof ( *context ) );
258
259 /* Parse modulus and exponent */
260 if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, key ) ) != 0 ){
261 DBGC ( context, "RSA %p invalid modulus/exponent:\n", context );
262 DBGC_HDA ( context, 0, key->data, key->len );
263 goto err_parse;
264 }
265
266 DBGC ( context, "RSA %p modulus:\n", context );
267 DBGC_HDA ( context, 0, modulus.data, modulus.len );
268 DBGC ( context, "RSA %p exponent:\n", context );
269 DBGC_HDA ( context, 0, exponent.data, exponent.len );
270
271 /* Construct MSB mask */
272 msb = *( ( const uint8_t * ) modulus.data );
273 if ( ! msb ) {
274 DBGC ( context, "RSA %p invalid modulus MSB\n", context );
275 rc = -EINVAL;
276 goto err_msb;
277 }
278 context->mask = ( ( 1 << ( fls ( msb ) - 1 ) ) - 1 );
279
280 /* Allocate dynamic storage */
281 if ( ( rc = rsa_alloc ( context, modulus.len, exponent.len ) ) != 0 )
282 goto err_alloc;
283
284 /* Construct big integers */
285 bigint_init ( ( ( bigint_t ( context->size ) * ) context->modulus0 ),
286 modulus.data, modulus.len );
287 bigint_init ( ( ( bigint_t ( context->exponent_size ) * )
288 context->exponent0 ), exponent.data, exponent.len );
289
290 return 0;
291
292 rsa_free ( context );
293 err_alloc:
294 err_msb:
295 err_parse:
296 return rc;
297}
298
299/**
300 * Perform RSA cipher operation
301 *
302 * @v context RSA context
303 * @v in Input buffer
304 * @v out Output buffer
305 * @ret canonical Input was in canonical form
306 */
307static int rsa_cipher ( struct rsa_context *context,
308 const void *in, void *out ) {
309 bigint_t ( context->size ) *input = ( ( void * ) context->input0 );
310 bigint_t ( context->size ) *output = ( ( void * ) context->output0 );
311 bigint_t ( context->size ) *modulus = ( ( void * ) context->modulus0 );
312 bigint_t ( context->exponent_size ) *exponent =
313 ( ( void * ) context->exponent0 );
314 int canonical;
315
316 /* Initialise big integer */
317 bigint_init ( input, in, context->max_len );
318 canonical = ( ! bigint_is_geq ( input, modulus ) );
319
320 /* Perform modular exponentiation */
321 bigint_mod_exp ( input, modulus, exponent, output, context->tmp );
322
323 /* Copy out result */
324 bigint_done ( output, out, context->max_len );
325
326 /* Check for canonical input */
327 return canonical;
328}
329
330/**
331 * Encrypt using RSA PKCS#1
332 *
333 * @v pubkey Public-key algorithm
334 * @v key Key
335 * @v plaintext Plaintext
336 * @v ciphertext Ciphertext
337 * @ret ciphertext_len Length of ciphertext, or negative error
338 */
339static int rsa_pkcs1_encrypt ( struct pubkey_algorithm *pubkey __unused,
340 const struct asn1_cursor *key,
341 const struct asn1_cursor *plaintext,
342 struct asn1_builder *ciphertext ) {
343 struct rsa_context context;
344 void *temp;
345 uint8_t *encoded;
346 size_t min_len;
347 size_t pad_len;
348 int canonical;
349 int rc;
350
351 DBGC ( &context, "RSA %p encrypting:\n", &context );
352 DBGC_HDA ( &context, 0, plaintext->data, plaintext->len );
353
354 /* Initialise context */
355 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
356 goto err_init;
357
358 /* Calculate lengths */
359 min_len = ( 1 /* "0x00" */ + 1 /* "0x02" */ + 8 /* minimum padding */
360 + 1 /* "0x00" */ + plaintext->len );
361 if ( min_len > context.max_len ) {
362 DBGC ( &context, "RSA %p modulus too small for %zd-byte "
363 "plaintext\n", &context, plaintext->len );
364 goto err_sanity;
365 }
366 pad_len = ( 8 /* minimum padding */ + context.max_len - min_len );
367
368 /* Construct encoded message (using the big integer output
369 * buffer as temporary storage)
370 */
371 temp = context.output0;
372 encoded = temp;
373 encoded[0] = 0x00;
374 encoded[1] = 0x02;
375 if ( ( rc = rsa_get_random ( &encoded[2], pad_len ) ) != 0 ) {
376 DBGC ( &context, "RSA %p could not generate random data: %s\n",
377 &context, strerror ( rc ) );
378 goto err_random;
379 }
380 encoded[ 2 + pad_len ] = 0x00;
381 memcpy ( &encoded[ context.max_len - plaintext->len ],
382 plaintext->data, plaintext->len );
383 DBGC ( &context, "RSA %p encoded:\n", &context );
384 DBGC_HDA ( &context, 0, encoded, context.max_len );
385
386 /* Create space for ciphertext */
387 if ( ( rc = asn1_grow ( ciphertext, context.max_len ) ) != 0 )
388 goto err_grow;
389
390 /* Encipher the encoded message */
391 canonical = rsa_cipher ( &context, encoded, ciphertext->data );
392 assert ( canonical );
393 DBGC ( &context, "RSA %p encrypted:\n", &context );
394 DBGC_HDA ( &context, 0, ciphertext->data, context.max_len );
395
396 /* Free context */
397 rsa_free ( &context );
398
399 return 0;
400
401 err_grow:
402 err_random:
403 err_sanity:
404 rsa_free ( &context );
405 err_init:
406 return rc;
407}
408
409/**
410 * Decrypt using RSA PKCS#1
411 *
412 * @v pubkey Public-key algorithm
413 * @v key Key
414 * @v ciphertext Ciphertext
415 * @v plaintext Plaintext
416 * @ret rc Return status code
417 */
418static int rsa_pkcs1_decrypt ( struct pubkey_algorithm *pubkey __unused,
419 const struct asn1_cursor *key,
420 const struct asn1_cursor *ciphertext,
421 struct asn1_builder *plaintext ) {
422 struct rsa_context context;
423 void *temp;
424 uint8_t *encoded;
425 uint8_t *end;
426 uint8_t *pad;
427 uint8_t *zero;
428 uint8_t *start;
429 size_t len;
430 int canonical;
431 int rc;
432
433 DBGC ( &context, "RSA %p decrypting:\n", &context );
434 DBGC_HDA ( &context, 0, ciphertext->data, ciphertext->len );
435
436 /* Initialise context */
437 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
438 goto err_init;
439
440 /* Sanity check */
441 if ( ciphertext->len != context.max_len ) {
442 DBGC ( &context, "RSA %p ciphertext incorrect length (%zd "
443 "bytes, should be %zd)\n",
444 &context, ciphertext->len, context.max_len );
445 rc = -ERANGE;
446 goto err_sanity;
447 }
448
449 /* Decipher the message (using the big integer input buffer as
450 * temporary storage)
451 */
452 temp = context.input0;
453 encoded = temp;
454 canonical = rsa_cipher ( &context, ciphertext->data, encoded );
455 DBGC ( &context, "RSA %p encoded:\n", &context );
456 DBGC_HDA ( &context, 0, encoded, context.max_len );
457 if ( ! canonical ) {
458 DBGC ( &context, "RSA %p ciphertext was not canonical\n",
459 &context );
460 rc = -EINVAL;
461 goto err_canonical;
462 }
463
464 /* Parse the message */
465 end = ( encoded + context.max_len );
466 if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) ) {
467 rc = -EINVAL;
468 goto err_invalid;
469 }
470 pad = &encoded[2];
471 zero = memchr ( pad, 0, ( end - pad ) );
472 if ( ( ! zero ) || ( ( zero - pad ) < 8 /* minimum padding */ ) ) {
473 DBGC ( &context, "RSA %p invalid decrypted message:\n",
474 &context );
475 DBGC_HDA ( &context, 0, encoded, context.max_len );
476 rc = -EINVAL;
477 goto err_invalid;
478 }
479 start = ( zero + 1 );
480 len = ( end - start );
481
482 /* Create space for plaintext */
483 if ( ( rc = asn1_grow ( plaintext, len ) ) != 0 )
484 goto err_grow;
485
486 /* Copy out message */
487 memcpy ( plaintext->data, start, len );
488 DBGC ( &context, "RSA %p decrypted:\n", &context );
489 DBGC_HDA ( &context, 0, plaintext->data, len );
490
491 /* Free context */
492 rsa_free ( &context );
493
494 return 0;
495
496 err_grow:
497 err_invalid:
498 err_canonical:
499 err_sanity:
500 rsa_free ( &context );
501 err_init:
502 return rc;
503}
504
505/**
506 * Encode digest using RSA PKCS#1
507 *
508 * @v context RSA context
509 * @v digest Digest algorithm
510 * @v value Digest value
511 * @v reference Reference encoded digest (or NULL)
512 * @v encoded Encoded digest
513 * @ret rc Return status code
514 */
515static int rsa_pkcs1_encode ( struct rsa_context *context,
516 struct digest_algorithm *digest,
517 const void *value,
518 const void *reference __unused,
519 void *encoded ) {
521 size_t digest_len = digest->digestsize;
522 uint8_t *temp = encoded;
523 size_t digestinfo_len;
524 size_t min_len;
525 size_t pad_len;
526
527 /* Identify prefix (if any) */
529 if ( ( ! prefix ) && ( ! is_md5_sha1 ( digest ) ) ) {
530 DBGC ( context, "RSA %p has no prefix for %s\n",
531 context, digest->name );
532 return -ENOTSUP;
533 }
534
535 /* Calculate length */
536 digestinfo_len = ( digest_len + ( prefix ? prefix->len : 0 ) );
537
538 /* Sanity check */
539 min_len = ( 1 /* "0x00" */ + 1 /* "0x01" */ + 8 /* minimum padding */
540 + 1 /* "0x00" */ + digestinfo_len );
541 if ( min_len > context->max_len ) {
542 DBGC ( context, "RSA %p modulus too small for %s digest\n",
543 context, digest->name );
544 return -ERANGE;
545 }
546 DBGC ( context, "RSA %p encoding %s digest using PKCS#1:\n",
547 context, digest->name );
548 DBGC_HDA ( context, 0, value, digest_len );
549
550 /* Construct encoded message */
551 *(temp++) = 0x00;
552 *(temp++) = 0x01;
553 pad_len = ( 8 /* minimum padding */ + context->max_len - min_len );
554 memset ( temp, 0xff, pad_len );
555 temp += pad_len;
556 *(temp++) = 0x00;
557 if ( prefix ) {
558 memcpy ( temp, prefix->data, prefix->len );
559 temp += prefix->len;
560 }
561 memcpy ( temp, value, digest_len );
562 temp += digest_len;
563 assert ( temp == ( encoded + context->max_len ) );
564 DBGC ( context, "RSA %p encoded %s digest using PKCS#1:\n",
565 context, digest->name );
566 DBGC_HDA ( context, 0, encoded, context->max_len );
567
568 return 0;
569}
570
571/**
572 * Apply RSA PSS mask generation function
573 *
574 * @v digest Digest algorithm
575 * @v ctx Digest context buffer
576 * @v out Digest output buffer
577 * @v seed Mask seed
578 * @v xor XOR buffer
579 * @v len Length of XOR buffer
580 */
581static void rsa_xor_mask ( struct digest_algorithm *digest, void *ctx,
582 void *out, const void *seed, void *xor,
583 size_t len ) {
584 size_t digest_len = digest->digestsize;
585 const uint8_t *out_byte = out;
586 uint8_t *xor_byte = xor;
587 uint32_t counter = 0;
588 unsigned int i;
589
590 while ( len ) {
591
592 /* Generate output */
594 digest_update ( digest, ctx, seed, digest_len );
595 digest_update ( digest, ctx, &counter, sizeof ( counter ) );
597
598 /* XOR output into buffer */
599 for ( i = 0 ; len && ( i < digest_len ) ; i++, len-- )
600 *(xor_byte++) ^= out_byte[i];
601
602 /* Increment counter */
603 counter = htonl ( ntohl ( counter ) + 1 );
604 }
605}
606
607/**
608 * Encode digest using RSA PSS
609 *
610 * @v context RSA context
611 * @v digest Digest algorithm
612 * @v value Digest value
613 * @v reference Reference encoded digest (or NULL)
614 * @v encoded Encoded digest
615 * @ret rc Return status code
616 */
617static int rsa_pss_encode ( struct rsa_context *context,
618 struct digest_algorithm *digest,
619 const void *value, const void *reference,
620 void *encoded ) {
621 static uint8_t zero[8];
624 size_t digest_len = digest->digestsize;
625 size_t mask_len;
626 size_t pad_len;
627 size_t min_len;
628 void *hash;
629 void *salt;
630 uint8_t *msb;
631 uint8_t *head;
632 uint8_t *tail;
633 int rc;
634
635 /* Sanity check */
636 min_len = ( sizeof ( *head ) + digest_len /* salt */ +
637 digest_len /* hash */ + sizeof ( *tail ) );
638 if ( context->max_len < min_len ) {
639 DBGC ( context, "RSA %p %s formatted digest value too long "
640 "(%zd bytes, max %zd)\n", context, digest->name,
641 min_len, context->max_len );
642 return -ERANGE;
643 }
644 DBGC ( context, "RSA %p encoding %s digest using PSS:\n",
645 context, digest->name );
646 DBGC_HDA ( context, 0, value, digest_len );
647
648 /* Split message into component parts */
649 pad_len = ( context->max_len - min_len );
650 msb = encoded;
651 head = ( msb + pad_len );
652 salt = ( head + sizeof ( *head ) );
653 hash = ( salt + digest_len );
654 tail = ( hash + digest_len );
655 mask_len = ( pad_len + sizeof ( *head ) + digest_len /* salt */ );
656 assert ( tail == ( encoded + context->max_len - 1 ) );
657
658 /* Generate or construct salt as applicable */
659 if ( reference ) {
660 memcpy ( encoded, reference, context->max_len );
661 rsa_xor_mask ( digest, ctx, out, hash, encoded, mask_len );
662 } else {
663 if ( ( rc = rsa_get_random ( salt, digest_len ) ) != 0 ) {
664 DBGC ( context, "RSA %p could not generate random "
665 "salt: %s\n", context, strerror ( rc ) );
666 return rc;
667 }
668 }
669 DBGC ( context, "RSA %p salt:\n", context );
670 DBGC_HDA ( context, 0, salt, digest_len );
671
672 /* Construct intermediate digest */
674 digest_update ( digest, ctx, zero, sizeof ( zero ) );
675 digest_update ( digest, ctx, value, digest_len );
676 digest_update ( digest, ctx, salt, digest_len );
678
679 /* Construct message */
680 memset ( encoded, 0, pad_len );
681 *head = 0x01;
682 rsa_xor_mask ( digest, ctx, out, hash, encoded, mask_len );
683 *msb &= context->mask;
684 *tail = 0xbc;
685 DBGC ( context, "RSA %p encoded %s digest using PSS:\n",
686 context, digest->name );
687 DBGC_HDA ( context, 0, encoded, context->max_len );
688
689 return 0;
690}
691
692/**
693 * Sign digest value using RSA
694 *
695 * @v pubkey Public-key algorithm
696 * @v key Key
697 * @v digest Digest algorithm
698 * @v value Digest value
699 * @v signature Signature
700 * @ret rc Return status code
701 */
702static int rsa_sign ( struct pubkey_algorithm *pubkey,
703 const struct asn1_cursor *key,
704 struct digest_algorithm *digest, const void *value,
705 struct asn1_builder *signature ) {
706 rsa_encode_t *encode = pubkey->priv;
707 struct rsa_context context;
708 int canonical;
709 int rc;
710
711 DBGC ( &context, "RSA %p signing %s digest:\n",
712 &context, digest->name );
713 DBGC_HDA ( &context, 0, value, digest->digestsize );
714
715 /* Initialise context */
716 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
717 goto err_init;
718
719 /* Create space for encoded digest and signature */
720 if ( ( rc = asn1_grow ( signature, context.max_len ) ) != 0 )
721 goto err_grow;
722
723 /* Encode digest */
724 if ( ( rc = encode ( &context, digest, value, NULL,
725 signature->data ) ) != 0 )
726 goto err_encode;
727
728 /* Encipher the encoded digest */
729 canonical = rsa_cipher ( &context, signature->data, signature->data );
730 assert ( canonical );
731 DBGC ( &context, "RSA %p signed %s digest:\n", &context, digest->name );
732 DBGC_HDA ( &context, 0, signature->data, signature->len );
733
734 /* Free context */
735 rsa_free ( &context );
736
737 return 0;
738
739 err_encode:
740 err_grow:
741 rsa_free ( &context );
742 err_init:
743 return rc;
744}
745
746/**
747 * Verify signed digest value using RSA
748 *
749 * @v pubkey Public-key algorithm
750 * @v key Key
751 * @v digest Digest algorithm
752 * @v value Digest value
753 * @v signature Signature
754 * @ret rc Return status code
755 */
756static int rsa_verify ( struct pubkey_algorithm *pubkey,
757 const struct asn1_cursor *key,
758 struct digest_algorithm *digest, const void *value,
759 const struct asn1_cursor *signature ) {
760 rsa_encode_t *encode = pubkey->priv;
761 struct rsa_context context;
762 void *temp;
763 void *expected;
764 void *actual;
765 int canonical;
766 int rc;
767
768 DBGC ( &context, "RSA %p verifying %s digest:\n",
769 &context, digest->name );
770 DBGC_HDA ( &context, 0, value, digest->digestsize );
771 DBGC_HDA ( &context, 0, signature->data, signature->len );
772
773 /* Initialise context */
774 if ( ( rc = rsa_init ( &context, key ) ) != 0 )
775 goto err_init;
776
777 /* Sanity check */
778 if ( signature->len != context.max_len ) {
779 DBGC ( &context, "RSA %p signature incorrect length (%zd "
780 "bytes, should be %zd)\n",
781 &context, signature->len, context.max_len );
782 rc = -ERANGE;
783 goto err_sanity;
784 }
785
786 /* Decipher the signature (using the big integer input buffer
787 * as temporary storage)
788 */
789 temp = context.input0;
790 expected = temp;
791 canonical = rsa_cipher ( &context, signature->data, expected );
792 DBGC ( &context, "RSA %p deciphered signature:\n", &context );
793 DBGC_HDA ( &context, 0, expected, context.max_len );
794 if ( ! canonical ) {
795 DBGC ( &context, "RSA %p signature was not canonical\n",
796 &context );
797 rc = -ERANGE;
798 goto err_canonical;
799 }
800
801 /* Encode digest (using the big integer output buffer as
802 * temporary storage)
803 */
804 temp = context.output0;
805 actual = temp;
806 if ( ( rc = encode ( &context, digest, value, expected,
807 actual ) ) != 0 )
808 goto err_encode;
809
810 /* Verify the signature */
811 if ( memcmp ( actual, expected, context.max_len ) != 0 ) {
812 DBGC ( &context, "RSA %p signature verification failed\n",
813 &context );
814 rc = -EACCES_VERIFY;
815 goto err_verify;
816 }
817
818 /* Free context */
819 rsa_free ( &context );
820
821 DBGC ( &context, "RSA %p signature verified successfully\n", &context );
822 return 0;
823
824 err_verify:
825 err_encode:
826 err_canonical:
827 err_sanity:
828 rsa_free ( &context );
829 err_init:
830 return rc;
831}
832
833/**
834 * Check for matching RSA public/private key pair
835 *
836 * @v pubkey Public-key algorithm
837 * @v private_key Private key
838 * @v public_key Public key
839 * @ret rc Return status code
840 */
841static int rsa_match ( struct pubkey_algorithm *pubkey __unused,
842 const struct asn1_cursor *private_key,
843 const struct asn1_cursor *public_key ) {
844 struct asn1_cursor private_modulus;
845 struct asn1_cursor private_exponent;
846 struct asn1_cursor public_modulus;
847 struct asn1_cursor public_exponent;
848 int rc;
849
850 /* Parse moduli and exponents */
851 if ( ( rc = rsa_parse_mod_exp ( &private_modulus, &private_exponent,
852 private_key ) ) != 0 )
853 return rc;
854 if ( ( rc = rsa_parse_mod_exp ( &public_modulus, &public_exponent,
855 public_key ) ) != 0 )
856 return rc;
857
858 /* Compare moduli */
859 if ( asn1_compare ( &private_modulus, &public_modulus ) != 0 )
860 return -ENOTTY;
861
862 return 0;
863}
864
865/** RSA public-key algorithm */
867 .name = "rsa",
868 .encrypt = rsa_pkcs1_encrypt,
869 .decrypt = rsa_pkcs1_decrypt,
870 .sign = rsa_sign,
871 .verify = rsa_verify,
872 .match = rsa_match,
873 .priv = rsa_pkcs1_encode,
874};
875
876/** RSA-PSS public-key algorithm */
878 .name = "rsa_pss",
879 .encrypt = pubkey_null_encrypt,
880 .decrypt = pubkey_null_decrypt,
881 .sign = rsa_sign,
882 .verify = rsa_verify,
883 .match = rsa_match,
884 .priv = rsa_pss_encode,
885};
886
887/* Drag in objects via rsa_algorithm */
889
890/* Drag in crypto configuration */
891REQUIRE_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
Hybrid MD5+SHA1 hash as used by TLSv1.1 and earlier.
static int is_md5_sha1(struct digest_algorithm *digest)
Check if a digest algorithm is MD5+SHA1.
Definition md5_sha1.h:74
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:49
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:339
static int rsa_cipher(struct rsa_context *context, const void *in, void *out)
Perform RSA cipher operation.
Definition rsa.c:307
static void rsa_free(struct rsa_context *context)
Free RSA dynamic storage.
Definition rsa.c:118
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:841
static struct rsa_digestinfo_prefix * rsa_find_prefix(struct digest_algorithm *digest)
Identify RSA prefix.
Definition rsa.c:103
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:172
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:581
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:418
int(* rsa_get_random)(void *data, size_t len)
Generate random data.
Definition rsa.c:94
static int rsa_init(struct rsa_context *context, const struct asn1_cursor *key)
Initialise RSA cipher.
Definition rsa.c:249
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:702
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:515
static int rsa_alloc(struct rsa_context *context, size_t modulus_len, size_t exponent_len)
Allocate RSA dynamic storage.
Definition rsa.c:131
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:617
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:756
struct pubkey_algorithm rsa_pss_algorithm
RSA-PSS public-key algorithm.
Definition rsa.c:877
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:88
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:55
bigint_element_t * exponent0
Exponent.
Definition rsa.c:65
bigint_element_t * input0
Input buffer.
Definition rsa.c:69
void * dynamic
Allocated memory.
Definition rsa.c:57
void * tmp
Temporary working space for modular exponentiation.
Definition rsa.c:73
bigint_element_t * modulus0
Modulus.
Definition rsa.c:59
unsigned int exponent_size
Exponent size.
Definition rsa.c:67
uint8_t mask
Modulus MSB mask.
Definition rsa.c:75
bigint_element_t * output0
Output buffer.
Definition rsa.c:71
size_t max_len
Modulus length.
Definition rsa.c:63
unsigned int size
Modulus size.
Definition rsa.c:61
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
struct pubkey_algorithm rsa_algorithm
Definition tls.c:199
char prefix[4]
Definition vmconsole.c:53