iPXE
rsa.c File Reference

RSA public-key cryptography. More...

#include <byteswap.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <ipxe/asn1.h>
#include <ipxe/crypto.h>
#include <ipxe/bigint.h>
#include <ipxe/random_nz.h>
#include <ipxe/rsa.h>

Go to the source code of this file.

Data Structures

struct  rsa_context
 An RSA context. More...

Macros

#define EACCES_VERIFY   __einfo_error ( EINFO_EACCES_VERIFY )
#define EINFO_EACCES_VERIFY   __einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" )

Typedefs

typedef int rsa_encode_t(struct rsa_context *context, struct digest_algorithm *digest, const void *value, const void *reference, void *encoded)
 Encode digest.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static struct rsa_digestinfo_prefixrsa_find_prefix (struct digest_algorithm *digest)
 Identify RSA prefix.
static void rsa_free (struct rsa_context *context)
 Free RSA dynamic storage.
static int rsa_alloc (struct rsa_context *context, size_t modulus_len, size_t exponent_len)
 Allocate RSA dynamic storage.
static int rsa_parse_mod_exp (struct asn1_cursor *modulus, struct asn1_cursor *exponent, const struct asn1_cursor *raw)
 Parse RSA modulus and exponent.
static int rsa_init (struct rsa_context *context, const struct asn1_cursor *key)
 Initialise RSA cipher.
static void rsa_cipher (struct rsa_context *context, const void *in, void *out)
 Perform RSA cipher operation.
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.
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.
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.
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.
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.
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.
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.
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.
 REQUIRING_SYMBOL (rsa_algorithm)
 REQUIRE_OBJECT (config_crypto)

Variables

int(* rsa_get_random )(void *data, size_t len) = get_random_nz
 Generate random data.
struct pubkey_algorithm rsa_algorithm
 RSA public-key algorithm.
struct pubkey_algorithm rsa_pss_algorithm
 RSA-PSS public-key algorithm.

Detailed Description

RSA public-key cryptography.

RSA is documented in RFC 3447 and updated in RFC 8017.

Definition in file rsa.c.

Macro Definition Documentation

◆ EACCES_VERIFY

#define EACCES_VERIFY   __einfo_error ( EINFO_EACCES_VERIFY )

Definition at line 48 of file rsa.c.

48#define EACCES_VERIFY \
49 __einfo_error ( EINFO_EACCES_VERIFY )

Referenced by rsa_verify().

◆ EINFO_EACCES_VERIFY

#define EINFO_EACCES_VERIFY   __einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" )

Definition at line 50 of file rsa.c.

50#define EINFO_EACCES_VERIFY \
51 __einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" )

Typedef Documentation

◆ rsa_encode_t

typedef int rsa_encode_t(struct rsa_context *context, struct digest_algorithm *digest, const void *value, const void *reference, void *encoded)

Encode digest.

Parameters
contextRSA context
digestDigest algorithm
valueDigest value
referenceReference encoded digest (or NULL)
encodedEncoded digest
Return values
rcReturn status code

Definition at line 87 of file rsa.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ rsa_find_prefix()

struct rsa_digestinfo_prefix * rsa_find_prefix ( struct digest_algorithm * digest)
static

Identify RSA prefix.

Parameters
digestDigest algorithm
Return values
prefixRSA prefix, or NULL

Definition at line 102 of file rsa.c.

102 {
104
106 if ( prefix->digest == digest )
107 return prefix;
108 }
109 return NULL;
110}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
#define RSA_DIGESTINFO_PREFIXES
RSA digestInfo prefix table.
Definition rsa.h:53
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
char prefix[4]
Definition vmconsole.c:53

References rsa_digestinfo_prefix::digest, for_each_table_entry, NULL, prefix, and RSA_DIGESTINFO_PREFIXES.

Referenced by rsa_pkcs1_encode().

◆ rsa_free()

void rsa_free ( struct rsa_context * context)
inlinestatic

Free RSA dynamic storage.

Parameters
contextRSA context

Definition at line 117 of file rsa.c.

117 {
118
119 zfree ( context->dynamic );
120}
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:682
void * dynamic
Allocated memory.
Definition rsa.c:56

References rsa_context::dynamic, and zfree().

Referenced by rsa_init(), rsa_pkcs1_decrypt(), rsa_pkcs1_encrypt(), rsa_sign(), and rsa_verify().

◆ rsa_alloc()

int rsa_alloc ( struct rsa_context * context,
size_t modulus_len,
size_t exponent_len )
static

Allocate RSA dynamic storage.

Parameters
contextRSA context
modulus_lenModulus length
exponent_lenExponent length
Return values
rcReturn status code

Definition at line 130 of file rsa.c.

