mirror of https://github.com/ipxe/ipxe.git
[crypto] Add native RSA algorithm
Add an implementation of RSA that uses the iPXE big-integer support. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/6/head
parent
c00eb6e190
commit
299dedcff0
|
@ -0,0 +1,600 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ipxe/asn1.h>
|
||||
#include <ipxe/crypto.h>
|
||||
#include <ipxe/bigint.h>
|
||||
#include <ipxe/random_nz.h>
|
||||
#include <ipxe/md5.h>
|
||||
#include <ipxe/sha1.h>
|
||||
#include <ipxe/sha256.h>
|
||||
#include <ipxe/rsa.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* RSA public-key cryptography
|
||||
*
|
||||
* RSA is documented in RFC 3447.
|
||||
*/
|
||||
|
||||
/** An RSA digestInfo prefix */
|
||||
struct rsa_digestinfo_prefix {
|
||||
/** Digest algorithm */
|
||||
struct digest_algorithm *digest;
|
||||
/** Prefix */
|
||||
const void *data;
|
||||
/** Length of prefix */
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/** "id-md5" object identifier */
|
||||
static const uint8_t rsa_md5_prefix[] =
|
||||
{ RSA_DIGESTINFO_PREFIX ( MD5_DIGEST_SIZE, ASN1_OID_MD5 ) };
|
||||
|
||||
/** "id-sha1" object identifier */
|
||||
static const uint8_t rsa_sha1_prefix[] =
|
||||
{ RSA_DIGESTINFO_PREFIX ( SHA1_DIGEST_SIZE, ASN1_OID_SHA1 ) };
|
||||
|
||||
/** "id-sha256" object identifier */
|
||||
static const uint8_t rsa_sha256_prefix[] =
|
||||
{ RSA_DIGESTINFO_PREFIX ( SHA256_DIGEST_SIZE, ASN1_OID_SHA256 ) };
|
||||
|
||||
/** RSA digestInfo prefixes */
|
||||
static struct rsa_digestinfo_prefix rsa_digestinfo_prefixes[] = {
|
||||
{
|
||||
.digest = &md5_algorithm,
|
||||
.data = rsa_md5_prefix,
|
||||
.len = sizeof ( rsa_md5_prefix ),
|
||||
},
|
||||
{
|
||||
.digest = &sha1_algorithm,
|
||||
.data = rsa_sha1_prefix,
|
||||
.len = sizeof ( rsa_sha1_prefix ),
|
||||
},
|
||||
{
|
||||
.digest = &sha256_algorithm,
|
||||
.data = rsa_sha256_prefix,
|
||||
.len = sizeof ( rsa_sha256_prefix ),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Identify RSA prefix
|
||||
*
|
||||
* @v digest Digest algorithm
|
||||
* @ret prefix RSA prefix, or NULL
|
||||
*/
|
||||
static struct rsa_digestinfo_prefix *
|
||||
rsa_find_prefix ( struct digest_algorithm *digest ) {
|
||||
struct rsa_digestinfo_prefix *prefix;
|
||||
unsigned int i;
|
||||
|
||||
for ( i = 0 ; i < ( sizeof ( rsa_digestinfo_prefixes ) /
|
||||
sizeof ( rsa_digestinfo_prefixes[0] ) ) ; i++ ) {
|
||||
prefix = &rsa_digestinfo_prefixes[i];
|
||||
if ( prefix->digest == digest )
|
||||
return prefix;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free RSA dynamic storage
|
||||
*
|
||||
* @v context RSA context
|
||||
*/
|
||||
static void rsa_free ( struct rsa_context *context ) {
|
||||
|
||||
free ( context->dynamic );
|
||||
context->dynamic = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate RSA dynamic storage
|
||||
*
|
||||
* @v context RSA context
|
||||
* @v modulus_len Modulus length
|
||||
* @v exponent_len Exponent length
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rsa_alloc ( struct rsa_context *context, size_t modulus_len,
|
||||
size_t exponent_len ) {
|
||||
unsigned int size = bigint_required_size ( modulus_len );
|
||||
unsigned int exponent_size = bigint_required_size ( exponent_len );
|
||||
struct {
|
||||
bigint_t ( size ) modulus;
|
||||
bigint_t ( exponent_size ) exponent;
|
||||
bigint_t ( size ) input;
|
||||
bigint_t ( size ) output;
|
||||
} __attribute__ (( packed )) *dynamic;
|
||||
|
||||
/* Free any existing dynamic storage */
|
||||
rsa_free ( context );
|
||||
|
||||
/* Allocate dynamic storage */
|
||||
dynamic = malloc ( sizeof ( *dynamic ) );
|
||||
if ( ! dynamic )
|
||||
return -ENOMEM;
|
||||
|
||||
/* Assign dynamic storage */
|
||||
context->dynamic = dynamic;
|
||||
context->modulus0 = &dynamic->modulus.element[0];
|
||||
context->size = size;
|
||||
context->max_len = modulus_len;
|
||||
context->exponent0 = &dynamic->exponent.element[0];
|
||||
context->exponent_size = exponent_size;
|
||||
context->input0 = &dynamic->input.element[0];
|
||||
context->output0 = &dynamic->output.element[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse RSA integer
|
||||
*
|
||||
* @v context RSA context
|
||||
* @v integer Integer to fill in
|
||||
* @v raw ASN.1 cursor
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rsa_parse_integer ( struct rsa_context *context,
|
||||
struct asn1_cursor *integer,
|
||||
const struct asn1_cursor *raw ) {
|
||||
|
||||
/* Enter integer */
|
||||
memcpy ( integer, raw, sizeof ( *integer ) );
|
||||
asn1_enter ( integer, ASN1_INTEGER );
|
||||
|
||||
/* Skip initial sign byte if applicable */
|
||||
if ( ( integer->len > 1 ) &&
|
||||
( *( ( uint8_t * ) integer->data ) == 0x00 ) ) {
|
||||
integer->data++;
|
||||
integer->len--;
|
||||
}
|
||||
|
||||
/* Fail if cursor or integer are invalid */
|
||||
if ( ! integer->len ) {
|
||||
DBGC ( context, "RSA %p invalid integer:\n", context );
|
||||
DBGC_HDA ( context, 0, raw->data, raw->len );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise RSA cipher
|
||||
*
|
||||
* @v ctx RSA context
|
||||
* @v key Key
|
||||
* @v key_len Length of key
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rsa_init ( void *ctx, const void *key, size_t key_len ) {
|
||||
struct rsa_context *context = ctx;
|
||||
const struct asn1_bit_string *bit_string;
|
||||
struct asn1_cursor modulus;
|
||||
struct asn1_cursor exponent;
|
||||
struct asn1_cursor cursor;
|
||||
int is_private;
|
||||
int rc;
|
||||
|
||||
/* Initialise context */
|
||||
memset ( context, 0, sizeof ( *context ) );
|
||||
|
||||
/* Initialise cursor */
|
||||
cursor.data = key;
|
||||
cursor.len = key_len;
|
||||
|
||||
/* Enter subjectPublicKeyInfo/RSAPrivateKey */
|
||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
||||
|
||||
/* Determine key format */
|
||||
if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
|
||||
/* Private key */
|
||||
is_private = 1;
|
||||
|
||||
/* Skip version */
|
||||
asn1_skip_any ( &cursor );
|
||||
|
||||
} else {
|
||||
/* Public key */
|
||||
is_private = 0;
|
||||
|
||||
/* Skip algorithm */
|
||||
asn1_skip ( &cursor, ASN1_SEQUENCE );
|
||||
|
||||
/* Enter subjectPublicKey */
|
||||
asn1_enter ( &cursor, ASN1_BIT_STRING );
|
||||
|
||||
/* Check and skip unused-bits byte of bit string */
|
||||
bit_string = cursor.data;
|
||||
if ( cursor.len < 1 ) {
|
||||
rc = -EINVAL;
|
||||
goto err_parse;
|
||||
}
|
||||
cursor.data++;
|
||||
cursor.len--;
|
||||
|
||||
/* Enter RSAPublicKey */
|
||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
||||
}
|
||||
|
||||
/* Extract modulus */
|
||||
if ( ( rc = rsa_parse_integer ( context, &modulus, &cursor ) ) != 0 )
|
||||
goto err_parse;
|
||||
asn1_skip_any ( &cursor );
|
||||
|
||||
/* Skip public exponent, if applicable */
|
||||
if ( is_private )
|
||||
asn1_skip ( &cursor, ASN1_INTEGER );
|
||||
|
||||
/* Extract publicExponent/privateExponent */
|
||||
if ( ( rc = rsa_parse_integer ( context, &exponent, &cursor ) ) != 0 )
|
||||
goto err_parse;
|
||||
|
||||
DBGC ( context, "RSA %p modulus:\n", context );
|
||||
DBGC_HDA ( context, 0, modulus.data, modulus.len );
|
||||
DBGC ( context, "RSA %p exponent:\n", context );
|
||||
DBGC_HDA ( context, 0, exponent.data, exponent.len );
|
||||
|
||||
/* Allocate dynamic storage */
|
||||
if ( ( rc = rsa_alloc ( context, modulus.len, exponent.len ) ) != 0 )
|
||||
goto err_alloc;
|
||||
|
||||
/* Construct big integers */
|
||||
bigint_init ( ( ( bigint_t ( context->size ) * ) context->modulus0 ),
|
||||
modulus.data, modulus.len );
|
||||
bigint_init ( ( ( bigint_t ( context->exponent_size ) * )
|
||||
context->exponent0 ), exponent.data, exponent.len );
|
||||
|
||||
return 0;
|
||||
|
||||
rsa_free ( context );
|
||||
err_alloc:
|
||||
err_parse:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate RSA maximum output length
|
||||
*
|
||||
* @v ctx RSA context
|
||||
* @ret max_len Maximum output length
|
||||
*/
|
||||
static size_t rsa_max_len ( void *ctx ) {
|
||||
struct rsa_context *context = ctx;
|
||||
|
||||
return context->max_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform RSA cipher operation
|
||||
*
|
||||
* @v context RSA context
|
||||
* @v in Input buffer
|
||||
* @v out Output buffer
|
||||
*/
|
||||
static void rsa_cipher ( struct rsa_context *context,
|
||||
const void *in, void *out ) {
|
||||
bigint_t ( context->size ) *input = ( ( void * ) context->input0 );
|
||||
bigint_t ( context->size ) *output = ( ( void * ) context->output0 );
|
||||
bigint_t ( context->size ) *modulus = ( ( void * ) context->modulus0 );
|
||||
bigint_t ( context->exponent_size ) *exponent =
|
||||
( ( void * ) context->exponent0 );
|
||||
|
||||
/* Initialise big integer */
|
||||
bigint_init ( input, in, context->max_len );
|
||||
|
||||
/* Perform modular exponentiation */
|
||||
bigint_mod_exp ( input, modulus, exponent, output );
|
||||
|
||||
/* Copy out result */
|
||||
bigint_done ( output, out, context->max_len );
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt using RSA
|
||||
*
|
||||
* @v ctx RSA context
|
||||
* @v plaintext Plaintext
|
||||
* @v plaintext_len Length of plaintext
|
||||
* @v ciphertext Ciphertext
|
||||
* @ret ciphertext_len Length of ciphertext, or negative error
|
||||
*/
|
||||
static int rsa_encrypt ( void *ctx, const void *plaintext,
|
||||
size_t plaintext_len, void *ciphertext ) {
|
||||
struct rsa_context *context = ctx;
|
||||
void *temp;
|
||||
uint8_t *encoded;
|
||||
size_t max_len = ( context->max_len - 11 );
|
||||
size_t random_nz_len = ( max_len - plaintext_len + 8 );
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
if ( plaintext_len > max_len ) {
|
||||
DBGC ( context, "RSA %p plaintext too long (%zd bytes, max "
|
||||
"%zd)\n", context, plaintext_len, max_len );
|
||||
return -ERANGE;
|
||||
}
|
||||
DBGC ( context, "RSA %p encrypting:\n", context );
|
||||
DBGC_HDA ( context, 0, plaintext, plaintext_len );
|
||||
|
||||
/* Construct encoded message (using the big integer output
|
||||
* buffer as temporary storage)
|
||||
*/
|
||||
temp = context->output0;
|
||||
encoded = temp;
|
||||
encoded[0] = 0x00;
|
||||
encoded[1] = 0x02;
|
||||
if ( ( rc = get_random_nz ( &encoded[2], random_nz_len ) ) != 0 ) {
|
||||
DBGC ( context, "RSA %p could not generate random data: %s\n",
|
||||
context, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
encoded[ 2 + random_nz_len ] = 0x00;
|
||||
memcpy ( &encoded[ context->max_len - plaintext_len ],
|
||||
plaintext, plaintext_len );
|
||||
|
||||
/* Encipher the encoded message */
|
||||
rsa_cipher ( context, encoded, ciphertext );
|
||||
DBGC ( context, "RSA %p encrypted:\n", context );
|
||||
DBGC_HDA ( context, 0, ciphertext, context->max_len );
|
||||
|
||||
return context->max_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt using RSA
|
||||
*
|
||||
* @v ctx RSA context
|
||||
* @v ciphertext Ciphertext
|
||||
* @v ciphertext_len Ciphertext length
|
||||
* @v plaintext Plaintext
|
||||
* @ret plaintext_len Plaintext length, or negative error
|
||||
*/
|
||||
static int rsa_decrypt ( void *ctx, const void *ciphertext,
|
||||
size_t ciphertext_len, void *plaintext ) {
|
||||
struct rsa_context *context = ctx;
|
||||
void *temp;
|
||||
uint8_t *encoded;
|
||||
uint8_t *end;
|
||||
uint8_t *zero;
|
||||
uint8_t *start;
|
||||
size_t plaintext_len;
|
||||
|
||||
/* Sanity check */
|
||||
if ( ciphertext_len != context->max_len ) {
|
||||
DBGC ( context, "RSA %p ciphertext incorrect length (%zd "
|
||||
"bytes, should be %zd)\n",
|
||||
context, ciphertext_len, context->max_len );
|
||||
return -ERANGE;
|
||||
}
|
||||
DBGC ( context, "RSA %p decrypting:\n", context );
|
||||
DBGC_HDA ( context, 0, ciphertext, ciphertext_len );
|
||||
|
||||
/* Decipher the message (using the big integer input buffer as
|
||||
* temporary storage)
|
||||
*/
|
||||
temp = context->input0;
|
||||
encoded = temp;
|
||||
rsa_cipher ( context, ciphertext, encoded );
|
||||
|
||||
/* Parse the message */
|
||||
end = ( encoded + context->max_len );
|
||||
if ( ( encoded[0] != 0x00 ) || ( encoded[1] != 0x02 ) )
|
||||
goto invalid;
|
||||
zero = memchr ( &encoded[2], 0, ( end - &encoded[2] ) );
|
||||
if ( ! zero )
|
||||
goto invalid;
|
||||
start = ( zero + 1 );
|
||||
plaintext_len = ( end - start );
|
||||
|
||||
/* Copy out message */
|
||||
memcpy ( plaintext, start, plaintext_len );
|
||||
DBGC ( context, "RSA %p decrypted:\n", context );
|
||||
DBGC_HDA ( context, 0, plaintext, plaintext_len );
|
||||
|
||||
return plaintext_len;
|
||||
|
||||
invalid:
|
||||
DBGC ( context, "RSA %p invalid decrypted message:\n", context );
|
||||
DBGC_HDA ( context, 0, encoded, context->max_len );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode RSA digest
|
||||
*
|
||||
* @v context RSA context
|
||||
* @v digest Digest algorithm
|
||||
* @v value Digest value
|
||||
* @v encoded Encoded digest
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rsa_encode_digest ( struct rsa_context *context,
|
||||
struct digest_algorithm *digest,
|
||||
const void *value, void *encoded ) {
|
||||
struct rsa_digestinfo_prefix *prefix;
|
||||
size_t digest_len = digest->digestsize;
|
||||
uint8_t *temp = encoded;
|
||||
size_t digestinfo_len;
|
||||
size_t max_len;
|
||||
size_t pad_len;
|
||||
|
||||
/* Identify prefix */
|
||||
prefix = rsa_find_prefix ( digest );
|
||||
if ( ! prefix ) {
|
||||
DBGC ( context, "RSA %p has no prefix for %s\n",
|
||||
context, digest->name );
|
||||
return -ENOTSUP;
|
||||
}
|
||||
digestinfo_len = ( prefix->len + digest_len );
|
||||
|
||||
/* Sanity check */
|
||||
max_len = ( context->max_len - 11 );
|
||||
if ( digestinfo_len > max_len ) {
|
||||
DBGC ( context, "RSA %p %s digestInfo too long (%zd bytes, max"
|
||||
"%zd)\n",
|
||||
context, digest->name, digestinfo_len, max_len );
|
||||
return -ERANGE;
|
||||
}
|
||||
DBGC ( context, "RSA %p encoding %s digest:\n",
|
||||
context, digest->name );
|
||||
DBGC_HDA ( context, 0, value, digest_len );
|
||||
|
||||
/* Construct encoded message */
|
||||
*(temp++) = 0x00;
|
||||
*(temp++) = 0x01;
|
||||
pad_len = ( max_len - digestinfo_len + 8 );
|
||||
memset ( temp, 0xff, pad_len );
|
||||
temp += pad_len;
|
||||
*(temp++) = 0x00;
|
||||
memcpy ( temp, prefix->data, prefix->len );
|
||||
temp += prefix->len;
|
||||
memcpy ( temp, value, digest_len );
|
||||
temp += digest_len;
|
||||
assert ( temp == ( encoded + context->max_len ) );
|
||||
DBGC ( context, "RSA %p encoded %s digest:\n", context, digest->name );
|
||||
DBGC_HDA ( context, 0, encoded, context->max_len );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign digest value using RSA
|
||||
*
|
||||
* @v ctx RSA context
|
||||
* @v digest Digest algorithm
|
||||
* @v value Digest value
|
||||
* @v signature Signature
|
||||
* @ret signature_len Signature length, or negative error
|
||||
*/
|
||||
static int rsa_sign ( void *ctx, struct digest_algorithm *digest,
|
||||
const void *value, void *signature ) {
|
||||
struct rsa_context *context = ctx;
|
||||
void *temp;
|
||||
int rc;
|
||||
|
||||
DBGC ( context, "RSA %p signing %s digest:\n", context, digest->name );
|
||||
DBGC_HDA ( context, 0, value, digest->digestsize );
|
||||
|
||||
/* Encode digest (using the big integer output buffer as
|
||||
* temporary storage)
|
||||
*/
|
||||
temp = context->output0;
|
||||
if ( ( rc = rsa_encode_digest ( context, digest, value, temp ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Encipher the encoded digest */
|
||||
rsa_cipher ( context, temp, signature );
|
||||
DBGC ( context, "RSA %p signed %s digest:\n", context, digest->name );
|
||||
DBGC_HDA ( context, 0, signature, context->max_len );
|
||||
|
||||
return context->max_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify signed digest value using RSA
|
||||
*
|
||||
* @v ctx RSA context
|
||||
* @v digest Digest algorithm
|
||||
* @v value Digest value
|
||||
* @v signature Signature
|
||||
* @v signature_len Signature length
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int rsa_verify ( void *ctx, struct digest_algorithm *digest,
|
||||
const void *value, const void *signature,
|
||||
size_t signature_len ) {
|
||||
struct rsa_context *context = ctx;
|
||||
void *temp;
|
||||
void *expected;
|
||||
void *actual;
|
||||
int rc;
|
||||
|
||||
/* Sanity check */
|
||||
if ( signature_len != context->max_len ) {
|
||||
DBGC ( context, "RSA %p signature incorrect length (%zd "
|
||||
"bytes, should be %zd)\n",
|
||||
context, signature_len, context->max_len );
|
||||
return -ERANGE;
|
||||
}
|
||||
DBGC ( context, "RSA %p verifying %s digest:\n",
|
||||
context, digest->name );
|
||||
DBGC_HDA ( context, 0, value, digest->digestsize );
|
||||
DBGC_HDA ( context, 0, signature, signature_len );
|
||||
|
||||
/* Decipher the signature (using the big integer input buffer
|
||||
* as temporary storage)
|
||||
*/
|
||||
temp = context->input0;
|
||||
expected = temp;
|
||||
rsa_cipher ( context, signature, expected );
|
||||
DBGC ( context, "RSA %p deciphered signature:\n", context );
|
||||
DBGC_HDA ( context, 0, expected, context->max_len );
|
||||
|
||||
/* Encode digest (using the big integer output buffer as
|
||||
* temporary storage)
|
||||
*/
|
||||
temp = context->output0;
|
||||
actual = temp;
|
||||
if ( ( rc = rsa_encode_digest ( context, digest, value, actual ) ) !=0 )
|
||||
return rc;
|
||||
|
||||
/* Verify the signature */
|
||||
if ( memcmp ( actual, expected, context->max_len ) != 0 ) {
|
||||
DBGC ( context, "RSA %p signature verification failed\n",
|
||||
context );
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
DBGC ( context, "RSA %p signature verified successfully\n", context );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise RSA cipher
|
||||
*
|
||||
* @v ctx RSA context
|
||||
*/
|
||||
static void rsa_final ( void *ctx ) {
|
||||
struct rsa_context *context = ctx;
|
||||
|
||||
rsa_free ( context );
|
||||
}
|
||||
|
||||
/** RSA public-key algorithm */
|
||||
struct pubkey_algorithm rsa_algorithm = {
|
||||
.name = "rsa",
|
||||
.ctxsize = sizeof ( struct rsa_context ),
|
||||
.init = rsa_init,
|
||||
.max_len = rsa_max_len,
|
||||
.encrypt = rsa_encrypt,
|
||||
.decrypt = rsa_decrypt,
|
||||
.sign = rsa_sign,
|
||||
.verify = rsa_verify,
|
||||
.final = rsa_final,
|
||||
};
|
|
@ -246,6 +246,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||
#define ERRFILE_hmac_drbg ( ERRFILE_OTHER | 0x00240000 )
|
||||
#define ERRFILE_drbg ( ERRFILE_OTHER | 0x00250000 )
|
||||
#define ERRFILE_entropy ( ERRFILE_OTHER | 0x00260000 )
|
||||
#define ERRFILE_rsa ( ERRFILE_OTHER | 0x00270000 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -1,12 +1,136 @@
|
|||
#ifndef _IPXE_RSA_H
|
||||
#define _IPXE_RSA_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* RSA public-key cryptography
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER );
|
||||
|
||||
struct pubkey_algorithm;
|
||||
#include <ipxe/crypto.h>
|
||||
#include <ipxe/bigint.h>
|
||||
#include <ipxe/asn1.h>
|
||||
|
||||
/** ASN.1 OID for iso(1) member-body(2) us(840) */
|
||||
#define ASN1_OID_ISO_US ASN1_OID_ISO_MEMBERBODY, ASN1_OID_DOUBLE ( 840 )
|
||||
|
||||
/** ASN.1 OID for iso(1) member-body(2) us(840) rsadsi(113549) */
|
||||
#define ASN1_OID_RSADSI ASN1_OID_ISO_US, ASN1_OID_TRIPLE ( 113549 )
|
||||
|
||||
/** ASN.1 OID for iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) */
|
||||
#define ASN1_OID_PKCS ASN1_OID_RSADSI, ASN1_OID_SINGLE ( 1 )
|
||||
|
||||
/** ASN.1 OID for iso(1) member-body(2) us(840) rsadsi(113549)
|
||||
* digestAlgorithm(2)
|
||||
*/
|
||||
#define ASN1_OID_DIGESTALGORITHM ASN1_OID_RSADSI, ASN1_OID_SINGLE ( 2 )
|
||||
|
||||
/** ASN.1 OID for iso(1) identified-organization(3) oiw(14) */
|
||||
#define ASN1_OID_OIW ASN1_OID_IDENTIFIED_ORGANIZATION, ASN1_OID_SINGLE ( 14 )
|
||||
|
||||
/** ASN.1 OID for iso(1) identified-organization(3) oiw(14) secsig(3) */
|
||||
#define ASN1_OID_SECSIG ASN1_OID_OIW, ASN1_OID_SINGLE ( 3 )
|
||||
|
||||
/** ASN1. OID for iso(1) identified-organization(3) oiw(14) secsig(3)
|
||||
* algorithms(2)
|
||||
*/
|
||||
#define ASN1_OID_SECSIG_ALGORITHMS ASN1_OID_SECSIG, ASN1_OID_SINGLE ( 2 )
|
||||
|
||||
/** ASN.1 OID for joint-iso-itu-t(2) country(16) us(840) */
|
||||
#define ASN1_OID_COUNTRY_US ASN1_OID_COUNTRY, ASN1_OID_DOUBLE ( 840 )
|
||||
|
||||
/** ASN.1 OID for joint-iso-itu-t(2) country(16) us(840) organization(1) */
|
||||
#define ASN1_OID_US_ORGANIZATION ASN1_OID_COUNTRY_US, ASN1_OID_SINGLE ( 1 )
|
||||
|
||||
/** ASN.1 OID for joint-iso-itu-t(2) country(16) us(840)
|
||||
* organization(1) gov(101)
|
||||
*/
|
||||
#define ASN1_OID_US_GOV ASN1_OID_US_ORGANIZATION, ASN1_OID_SINGLE ( 101 )
|
||||
|
||||
/** ASN.1 OID for joint-iso-itu-t(2) country(16) us(840)
|
||||
* organization(1) gov(101) csor(3)
|
||||
*/
|
||||
#define ASN1_OID_CSOR ASN1_OID_US_GOV, ASN1_OID_SINGLE ( 3 )
|
||||
|
||||
/** ASN.1 OID for joint-iso-itu-t(2) country(16) us(840)
|
||||
* organization(1) gov(101) csor(3) nistalgorithm(4)
|
||||
*/
|
||||
#define ASN1_OID_NISTALGORITHM ASN1_OID_CSOR, ASN1_OID_SINGLE ( 4 )
|
||||
|
||||
/** ASN.1 OID for joint-iso-itu-t(2) country(16) us(840)
|
||||
* organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2)
|
||||
*/
|
||||
#define ASN1_OID_HASHALGS ASN1_OID_NISTALGORITHM, ASN1_OID_SINGLE ( 2 )
|
||||
|
||||
/** ASN.1 OID for pkcs-1 */
|
||||
#define ASN1_OID_PKCS_1 ASN1_OID_PKCS, ASN1_OID_SINGLE ( 1 )
|
||||
|
||||
/** ASN.1 OID for rsaEncryption */
|
||||
#define ASN1_OID_RSAENCRYPTION ASN1_OID_PKCS_1, ASN1_OID_SINGLE ( 1 )
|
||||
|
||||
/** ASN.1 OID for md5WithRSAEncryption */
|
||||
#define ASN1_OID_MD5WITHRSAENCRYPTION ASN1_OID_PKCS_1, ASN1_OID_SINGLE ( 4 )
|
||||
|
||||
/** ASN.1 OID for sha1WithRSAEncryption */
|
||||
#define ASN1_OID_SHA1WITHRSAENCRYPTION ASN1_OID_PKCS_1, ASN1_OID_SINGLE ( 5 )
|
||||
|
||||
/** ASN.1 OID for sha256WithRSAEncryption */
|
||||
#define ASN1_OID_SHA256WITHRSAENCRYPTION ASN1_OID_PKCS_1, ASN1_OID_SINGLE ( 11 )
|
||||
|
||||
/** ASN.1 OID for id-md5 */
|
||||
#define ASN1_OID_MD5 ASN1_OID_DIGESTALGORITHM, ASN1_OID_SINGLE ( 5 )
|
||||
|
||||
/** ASN.1 OID for id-sha1 */
|
||||
#define ASN1_OID_SHA1 ASN1_OID_SECSIG_ALGORITHMS, ASN1_OID_SINGLE ( 26 )
|
||||
|
||||
/** ASN.1 OID for id-sha256 */
|
||||
#define ASN1_OID_SHA256 ASN1_OID_HASHALGS, ASN1_OID_SINGLE ( 1 )
|
||||
|
||||
/** RSA digestAlgorithm sequence contents */
|
||||
#define RSA_DIGESTALGORITHM_CONTENTS( ... ) \
|
||||
ASN1_OID, VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__, \
|
||||
ASN1_NULL, 0x00
|
||||
|
||||
/** RSA digestAlgorithm sequence */
|
||||
#define RSA_DIGESTALGORITHM( ... ) \
|
||||
ASN1_SEQUENCE, \
|
||||
VA_ARG_COUNT ( RSA_DIGESTALGORITHM_CONTENTS ( __VA_ARGS__ ) ), \
|
||||
RSA_DIGESTALGORITHM_CONTENTS ( __VA_ARGS__ )
|
||||
|
||||
/** RSA digest prefix */
|
||||
#define RSA_DIGEST_PREFIX( digest_size ) \
|
||||
ASN1_OCTET_STRING, digest_size
|
||||
|
||||
/** RSA digestInfo prefix */
|
||||
#define RSA_DIGESTINFO_PREFIX( digest_size, ... ) \
|
||||
ASN1_SEQUENCE, \
|
||||
( VA_ARG_COUNT ( RSA_DIGESTALGORITHM ( __VA_ARGS__ ) ) + \
|
||||
VA_ARG_COUNT ( RSA_DIGEST_PREFIX ( digest_size ) ) + \
|
||||
digest_size ), \
|
||||
RSA_DIGESTALGORITHM ( __VA_ARGS__ ), \
|
||||
RSA_DIGEST_PREFIX ( digest_size )
|
||||
|
||||
/** An RSA context */
|
||||
struct rsa_context {
|
||||
/** Allocated memory */
|
||||
void *dynamic;
|
||||
/** Modulus */
|
||||
bigint_element_t *modulus0;
|
||||
/** Modulus size */
|
||||
unsigned int size;
|
||||
/** Modulus length */
|
||||
size_t max_len;
|
||||
/** Exponent */
|
||||
bigint_element_t *exponent0;
|
||||
/** Exponent size */
|
||||
unsigned int exponent_size;
|
||||
/** Input buffer */
|
||||
bigint_element_t *input0;
|
||||
/** Output buffer */
|
||||
bigint_element_t *output0;
|
||||
};
|
||||
|
||||
extern struct pubkey_algorithm rsa_algorithm;
|
||||
|
||||
#include "crypto/axtls/crypto.h"
|
||||
|
||||
#endif /* _IPXE_RSA_H */
|
||||
|
|
Loading…
Reference in New Issue