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/md5_sha1.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_prefix * rsa_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 int 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 49 of file rsa.c.

49#define EACCES_VERIFY \
50 __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 51 of file rsa.c.

51#define EINFO_EACCES_VERIFY \
52 __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 88 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 103 of file rsa.c.

103 {
105
107 if ( prefix->digest == digest )
108 return prefix;
109 }
110 return NULL;
111}
#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 118 of file rsa.c.

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

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 131 of file rsa.c.

132 {
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}
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:578
#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:677
bigint_element_t * exponent0
Exponent.
Definition rsa.c:65
bigint_element_t * input0
Input buffer.
Definition rsa.c:69
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
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

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 172 of file rsa.c.

174 {
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}
__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: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_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
#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
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 249 of file rsa.c.

250 {
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}
union @162305117151260234136356364136041353210355154177 key
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define EINVAL
Invalid argument.
Definition errno.h:472
#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:118
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 int rsa_alloc(struct rsa_context *context, size_t modulus_len, size_t exponent_len)
Allocate RSA dynamic storage.
Definition rsa.c:131
uint8_t mask
Modulus MSB mask.
Definition rsa.c:75

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()

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

Perform RSA cipher operation.

Parameters
contextRSA context
inInput buffer
outOutput buffer
Return values
canonicalInput was in canonical form

Definition at line 307 of file rsa.c.

308 {
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}
__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_is_geq(value, reference)
Compare big integers.
Definition bigint.h:146
#define bigint_done(value, out, len)
Finalise big integer.
Definition bigint.h:76

References bigint_done, bigint_init, bigint_is_geq, 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 339 of file rsa.c.

342 {
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}
int asn1_grow(struct asn1_builder *builder, size_t extra)
Grow ASN.1 builder.
Definition asn1.c:1036
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
static int rsa_cipher(struct rsa_context *context, const void *in, void *out)
Perform RSA cipher operation.
Definition rsa.c:307
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
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:55

References __unused, asn1_grow(), assert, 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 418 of file rsa.c.

421 {
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}
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
ring len
Length.
Definition dwmac.h:226
uint32_t start
Starting offset.
Definition netvsc.h:1
#define ERANGE
Result too large.
Definition errno.h:683
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(), pad, 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 515 of file rsa.c.

519 {
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}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
#define ENOTSUP
Operation not supported.
Definition errno.h:633
static int is_md5_sha1(struct digest_algorithm *digest)
Check if a digest algorithm is MD5+SHA1.
Definition md5_sha1.h:74
static struct rsa_digestinfo_prefix * rsa_find_prefix(struct digest_algorithm *digest)
Identify RSA prefix.
Definition rsa.c:103
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, is_md5_sha1(), 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 581 of file rsa.c.

583 {
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 */
593 digest_init ( digest, ctx );
594 digest_update ( digest, ctx, seed, digest_len );
595 digest_update ( digest, ctx, &counter, sizeof ( counter ) );
596 digest_final ( digest, ctx, out );
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}
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 617 of file rsa.c.

620 {
621 static uint8_t zero[8];
622 uint8_t ctx[ digest->ctxsize ];
623 uint8_t out[ digest->digestsize ];
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 */
673 digest_init ( digest, ctx );
674 digest_update ( digest, ctx, zero, sizeof ( zero ) );
675 digest_update ( digest, ctx, value, digest_len );
676 digest_update ( digest, ctx, salt, digest_len );
677 digest_final ( digest, ctx, hash );
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}
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:581
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 702 of file rsa.c.

705 {
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}
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:88
void * priv
Algorithm private data.
Definition crypto.h:206

References asn1_grow(), assert, 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 756 of file rsa.c.

759 {
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}
#define EACCES_VERIFY
Definition rsa.c:49
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 841 of file rsa.c.

843 {
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}
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:566
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
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 94 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:339
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 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
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_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

RSA public-key algorithm.

Definition at line 866 of file rsa.c.

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

◆ 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:617

RSA-PSS public-key algorithm.

Definition at line 877 of file rsa.c.

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

Referenced by PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), PUBKEY_TEST(), and PUBKEY_TEST().