131 {
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}
unsigned char uint8_t
Definition stdint.h:10
uint16_t size
Buffer size.
Definition dwmac.h:3
#define ENOMEM
Not enough space.
Definition errno.h:535
#define __attribute__(x)
Definition compiler.h:10
#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
unsigned long tmp
Definition linux_pci.h:65
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
bigint_element_t * exponent0
Exponent.
Definition rsa.c:64
bigint_element_t * input0
Input buffer.
Definition rsa.c:68
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
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

References __attribute__, bigint_mod_exp_tmp_len, bigint_required_size, bigint_t, rsa_context::dynamic, ENOMEM, rsa_context::exponent0, rsa_context::exponent_size, rsa_context::input0, malloc(), rsa_context::max_len, rsa_context::modulus0, rsa_context::output0, rsa_context::size, size, rsa_context::tmp, and tmp.

Referenced by rsa_init().

◆ rsa_parse_mod_exp()

int rsa_parse_mod_exp ( struct asn1_cursor * modulus,
struct asn1_cursor * exponent,
const struct asn1_cursor * raw )
static

Parse RSA modulus and exponent.

Parameters
modulusModulus to fill in
exponentExponent to fill in
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 171 of file rsa.c.

173 {
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}
__be32 raw[7]
Definition CIB_PRM.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
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_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
#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
void * memcpy(void *dest, const void *src, size_t len) __nonnull
An ASN.1 object cursor.
Definition asn1.h:21

References asn1_check_algorithm(), asn1_enter(), asn1_enter_bits(), asn1_enter_unsigned(), ASN1_INTEGER, ASN1_OCTET_STRING, ASN1_SEQUENCE, asn1_skip(), asn1_skip_any(), asn1_type(), memcpy(), NULL, raw, and rc.

Referenced by rsa_init(), and rsa_match().

◆ rsa_init()

int rsa_init ( struct rsa_context * context,
const struct asn1_cursor * key )
static

Initialise RSA cipher.

Parameters
contextRSA context
keyKey
Return values
rcReturn status code

Definition at line 248 of file rsa.c.

249 {
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}
union @162305117151260234136356364136041353210355154177 key
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define EINVAL
Invalid argument.
Definition errno.h:429
#define bigint_init(value, data, len)
Initialise big integer.
Definition bigint.h:63
void * memset(void *dest, int character, size_t len) __nonnull
#define fls(x)
Find last (i.e.
Definition strings.h:167
static void rsa_free(struct rsa_context *context)
Free RSA dynamic storage.
Definition rsa.c:117
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 int rsa_alloc(struct rsa_context *context, size_t modulus_len, size_t exponent_len)
Allocate RSA dynamic storage.
Definition rsa.c:130
uint8_t mask
Modulus MSB mask.
Definition rsa.c:74

References bigint_init, bigint_t, asn1_cursor::data, DBGC, DBGC_HDA, EINVAL, rsa_context::exponent0, rsa_context::exponent_size, fls, key, asn1_cursor::len, rsa_context::mask, memset(), rsa_context::modulus0, rc, rsa_alloc(), rsa_free(), rsa_parse_mod_exp(), and rsa_context::size.

Referenced by rsa_pkcs1_decrypt(), rsa_pkcs1_encrypt(), rsa_sign(), and rsa_verify().

◆ rsa_cipher()

void rsa_cipher ( struct rsa_context * context,
const void * in,
void * out )
static

Perform RSA cipher operation.

Parameters
contextRSA context
inInput buffer
outOutput buffer

Definition at line 305 of file rsa.c.

306 {
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}
__be32 out[4]
Definition CIB_PRM.h:8
__be32 in[4]
Definition CIB_PRM.h:7
#define bigint_mod_exp(base, modulus, exponent, result, tmp)
Perform modular exponentiation of big integers.
Definition bigint.h:348
#define bigint_done(value, out, len)
Finalise big integer.
Definition bigint.h:76

References bigint_done, bigint_init, bigint_mod_exp, bigint_t, rsa_context::exponent0, rsa_context::exponent_size, in, rsa_context::input0, rsa_context::max_len, rsa_context::modulus0, out, rsa_context::output0, rsa_context::size, and rsa_context::tmp.

Referenced by rsa_pkcs1_decrypt(), rsa_pkcs1_encrypt(), rsa_sign(), and rsa_verify().

◆ rsa_pkcs1_encrypt()

int rsa_pkcs1_encrypt ( struct pubkey_algorithm *pubkey __unused,
const struct asn1_cursor * key,
const struct asn1_cursor * plaintext,
struct asn1_builder * ciphertext )
static

Encrypt using RSA PKCS#1.

Parameters
pubkeyPublic-key algorithm
keyKey
plaintextPlaintext
ciphertextCiphertext
Return values
ciphertext_lenLength of ciphertext, or negative error

Definition at line 332 of file rsa.c.

335 {
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}
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:986
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
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
void * data
Data.
Definition asn1.h:36
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
An RSA context.
Definition rsa.c:54

References __unused, asn1_grow(), asn1_builder::data, asn1_cursor::data, DBGC, DBGC_HDA, key, asn1_cursor::len, rsa_context::max_len, memcpy(), rsa_context::output0, rc, rsa_cipher(), rsa_free(), rsa_get_random, rsa_init(), and strerror().

◆ rsa_pkcs1_decrypt()

int rsa_pkcs1_decrypt ( struct pubkey_algorithm *pubkey __unused,
const struct asn1_cursor * key,
const struct asn1_cursor * ciphertext,
struct asn1_builder * plaintext )
static

Decrypt using RSA PKCS#1.

Parameters
pubkeyPublic-key algorithm
keyKey
ciphertextCiphertext
plaintextPlaintext
Return values
rcReturn status code

Definition at line 409 of file rsa.c.

412 {
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}
ring len
Length.
Definition dwmac.h:226
uint32_t start
Starting offset.
Definition netvsc.h:1
#define ERANGE
Result too large.
Definition errno.h:640
uint32_t end
Ending offset.
Definition netvsc.h:7
void * memchr(const void *src, int character, size_t len)
Find character within a memory region.
Definition string.c:136

References __unused, asn1_grow(), asn1_builder::data, asn1_cursor::data, DBGC, DBGC_HDA, EINVAL, end, ERANGE, rsa_context::input0, key, asn1_cursor::len, len, rsa_context::max_len, memchr(), memcpy(), rc, rsa_cipher(), rsa_free(), rsa_init(), and start.

◆ rsa_pkcs1_encode()

int rsa_pkcs1_encode ( struct rsa_context * context,
struct digest_algorithm * digest,
const void * value,
const void *reference __unused,
void * encoded )
static

Encode digest using RSA PKCS#1.

Parameters
contextRSA context
digestDigest algorithm
valueDigest value
referenceReference encoded digest (or NULL)
encodedEncoded digest
Return values
rcReturn status code

Definition at line 496 of file rsa.c.

500 {
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}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define ENOTSUP
Operation not supported.
Definition errno.h:590
static struct rsa_digestinfo_prefix * rsa_find_prefix(struct digest_algorithm *digest)
Identify RSA prefix.
Definition rsa.c:102
size_t digestsize
Digest size.
Definition crypto.h:27
const char * name
Algorithm name.
Definition crypto.h:21

References __unused, assert, DBGC, DBGC_HDA, rsa_digestinfo_prefix::digest, digest_algorithm::digestsize, ENOTSUP, ERANGE, rsa_context::max_len, memcpy(), memset(), digest_algorithm::name, prefix, rsa_find_prefix(), and value.

◆ rsa_xor_mask()

void rsa_xor_mask ( struct digest_algorithm * digest,
void * ctx,
void * out,
const void * seed,
void * xor,
size_t len )
static

Apply RSA PSS mask generation function.

Parameters
digestDigest algorithm
ctxDigest context buffer
outDigest output buffer
seedMask seed
xorXOR buffer
lenLength of XOR buffer

Definition at line 558 of file rsa.c.

560 {
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 */
570 digest_init ( digest, ctx );
571 digest_update ( digest, ctx, seed, digest_len );
572 digest_update ( digest, ctx, &counter, sizeof ( counter ) );
573 digest_final ( digest, ctx, out );
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}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
unsigned int uint32_t
Definition stdint.h:12
#define ntohl(value)
Definition byteswap.h:135
#define htonl(value)
Definition byteswap.h:134
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
static u32 xor(u32 a, u32 b)
Definition tlan.h:457

References ctx, rsa_digestinfo_prefix::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, htonl, len, ntohl, out, and xor().

Referenced by rsa_pss_encode().

◆ rsa_pss_encode()

int rsa_pss_encode ( struct rsa_context * context,
struct digest_algorithm * digest,
const void * value,
const void * reference,
void * encoded )
static

Encode digest using RSA PSS.

Parameters
contextRSA context
digestDigest algorithm
valueDigest value
referenceReference encoded digest (or NULL)
encodedEncoded digest
Return values
rcReturn status code

Definition at line 594 of file rsa.c.

597 {
598 static uint8_t zero[8];
599 uint8_t ctx[ digest->ctxsize ];
600 uint8_t out[ digest->digestsize ];
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 */
650 digest_init ( digest, ctx );
651 digest_update ( digest, ctx, zero, sizeof ( zero ) );
652 digest_update ( digest, ctx, value, digest_len );
653 digest_update ( digest, ctx, salt, digest_len );
654 digest_final ( digest, ctx, hash );
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}
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
uint8_t head
Head number.
Definition int13.h:23
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
size_t ctxsize
Context size.
Definition crypto.h:23

References assert, ctx, digest_algorithm::ctxsize, DBGC, DBGC_HDA, rsa_digestinfo_prefix::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, ERANGE, hash, head, rsa_context::mask, rsa_context::max_len, memcpy(), memset(), digest_algorithm::name, out, rc, rsa_get_random, rsa_xor_mask(), strerror(), and value.

◆ rsa_sign()

int rsa_sign ( struct pubkey_algorithm * pubkey,
const struct asn1_cursor * key,
struct digest_algorithm * digest,
const void * value,
struct asn1_builder * signature )
static

Sign digest value using RSA.

Parameters
pubkeyPublic-key algorithm
keyKey
digestDigest algorithm
valueDigest value
signatureSignature
Return values
rcReturn status code

Definition at line 679 of file rsa.c.

682 {
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}
u8 signature
CPU signature.
Definition CIB_PRM.h:7
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
void * priv
Algorithm private data.
Definition crypto.h:206

References asn1_grow(), DBGC, DBGC_HDA, digest_algorithm::digestsize, key, rsa_context::max_len, digest_algorithm::name, NULL, pubkey_algorithm::priv, rc, rsa_cipher(), rsa_free(), rsa_init(), signature, and value.

◆ rsa_verify()

int rsa_verify ( struct pubkey_algorithm * pubkey,
const struct asn1_cursor * key,
struct digest_algorithm * digest,
const void * value,
const struct asn1_cursor * signature )
static

Verify signed digest value using RSA.

Parameters
pubkeyPublic-key algorithm
keyKey
digestDigest algorithm
valueDigest value
signatureSignature
Return values
rcReturn status code

Definition at line 731 of file rsa.c.

734 {
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}
#define EACCES_VERIFY
Definition rsa.c:48
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115

References DBGC, DBGC_HDA, digest_algorithm::digestsize, EACCES_VERIFY, ERANGE, rsa_context::input0, key, rsa_context::max_len, memcmp(), digest_algorithm::name, rsa_context::output0, pubkey_algorithm::priv, rc, rsa_cipher(), rsa_free(), rsa_init(), signature, and value.

◆ rsa_match()

int rsa_match ( struct pubkey_algorithm *pubkey __unused,
const struct asn1_cursor * private_key,
const struct asn1_cursor * public_key )
static

Check for matching RSA public/private key pair.

Parameters
pubkeyPublic-key algorithm
private_keyPrivate key
public_keyPublic key
Return values
rcReturn status code

Definition at line 808 of file rsa.c.

810 {
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}
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:528
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
A private key.
Definition privkey.h:17

References __unused, asn1_compare(), ENOTTY, rc, and rsa_parse_mod_exp().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( rsa_algorithm )

References rsa_algorithm.

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_crypto )

Variable Documentation

◆ rsa_get_random

int(* rsa_get_random) (void *data, size_t len) ( void * data,
size_t len ) = get_random_nz

Generate random data.

Definition at line 93 of file rsa.c.

Referenced by rsa_pkcs1_encrypt(), rsa_pss_encode(), and rsa_test_exec().

◆ rsa_algorithm

struct pubkey_algorithm rsa_algorithm
Initial value:
= {
.name = "rsa",
.encrypt = rsa_pkcs1_encrypt,
.decrypt = rsa_pkcs1_decrypt,
.sign = rsa_sign,
.verify = rsa_verify,
.match = rsa_match,
}
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 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 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
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_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

RSA public-key algorithm.

Definition at line 833 of file rsa.c.

833 {
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};

Referenced by __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), __tls_cipher_suite(), icert_cert(), PUBKEY_SIGN_TEST(), PUBKEY_SIGN_TEST(), PUBKEY_SIGN_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), and REQUIRING_SYMBOL().

◆ rsa_pss_algorithm

struct pubkey_algorithm rsa_pss_algorithm
Initial value:
= {
.name = "rsa_pss",
.encrypt = pubkey_null_encrypt,
.decrypt = pubkey_null_decrypt,
.sign = rsa_sign,
.verify = rsa_verify,
.match = rsa_match,
.priv = rsa_pss_encode,
}
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)
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

RSA-PSS public-key algorithm.

Definition at line 844 of file rsa.c.

844 {
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};

Referenced by PUBKEY_SIGN_TEST(), PUBKEY_SIGN_TEST(), and PUBKEY_SIGN_TEST().