diff options
author | 2017-04-25 03:31:15 -0700 | |
---|---|---|
committer | 2017-05-22 06:48:08 +0000 | |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/roms/ipxe/src/crypto | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/roms/ipxe/src/crypto')
43 files changed, 0 insertions, 12130 deletions
diff --git a/qemu/roms/ipxe/src/crypto/aes.c b/qemu/roms/ipxe/src/crypto/aes.c deleted file mode 100644 index b9e206bfb..000000000 --- a/qemu/roms/ipxe/src/crypto/aes.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * AES algorithm - * - */ - -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <byteswap.h> -#include <ipxe/rotate.h> -#include <ipxe/crypto.h> -#include <ipxe/ecb.h> -#include <ipxe/cbc.h> -#include <ipxe/aes.h> - -/** AES strides - * - * These are the strides (modulo 16) used to walk through the AES - * input state bytes in order of byte position after [Inv]ShiftRows. - */ -enum aes_stride { - /** Input stride for ShiftRows - * - * 0 4 8 c - * \ \ \ - * 1 5 9 d - * \ \ \ - * 2 6 a e - * \ \ \ - * 3 7 b f - */ - AES_STRIDE_SHIFTROWS = +5, - /** Input stride for InvShiftRows - * - * 0 4 8 c - * / / / - * 1 5 9 d - * / / / - * 2 6 a e - * / / / - * 3 7 b f - */ - AES_STRIDE_INVSHIFTROWS = -3, -}; - -/** A single AES lookup table entry - * - * This represents the product (in the Galois field GF(2^8)) of an - * eight-byte vector multiplier with a single scalar multiplicand. - * - * The vector multipliers used for AES will be {1,1,1,3,2,1,1,3} for - * MixColumns and {1,9,13,11,14,9,13,11} for InvMixColumns. This - * allows for the result of multiplying any single column of the - * [Inv]MixColumns matrix by a scalar value to be obtained simply by - * extracting the relevant four-byte subset from the lookup table - * entry. - * - * For example, to find the result of multiplying the second column of - * the MixColumns matrix by the scalar value 0x80: - * - * MixColumns column[0]: { 2, 1, 1, 3 } - * MixColumns column[1]: { 3, 2, 1, 1 } - * MixColumns column[2]: { 1, 3, 2, 1 } - * MixColumns column[3]: { 1, 1, 3, 2 } - * Vector multiplier: { 1, 1, 1, 3, 2, 1, 1, 3 } - * Scalar multiplicand: 0x80 - * Lookup table entry: { 0x80, 0x80, 0x80, 0x9b, 0x1b, 0x80, 0x80, 0x9b } - * - * The second column of the MixColumns matrix is {3,2,1,1}. The - * product of this column with the scalar value 0x80 can be obtained - * by extracting the relevant four-byte subset of the lookup table - * entry: - * - * MixColumns column[1]: { 3, 2, 1, 1 } - * Vector multiplier: { 1, 1, 1, 3, 2, 1, 1, 3 } - * Lookup table entry: { 0x80, 0x80, 0x80, 0x9b, 0x1b, 0x80, 0x80, 0x9b } - * Product: { 0x9b, 0x1b, 0x80, 0x80 } - * - * The column lookups require only seven bytes of the eight-byte - * entry: the remaining (first) byte is used to hold the scalar - * multiplicand itself (i.e. the first byte of the vector multiplier - * is always chosen to be 1). - */ -union aes_table_entry { - /** Viewed as an array of bytes */ - uint8_t byte[8]; -} __attribute__ (( packed )); - -/** An AES lookup table - * - * This represents the products (in the Galois field GF(2^8)) of a - * constant eight-byte vector multiplier with all possible 256 scalar - * multiplicands. - * - * The entries are indexed by the AES [Inv]SubBytes S-box output - * values (denoted S(N)). This allows for the result of multiplying - * any single column of the [Inv]MixColumns matrix by S(N) to be - * obtained simply by extracting the relevant four-byte subset from - * the Nth table entry. For example: - * - * Input byte (N): 0x3a - * SubBytes output S(N): 0x80 - * MixColumns column[1]: { 3, 2, 1, 1 } - * Vector multiplier: { 1, 1, 1, 3, 2, 1, 1, 3 } - * Table entry[0x3a]: { 0x80, 0x80, 0x80, 0x9b, 0x1b, 0x80, 0x80, 0x9b } - * Product: { 0x9b, 0x1b, 0x80, 0x80 } - * - * Since the first byte of the eight-byte vector multiplier is always - * chosen to be 1, the value of S(N) may be lookup up by extracting - * the first byte of the Nth table entry. - */ -struct aes_table { - /** Table entries, indexed by S(N) */ - union aes_table_entry entry[256]; -} __attribute__ (( aligned ( 8 ) )); - -/** AES MixColumns lookup table */ -static struct aes_table aes_mixcolumns; - -/** AES InvMixColumns lookup table */ -static struct aes_table aes_invmixcolumns; - -/** - * Multiply [Inv]MixColumns matrix column by scalar multiplicand - * - * @v entry AES lookup table entry for scalar multiplicand - * @v column [Inv]MixColumns matrix column index - * @ret product Product of matrix column with scalar multiplicand - */ -static inline __attribute__ (( always_inline )) uint32_t -aes_entry_column ( const union aes_table_entry *entry, unsigned int column ) { - const union { - uint8_t byte; - uint32_t column; - } __attribute__ (( may_alias )) *product; - - /* Locate relevant four-byte subset */ - product = container_of ( &entry->byte[ 4 - column ], - typeof ( *product ), byte ); - - /* Extract this four-byte subset */ - return product->column; -} - -/** - * Multiply [Inv]MixColumns matrix column by S-boxed input byte - * - * @v table AES lookup table - * @v stride AES row shift stride - * @v in AES input state - * @v offset Output byte offset (after [Inv]ShiftRows) - * @ret product Product of matrix column with S(input byte) - * - * Note that the specified offset is not the offset of the input byte; - * it is the offset of the output byte which corresponds to the input - * byte. This output byte offset is used to calculate both the input - * byte offset and to select the appropriate matric column. - * - * With a compile-time constant offset, this function will optimise - * down to a single "movzbl" (to extract the input byte) and will - * generate a single x86 memory reference expression which can then be - * used directly within a single "xorl" instruction. - */ -static inline __attribute__ (( always_inline )) uint32_t -aes_column ( const struct aes_table *table, size_t stride, - const union aes_matrix *in, size_t offset ) { - const union aes_table_entry *entry; - unsigned int byte; - - /* Extract input byte corresponding to this output byte offset - * (i.e. perform [Inv]ShiftRows). - */ - byte = in->byte[ ( stride * offset ) & 0xf ]; - - /* Locate lookup table entry for this input byte (i.e. perform - * [Inv]SubBytes). - */ - entry = &table->entry[byte]; - - /* Multiply appropriate matrix column by this input byte - * (i.e. perform [Inv]MixColumns). - */ - return aes_entry_column ( entry, ( offset & 0x3 ) ); -} - -/** - * Calculate intermediate round output column - * - * @v table AES lookup table - * @v stride AES row shift stride - * @v in AES input state - * @v key AES round key - * @v column Column index - * @ret output Output column value - */ -static inline __attribute__ (( always_inline )) uint32_t -aes_output ( const struct aes_table *table, size_t stride, - const union aes_matrix *in, const union aes_matrix *key, - unsigned int column ) { - size_t offset = ( column * 4 ); - - /* Perform [Inv]ShiftRows, [Inv]SubBytes, [Inv]MixColumns, and - * AddRoundKey for this column. The loop is unrolled to allow - * for the required compile-time constant optimisations. - */ - return ( aes_column ( table, stride, in, ( offset + 0 ) ) ^ - aes_column ( table, stride, in, ( offset + 1 ) ) ^ - aes_column ( table, stride, in, ( offset + 2 ) ) ^ - aes_column ( table, stride, in, ( offset + 3 ) ) ^ - key->column[column] ); -} - -/** - * Perform a single intermediate round - * - * @v table AES lookup table - * @v stride AES row shift stride - * @v in AES input state - * @v out AES output state - * @v key AES round key - */ -static inline __attribute__ (( always_inline )) void -aes_round ( const struct aes_table *table, size_t stride, - const union aes_matrix *in, union aes_matrix *out, - const union aes_matrix *key ) { - - /* Perform [Inv]ShiftRows, [Inv]SubBytes, [Inv]MixColumns, and - * AddRoundKey for all columns. The loop is unrolled to allow - * for the required compile-time constant optimisations. - */ - out->column[0] = aes_output ( table, stride, in, key, 0 ); - out->column[1] = aes_output ( table, stride, in, key, 1 ); - out->column[2] = aes_output ( table, stride, in, key, 2 ); - out->column[3] = aes_output ( table, stride, in, key, 3 ); -} - -/** - * Perform encryption intermediate rounds - * - * @v in AES input state - * @v out AES output state - * @v key Round keys - * @v rounds Number of rounds (must be odd) - * - * This function is deliberately marked as non-inlinable to ensure - * maximal availability of registers for GCC's register allocator, - * which has a tendency to otherwise spill performance-critical - * registers to the stack. - */ -static __attribute__ (( noinline )) void -aes_encrypt_rounds ( union aes_matrix *in, union aes_matrix *out, - const union aes_matrix *key, unsigned int rounds ) { - union aes_matrix *tmp; - - /* Perform intermediate rounds */ - do { - /* Perform one intermediate round */ - aes_round ( &aes_mixcolumns, AES_STRIDE_SHIFTROWS, - in, out, key++ ); - - /* Swap input and output states for next round */ - tmp = in; - in = out; - out = tmp; - - } while ( --rounds ); -} - -/** - * Perform decryption intermediate rounds - * - * @v in AES input state - * @v out AES output state - * @v key Round keys - * @v rounds Number of rounds (must be odd) - * - * As with aes_encrypt_rounds(), this function is deliberately marked - * as non-inlinable. - * - * This function could potentially use the same binary code as is used - * for encryption. To compensate for the difference between ShiftRows - * and InvShiftRows, half of the input byte offsets would have to be - * modifiable at runtime (half by an offset of +4/-4, half by an - * offset of -4/+4 for ShiftRows/InvShiftRows). This can be - * accomplished in x86 assembly within the number of available - * registers, but GCC's register allocator struggles to do so, - * resulting in a significant performance decrease due to registers - * being spilled to the stack. We therefore use two separate but very - * similar binary functions based on the same C source. - */ -static __attribute__ (( noinline )) void -aes_decrypt_rounds ( union aes_matrix *in, union aes_matrix *out, - const union aes_matrix *key, unsigned int rounds ) { - union aes_matrix *tmp; - - /* Perform intermediate rounds */ - do { - /* Perform one intermediate round */ - aes_round ( &aes_invmixcolumns, AES_STRIDE_INVSHIFTROWS, - in, out, key++ ); - - /* Swap input and output states for next round */ - tmp = in; - in = out; - out = tmp; - - } while ( --rounds ); -} - -/** - * Perform standalone AddRoundKey - * - * @v state AES state - * @v key AES round key - */ -static inline __attribute__ (( always_inline )) void -aes_addroundkey ( union aes_matrix *state, const union aes_matrix *key ) { - - state->column[0] ^= key->column[0]; - state->column[1] ^= key->column[1]; - state->column[2] ^= key->column[2]; - state->column[3] ^= key->column[3]; -} - -/** - * Perform final round - * - * @v table AES lookup table - * @v stride AES row shift stride - * @v in AES input state - * @v out AES output state - * @v key AES round key - */ -static void aes_final ( const struct aes_table *table, size_t stride, - const union aes_matrix *in, union aes_matrix *out, - const union aes_matrix *key ) { - const union aes_table_entry *entry; - unsigned int byte; - size_t out_offset; - size_t in_offset; - - /* Perform [Inv]ShiftRows and [Inv]SubBytes */ - for ( out_offset = 0, in_offset = 0 ; out_offset < 16 ; - out_offset++, in_offset = ( ( in_offset + stride ) & 0xf ) ) { - - /* Extract input byte (i.e. perform [Inv]ShiftRows) */ - byte = in->byte[in_offset]; - - /* Locate lookup table entry for this input byte - * (i.e. perform [Inv]SubBytes). - */ - entry = &table->entry[byte]; - - /* Store output byte */ - out->byte[out_offset] = entry->byte[0]; - } - - /* Perform AddRoundKey */ - aes_addroundkey ( out, key ); -} - -/** - * Encrypt data - * - * @v ctx Context - * @v src Data to encrypt - * @v dst Buffer for encrypted data - * @v len Length of data - */ -static void aes_encrypt ( void *ctx, const void *src, void *dst, size_t len ) { - struct aes_context *aes = ctx; - union aes_matrix buffer[2]; - union aes_matrix *in = &buffer[0]; - union aes_matrix *out = &buffer[1]; - unsigned int rounds = aes->rounds; - - /* Sanity check */ - assert ( len == sizeof ( *in ) ); - - /* Initialise input state */ - memcpy ( in, src, sizeof ( *in ) ); - - /* Perform initial round (AddRoundKey) */ - aes_addroundkey ( in, &aes->encrypt.key[0] ); - - /* Perform intermediate rounds (ShiftRows, SubBytes, - * MixColumns, AddRoundKey). - */ - aes_encrypt_rounds ( in, out, &aes->encrypt.key[1], ( rounds - 2 ) ); - in = out; - - /* Perform final round (ShiftRows, SubBytes, AddRoundKey) */ - out = dst; - aes_final ( &aes_mixcolumns, AES_STRIDE_SHIFTROWS, in, out, - &aes->encrypt.key[ rounds - 1 ] ); -} - -/** - * Decrypt data - * - * @v ctx Context - * @v src Data to decrypt - * @v dst Buffer for decrypted data - * @v len Length of data - */ -static void aes_decrypt ( void *ctx, const void *src, void *dst, size_t len ) { - struct aes_context *aes = ctx; - union aes_matrix buffer[2]; - union aes_matrix *in = &buffer[0]; - union aes_matrix *out = &buffer[1]; - unsigned int rounds = aes->rounds; - - /* Sanity check */ - assert ( len == sizeof ( *in ) ); - - /* Initialise input state */ - memcpy ( in, src, sizeof ( *in ) ); - - /* Perform initial round (AddRoundKey) */ - aes_addroundkey ( in, &aes->decrypt.key[0] ); - - /* Perform intermediate rounds (InvShiftRows, InvSubBytes, - * InvMixColumns, AddRoundKey). - */ - aes_decrypt_rounds ( in, out, &aes->decrypt.key[1], ( rounds - 2 ) ); - in = out; - - /* Perform final round (InvShiftRows, InvSubBytes, AddRoundKey) */ - out = dst; - aes_final ( &aes_invmixcolumns, AES_STRIDE_INVSHIFTROWS, in, out, - &aes->decrypt.key[ rounds - 1 ] ); -} - -/** - * Multiply a polynomial by (x) modulo (x^8 + x^4 + x^3 + x^2 + 1) in GF(2^8) - * - * @v poly Polynomial to be multiplied - * @ret result Result - */ -static __attribute__ (( const )) unsigned int aes_double ( unsigned int poly ) { - - /* Multiply polynomial by (x), placing the resulting x^8 - * coefficient in the LSB (i.e. rotate byte left by one). - */ - poly = rol8 ( poly, 1 ); - - /* If coefficient of x^8 (in LSB) is non-zero, then reduce by - * subtracting (x^8 + x^4 + x^3 + x^2 + 1) in GF(2^8). - */ - if ( poly & 0x01 ) { - poly ^= 0x01; /* Subtract x^8 (currently in LSB) */ - poly ^= 0x1b; /* Subtract (x^4 + x^3 + x^2 + 1) */ - } - - return poly; -} - -/** - * Fill in MixColumns lookup table entry - * - * @v entry AES lookup table entry for scalar multiplicand - * - * The MixColumns lookup table vector multiplier is {1,1,1,3,2,1,1,3}. - */ -static void aes_mixcolumns_entry ( union aes_table_entry *entry ) { - unsigned int scalar_x_1; - unsigned int scalar_x; - unsigned int scalar; - - /* Retrieve scalar multiplicand */ - scalar = entry->byte[0]; - entry->byte[1] = scalar; - entry->byte[2] = scalar; - entry->byte[5] = scalar; - entry->byte[6] = scalar; - - /* Calculate scalar multiplied by (x) */ - scalar_x = aes_double ( scalar ); - entry->byte[4] = scalar_x; - - /* Calculate scalar multiplied by (x + 1) */ - scalar_x_1 = ( scalar_x ^ scalar ); - entry->byte[3] = scalar_x_1; - entry->byte[7] = scalar_x_1; -} - -/** - * Fill in InvMixColumns lookup table entry - * - * @v entry AES lookup table entry for scalar multiplicand - * - * The InvMixColumns lookup table vector multiplier is {1,9,13,11,14,9,13,11}. - */ -static void aes_invmixcolumns_entry ( union aes_table_entry *entry ) { - unsigned int scalar_x3_x2_x; - unsigned int scalar_x3_x2_1; - unsigned int scalar_x3_x2; - unsigned int scalar_x3_x_1; - unsigned int scalar_x3_1; - unsigned int scalar_x3; - unsigned int scalar_x2; - unsigned int scalar_x; - unsigned int scalar; - - /* Retrieve scalar multiplicand */ - scalar = entry->byte[0]; - - /* Calculate scalar multiplied by (x) */ - scalar_x = aes_double ( scalar ); - - /* Calculate scalar multiplied by (x^2) */ - scalar_x2 = aes_double ( scalar_x ); - - /* Calculate scalar multiplied by (x^3) */ - scalar_x3 = aes_double ( scalar_x2 ); - - /* Calculate scalar multiplied by (x^3 + 1) */ - scalar_x3_1 = ( scalar_x3 ^ scalar ); - entry->byte[1] = scalar_x3_1; - entry->byte[5] = scalar_x3_1; - - /* Calculate scalar multiplied by (x^3 + x + 1) */ - scalar_x3_x_1 = ( scalar_x3_1 ^ scalar_x ); - entry->byte[3] = scalar_x3_x_1; - entry->byte[7] = scalar_x3_x_1; - - /* Calculate scalar multiplied by (x^3 + x^2) */ - scalar_x3_x2 = ( scalar_x3 ^ scalar_x2 ); - - /* Calculate scalar multiplied by (x^3 + x^2 + 1) */ - scalar_x3_x2_1 = ( scalar_x3_x2 ^ scalar ); - entry->byte[2] = scalar_x3_x2_1; - entry->byte[6] = scalar_x3_x2_1; - - /* Calculate scalar multiplied by (x^3 + x^2 + x) */ - scalar_x3_x2_x = ( scalar_x3_x2 ^ scalar_x ); - entry->byte[4] = scalar_x3_x2_x; -} - -/** - * Generate AES lookup tables - * - */ -static void aes_generate ( void ) { - union aes_table_entry *entry; - union aes_table_entry *inventry; - unsigned int poly = 0x01; - unsigned int invpoly = 0x01; - unsigned int transformed; - unsigned int i; - - /* Iterate over non-zero values of GF(2^8) using generator (x + 1) */ - do { - - /* Multiply polynomial by (x + 1) */ - poly ^= aes_double ( poly ); - - /* Divide inverse polynomial by (x + 1). This code - * fragment is taken directly from the Wikipedia page - * on the Rijndael S-box. An explanation of why it - * works would be greatly appreciated. - */ - invpoly ^= ( invpoly << 1 ); - invpoly ^= ( invpoly << 2 ); - invpoly ^= ( invpoly << 4 ); - if ( invpoly & 0x80 ) - invpoly ^= 0x09; - invpoly &= 0xff; - - /* Apply affine transformation */ - transformed = ( 0x63 ^ invpoly ^ rol8 ( invpoly, 1 ) ^ - rol8 ( invpoly, 2 ) ^ rol8 ( invpoly, 3 ) ^ - rol8 ( invpoly, 4 ) ); - - /* Populate S-box (within MixColumns lookup table) */ - aes_mixcolumns.entry[poly].byte[0] = transformed; - - } while ( poly != 0x01 ); - - /* Populate zeroth S-box entry (which has no inverse) */ - aes_mixcolumns.entry[0].byte[0] = 0x63; - - /* Fill in MixColumns and InvMixColumns lookup tables */ - for ( i = 0 ; i < 256 ; i++ ) { - - /* Fill in MixColumns lookup table entry */ - entry = &aes_mixcolumns.entry[i]; - aes_mixcolumns_entry ( entry ); - - /* Populate inverse S-box (within InvMixColumns lookup table) */ - inventry = &aes_invmixcolumns.entry[ entry->byte[0] ]; - inventry->byte[0] = i; - - /* Fill in InvMixColumns lookup table entry */ - aes_invmixcolumns_entry ( inventry ); - } -} - -/** - * Rotate key column - * - * @v column Key column - * @ret column Updated key column - */ -static inline __attribute__ (( always_inline )) uint32_t -aes_key_rotate ( uint32_t column ) { - - return ( ( __BYTE_ORDER == __LITTLE_ENDIAN ) ? - ror32 ( column, 8 ) : rol32 ( column, 8 ) ); -} - -/** - * Apply S-box to key column - * - * @v column Key column - * @ret column Updated key column - */ -static uint32_t aes_key_sbox ( uint32_t column ) { - unsigned int i; - uint8_t byte; - - for ( i = 0 ; i < 4 ; i++ ) { - byte = ( column & 0xff ); - byte = aes_mixcolumns.entry[byte].byte[0]; - column = ( ( column & ~0xff ) | byte ); - column = rol32 ( column, 8 ); - } - return column; -} - -/** - * Apply schedule round constant to key column - * - * @v column Key column - * @v rcon Round constant - * @ret column Updated key column - */ -static inline __attribute__ (( always_inline )) uint32_t -aes_key_rcon ( uint32_t column, unsigned int rcon ) { - - return ( ( __BYTE_ORDER == __LITTLE_ENDIAN ) ? - ( column ^ rcon ) : ( column ^ ( rcon << 24 ) ) ); -} - -/** - * Set key - * - * @v ctx Context - * @v key Key - * @v keylen Key length - * @ret rc Return status code - */ -static int aes_setkey ( void *ctx, const void *key, size_t keylen ) { - struct aes_context *aes = ctx; - union aes_matrix *enc; - union aes_matrix *dec; - union aes_matrix temp; - union aes_matrix zero; - unsigned int rcon = 0x01; - unsigned int rounds; - size_t offset = 0; - uint32_t *prev; - uint32_t *next; - uint32_t *end; - uint32_t tmp; - - /* Generate lookup tables, if not already done */ - if ( ! aes_mixcolumns.entry[0].byte[0] ) - aes_generate(); - - /* Validate key length and calculate number of intermediate rounds */ - switch ( keylen ) { - case ( 128 / 8 ) : - rounds = 11; - break; - case ( 192 / 8 ) : - rounds = 13; - break; - case ( 256 / 8 ) : - rounds = 15; - break; - default: - DBGC ( aes, "AES %p unsupported key length (%zd bits)\n", - aes, ( keylen * 8 ) ); - return -EINVAL; - } - aes->rounds = rounds; - enc = aes->encrypt.key; - end = enc[rounds].column; - - /* Copy raw key */ - memcpy ( enc, key, keylen ); - prev = enc->column; - next = ( ( ( void * ) prev ) + keylen ); - tmp = next[-1]; - - /* Construct expanded key */ - while ( next < end ) { - - /* If this is the first column of an expanded key - * block, or the middle column of an AES-256 key - * block, then apply the S-box. - */ - if ( ( offset == 0 ) || ( ( offset | keylen ) == 48 ) ) - tmp = aes_key_sbox ( tmp ); - - /* If this is the first column of an expanded key - * block then rotate and apply the round constant. - */ - if ( offset == 0 ) { - tmp = aes_key_rotate ( tmp ); - tmp = aes_key_rcon ( tmp, rcon ); - rcon = aes_double ( rcon ); - } - - /* XOR with previous key column */ - tmp ^= *prev; - - /* Store column */ - *next = tmp; - - /* Move to next column */ - offset += sizeof ( *next ); - if ( offset == keylen ) - offset = 0; - next++; - prev++; - } - DBGC2 ( aes, "AES %p expanded %zd-bit key:\n", aes, ( keylen * 8 ) ); - DBGC2_HDA ( aes, 0, &aes->encrypt, ( rounds * sizeof ( *enc ) ) ); - - /* Convert to decryption key */ - memset ( &zero, 0, sizeof ( zero ) ); - dec = &aes->decrypt.key[ rounds - 1 ]; - memcpy ( dec--, enc++, sizeof ( *dec ) ); - while ( dec > aes->decrypt.key ) { - /* Perform InvMixColumns (by reusing the encryption - * final-round code to perform ShiftRows+SubBytes and - * reusing the decryption intermediate-round code to - * perform InvShiftRows+InvSubBytes+InvMixColumns, all - * with a zero encryption key). - */ - aes_final ( &aes_mixcolumns, AES_STRIDE_SHIFTROWS, - enc++, &temp, &zero ); - aes_decrypt_rounds ( &temp, dec--, &zero, 1 ); - } - memcpy ( dec--, enc++, sizeof ( *dec ) ); - DBGC2 ( aes, "AES %p inverted %zd-bit key:\n", aes, ( keylen * 8 ) ); - DBGC2_HDA ( aes, 0, &aes->decrypt, ( rounds * sizeof ( *dec ) ) ); - - return 0; -} - -/** - * Set initialisation vector - * - * @v ctx Context - * @v iv Initialisation vector - */ -static void aes_setiv ( void *ctx __unused, const void *iv __unused ) { - /* Nothing to do */ -} - -/** Basic AES algorithm */ -struct cipher_algorithm aes_algorithm = { - .name = "aes", - .ctxsize = sizeof ( struct aes_context ), - .blocksize = AES_BLOCKSIZE, - .setkey = aes_setkey, - .setiv = aes_setiv, - .encrypt = aes_encrypt, - .decrypt = aes_decrypt, -}; - -/* AES in Electronic Codebook mode */ -ECB_CIPHER ( aes_ecb, aes_ecb_algorithm, - aes_algorithm, struct aes_context, AES_BLOCKSIZE ); - -/* AES in Cipher Block Chaining mode */ -CBC_CIPHER ( aes_cbc, aes_cbc_algorithm, - aes_algorithm, struct aes_context, AES_BLOCKSIZE ); diff --git a/qemu/roms/ipxe/src/crypto/aes_wrap.c b/qemu/roms/ipxe/src/crypto/aes_wrap.c deleted file mode 100644 index c09480e5a..000000000 --- a/qemu/roms/ipxe/src/crypto/aes_wrap.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdlib.h> -#include <string.h> -#include <ipxe/crypto.h> -#include <ipxe/aes.h> - -/** - * Wrap a key or other data using AES Key Wrap (RFC 3394) - * - * @v kek Key Encryption Key, 16 bytes - * @v src Data to encrypt - * @v nblk Number of 8-byte blocks in @a data - * @ret dest Encrypted data (8 bytes longer than input) - * - * The algorithm is implemented such that @a src and @a dest may point - * to the same buffer. - */ -int aes_wrap ( const void *kek, const void *src, void *dest, int nblk ) -{ - u8 *A = dest; - u8 B[16]; - u8 *R; - int i, j; - void *aes_ctx = malloc ( AES_CTX_SIZE ); - - if ( ! aes_ctx ) - return -1; - - cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 ); - - /* Set up */ - memset ( A, 0xA6, 8 ); - memmove ( dest + 8, src, nblk * 8 ); - - /* Wrap */ - for ( j = 0; j < 6; j++ ) { - R = dest + 8; - for ( i = 1; i <= nblk; i++ ) { - memcpy ( B, A, 8 ); - memcpy ( B + 8, R, 8 ); - cipher_encrypt ( &aes_algorithm, aes_ctx, B, B, 16 ); - memcpy ( A, B, 8 ); - A[7] ^= ( nblk * j ) + i; - memcpy ( R, B + 8, 8 ); - R += 8; - } - } - - free ( aes_ctx ); - return 0; -} - -/** - * Unwrap a key or other data using AES Key Wrap (RFC 3394) - * - * @v kek Key Encryption Key, 16 bytes - * @v src Data to decrypt - * @v nblk Number of 8-byte blocks in @e plaintext key - * @ret dest Decrypted data (8 bytes shorter than input) - * @ret rc Zero on success, nonzero on IV mismatch - * - * The algorithm is implemented such that @a src and @a dest may point - * to the same buffer. - */ -int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk ) -{ - u8 A[8], B[16]; - u8 *R; - int i, j; - void *aes_ctx = malloc ( AES_CTX_SIZE ); - - if ( ! aes_ctx ) - return -1; - - cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 ); - - /* Set up */ - memcpy ( A, src, 8 ); - memmove ( dest, src + 8, nblk * 8 ); - - /* Unwrap */ - for ( j = 5; j >= 0; j-- ) { - R = dest + ( nblk - 1 ) * 8; - for ( i = nblk; i >= 1; i-- ) { - memcpy ( B, A, 8 ); - memcpy ( B + 8, R, 8 ); - B[7] ^= ( nblk * j ) + i; - cipher_decrypt ( &aes_algorithm, aes_ctx, B, B, 16 ); - memcpy ( A, B, 8 ); - memcpy ( R, B + 8, 8 ); - R -= 8; - } - } - - free ( aes_ctx ); - - /* Check IV */ - for ( i = 0; i < 8; i++ ) { - if ( A[i] != 0xA6 ) - return -1; - } - - return 0; -} diff --git a/qemu/roms/ipxe/src/crypto/arc4.c b/qemu/roms/ipxe/src/crypto/arc4.c deleted file mode 100644 index 91a732019..000000000 --- a/qemu/roms/ipxe/src/crypto/arc4.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * The ARC4 stream cipher. - * - * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <ipxe/crypto.h> -#include <ipxe/arc4.h> - -#define SWAP( ary, i, j ) \ - ({ u8 temp = ary[i]; ary[i] = ary[j]; ary[j] = temp; }) - -/** - * Set ARC4 key - * - * @v ctxv ARC4 encryption context - * @v keyv Key to set - * @v keylen Length of key - * - * If an initialisation vector is to be used, it should be prepended - * to the key; ARC4 does not implement the @c setiv function because - * there is no standard length for an initialisation vector in the - * cipher. - */ -static int arc4_setkey ( void *ctxv, const void *keyv, size_t keylen ) -{ - struct arc4_ctx *ctx = ctxv; - const u8 *key = keyv; - u8 *S = ctx->state; - int i, j; - - for ( i = 0; i < 256; i++ ) { - S[i] = i; - } - - for ( i = j = 0; i < 256; i++ ) { - j = ( j + S[i] + key[i % keylen] ) & 0xff; - SWAP ( S, i, j ); - } - - ctx->i = ctx->j = 0; - return 0; -} - -/** - * Perform ARC4 encryption or decryption - * - * @v ctxv ARC4 encryption context - * @v srcv Data to encrypt or decrypt - * @v dstv Location to store encrypted or decrypted data - * @v len Length of data to operate on - * - * ARC4 is a stream cipher that works by generating a stream of PRNG - * data based on the key, and XOR'ing it with the data to be - * encrypted. Since XOR is symmetric, encryption and decryption in - * ARC4 are the same operation. - * - * If you pass a @c NULL source or destination pointer, @a len - * keystream bytes will be consumed without encrypting any data. - */ -static void arc4_xor ( void *ctxv, const void *srcv, void *dstv, - size_t len ) -{ - struct arc4_ctx *ctx = ctxv; - const u8 *src = srcv; - u8 *dst = dstv; - u8 *S = ctx->state; - int i = ctx->i, j = ctx->j; - - while ( len-- ) { - i = ( i + 1 ) & 0xff; - j = ( j + S[i] ) & 0xff; - SWAP ( S, i, j ); - if ( srcv && dstv ) - *dst++ = *src++ ^ S[(S[i] + S[j]) & 0xff]; - } - - ctx->i = i; - ctx->j = j; -} - -static void arc4_setiv ( void *ctx __unused, const void *iv __unused ) -{ - /* ARC4 does not use a fixed-length IV */ -} - - -/** - * Perform ARC4 encryption or decryption, skipping initial keystream bytes - * - * @v key ARC4 encryption key - * @v keylen Key length - * @v skip Number of bytes of keystream to skip - * @v src Message to encrypt or decrypt - * @v msglen Length of message - * @ret dst Encrypted or decrypted message - */ -void arc4_skip ( const void *key, size_t keylen, size_t skip, - const void *src, void *dst, size_t msglen ) -{ - struct arc4_ctx ctx; - arc4_setkey ( &ctx, key, keylen ); - arc4_xor ( &ctx, NULL, NULL, skip ); - arc4_xor ( &ctx, src, dst, msglen ); -} - -struct cipher_algorithm arc4_algorithm = { - .name = "ARC4", - .ctxsize = ARC4_CTX_SIZE, - .blocksize = 1, - .setkey = arc4_setkey, - .setiv = arc4_setiv, - .encrypt = arc4_xor, - .decrypt = arc4_xor, -}; diff --git a/qemu/roms/ipxe/src/crypto/asn1.c b/qemu/roms/ipxe/src/crypto/asn1.c deleted file mode 100644 index aca12bf30..000000000 --- a/qemu/roms/ipxe/src/crypto/asn1.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <time.h> -#include <ipxe/tables.h> -#include <ipxe/asn1.h> - -/** @file - * - * ASN.1 encoding - * - */ - -/* Disambiguate the various error causes */ -#define EINVAL_ASN1_EMPTY \ - __einfo_error ( EINFO_EINVAL_ASN1_EMPTY ) -#define EINFO_EINVAL_ASN1_EMPTY \ - __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" ) -#define EINVAL_ASN1_LEN_LEN \ - __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN ) -#define EINFO_EINVAL_ASN1_LEN_LEN \ - __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" ) -#define EINVAL_ASN1_LEN \ - __einfo_error ( EINFO_EINVAL_ASN1_LEN ) -#define EINFO_EINVAL_ASN1_LEN \ - __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" ) -#define EINVAL_ASN1_BOOLEAN \ - __einfo_error ( EINFO_EINVAL_ASN1_BOOLEAN ) -#define EINFO_EINVAL_ASN1_BOOLEAN \ - __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid boolean" ) -#define EINVAL_ASN1_INTEGER \ - __einfo_error ( EINFO_EINVAL_ASN1_INTEGER ) -#define EINFO_EINVAL_ASN1_INTEGER \ - __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" ) -#define EINVAL_ASN1_TIME \ - __einfo_error ( EINFO_EINVAL_ASN1_TIME ) -#define EINFO_EINVAL_ASN1_TIME \ - __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" ) -#define EINVAL_ASN1_ALGORITHM \ - __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM ) -#define EINFO_EINVAL_ASN1_ALGORITHM \ - __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" ) -#define EINVAL_BIT_STRING \ - __einfo_error ( EINFO_EINVAL_BIT_STRING ) -#define EINFO_EINVAL_BIT_STRING \ - __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" ) -#define ENOTSUP_ALGORITHM \ - __einfo_error ( EINFO_ENOTSUP_ALGORITHM ) -#define EINFO_ENOTSUP_ALGORITHM \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" ) -#define ENOTTY_ALGORITHM \ - __einfo_error ( EINFO_ENOTTY_ALGORITHM ) -#define EINFO_ENOTTY_ALGORITHM \ - __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" ) - -/** - * Invalidate ASN.1 object cursor - * - * @v cursor ASN.1 object cursor - */ -void asn1_invalidate_cursor ( struct asn1_cursor *cursor ) { - static uint8_t asn1_invalid_object[] = { ASN1_END, 0 }; - - cursor->data = asn1_invalid_object; - cursor->len = 0; -} - -/** - * Start parsing ASN.1 object - * - * @v cursor ASN.1 object cursor - * @v type Expected type, or ASN1_ANY - * @ret len Length of object body, or negative error - * - * The object cursor will be updated to point to the start of the - * object body (i.e. the first byte following the length byte(s)), and - * the length of the object body (i.e. the number of bytes until the - * following object tag, if any) is returned. - */ -static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) { - unsigned int len_len; - unsigned int len; - - /* Sanity check */ - if ( cursor->len < 2 /* Tag byte and first length byte */ ) { - if ( cursor->len ) - DBGC ( cursor, "ASN1 %p too short\n", cursor ); - return -EINVAL_ASN1_EMPTY; - } - - /* Check the tag byte */ - if ( ( type != ASN1_ANY ) && ( type != asn1_type ( cursor ) ) ) { - DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n", - cursor, type, *( ( uint8_t * ) cursor->data ) ); - return -ENXIO; - } - cursor->data++; - cursor->len--; - - /* Extract length of the length field and sanity check */ - len_len = *( ( uint8_t * ) cursor->data ); - if ( len_len & 0x80 ) { - len_len = ( len_len & 0x7f ); - cursor->data++; - cursor->len--; - } else { - len_len = 1; - } - if ( cursor->len < len_len ) { - DBGC ( cursor, "ASN1 %p bad length field length %d (max " - "%zd)\n", cursor, len_len, cursor->len ); - return -EINVAL_ASN1_LEN_LEN; - } - - /* Extract the length and sanity check */ - for ( len = 0 ; len_len ; len_len-- ) { - len <<= 8; - len |= *( ( uint8_t * ) cursor->data ); - cursor->data++; - cursor->len--; - } - if ( cursor->len < len ) { - DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n", - cursor, len, cursor->len ); - return -EINVAL_ASN1_LEN; - } - - return len; -} - -/** - * Enter ASN.1 object - * - * @v cursor ASN.1 object cursor - * @v type Expected type, or ASN1_ANY - * @ret rc Return status code - * - * The object cursor will be updated to point to the body of the - * current ASN.1 object. If any error occurs, the object cursor will - * be invalidated. - */ -int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) { - int len; - - len = asn1_start ( cursor, type ); - if ( len < 0 ) { - asn1_invalidate_cursor ( cursor ); - return len; - } - - cursor->len = len; - DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n", - cursor, type, len ); - - return 0; -} - -/** - * Skip ASN.1 object if present - * - * @v cursor ASN.1 object cursor - * @v type Expected type, or ASN1_ANY - * @ret rc Return status code - * - * The object cursor will be updated to point to the next ASN.1 - * object. If any error occurs, the object cursor will not be - * modified. - */ -int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) { - int len; - - len = asn1_start ( cursor, type ); - if ( len < 0 ) - return len; - - cursor->data += len; - cursor->len -= len; - DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n", - cursor, type, len ); - - if ( ! cursor->len ) { - DBGC ( cursor, "ASN1 %p reached end of object\n", cursor ); - return -ENOENT; - } - - return 0; -} - -/** - * Skip ASN.1 object - * - * @v cursor ASN.1 object cursor - * @v type Expected type, or ASN1_ANY - * @ret rc Return status code - * - * The object cursor will be updated to point to the next ASN.1 - * object. If any error occurs, the object cursor will be - * invalidated. - */ -int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) { - int rc; - - if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) != 0 ) { - asn1_invalidate_cursor ( cursor ); - return rc; - } - - return 0; -} - -/** - * Shrink ASN.1 cursor to fit object - * - * @v cursor ASN.1 object cursor - * @v type Expected type, or ASN1_ANY - * @ret rc Return status code - * - * The object cursor will be shrunk to contain only the current ASN.1 - * object. If any error occurs, the object cursor will be - * invalidated. - */ -int asn1_shrink ( struct asn1_cursor *cursor, unsigned int type ) { - struct asn1_cursor temp; - const void *end; - int len; - - /* Find end of object */ - memcpy ( &temp, cursor, sizeof ( temp ) ); - len = asn1_start ( &temp, type ); - if ( len < 0 ) { - asn1_invalidate_cursor ( cursor ); - return len; - } - end = ( temp.data + len ); - - /* Shrink original cursor to contain only its first object */ - cursor->len = ( end - cursor->data ); - - return 0; -} - -/** - * Enter ASN.1 object of any type - * - * @v cursor ASN.1 object cursor - * @ret rc Return status code - */ -int asn1_enter_any ( struct asn1_cursor *cursor ) { - return asn1_enter ( cursor, ASN1_ANY ); -} - -/** - * Skip ASN.1 object of any type - * - * @v cursor ASN.1 object cursor - * @ret rc Return status code - */ -int asn1_skip_any ( struct asn1_cursor *cursor ) { - return asn1_skip ( cursor, ASN1_ANY ); -} - -/** - * Shrink ASN.1 object of any type - * - * @v cursor ASN.1 object cursor - * @ret rc Return status code - */ -int asn1_shrink_any ( struct asn1_cursor *cursor ) { - return asn1_shrink ( cursor, ASN1_ANY ); -} - -/** - * Parse value of ASN.1 boolean - * - * @v cursor ASN.1 object cursor - * @ret value Value, or negative error - */ -int asn1_boolean ( const struct asn1_cursor *cursor ) { - struct asn1_cursor contents; - const struct { - uint8_t value; - } __attribute__ (( packed )) *boolean; - - /* Enter boolean */ - memcpy ( &contents, cursor, sizeof ( contents ) ); - asn1_enter ( &contents, ASN1_BOOLEAN ); - if ( contents.len != sizeof ( *boolean ) ) - return -EINVAL_ASN1_BOOLEAN; - - /* Extract value */ - boolean = contents.data; - return boolean->value; -} - -/** - * Parse value of ASN.1 integer - * - * @v cursor ASN.1 object cursor - * @v value Value to fill in - * @ret rc Return status code - */ -int asn1_integer ( const struct asn1_cursor *cursor, int *value ) { - struct asn1_cursor contents; - uint8_t high_byte; - int rc; - - /* Enter integer */ - memcpy ( &contents, cursor, sizeof ( contents ) ); - if ( ( rc = asn1_enter ( &contents, ASN1_INTEGER ) ) != 0 ) - return rc; - if ( contents.len < 1 ) - return -EINVAL_ASN1_INTEGER; - - /* Initialise value according to sign byte */ - *value = *( ( int8_t * ) contents.data ); - contents.data++; - contents.len--; - - /* Process value */ - while ( contents.len ) { - high_byte = ( (*value) >> ( 8 * ( sizeof ( *value ) - 1 ) ) ); - if ( ( high_byte != 0x00 ) && ( high_byte != 0xff ) ) { - DBGC ( cursor, "ASN1 %p integer overflow\n", cursor ); - return -EINVAL_ASN1_INTEGER; - } - *value = ( ( *value << 8 ) | *( ( uint8_t * ) contents.data ) ); - contents.data++; - contents.len--; - } - - return 0; -} - -/** - * Parse ASN.1 bit string - * - * @v cursor ASN.1 cursor - * @v bits Bit string to fill in - * @ret rc Return status code - */ -int asn1_bit_string ( const struct asn1_cursor *cursor, - struct asn1_bit_string *bits ) { - struct asn1_cursor contents; - const struct { - uint8_t unused; - uint8_t data[0]; - } __attribute__ (( packed )) *bit_string; - size_t len; - unsigned int unused; - uint8_t unused_mask; - const uint8_t *last; - int rc; - - /* Enter bit string */ - memcpy ( &contents, cursor, sizeof ( contents ) ); - if ( ( rc = asn1_enter ( &contents, ASN1_BIT_STRING ) ) != 0 ) { - DBGC ( cursor, "ASN1 %p cannot locate bit string:\n", cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return rc; - } - - /* Validity checks */ - if ( contents.len < sizeof ( *bit_string ) ) { - DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_BIT_STRING; - } - bit_string = contents.data; - len = ( contents.len - offsetof ( typeof ( *bit_string ), data ) ); - unused = bit_string->unused; - unused_mask = ( 0xff >> ( 8 - unused ) ); - last = ( bit_string->data + len - 1 ); - if ( ( unused >= 8 ) || - ( ( unused > 0 ) && ( len == 0 ) ) || - ( ( *last & unused_mask ) != 0 ) ) { - DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_BIT_STRING; - } - - /* Populate bit string */ - bits->data = &bit_string->data; - bits->len = len; - bits->unused = unused; - - return 0; -} - -/** - * Parse ASN.1 bit string that must be an integral number of bytes - * - * @v cursor ASN.1 cursor - * @v bits Bit string to fill in - * @ret rc Return status code - */ -int asn1_integral_bit_string ( const struct asn1_cursor *cursor, - struct asn1_bit_string *bits ) { - int rc; - - /* Parse bit string */ - if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 ) - return rc; - - /* Check that there are no unused bits at end of string */ - if ( bits->unused ) { - DBGC ( cursor, "ASN1 %p invalid integral bit string:\n", - cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_BIT_STRING; - } - - return 0; -} - -/** - * Compare two ASN.1 objects - * - * @v cursor1 ASN.1 object cursor - * @v cursor2 ASN.1 object cursor - * @ret difference Difference as returned by memcmp() - * - * Note that invalid and empty cursors will compare as equal with each - * other. - */ -int asn1_compare ( const struct asn1_cursor *cursor1, - const struct asn1_cursor *cursor2 ) { - int difference; - - difference = ( cursor2->len - cursor1->len ); - return ( difference ? difference : - memcmp ( cursor1->data, cursor2->data, cursor1->len ) ); -} - -/** - * Identify ASN.1 algorithm by OID - * - * @v cursor ASN.1 object cursor - - * @ret algorithm Algorithm, or NULL - */ -static struct asn1_algorithm * -asn1_find_algorithm ( const struct asn1_cursor *cursor ) { - struct asn1_algorithm *algorithm; - - for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) { - if ( asn1_compare ( &algorithm->oid, cursor ) == 0 ) - return algorithm; - } - - return NULL; -} - -/** - * Parse ASN.1 OID-identified algorithm - * - * @v cursor ASN.1 object cursor - * @ret algorithm Algorithm - * @ret rc Return status code - */ -int asn1_algorithm ( const struct asn1_cursor *cursor, - struct asn1_algorithm **algorithm ) { - struct asn1_cursor contents; - int rc; - - /* Enter signatureAlgorithm */ - memcpy ( &contents, cursor, sizeof ( contents ) ); - asn1_enter ( &contents, ASN1_SEQUENCE ); - - /* Enter algorithm */ - if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) { - DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n", - cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_ASN1_ALGORITHM; - } - - /* Identify algorithm */ - *algorithm = asn1_find_algorithm ( &contents ); - if ( ! *algorithm ) { - DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -ENOTSUP_ALGORITHM; - } - - return 0; -} - -/** - * Parse ASN.1 OID-identified public-key algorithm - * - * @v cursor ASN.1 object cursor - * @ret algorithm Algorithm - * @ret rc Return status code - */ -int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor, - struct asn1_algorithm **algorithm ) { - int rc; - - /* Parse algorithm */ - if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) - return rc; - - /* Check algorithm has a public key */ - if ( ! (*algorithm)->pubkey ) { - DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key " - "algorithm:\n", cursor, (*algorithm)->name ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -ENOTTY_ALGORITHM; - } - - return 0; -} - -/** - * Parse ASN.1 OID-identified digest algorithm - * - * @v cursor ASN.1 object cursor - * @ret algorithm Algorithm - * @ret rc Return status code - */ -int asn1_digest_algorithm ( const struct asn1_cursor *cursor, - struct asn1_algorithm **algorithm ) { - int rc; - - /* Parse algorithm */ - if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) - return rc; - - /* Check algorithm has a digest */ - if ( ! (*algorithm)->digest ) { - DBGC ( cursor, "ASN1 %p algorithm %s is not a digest " - "algorithm:\n", cursor, (*algorithm)->name ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -ENOTTY_ALGORITHM; - } - - return 0; -} - -/** - * Parse ASN.1 OID-identified signature algorithm - * - * @v cursor ASN.1 object cursor - * @ret algorithm Algorithm - * @ret rc Return status code - */ -int asn1_signature_algorithm ( const struct asn1_cursor *cursor, - struct asn1_algorithm **algorithm ) { - int rc; - - /* Parse algorithm */ - if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) - return rc; - - /* Check algorithm has a public key */ - if ( ! (*algorithm)->pubkey ) { - DBGC ( cursor, "ASN1 %p algorithm %s is not a signature " - "algorithm:\n", cursor, (*algorithm)->name ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -ENOTTY_ALGORITHM; - } - - /* Check algorithm has a digest */ - if ( ! (*algorithm)->digest ) { - DBGC ( cursor, "ASN1 %p algorithm %s is not a signature " - "algorithm:\n", cursor, (*algorithm)->name ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -ENOTTY_ALGORITHM; - } - - return 0; -} - -/** - * Parse ASN.1 GeneralizedTime - * - * @v cursor ASN.1 cursor - * @v time Time to fill in - * @ret rc Return status code - * - * RFC 5280 section 4.1.2.5 places several restrictions on the allowed - * formats for UTCTime and GeneralizedTime, and mandates the - * interpretation of centuryless year values. - */ -int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) { - struct asn1_cursor contents; - unsigned int have_century; - unsigned int type; - union { - struct { - uint8_t century; - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - } __attribute__ (( packed )) named; - uint8_t raw[7]; - } pairs; - struct tm tm; - const uint8_t *data; - size_t remaining; - unsigned int tens; - unsigned int units; - unsigned int i; - int rc; - - /* Determine time format utcTime/generalizedTime */ - memcpy ( &contents, cursor, sizeof ( contents ) ); - type = asn1_type ( &contents ); - switch ( type ) { - case ASN1_UTC_TIME: - have_century = 0; - break; - case ASN1_GENERALIZED_TIME: - have_century = 1; - break; - default: - DBGC ( cursor, "ASN1 %p invalid time type %02x\n", - cursor, type ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_ASN1_TIME; - } - - /* Enter utcTime/generalizedTime */ - if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) { - DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor, - ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return rc; - } - - /* Parse digit string a pair at a time */ - memset ( &pairs, 0, sizeof ( pairs ) ); - data = contents.data; - remaining = contents.len; - for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) { - if ( remaining < 2 ) { - /* Some certificates violate the X.509 RFC by - * omitting the "seconds" value. - */ - if ( i == ( sizeof ( pairs.raw ) - 1 ) ) - break; - DBGC ( cursor, "ASN1 %p invalid time:\n", cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_ASN1_TIME; - } - tens = data[0]; - units = data[1]; - if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) { - DBGC ( cursor, "ASN1 %p invalid time:\n", cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_ASN1_TIME; - } - pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) ); - data += 2; - remaining -= 2; - } - - /* Determine century if applicable */ - if ( ! have_century ) - pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 ); - - /* Check for trailing "Z" */ - if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) { - DBGC ( cursor, "ASN1 %p invalid time:\n", cursor ); - DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return -EINVAL_ASN1_TIME; - } - - /* Fill in time */ - tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) + - pairs.named.year ); - tm.tm_mon = ( pairs.named.month - 1 ); - tm.tm_mday = pairs.named.day; - tm.tm_hour = pairs.named.hour; - tm.tm_min = pairs.named.minute; - tm.tm_sec = pairs.named.second; - - /* Convert to seconds since the Epoch */ - *time = mktime ( &tm ); - - return 0; -} - -/** - * Construct ASN.1 header - * - * @v header ASN.1 builder header - * @v type Type - * @v len Content length - * @ret header_len Header length - */ -static size_t asn1_header ( struct asn1_builder_header *header, - unsigned int type, size_t len ) { - unsigned int header_len = 2; - unsigned int len_len = 0; - size_t temp; - - /* Construct header */ - header->type = type; - if ( len < 0x80 ) { - header->length[0] = len; - } else { - for ( temp = len ; temp ; temp >>= 8 ) - len_len++; - header->length[0] = ( 0x80 | len_len ); - header_len += len_len; - for ( temp = len ; temp ; temp >>= 8 ) - header->length[len_len--] = ( temp & 0xff ); - } - - return header_len; -} - -/** - * Grow ASN.1 builder - * - * @v builder ASN.1 builder - * @v extra Extra space to prepend - * @ret rc Return status code - */ -static int asn1_grow ( struct asn1_builder *builder, size_t extra ) { - size_t new_len; - void *new; - - /* As with the ASN1 parsing functions, make errors permanent */ - if ( builder->len && ! builder->data ) - return -ENOMEM; - - /* Reallocate data buffer */ - new_len = ( builder->len + extra ); - new = realloc ( builder->data, new_len ); - if ( ! new ) { - free ( builder->data ); - builder->data = NULL; - return -ENOMEM; - } - builder->data = new; - - /* Move existing data to end of buffer */ - memmove ( ( builder->data + extra ), builder->data, builder->len ); - builder->len = new_len; - - return 0; -} - -/** - * Prepend raw data to ASN.1 builder - * - * @v builder ASN.1 builder - * @v data Data to prepend - * @v len Length of data to prepend - * @ret rc Return status code - */ -int asn1_prepend_raw ( struct asn1_builder *builder, const void *data, - size_t len ) { - int rc; - - /* Grow buffer */ - if ( ( rc = asn1_grow ( builder, len ) ) != 0 ) - return rc; - - /* Populate data buffer */ - memcpy ( builder->data, data, len ); - - return 0; -} - -/** - * Prepend data to ASN.1 builder - * - * @v builder ASN.1 builder - * @v type Type - * @v data Data to prepend - * @v len Length of data to prepend - * @ret rc Return status code - */ -int asn1_prepend ( struct asn1_builder *builder, unsigned int type, - const void *data, size_t len ) { - struct asn1_builder_header header; - size_t header_len; - int rc; - - /* Construct header */ - header_len = asn1_header ( &header, type, len ); - - /* Grow buffer */ - if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 ) - return rc; - - /* Populate data buffer */ - memcpy ( builder->data, &header, header_len ); - memcpy ( ( builder->data + header_len ), data, len ); - - return 0; -} - -/** - * Wrap ASN.1 builder - * - * @v builder ASN.1 builder - * @v type Type - * @ret rc Return status code - */ -int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) { - struct asn1_builder_header header; - size_t header_len; - int rc; - - /* Construct header */ - header_len = asn1_header ( &header, type, builder->len ); - - /* Grow buffer */ - if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 ) - return rc; - - /* Populate data buffer */ - memcpy ( builder->data, &header, header_len ); - - return 0; -} diff --git a/qemu/roms/ipxe/src/crypto/bigint.c b/qemu/roms/ipxe/src/crypto/bigint.c deleted file mode 100644 index 50f320302..000000000 --- a/qemu/roms/ipxe/src/crypto/bigint.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <string.h> -#include <assert.h> -#include <ipxe/bigint.h> - -/** @file - * - * Big integer support - */ - -/** - * Perform modular multiplication of big integers - * - * @v multiplicand0 Element 0 of big integer to be multiplied - * @v multiplier0 Element 0 of big integer to be multiplied - * @v modulus0 Element 0 of big integer modulus - * @v result0 Element 0 of big integer to hold result - * @v size Number of elements in base, modulus, and result - * @v tmp Temporary working space - */ -void bigint_mod_multiply_raw ( const bigint_element_t *multiplicand0, - const bigint_element_t *multiplier0, - const bigint_element_t *modulus0, - bigint_element_t *result0, - unsigned int size, void *tmp ) { - const bigint_t ( size ) __attribute__ (( may_alias )) *multiplicand = - ( ( const void * ) multiplicand0 ); - const bigint_t ( size ) __attribute__ (( may_alias )) *multiplier = - ( ( const void * ) multiplier0 ); - const bigint_t ( size ) __attribute__ (( may_alias )) *modulus = - ( ( const void * ) modulus0 ); - bigint_t ( size ) __attribute__ (( may_alias )) *result = - ( ( void * ) result0 ); - struct { - bigint_t ( size * 2 ) result; - bigint_t ( size * 2 ) modulus; - } *temp = tmp; - int rotation; - int i; - - /* Sanity check */ - assert ( sizeof ( *temp ) == bigint_mod_multiply_tmp_len ( modulus ) ); - - /* Perform multiplication */ - bigint_multiply ( multiplicand, multiplier, &temp->result ); - - /* Rescale modulus to match result */ - bigint_grow ( modulus, &temp->modulus ); - rotation = ( bigint_max_set_bit ( &temp->result ) - - bigint_max_set_bit ( &temp->modulus ) ); - for ( i = 0 ; i < rotation ; i++ ) - bigint_rol ( &temp->modulus ); - - /* Subtract multiples of modulus */ - for ( i = 0 ; i <= rotation ; i++ ) { - if ( bigint_is_geq ( &temp->result, &temp->modulus ) ) - bigint_subtract ( &temp->modulus, &temp->result ); - bigint_ror ( &temp->modulus ); - } - - /* Resize result */ - bigint_shrink ( &temp->result, result ); - - /* Sanity check */ - assert ( bigint_is_geq ( modulus, result ) ); -} - -/** - * Perform modular exponentiation of big integers - * - * @v base0 Element 0 of big integer base - * @v modulus0 Element 0 of big integer modulus - * @v exponent0 Element 0 of big integer exponent - * @v result0 Element 0 of big integer to hold result - * @v size Number of elements in base, modulus, and result - * @v exponent_size Number of elements in exponent - * @v tmp Temporary working space - */ -void bigint_mod_exp_raw ( const bigint_element_t *base0, - const bigint_element_t *modulus0, - const bigint_element_t *exponent0, - bigint_element_t *result0, - unsigned int size, unsigned int exponent_size, - void *tmp ) { - const bigint_t ( size ) __attribute__ (( may_alias )) *base = - ( ( const void * ) base0 ); - const bigint_t ( size ) __attribute__ (( may_alias )) *modulus = - ( ( const void * ) modulus0 ); - const bigint_t ( exponent_size ) __attribute__ (( may_alias )) - *exponent = ( ( const void * ) exponent0 ); - bigint_t ( size ) __attribute__ (( may_alias )) *result = - ( ( void * ) result0 ); - size_t mod_multiply_len = bigint_mod_multiply_tmp_len ( modulus ); - struct { - bigint_t ( size ) base; - bigint_t ( exponent_size ) exponent; - uint8_t mod_multiply[mod_multiply_len]; - } *temp = tmp; - static const uint8_t start[1] = { 0x01 }; - - memcpy ( &temp->base, base, sizeof ( temp->base ) ); - memcpy ( &temp->exponent, exponent, sizeof ( temp->exponent ) ); - bigint_init ( result, start, sizeof ( start ) ); - - while ( ! bigint_is_zero ( &temp->exponent ) ) { - if ( bigint_bit_is_set ( &temp->exponent, 0 ) ) { - bigint_mod_multiply ( result, &temp->base, modulus, - result, temp->mod_multiply ); - } - bigint_ror ( &temp->exponent ); - bigint_mod_multiply ( &temp->base, &temp->base, modulus, - &temp->base, temp->mod_multiply ); - } -} diff --git a/qemu/roms/ipxe/src/crypto/cbc.c b/qemu/roms/ipxe/src/crypto/cbc.c deleted file mode 100644 index 0ba17ee48..000000000 --- a/qemu/roms/ipxe/src/crypto/cbc.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <string.h> -#include <assert.h> -#include <ipxe/crypto.h> -#include <ipxe/cbc.h> - -/** @file - * - * Cipher-block chaining - * - */ - -/** - * XOR data blocks - * - * @v src Input data - * @v dst Second input data and output data buffer - * @v len Length of data - */ -static void cbc_xor ( const void *src, void *dst, size_t len ) { - const uint32_t *srcl = src; - uint32_t *dstl = dst; - unsigned int i; - - /* Assume that block sizes will always be dword-aligned, for speed */ - assert ( ( len % sizeof ( *srcl ) ) == 0 ); - - for ( i = 0 ; i < ( len / sizeof ( *srcl ) ) ; i++ ) - dstl[i] ^= srcl[i]; -} - -/** - * Encrypt data - * - * @v ctx Context - * @v src Data to encrypt - * @v dst Buffer for encrypted data - * @v len Length of data - * @v raw_cipher Underlying cipher algorithm - * @v cbc_ctx CBC context - */ -void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len, - struct cipher_algorithm *raw_cipher, void *cbc_ctx ) { - size_t blocksize = raw_cipher->blocksize; - - assert ( ( len % blocksize ) == 0 ); - - while ( len ) { - cbc_xor ( src, cbc_ctx, blocksize ); - cipher_encrypt ( raw_cipher, ctx, cbc_ctx, dst, blocksize ); - memcpy ( cbc_ctx, dst, blocksize ); - dst += blocksize; - src += blocksize; - len -= blocksize; - } -} - -/** - * Decrypt data - * - * @v ctx Context - * @v src Data to decrypt - * @v dst Buffer for decrypted data - * @v len Length of data - * @v raw_cipher Underlying cipher algorithm - * @v cbc_ctx CBC context - */ -void cbc_decrypt ( void *ctx, const void *src, void *dst, size_t len, - struct cipher_algorithm *raw_cipher, void *cbc_ctx ) { - size_t blocksize = raw_cipher->blocksize; - uint8_t next_cbc_ctx[blocksize]; - - assert ( ( len % blocksize ) == 0 ); - - while ( len ) { - memcpy ( next_cbc_ctx, src, blocksize ); - cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize ); - cbc_xor ( cbc_ctx, dst, blocksize ); - memcpy ( cbc_ctx, next_cbc_ctx, blocksize ); - dst += blocksize; - src += blocksize; - len -= blocksize; - } -} diff --git a/qemu/roms/ipxe/src/crypto/certstore.c b/qemu/roms/ipxe/src/crypto/certstore.c deleted file mode 100644 index 503ce499e..000000000 --- a/qemu/roms/ipxe/src/crypto/certstore.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <string.h> -#include <stdlib.h> -#include <ipxe/init.h> -#include <ipxe/dhcp.h> -#include <ipxe/settings.h> -#include <ipxe/malloc.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/x509.h> -#include <ipxe/certstore.h> - -/** @file - * - * Certificate store - * - */ - -/** Raw certificate data for all permanent stored certificates */ -#undef CERT -#define CERT( _index, _path ) \ - extern char stored_cert_ ## _index ## _data[]; \ - extern char stored_cert_ ## _index ## _len[]; \ - __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" \ - "\nstored_cert_" #_index "_data:\n\t" \ - ".incbin \"" _path "\"\n\t" \ - "\nstored_cert_" #_index "_end:\n\t" \ - ".equ stored_cert_" #_index "_len, " \ - "( stored_cert_" #_index "_end - " \ - " stored_cert_" #_index "_data )\n\t" \ - ".previous\n\t" ); -CERT_ALL - -/** Raw certificate cursors for all permanent stored certificates */ -#undef CERT -#define CERT( _index, _path ) { \ - .data = stored_cert_ ## _index ## _data, \ - .len = ( size_t ) stored_cert_ ## _index ## _len, \ -}, -static struct asn1_cursor certstore_raw[] = { - CERT_ALL -}; - -/** X.509 certificate structures for all permanent stored certificates */ -static struct x509_certificate certstore_certs[ sizeof ( certstore_raw ) / - sizeof ( certstore_raw[0] ) ]; - -/** Certificate store */ -struct x509_chain certstore = { - .refcnt = REF_INIT ( ref_no_free ), - .links = LIST_HEAD_INIT ( certstore.links ), -}; - -/** - * Mark stored certificate as most recently used - * - * @v cert X.509 certificate - * @ret cert X.509 certificate - */ -static struct x509_certificate * -certstore_found ( struct x509_certificate *cert ) { - - /* Mark as most recently used */ - list_del ( &cert->store.list ); - list_add ( &cert->store.list, &certstore.links ); - DBGC2 ( &certstore, "CERTSTORE found certificate %s\n", - x509_name ( cert ) ); - - return cert; -} - -/** - * Find certificate in store - * - * @v raw Raw certificate data - * @ret cert X.509 certificate, or NULL if not found - */ -struct x509_certificate * certstore_find ( struct asn1_cursor *raw ) { - struct x509_certificate *cert; - - /* Search for certificate within store */ - list_for_each_entry ( cert, &certstore.links, store.list ) { - if ( asn1_compare ( raw, &cert->raw ) == 0 ) - return certstore_found ( cert ); - } - return NULL; -} - -/** - * Find certificate in store corresponding to a private key - * - * @v key Private key - * @ret cert X.509 certificate, or NULL if not found - */ -struct x509_certificate * certstore_find_key ( struct asn1_cursor *key ) { - struct x509_certificate *cert; - - /* Search for certificate within store */ - list_for_each_entry ( cert, &certstore.links, store.list ) { - if ( pubkey_match ( cert->signature_algorithm->pubkey, - key->data, key->len, - cert->subject.public_key.raw.data, - cert->subject.public_key.raw.len ) == 0 ) - return certstore_found ( cert ); - } - return NULL; -} - -/** - * Add certificate to store - * - * @v cert X.509 certificate - */ -void certstore_add ( struct x509_certificate *cert ) { - - /* Add certificate to store */ - cert->store.cert = cert; - x509_get ( cert ); - list_add ( &cert->store.list, &certstore.links ); - DBGC ( &certstore, "CERTSTORE added certificate %s\n", - x509_name ( cert ) ); -} - -/** - * Discard a stored certificate - * - * @ret discarded Number of cached items discarded - */ -static unsigned int certstore_discard ( void ) { - struct x509_certificate *cert; - - /* Discard the least recently used certificate for which the - * only reference is held by the store itself. - */ - list_for_each_entry_reverse ( cert, &certstore.links, store.list ) { - if ( cert->refcnt.count == 0 ) { - DBGC ( &certstore, "CERTSTORE discarded certificate " - "%s\n", x509_name ( cert ) ); - list_del ( &cert->store.list ); - x509_put ( cert ); - return 1; - } - } - return 0; -} - -/** Certificate store cache discarder */ -struct cache_discarder certstore_discarder __cache_discarder ( CACHE_NORMAL ) ={ - .discard = certstore_discard, -}; - -/** - * Construct permanent certificate store - * - */ -static void certstore_init ( void ) { - struct asn1_cursor *raw; - struct x509_certificate *cert; - int i; - int rc; - - /* Skip if we have no permanent stored certificates */ - if ( ! sizeof ( certstore_raw ) ) - return; - - /* Add certificates */ - for ( i = 0 ; i < ( int ) ( sizeof ( certstore_raw ) / - sizeof ( certstore_raw[0] ) ) ; i++ ) { - - /* Skip if certificate already present in store */ - raw = &certstore_raw[i]; - if ( ( cert = certstore_find ( raw ) ) != NULL ) { - DBGC ( &certstore, "CERTSTORE permanent certificate %d " - "is a duplicate of %s\n", i, x509_name ( cert )); - continue; - } - - /* Parse certificate */ - cert = &certstore_certs[i]; - ref_init ( &cert->refcnt, ref_no_free ); - if ( ( rc = x509_parse ( cert, raw ) ) != 0 ) { - DBGC ( &certstore, "CERTSTORE could not parse " - "permanent certificate %d: %s\n", - i, strerror ( rc ) ); - continue; - } - - /* Add certificate to store. Certificate will never - * be discarded from the store, since we retain a - * permanent reference to it. - */ - certstore_add ( cert ); - DBGC ( &certstore, "CERTSTORE permanent certificate %d is %s\n", - i, x509_name ( cert ) ); - } -} - -/** Certificate store initialisation function */ -struct init_fn certstore_init_fn __init_fn ( INIT_LATE ) = { - .initialise = certstore_init, -}; - -/** Additional certificate setting */ -static struct setting cert_setting __setting ( SETTING_CRYPTO, cert ) = { - .name = "cert", - .description = "Certificate", - .tag = DHCP_EB_CERT, - .type = &setting_type_hex, -}; - -/** - * Apply certificate store configuration settings - * - * @ret rc Return status code - */ -static int certstore_apply_settings ( void ) { - static struct x509_certificate *cert = NULL; - struct x509_certificate *old_cert; - void *cert_data; - int len; - int rc; - - /* Record any existing additional certificate */ - old_cert = cert; - cert = NULL; - - /* Add additional certificate, if any */ - if ( ( len = fetch_raw_setting_copy ( NULL, &cert_setting, - &cert_data ) ) >= 0 ) { - if ( ( rc = x509_certificate ( cert_data, len, &cert ) ) == 0 ){ - DBGC ( &certstore, "CERTSTORE added additional " - "certificate %s\n", x509_name ( cert ) ); - } else { - DBGC ( &certstore, "CERTSTORE could not parse " - "additional certificate: %s\n", - strerror ( rc ) ); - /* Do not fail; leave as an unusable certificate */ - } - free ( cert_data ); - } - - /* Free old additional certificiate. Do this after reparsing - * the additional certificate; in the common case that the - * certificate has not changed, this will allow the stored - * certificate to be reused. - */ - x509_put ( old_cert ); - - return 0; -} - -/** Certificate store settings applicator */ -struct settings_applicator certstore_applicator __settings_applicator = { - .apply = certstore_apply_settings, -}; diff --git a/qemu/roms/ipxe/src/crypto/chap.c b/qemu/roms/ipxe/src/crypto/chap.c deleted file mode 100644 index c90c16def..000000000 --- a/qemu/roms/ipxe/src/crypto/chap.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/crypto.h> -#include <ipxe/chap.h> - -/** @file - * - * CHAP protocol - * - */ - -/** - * Initialise CHAP challenge/response - * - * @v chap CHAP challenge/response - * @v digest Digest algorithm to use - * @ret rc Return status code - * - * Initialises a CHAP challenge/response structure. This routine - * allocates memory, and so may fail. The allocated memory must - * eventually be freed by a call to chap_finish(). - */ -int chap_init ( struct chap_response *chap, - struct digest_algorithm *digest ) { - size_t state_len; - void *state; - - assert ( chap->digest == NULL ); - assert ( chap->digest_context == NULL ); - assert ( chap->response == NULL ); - - DBG ( "CHAP %p initialising with %s digest\n", chap, digest->name ); - - state_len = ( digest->ctxsize + digest->digestsize ); - state = malloc ( state_len ); - if ( ! state ) { - DBG ( "CHAP %p could not allocate %zd bytes for state\n", - chap, state_len ); - return -ENOMEM; - } - - chap->digest = digest; - chap->digest_context = state; - chap->response = ( state + digest->ctxsize ); - chap->response_len = digest->digestsize; - digest_init ( chap->digest, chap->digest_context ); - return 0; -} - -/** - * Add data to the CHAP challenge - * - * @v chap CHAP response - * @v data Data to add - * @v len Length of data to add - */ -void chap_update ( struct chap_response *chap, const void *data, - size_t len ) { - assert ( chap->digest != NULL ); - assert ( chap->digest_context != NULL ); - - if ( ! chap->digest ) - return; - - digest_update ( chap->digest, chap->digest_context, data, len ); -} - -/** - * Respond to the CHAP challenge - * - * @v chap CHAP response - * - * Calculates the final CHAP response value, and places it in @c - * chap->response, with a length of @c chap->response_len. - */ -void chap_respond ( struct chap_response *chap ) { - assert ( chap->digest != NULL ); - assert ( chap->digest_context != NULL ); - assert ( chap->response != NULL ); - - DBG ( "CHAP %p responding to challenge\n", chap ); - - if ( ! chap->digest ) - return; - - digest_final ( chap->digest, chap->digest_context, chap->response ); -} - -/** - * Free resources used by a CHAP response - * - * @v chap CHAP response - */ -void chap_finish ( struct chap_response *chap ) { - void *state = chap->digest_context; - - DBG ( "CHAP %p finished\n", chap ); - - free ( state ); - memset ( chap, 0, sizeof ( *chap ) ); -} diff --git a/qemu/roms/ipxe/src/crypto/cms.c b/qemu/roms/ipxe/src/crypto/cms.c deleted file mode 100644 index bc2148e8a..000000000 --- a/qemu/roms/ipxe/src/crypto/cms.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Cryptographic Message Syntax (PKCS #7) - * - * The format of CMS messages is defined in RFC 5652. - * - */ - -#include <stdint.h> -#include <string.h> -#include <time.h> -#include <errno.h> -#include <ipxe/asn1.h> -#include <ipxe/x509.h> -#include <ipxe/malloc.h> -#include <ipxe/uaccess.h> -#include <ipxe/cms.h> - -/* Disambiguate the various error causes */ -#define EACCES_NON_SIGNING \ - __einfo_error ( EINFO_EACCES_NON_SIGNING ) -#define EINFO_EACCES_NON_SIGNING \ - __einfo_uniqify ( EINFO_EACCES, 0x01, "Not a signing certificate" ) -#define EACCES_NON_CODE_SIGNING \ - __einfo_error ( EINFO_EACCES_NON_CODE_SIGNING ) -#define EINFO_EACCES_NON_CODE_SIGNING \ - __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" ) -#define EACCES_WRONG_NAME \ - __einfo_error ( EINFO_EACCES_WRONG_NAME ) -#define EINFO_EACCES_WRONG_NAME \ - __einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" ) -#define EACCES_NO_SIGNATURES \ - __einfo_error ( EINFO_EACCES_NO_SIGNATURES ) -#define EINFO_EACCES_NO_SIGNATURES \ - __einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" ) -#define EINVAL_DIGEST \ - __einfo_error ( EINFO_EINVAL_DIGEST ) -#define EINFO_EINVAL_DIGEST \ - __einfo_uniqify ( EINFO_EINVAL, 0x01, "Not a digest algorithm" ) -#define EINVAL_PUBKEY \ - __einfo_error ( EINFO_EINVAL_PUBKEY ) -#define EINFO_EINVAL_PUBKEY \ - __einfo_uniqify ( EINFO_EINVAL, 0x02, "Not a public-key algorithm" ) -#define ENOTSUP_SIGNEDDATA \ - __einfo_error ( EINFO_ENOTSUP_SIGNEDDATA ) -#define EINFO_ENOTSUP_SIGNEDDATA \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Not a digital signature" ) - -/** "pkcs7-signedData" object identifier */ -static uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA }; - -/** "pkcs7-signedData" object identifier cursor */ -static struct asn1_cursor oid_signeddata_cursor = - ASN1_OID_CURSOR ( oid_signeddata ); - -/** - * Parse CMS signature content type - * - * @v sig CMS signature - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse_content_type ( struct cms_signature *sig, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - - /* Enter contentType */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_OID ); - - /* Check OID is pkcs7-signedData */ - if ( asn1_compare ( &cursor, &oid_signeddata_cursor ) != 0 ) { - DBGC ( sig, "CMS %p does not contain signedData:\n", sig ); - DBGC_HDA ( sig, 0, raw->data, raw->len ); - return -ENOTSUP_SIGNEDDATA; - } - - DBGC ( sig, "CMS %p contains signedData\n", sig ); - return 0; -} - -/** - * Parse CMS signature certificate list - * - * @v sig CMS signature - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse_certificates ( struct cms_signature *sig, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - struct x509_certificate *cert; - int rc; - - /* Enter certificates */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - - /* Add each certificate */ - while ( cursor.len ) { - - /* Add certificate to chain */ - if ( ( rc = x509_append_raw ( sig->certificates, cursor.data, - cursor.len ) ) != 0 ) { - DBGC ( sig, "CMS %p could not append certificate: %s\n", - sig, strerror ( rc) ); - DBGC_HDA ( sig, 0, cursor.data, cursor.len ); - return rc; - } - cert = x509_last ( sig->certificates ); - DBGC ( sig, "CMS %p found certificate %s\n", - sig, x509_name ( cert ) ); - - /* Move to next certificate */ - asn1_skip_any ( &cursor ); - } - - return 0; -} - -/** - * Identify CMS signature certificate by issuer and serial number - * - * @v sig CMS signature - * @v issuer Issuer - * @v serial Serial number - * @ret cert X.509 certificate, or NULL if not found - */ -static struct x509_certificate * -cms_find_issuer_serial ( struct cms_signature *sig, - const struct asn1_cursor *issuer, - const struct asn1_cursor *serial ) { - struct x509_link *link; - struct x509_certificate *cert; - - /* Scan through certificate list */ - list_for_each_entry ( link, &sig->certificates->links, list ) { - - /* Check issuer and serial number */ - cert = link->cert; - if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) && - ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) ) - return cert; - } - - return NULL; -} - -/** - * Parse CMS signature signer identifier - * - * @v sig CMS signature - * @v info Signer information to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse_signer_identifier ( struct cms_signature *sig, - struct cms_signer_info *info, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - struct asn1_cursor serial; - struct asn1_cursor issuer; - struct x509_certificate *cert; - int rc; - - /* Enter issuerAndSerialNumber */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Identify issuer */ - memcpy ( &issuer, &cursor, sizeof ( issuer ) ); - if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not locate issuer: %s\n", - sig, info, strerror ( rc ) ); - DBGC_HDA ( sig, 0, raw->data, raw->len ); - return rc; - } - DBGC ( sig, "CMS %p/%p issuer is:\n", sig, info ); - DBGC_HDA ( sig, 0, issuer.data, issuer.len ); - asn1_skip_any ( &cursor ); - - /* Identify serialNumber */ - memcpy ( &serial, &cursor, sizeof ( serial ) ); - if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not locate serialNumber: %s\n", - sig, info, strerror ( rc ) ); - DBGC_HDA ( sig, 0, raw->data, raw->len ); - return rc; - } - DBGC ( sig, "CMS %p/%p serial number is:\n", sig, info ); - DBGC_HDA ( sig, 0, serial.data, serial.len ); - - /* Identify certificate */ - cert = cms_find_issuer_serial ( sig, &issuer, &serial ); - if ( ! cert ) { - DBGC ( sig, "CMS %p/%p could not identify signer's " - "certificate\n", sig, info ); - return -ENOENT; - } - - /* Append certificate to chain */ - if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not append certificate: %s\n", - sig, info, strerror ( rc ) ); - return rc; - } - - /* Append remaining certificates to chain */ - if ( ( rc = x509_auto_append ( info->chain, - sig->certificates ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not append certificates: %s\n", - sig, info, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Parse CMS signature digest algorithm - * - * @v sig CMS signature - * @v info Signer information to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse_digest_algorithm ( struct cms_signature *sig, - struct cms_signer_info *info, - const struct asn1_cursor *raw ) { - struct asn1_algorithm *algorithm; - int rc; - - /* Identify algorithm */ - if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not identify digest algorithm: " - "%s\n", sig, info, strerror ( rc ) ); - DBGC_HDA ( sig, 0, raw->data, raw->len ); - return rc; - } - - /* Record digest algorithm */ - info->digest = algorithm->digest; - DBGC ( sig, "CMS %p/%p digest algorithm is %s\n", - sig, info, algorithm->name ); - - return 0; -} - -/** - * Parse CMS signature algorithm - * - * @v sig CMS signature - * @v info Signer information to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse_signature_algorithm ( struct cms_signature *sig, - struct cms_signer_info *info, - const struct asn1_cursor *raw ) { - struct asn1_algorithm *algorithm; - int rc; - - /* Identify algorithm */ - if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not identify public-key " - "algorithm: %s\n", sig, info, strerror ( rc ) ); - DBGC_HDA ( sig, 0, raw->data, raw->len ); - return rc; - } - - /* Record signature algorithm */ - info->pubkey = algorithm->pubkey; - DBGC ( sig, "CMS %p/%p public-key algorithm is %s\n", - sig, info, algorithm->name ); - - return 0; -} - -/** - * Parse CMS signature value - * - * @v sig CMS signature - * @v info Signer information to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse_signature_value ( struct cms_signature *sig, - struct cms_signer_info *info, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int rc; - - /* Enter signature */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not locate signature:\n", - sig, info ); - DBGC_HDA ( sig, 0, raw->data, raw->len ); - return rc; - } - - /* Record signature */ - info->signature_len = cursor.len; - info->signature = malloc ( info->signature_len ); - if ( ! info->signature ) - return -ENOMEM; - memcpy ( info->signature, cursor.data, info->signature_len ); - DBGC ( sig, "CMS %p/%p signature value is:\n", sig, info ); - DBGC_HDA ( sig, 0, info->signature, info->signature_len ); - - return 0; -} - -/** - * Parse CMS signature signer information - * - * @v sig CMS signature - * @v info Signer information to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse_signer_info ( struct cms_signature *sig, - struct cms_signer_info *info, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int rc; - - /* Enter signerInfo */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Skip version */ - asn1_skip ( &cursor, ASN1_INTEGER ); - - /* Parse sid */ - if ( ( rc = cms_parse_signer_identifier ( sig, info, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse digestAlgorithm */ - if ( ( rc = cms_parse_digest_algorithm ( sig, info, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Skip signedAttrs, if present */ - asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - - /* Parse signatureAlgorithm */ - if ( ( rc = cms_parse_signature_algorithm ( sig, info, &cursor ) ) != 0) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse signature */ - if ( ( rc = cms_parse_signature_value ( sig, info, &cursor ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Parse CMS signature from ASN.1 data - * - * @v sig CMS signature - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int cms_parse ( struct cms_signature *sig, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - struct cms_signer_info *info; - int rc; - - /* Enter contentInfo */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse contentType */ - - if ( ( rc = cms_parse_content_type ( sig, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Enter content */ - asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - - /* Enter signedData */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Skip version */ - asn1_skip ( &cursor, ASN1_INTEGER ); - - /* Skip digestAlgorithms */ - asn1_skip ( &cursor, ASN1_SET ); - - /* Skip encapContentInfo */ - asn1_skip ( &cursor, ASN1_SEQUENCE ); - - /* Parse certificates */ - if ( ( rc = cms_parse_certificates ( sig, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Skip crls, if present */ - asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) ); - - /* Enter signerInfos */ - asn1_enter ( &cursor, ASN1_SET ); - - /* Add each signerInfo. Errors are handled by ensuring that - * cms_put() will always be able to free any allocated memory. - */ - while ( cursor.len ) { - - /* Allocate signer information block */ - info = zalloc ( sizeof ( *info ) ); - if ( ! info ) - return -ENOMEM; - list_add ( &info->list, &sig->info ); - - /* Allocate certificate chain */ - info->chain = x509_alloc_chain(); - if ( ! info->chain ) - return -ENOMEM; - - /* Parse signerInfo */ - if ( ( rc = cms_parse_signer_info ( sig, info, - &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - } - - return 0; -} - -/** - * Free CMS signature - * - * @v refcnt Reference count - */ -static void cms_free ( struct refcnt *refcnt ) { - struct cms_signature *sig = - container_of ( refcnt, struct cms_signature, refcnt ); - struct cms_signer_info *info; - struct cms_signer_info *tmp; - - list_for_each_entry_safe ( info, tmp, &sig->info, list ) { - list_del ( &info->list ); - x509_chain_put ( info->chain ); - free ( info->signature ); - free ( info ); - } - x509_chain_put ( sig->certificates ); - free ( sig ); -} - -/** - * Create CMS signature - * - * @v data Raw signature data - * @v len Length of raw data - * @ret sig CMS signature - * @ret rc Return status code - * - * On success, the caller holds a reference to the CMS signature, and - * is responsible for ultimately calling cms_put(). - */ -int cms_signature ( const void *data, size_t len, struct cms_signature **sig ) { - struct asn1_cursor cursor; - int rc; - - /* Allocate and initialise signature */ - *sig = zalloc ( sizeof ( **sig ) ); - if ( ! *sig ) { - rc = -ENOMEM; - goto err_alloc; - } - ref_init ( &(*sig)->refcnt, cms_free ); - INIT_LIST_HEAD ( &(*sig)->info ); - - /* Allocate certificate list */ - (*sig)->certificates = x509_alloc_chain(); - if ( ! (*sig)->certificates ) { - rc = -ENOMEM; - goto err_alloc_chain; - } - - /* Initialise cursor */ - cursor.data = data; - cursor.len = len; - asn1_shrink_any ( &cursor ); - - /* Parse signature */ - if ( ( rc = cms_parse ( *sig, &cursor ) ) != 0 ) - goto err_parse; - - return 0; - - err_parse: - err_alloc_chain: - cms_put ( *sig ); - err_alloc: - return rc; -} - -/** - * Calculate digest of CMS-signed data - * - * @v sig CMS signature - * @v info Signer information - * @v data Signed data - * @v len Length of signed data - * @v out Digest output - */ -static void cms_digest ( struct cms_signature *sig, - struct cms_signer_info *info, - userptr_t data, size_t len, void *out ) { - struct digest_algorithm *digest = info->digest; - uint8_t ctx[ digest->ctxsize ]; - uint8_t block[ digest->blocksize ]; - size_t offset = 0; - size_t frag_len; - - /* Initialise digest */ - digest_init ( digest, ctx ); - - /* Process data one block at a time */ - while ( len ) { - frag_len = len; - if ( frag_len > sizeof ( block ) ) - frag_len = sizeof ( block ); - copy_from_user ( block, data, offset, frag_len ); - digest_update ( digest, ctx, block, frag_len ); - offset += frag_len; - len -= frag_len; - } - - /* Finalise digest */ - digest_final ( digest, ctx, out ); - - DBGC ( sig, "CMS %p/%p digest value:\n", sig, info ); - DBGC_HDA ( sig, 0, out, digest->digestsize ); -} - -/** - * Verify digest of CMS-signed data - * - * @v sig CMS signature - * @v info Signer information - * @v cert Corresponding certificate - * @v data Signed data - * @v len Length of signed data - * @ret rc Return status code - */ -static int cms_verify_digest ( struct cms_signature *sig, - struct cms_signer_info *info, - struct x509_certificate *cert, - userptr_t data, size_t len ) { - struct digest_algorithm *digest = info->digest; - struct pubkey_algorithm *pubkey = info->pubkey; - struct x509_public_key *public_key = &cert->subject.public_key; - uint8_t digest_out[ digest->digestsize ]; - uint8_t ctx[ pubkey->ctxsize ]; - int rc; - - /* Generate digest */ - cms_digest ( sig, info, data, len, digest_out ); - - /* Initialise public-key algorithm */ - if ( ( rc = pubkey_init ( pubkey, ctx, public_key->raw.data, - public_key->raw.len ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not initialise public key: %s\n", - sig, info, strerror ( rc ) ); - goto err_init; - } - - /* Verify digest */ - if ( ( rc = pubkey_verify ( pubkey, ctx, digest, digest_out, - info->signature, - info->signature_len ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p signature verification failed: %s\n", - sig, info, strerror ( rc ) ); - goto err_verify; - } - - err_verify: - pubkey_final ( pubkey, ctx ); - err_init: - return rc; -} - -/** - * Verify CMS signature signer information - * - * @v sig CMS signature - * @v info Signer information - * @v data Signed data - * @v len Length of signed data - * @v time Time at which to validate certificates - * @v store Certificate store, or NULL to use default - * @v root Root certificate list, or NULL to use default - * @ret rc Return status code - */ -static int cms_verify_signer_info ( struct cms_signature *sig, - struct cms_signer_info *info, - userptr_t data, size_t len, - time_t time, struct x509_chain *store, - struct x509_root *root ) { - struct x509_certificate *cert; - int rc; - - /* Validate certificate chain */ - if ( ( rc = x509_validate_chain ( info->chain, time, store, - root ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not validate chain: %s\n", - sig, info, strerror ( rc ) ); - return rc; - } - - /* Extract code-signing certificate */ - cert = x509_first ( info->chain ); - assert ( cert != NULL ); - - /* Check that certificate can create digital signatures */ - if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) { - DBGC ( sig, "CMS %p/%p certificate cannot create signatures\n", - sig, info ); - return -EACCES_NON_SIGNING; - } - - /* Check that certificate can sign code */ - if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) { - DBGC ( sig, "CMS %p/%p certificate is not code-signing\n", - sig, info ); - return -EACCES_NON_CODE_SIGNING; - } - - /* Verify digest */ - if ( ( rc = cms_verify_digest ( sig, info, cert, data, len ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Verify CMS signature - * - * @v sig CMS signature - * @v data Signed data - * @v len Length of signed data - * @v name Required common name, or NULL to check all signatures - * @v time Time at which to validate certificates - * @v store Certificate store, or NULL to use default - * @v root Root certificate list, or NULL to use default - * @ret rc Return status code - */ -int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len, - const char *name, time_t time, struct x509_chain *store, - struct x509_root *root ) { - struct cms_signer_info *info; - struct x509_certificate *cert; - int count = 0; - int rc; - - /* Verify using all signerInfos */ - list_for_each_entry ( info, &sig->info, list ) { - cert = x509_first ( info->chain ); - if ( name && ( x509_check_name ( cert, name ) != 0 ) ) - continue; - if ( ( rc = cms_verify_signer_info ( sig, info, data, len, time, - store, root ) ) != 0 ) - return rc; - count++; - } - - /* Check that we have verified at least one signature */ - if ( count == 0 ) { - if ( name ) { - DBGC ( sig, "CMS %p had no signatures matching name " - "%s\n", sig, name ); - return -EACCES_WRONG_NAME; - } else { - DBGC ( sig, "CMS %p had no signatures\n", sig ); - return -EACCES_NO_SIGNATURES; - } - } - - return 0; -} diff --git a/qemu/roms/ipxe/src/crypto/crc32.c b/qemu/roms/ipxe/src/crypto/crc32.c deleted file mode 100644 index cfef68c02..000000000 --- a/qemu/roms/ipxe/src/crypto/crc32.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Little-endian CRC32 implementation. - * - * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <ipxe/crc32.h> - -#define CRCPOLY 0xedb88320 - -/** - * Calculate 32-bit little-endian CRC checksum - * - * @v seed Initial value - * @v data Data to checksum - * @v len Length of data - * - * Usually @a seed is initially zero or all one bits, depending on the - * protocol. To continue a CRC checksum over multiple calls, pass the - * return value from one call as the @a seed parameter to the next. - */ -u32 crc32_le ( u32 seed, const void *data, size_t len ) -{ - u32 crc = seed; - const u8 *src = data; - u32 mult; - int i; - - while ( len-- ) { - crc ^= *src++; - for ( i = 0; i < 8; i++ ) { - mult = ( crc & 1 ) ? CRCPOLY : 0; - crc = ( crc >> 1 ) ^ mult; - } - } - - return crc; -} diff --git a/qemu/roms/ipxe/src/crypto/crypto_null.c b/qemu/roms/ipxe/src/crypto/crypto_null.c deleted file mode 100644 index 15a1c538b..000000000 --- a/qemu/roms/ipxe/src/crypto/crypto_null.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** - * @file - * - * Null crypto algorithm - */ - -#include <string.h> -#include <ipxe/crypto.h> - -static void digest_null_init ( void *ctx __unused ) { - /* Do nothing */ -} - -static void digest_null_update ( void *ctx __unused, const void *src __unused, - size_t len __unused ) { - /* Do nothing */ -} - -static void digest_null_final ( void *ctx __unused, void *out __unused ) { - /* Do nothing */ -} - -struct digest_algorithm digest_null = { - .name = "null", - .ctxsize = 0, - .blocksize = 1, - .digestsize = 0, - .init = digest_null_init, - .update = digest_null_update, - .final = digest_null_final, -}; - -static int cipher_null_setkey ( void *ctx __unused, const void *key __unused, - size_t keylen __unused ) { - /* Do nothing */ - return 0; -} - -static void cipher_null_setiv ( void *ctx __unused, - const void *iv __unused ) { - /* Do nothing */ -} - -static void cipher_null_encrypt ( void *ctx __unused, const void *src, - void *dst, size_t len ) { - memcpy ( dst, src, len ); -} - -static void cipher_null_decrypt ( void *ctx __unused, const void *src, - void *dst, size_t len ) { - memcpy ( dst, src, len ); -} - -struct cipher_algorithm cipher_null = { - .name = "null", - .ctxsize = 0, - .blocksize = 1, - .setkey = cipher_null_setkey, - .setiv = cipher_null_setiv, - .encrypt = cipher_null_encrypt, - .decrypt = cipher_null_decrypt, -}; - -static int pubkey_null_init ( void *ctx __unused, const void *key __unused, - size_t key_len __unused ) { - return 0; -} - -static size_t pubkey_null_max_len ( void *ctx __unused ) { - return 0; -} - -static int pubkey_null_encrypt ( void *ctx __unused, - const void *plaintext __unused, - size_t plaintext_len __unused, - void *ciphertext __unused ) { - return 0; -} - -static int pubkey_null_decrypt ( void *ctx __unused, - const void *ciphertext __unused, - size_t ciphertext_len __unused, - void *plaintext __unused ) { - return 0; -} - -static int pubkey_null_sign ( void *ctx __unused, - struct digest_algorithm *digest __unused, - const void *value __unused, - void *signature __unused ) { - return 0; -} - -static int pubkey_null_verify ( void *ctx __unused, - struct digest_algorithm *digest __unused, - const void *value __unused, - const void *signature __unused , - size_t signature_len __unused ) { - return 0; -} - -static void pubkey_null_final ( void *ctx __unused ) { - /* Do nothing */ -} - -struct pubkey_algorithm pubkey_null = { - .name = "null", - .ctxsize = 0, - .init = pubkey_null_init, - .max_len = pubkey_null_max_len, - .encrypt = pubkey_null_encrypt, - .decrypt = pubkey_null_decrypt, - .sign = pubkey_null_sign, - .verify = pubkey_null_verify, - .final = pubkey_null_final, -}; diff --git a/qemu/roms/ipxe/src/crypto/deflate.c b/qemu/roms/ipxe/src/crypto/deflate.c deleted file mode 100644 index e1c87d5fe..000000000 --- a/qemu/roms/ipxe/src/crypto/deflate.c +++ /dev/null @@ -1,1049 +0,0 @@ -/* - * Copyright (C) 2014 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <string.h> -#include <strings.h> -#include <errno.h> -#include <assert.h> -#include <ctype.h> -#include <ipxe/uaccess.h> -#include <ipxe/deflate.h> - -/** @file - * - * DEFLATE decompression algorithm - * - * This file implements the decompression half of the DEFLATE - * algorithm specified in RFC 1951. - * - * Portions of this code are derived from wimboot's xca.c. - * - */ - -/** - * Byte reversal table - * - * For some insane reason, the DEFLATE format stores some values in - * bit-reversed order. - */ -static uint8_t deflate_reverse[256]; - -/** Literal/length base values - * - * We include entries only for literal/length codes 257-284. Code 285 - * does not fit the pattern (it represents a length of 258; following - * the pattern from the earlier codes would give a length of 259), and - * has no extra bits. Codes 286-287 are invalid, but can occur. We - * treat any code greater than 284 as meaning "length 285, no extra - * bits". - */ -static uint8_t deflate_litlen_base[28]; - -/** Distance base values - * - * We include entries for all possible codes 0-31, avoiding the need - * to check for undefined codes 30 and 31 before performing the - * lookup. Codes 30 and 31 are never initialised, and will therefore - * be treated as meaning "14 extra bits, base distance 0". - */ -static uint16_t deflate_distance_base[32]; - -/** Code length map */ -static uint8_t deflate_codelen_map[19] = { - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 -}; - -/** Static Huffman alphabet length patterns */ -static struct deflate_static_length_pattern deflate_static_length_patterns[] = { - /* Literal/length code lengths */ - { 0x88, ( ( ( 143 - 0 ) + 1 ) / 2 ) }, - { 0x99, ( ( ( 255 - 144 ) + 1 ) / 2 ) }, - { 0x77, ( ( ( 279 - 256 ) + 1 ) / 2 ) }, - { 0x88, ( ( ( 287 - 280 ) + 1 ) / 2 ) }, - /* Distance code lengths */ - { 0x55, ( ( ( 31 - 0 ) + 1 ) / 2 ) }, - /* End marker */ - { 0, 0 } -}; - -/** - * Transcribe binary value (for debugging) - * - * @v value Value - * @v bits Length of value (in bits) - * @ret string Transcribed value - */ -static const char * deflate_bin ( unsigned long value, unsigned int bits ) { - static char buf[ ( 8 * sizeof ( value ) ) + 1 /* NUL */ ]; - char *out = buf; - - /* Sanity check */ - assert ( bits < sizeof ( buf ) ); - - /* Transcribe value */ - while ( bits-- ) - *(out++) = ( ( value & ( 1 << bits ) ) ? '1' : '0' ); - *out = '\0'; - - return buf; -} - -/** - * Set Huffman symbol length - * - * @v deflate Decompressor - * @v index Index within lengths - * @v bits Symbol length (in bits) - */ -static void deflate_set_length ( struct deflate *deflate, unsigned int index, - unsigned int bits ) { - - deflate->lengths[ index / 2 ] |= ( bits << ( 4 * ( index % 2 ) ) ); -} - -/** - * Get Huffman symbol length - * - * @v deflate Decompressor - * @v index Index within lengths - * @ret bits Symbol length (in bits) - */ -static unsigned int deflate_length ( struct deflate *deflate, - unsigned int index ) { - - return ( ( deflate->lengths[ index / 2 ] >> ( 4 * ( index % 2 ) ) ) - & 0x0f ); -} - -/** - * Determine Huffman alphabet name (for debugging) - * - * @v deflate Decompressor - * @v alphabet Huffman alphabet - * @ret name Alphabet name - */ -static const char * deflate_alphabet_name ( struct deflate *deflate, - struct deflate_alphabet *alphabet ){ - - if ( alphabet == &deflate->litlen ) { - return "litlen"; - } else if ( alphabet == &deflate->distance_codelen ) { - return "distance/codelen"; - } else { - return "<UNKNOWN>"; - } -} - -/** - * Dump Huffman alphabet (for debugging) - * - * @v deflate Decompressor - * @v alphabet Huffman alphabet - */ -static void deflate_dump_alphabet ( struct deflate *deflate, - struct deflate_alphabet *alphabet ) { - struct deflate_huf_symbols *huf_sym; - unsigned int bits; - unsigned int huf; - unsigned int i; - - /* Do nothing unless debugging is enabled */ - if ( ! DBG_EXTRA ) - return; - - /* Dump symbol table for each utilised length */ - for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / - sizeof ( alphabet->huf[0] ) ) ; bits++ ) { - huf_sym = &alphabet->huf[ bits - 1 ]; - if ( huf_sym->freq == 0 ) - continue; - huf = ( huf_sym->start >> huf_sym->shift ); - DBGC2 ( alphabet, "DEFLATE %p \"%s\" length %d start \"%s\" " - "freq %d:", deflate, - deflate_alphabet_name ( deflate, alphabet ), bits, - deflate_bin ( huf, huf_sym->bits ), huf_sym->freq ); - for ( i = 0 ; i < huf_sym->freq ; i++ ) { - DBGC2 ( alphabet, " %03x", - huf_sym->raw[ huf + i ] ); - } - DBGC2 ( alphabet, "\n" ); - } - - /* Dump quick lookup table */ - DBGC2 ( alphabet, "DEFLATE %p \"%s\" quick lookup:", deflate, - deflate_alphabet_name ( deflate, alphabet ) ); - for ( i = 0 ; i < ( sizeof ( alphabet->lookup ) / - sizeof ( alphabet->lookup[0] ) ) ; i++ ) { - DBGC2 ( alphabet, " %d", ( alphabet->lookup[i] + 1 ) ); - } - DBGC2 ( alphabet, "\n" ); -} - -/** - * Construct Huffman alphabet - * - * @v deflate Decompressor - * @v alphabet Huffman alphabet - * @v count Number of symbols - * @v offset Starting offset within length table - * @ret rc Return status code - */ -static int deflate_alphabet ( struct deflate *deflate, - struct deflate_alphabet *alphabet, - unsigned int count, unsigned int offset ) { - struct deflate_huf_symbols *huf_sym; - unsigned int huf; - unsigned int cum_freq; - unsigned int bits; - unsigned int raw; - unsigned int adjustment; - unsigned int prefix; - int complete; - - /* Clear symbol table */ - memset ( alphabet->huf, 0, sizeof ( alphabet->huf ) ); - - /* Count number of symbols with each Huffman-coded length */ - for ( raw = 0 ; raw < count ; raw++ ) { - bits = deflate_length ( deflate, ( raw + offset ) ); - if ( bits ) - alphabet->huf[ bits - 1 ].freq++; - } - - /* Populate Huffman-coded symbol table */ - huf = 0; - cum_freq = 0; - for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / - sizeof ( alphabet->huf[0] ) ) ; bits++ ) { - huf_sym = &alphabet->huf[ bits - 1 ]; - huf_sym->bits = bits; - huf_sym->shift = ( 16 - bits ); - huf_sym->start = ( huf << huf_sym->shift ); - huf_sym->raw = &alphabet->raw[cum_freq]; - huf += huf_sym->freq; - if ( huf > ( 1U << bits ) ) { - DBGC ( alphabet, "DEFLATE %p \"%s\" has too many " - "symbols with lengths <=%d\n", deflate, - deflate_alphabet_name ( deflate, alphabet ), - bits ); - return -EINVAL; - } - huf <<= 1; - cum_freq += huf_sym->freq; - } - complete = ( huf == ( 1U << bits ) ); - - /* Populate raw symbol table */ - for ( raw = 0 ; raw < count ; raw++ ) { - bits = deflate_length ( deflate, ( raw + offset ) ); - if ( bits ) { - huf_sym = &alphabet->huf[ bits - 1 ]; - *(huf_sym->raw++) = raw; - } - } - - /* Adjust Huffman-coded symbol table raw pointers and populate - * quick lookup table. - */ - for ( bits = 1 ; bits <= ( sizeof ( alphabet->huf ) / - sizeof ( alphabet->huf[0] ) ) ; bits++ ) { - huf_sym = &alphabet->huf[ bits - 1 ]; - - /* Adjust raw pointer */ - huf_sym->raw -= huf_sym->freq; /* Reset to first symbol */ - adjustment = ( huf_sym->start >> huf_sym->shift ); - huf_sym->raw -= adjustment; /* Adjust for quick indexing */ - - /* Populate quick lookup table */ - for ( prefix = ( huf_sym->start >> DEFLATE_HUFFMAN_QL_SHIFT ) ; - prefix < ( 1 << DEFLATE_HUFFMAN_QL_BITS ) ; prefix++ ) { - alphabet->lookup[prefix] = ( bits - 1 ); - } - } - - /* Dump alphabet (for debugging) */ - deflate_dump_alphabet ( deflate, alphabet ); - - /* Check that there are no invalid codes */ - if ( ! complete ) { - DBGC ( alphabet, "DEFLATE %p \"%s\" is incomplete\n", deflate, - deflate_alphabet_name ( deflate, alphabet ) ); - return -EINVAL; - } - - return 0; -} - -/** - * Attempt to accumulate bits from input stream - * - * @v deflate Decompressor - * @v in Compressed input data - * @v target Number of bits to accumulate - * @ret excess Number of excess bits accumulated (may be negative) - */ -static int deflate_accumulate ( struct deflate *deflate, - struct deflate_chunk *in, - unsigned int target ) { - uint8_t byte; - - while ( deflate->bits < target ) { - - /* Check for end of input */ - if ( in->offset >= in->len ) - break; - - /* Acquire byte from input */ - copy_from_user ( &byte, in->data, in->offset++, - sizeof ( byte ) ); - deflate->accumulator = ( deflate->accumulator | - ( byte << deflate->bits ) ); - deflate->rotalumucca = ( deflate->rotalumucca | - ( deflate_reverse[byte] << - ( 24 - deflate->bits ) ) ); - deflate->bits += 8; - - /* Sanity check */ - assert ( deflate->bits <= - ( 8 * sizeof ( deflate->accumulator ) ) ); - } - - return ( deflate->bits - target ); -} - -/** - * Consume accumulated bits from the input stream - * - * @v deflate Decompressor - * @v count Number of accumulated bits to consume - * @ret data Consumed bits - */ -static int deflate_consume ( struct deflate *deflate, unsigned int count ) { - int data; - - /* Sanity check */ - assert ( count <= deflate->bits ); - - /* Extract data and consume bits */ - data = ( deflate->accumulator & ( ( 1 << count ) - 1 ) ); - deflate->accumulator >>= count; - deflate->rotalumucca <<= count; - deflate->bits -= count; - - return data; -} - -/** - * Attempt to extract a fixed number of bits from input stream - * - * @v deflate Decompressor - * @v in Compressed input data - * @v target Number of bits to extract - * @ret data Extracted bits (or negative if not yet accumulated) - */ -static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in, - unsigned int target ) { - int excess; - int data; - - /* Return immediately if we are attempting to extract zero bits */ - if ( target == 0 ) - return 0; - - /* Attempt to accumulate bits */ - excess = deflate_accumulate ( deflate, in, target ); - if ( excess < 0 ) - return excess; - - /* Extract data and consume bits */ - data = deflate_consume ( deflate, target ); - DBGCP ( deflate, "DEFLATE %p extracted %s = %#x = %d\n", deflate, - deflate_bin ( data, target ), data, data ); - - return data; -} - -/** - * Attempt to decode a Huffman-coded symbol from input stream - * - * @v deflate Decompressor - * @v in Compressed input data - * @v alphabet Huffman alphabet - * @ret code Raw code (or negative if not yet accumulated) - */ -static int deflate_decode ( struct deflate *deflate, - struct deflate_chunk *in, - struct deflate_alphabet *alphabet ) { - struct deflate_huf_symbols *huf_sym; - uint16_t huf; - unsigned int lookup_index; - int excess; - unsigned int raw; - - /* Attempt to accumulate maximum required number of bits. - * There may be fewer bits than this remaining in the stream, - * even if the stream still contains some complete - * Huffman-coded symbols. - */ - deflate_accumulate ( deflate, in, DEFLATE_HUFFMAN_BITS ); - - /* Normalise the bit-reversed accumulated value to 16 bits */ - huf = ( deflate->rotalumucca >> 16 ); - - /* Find symbol set for this length */ - lookup_index = ( huf >> DEFLATE_HUFFMAN_QL_SHIFT ); - huf_sym = &alphabet->huf[ alphabet->lookup[ lookup_index ] ]; - while ( huf < huf_sym->start ) - huf_sym--; - - /* Calculate number of excess bits, and return if not yet complete */ - excess = ( deflate->bits - huf_sym->bits ); - if ( excess < 0 ) - return excess; - - /* Consume bits */ - deflate_consume ( deflate, huf_sym->bits ); - - /* Look up raw symbol */ - raw = huf_sym->raw[ huf >> huf_sym->shift ]; - DBGCP ( deflate, "DEFLATE %p decoded %s = %#x = %d\n", deflate, - deflate_bin ( ( huf >> huf_sym->shift ), huf_sym->bits ), - raw, raw ); - - return raw; -} - -/** - * Discard bits up to the next byte boundary - * - * @v deflate Decompressor - */ -static void deflate_discard_to_byte ( struct deflate *deflate ) { - - deflate_consume ( deflate, ( deflate->bits & 7 ) ); -} - -/** - * Copy data to output buffer (if available) - * - * @v out Output data buffer - * @v start Source data - * @v offset Starting offset within source data - * @v len Length to copy - */ -static void deflate_copy ( struct deflate_chunk *out, - userptr_t start, size_t offset, size_t len ) { - size_t out_offset = out->offset; - size_t copy_len; - - /* Copy data one byte at a time, to allow for overlap */ - if ( out_offset < out->len ) { - copy_len = ( out->len - out_offset ); - if ( copy_len > len ) - copy_len = len; - while ( copy_len-- ) { - memcpy_user ( out->data, out_offset++, - start, offset++, 1 ); - } - } - out->offset += len; -} - -/** - * Inflate compressed data - * - * @v deflate Decompressor - * @v in Compressed input data - * @v out Output data buffer - * @ret rc Return status code - * - * The caller can use deflate_finished() to determine whether a - * successful return indicates that the decompressor is merely waiting - * for more input. - * - * Data will not be written beyond the specified end of the output - * data buffer, but the offset within the output data buffer will be - * updated to reflect the amount that should have been written. The - * caller can use this to find the length of the decompressed data - * before allocating the output data buffer. - */ -int deflate_inflate ( struct deflate *deflate, - struct deflate_chunk *in, - struct deflate_chunk *out ) { - - /* This could be implemented more neatly if gcc offered a - * means for enforcing tail recursion. - */ - if ( deflate->resume ) { - goto *(deflate->resume); - } else switch ( deflate->format ) { - case DEFLATE_RAW: goto block_header; - case DEFLATE_ZLIB: goto zlib_header; - default: assert ( 0 ); - } - - zlib_header: { - int header; - int cm; - - /* Extract header */ - header = deflate_extract ( deflate, in, ZLIB_HEADER_BITS ); - if ( header < 0 ) { - deflate->resume = &&zlib_header; - return 0; - } - - /* Parse header */ - cm = ( ( header >> ZLIB_HEADER_CM_LSB ) & ZLIB_HEADER_CM_MASK ); - if ( cm != ZLIB_HEADER_CM_DEFLATE ) { - DBGC ( deflate, "DEFLATE %p unsupported ZLIB " - "compression method %d\n", deflate, cm ); - return -ENOTSUP; - } - if ( header & ( 1 << ZLIB_HEADER_FDICT_BIT ) ) { - DBGC ( deflate, "DEFLATE %p unsupported ZLIB preset " - "dictionary\n", deflate ); - return -ENOTSUP; - } - - /* Process first block header */ - goto block_header; - } - - block_header: { - int header; - int bfinal; - int btype; - - /* Extract block header */ - header = deflate_extract ( deflate, in, DEFLATE_HEADER_BITS ); - if ( header < 0 ) { - deflate->resume = &&block_header; - return 0; - } - - /* Parse header */ - deflate->header = header; - bfinal = ( header & ( 1 << DEFLATE_HEADER_BFINAL_BIT ) ); - btype = ( header >> DEFLATE_HEADER_BTYPE_LSB ); - DBGC ( deflate, "DEFLATE %p found %sblock type %#x\n", - deflate, ( bfinal ? "final " : "" ), btype ); - switch ( btype ) { - case DEFLATE_HEADER_BTYPE_LITERAL: - goto literal_block; - case DEFLATE_HEADER_BTYPE_STATIC: - goto static_block; - case DEFLATE_HEADER_BTYPE_DYNAMIC: - goto dynamic_block; - default: - DBGC ( deflate, "DEFLATE %p unsupported block type " - "%#x\n", deflate, btype ); - return -ENOTSUP; - } - } - - literal_block: { - - /* Discard any bits up to the next byte boundary */ - deflate_discard_to_byte ( deflate ); - } - - literal_len: { - int len; - - /* Extract LEN field */ - len = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS ); - if ( len < 0 ) { - deflate->resume = &&literal_len; - return 0; - } - - /* Record length of literal data */ - deflate->remaining = len; - DBGC2 ( deflate, "DEFLATE %p literal block length %#04zx\n", - deflate, deflate->remaining ); - } - - literal_nlen: { - int nlen; - - /* Extract NLEN field */ - nlen = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS); - if ( nlen < 0 ) { - deflate->resume = &&literal_nlen; - return 0; - } - - /* Verify NLEN */ - if ( ( ( deflate->remaining ^ ~nlen ) & - ( ( 1 << DEFLATE_LITERAL_LEN_BITS ) - 1 ) ) != 0 ) { - DBGC ( deflate, "DEFLATE %p invalid len/nlen " - "%#04zx/%#04x\n", deflate, - deflate->remaining, nlen ); - return -EINVAL; - } - } - - literal_data: { - size_t in_remaining; - size_t len; - - /* Calculate available amount of literal data */ - in_remaining = ( in->len - in->offset ); - len = deflate->remaining; - if ( len > in_remaining ) - len = in_remaining; - - /* Copy data to output buffer */ - deflate_copy ( out, in->data, in->offset, len ); - - /* Consume data from input buffer */ - in->offset += len; - deflate->remaining -= len; - - /* Finish processing if we are blocked */ - if ( deflate->remaining ) { - deflate->resume = &&literal_data; - return 0; - } - - /* Otherwise, finish block */ - goto block_done; - } - - static_block: { - struct deflate_static_length_pattern *pattern; - uint8_t *lengths = deflate->lengths; - - /* Construct static Huffman lengths as per RFC 1950 */ - for ( pattern = deflate_static_length_patterns ; - pattern->count ; pattern++ ) { - memset ( lengths, pattern->fill, pattern->count ); - lengths += pattern->count; - } - deflate->litlen_count = 288; - deflate->distance_count = 32; - goto construct_alphabets; - } - - dynamic_block: - - dynamic_header: { - int header; - unsigned int hlit; - unsigned int hdist; - unsigned int hclen; - - /* Extract block header */ - header = deflate_extract ( deflate, in, DEFLATE_DYNAMIC_BITS ); - if ( header < 0 ) { - deflate->resume = &&dynamic_header; - return 0; - } - - /* Parse header */ - hlit = ( ( header >> DEFLATE_DYNAMIC_HLIT_LSB ) & - DEFLATE_DYNAMIC_HLIT_MASK ); - hdist = ( ( header >> DEFLATE_DYNAMIC_HDIST_LSB ) & - DEFLATE_DYNAMIC_HDIST_MASK ); - hclen = ( ( header >> DEFLATE_DYNAMIC_HCLEN_LSB ) & - DEFLATE_DYNAMIC_HCLEN_MASK ); - deflate->litlen_count = ( hlit + 257 ); - deflate->distance_count = ( hdist + 1 ); - deflate->length_index = 0; - deflate->length_target = ( hclen + 4 ); - DBGC2 ( deflate, "DEFLATE %p dynamic block %d codelen, %d " - "litlen, %d distance\n", deflate, - deflate->length_target, deflate->litlen_count, - deflate->distance_count ); - - /* Prepare for decoding code length code lengths */ - memset ( &deflate->lengths, 0, sizeof ( deflate->lengths ) ); - } - - dynamic_codelen: { - int len; - unsigned int index; - int rc; - - /* Extract all code lengths */ - while ( deflate->length_index < deflate->length_target ) { - - /* Extract code length length */ - len = deflate_extract ( deflate, in, - DEFLATE_CODELEN_BITS ); - if ( len < 0 ) { - deflate->resume = &&dynamic_codelen; - return 0; - } - - /* Store code length */ - index = deflate_codelen_map[deflate->length_index++]; - deflate_set_length ( deflate, index, len ); - DBGCP ( deflate, "DEFLATE %p codelen for %d is %d\n", - deflate, index, len ); - } - - /* Generate code length alphabet */ - if ( ( rc = deflate_alphabet ( deflate, - &deflate->distance_codelen, - ( DEFLATE_CODELEN_MAX_CODE + 1 ), - 0 ) ) != 0 ) - return rc; - - /* Prepare for decoding literal/length/distance code lengths */ - memset ( &deflate->lengths, 0, sizeof ( deflate->lengths ) ); - deflate->length_index = 0; - deflate->length_target = ( deflate->litlen_count + - deflate->distance_count ); - deflate->length = 0; - } - - dynamic_litlen_distance: { - int len; - int index; - - /* Decode literal/length/distance code length */ - len = deflate_decode ( deflate, in, &deflate->distance_codelen); - if ( len < 0 ) { - deflate->resume = &&dynamic_litlen_distance; - return 0; - } - - /* Prepare for extra bits */ - if ( len < 16 ) { - deflate->length = len; - deflate->extra_bits = 0; - deflate->dup_len = 1; - } else { - static const uint8_t dup_len[3] = { 3, 3, 11 }; - static const uint8_t extra_bits[3] = { 2, 3, 7 }; - index = ( len - 16 ); - deflate->dup_len = dup_len[index]; - deflate->extra_bits = extra_bits[index]; - if ( index ) - deflate->length = 0; - } - } - - dynamic_litlen_distance_extra: { - int extra; - unsigned int dup_len; - - /* Extract extra bits */ - extra = deflate_extract ( deflate, in, deflate->extra_bits ); - if ( extra < 0 ) { - deflate->resume = &&dynamic_litlen_distance_extra; - return 0; - } - - /* Store code lengths */ - dup_len = ( deflate->dup_len + extra ); - while ( ( deflate->length_index < deflate->length_target ) && - dup_len-- ) { - deflate_set_length ( deflate, deflate->length_index++, - deflate->length ); - } - - /* Process next literal/length or distance code - * length, if more are required. - */ - if ( deflate->length_index < deflate->length_target ) - goto dynamic_litlen_distance; - - /* Construct alphabets */ - goto construct_alphabets; - } - - construct_alphabets: { - unsigned int distance_offset = deflate->litlen_count; - unsigned int distance_count = deflate->distance_count; - int rc; - - /* Generate literal/length alphabet */ - if ( ( rc = deflate_alphabet ( deflate, &deflate->litlen, - deflate->litlen_count, 0 ) ) !=0) - return rc; - - /* Handle degenerate case of a single distance code - * (for which it is impossible to construct a valid, - * complete Huffman alphabet). RFC 1951 states: - * - * If only one distance code is used, it is encoded - * using one bit, not zero bits; in this case there - * is a single code length of one, with one unused - * code. One distance code of zero bits means that - * there are no distance codes used at all (the data - * is all literals). - * - * If we have only a single distance code, then we - * instead use two distance codes both with length 1. - * This results in a valid Huffman alphabet. The code - * "0" will mean distance code 0 (which is either - * correct or irrelevant), and the code "1" will mean - * distance code 1 (which is always irrelevant). - */ - if ( deflate->distance_count == 1 ) { - - deflate->lengths[0] = 0x11; - distance_offset = 0; - distance_count = 2; - } - - /* Generate distance alphabet */ - if ( ( rc = deflate_alphabet ( deflate, - &deflate->distance_codelen, - distance_count, - distance_offset ) ) != 0 ) - return rc; - } - - lzhuf_litlen: { - int code; - uint8_t byte; - unsigned int extra; - unsigned int bits; - - /* Decode Huffman codes */ - while ( 1 ) { - - /* Decode Huffman code */ - code = deflate_decode ( deflate, in, &deflate->litlen ); - if ( code < 0 ) { - deflate->resume = &&lzhuf_litlen; - return 0; - } - - /* Handle according to code type */ - if ( code < DEFLATE_LITLEN_END ) { - - /* Literal value: copy to output buffer */ - byte = code; - DBGCP ( deflate, "DEFLATE %p literal %#02x " - "('%c')\n", deflate, byte, - ( isprint ( byte ) ? byte : '.' ) ); - deflate_copy ( out, virt_to_user ( &byte ), 0, - sizeof ( byte ) ); - - } else if ( code == DEFLATE_LITLEN_END ) { - - /* End of block */ - goto block_done; - - } else { - - /* Length code: process extra bits */ - extra = ( code - DEFLATE_LITLEN_END - 1 ); - if ( extra < 28 ) { - bits = ( extra / 4 ); - if ( bits ) - bits--; - deflate->extra_bits = bits; - deflate->dup_len = - deflate_litlen_base[extra]; - } else { - deflate->extra_bits = 0; - deflate->dup_len = 258; - } - goto lzhuf_litlen_extra; - } - } - } - - lzhuf_litlen_extra: { - int extra; - - /* Extract extra bits */ - extra = deflate_extract ( deflate, in, deflate->extra_bits ); - if ( extra < 0 ) { - deflate->resume = &&lzhuf_litlen_extra; - return 0; - } - - /* Update duplicate length */ - deflate->dup_len += extra; - } - - lzhuf_distance: { - int code; - unsigned int extra; - unsigned int bits; - - /* Decode Huffman code */ - code = deflate_decode ( deflate, in, - &deflate->distance_codelen ); - if ( code < 0 ) { - deflate->resume = &&lzhuf_distance; - return 0; - } - - /* Process extra bits */ - extra = code; - bits = ( extra / 2 ); - if ( bits ) - bits--; - deflate->extra_bits = bits; - deflate->dup_distance = deflate_distance_base[extra]; - } - - lzhuf_distance_extra: { - int extra; - size_t dup_len; - size_t dup_distance; - - /* Extract extra bits */ - extra = deflate_extract ( deflate, in, deflate->extra_bits ); - if ( extra < 0 ) { - deflate->resume = &&lzhuf_distance_extra; - return 0; - } - - /* Update duplicate distance */ - dup_distance = ( deflate->dup_distance + extra ); - dup_len = deflate->dup_len; - DBGCP ( deflate, "DEFLATE %p duplicate length %zd distance " - "%zd\n", deflate, dup_len, dup_distance ); - - /* Sanity check */ - if ( dup_distance > out->offset ) { - DBGC ( deflate, "DEFLATE %p bad distance %zd (max " - "%zd)\n", deflate, dup_distance, out->offset ); - return -EINVAL; - } - - /* Copy data, allowing for overlap */ - deflate_copy ( out, out->data, ( out->offset - dup_distance ), - dup_len ); - - /* Process next literal/length symbol */ - goto lzhuf_litlen; - } - - block_done: { - - DBGCP ( deflate, "DEFLATE %p end of block\n", deflate ); - - /* If this was not the final block, process next block header */ - if ( ! ( deflate->header & ( 1 << DEFLATE_HEADER_BFINAL_BIT ) )) - goto block_header; - - /* Otherwise, process footer (if any) */ - switch ( deflate->format ) { - case DEFLATE_RAW: goto finished; - case DEFLATE_ZLIB: goto zlib_footer; - default: assert ( 0 ); - } - } - - zlib_footer: { - - /* Discard any bits up to the next byte boundary */ - deflate_discard_to_byte ( deflate ); - } - - zlib_adler32: { - int excess; - - /* Accumulate the 32 bits of checksum. We don't check - * the value, stop processing immediately afterwards, - * and so don't have to worry about the nasty corner - * cases involved in calling deflate_extract() to - * obtain a full 32 bits. - */ - excess = deflate_accumulate ( deflate, in, ZLIB_ADLER32_BITS ); - if ( excess < 0 ) { - deflate->resume = &&zlib_adler32; - return 0; - } - - /* Finish processing */ - goto finished; - } - - finished: { - /* Mark as finished and terminate */ - DBGCP ( deflate, "DEFLATE %p finished\n", deflate ); - deflate->resume = NULL; - return 0; - } -} - -/** - * Initialise decompressor - * - * @v deflate Decompressor - * @v format Compression format code - */ -void deflate_init ( struct deflate *deflate, enum deflate_format format ) { - static int global_init_done; - uint8_t i; - uint8_t bit; - uint8_t byte; - unsigned int base; - unsigned int bits; - - /* Perform global initialisation if required */ - if ( ! global_init_done ) { - - /* Initialise byte reversal table */ - for ( i = 255 ; i ; i-- ) { - for ( bit = 1, byte = 0 ; bit ; bit <<= 1 ) { - byte <<= 1; - if ( i & bit ) - byte |= 1; - } - deflate_reverse[i] = byte; - } - - /* Initialise literal/length extra bits table */ - base = 3; - for ( i = 0 ; i < 28 ; i++ ) { - bits = ( i / 4 ); - if ( bits ) - bits--; - deflate_litlen_base[i] = base; - base += ( 1 << bits ); - } - assert ( base == 259 ); /* sic */ - - /* Initialise distance extra bits table */ - base = 1; - for ( i = 0 ; i < 30 ; i++ ) { - bits = ( i / 2 ); - if ( bits ) - bits--; - deflate_distance_base[i] = base; - base += ( 1 << bits ); - } - assert ( base == 32769 ); - - /* Record global initialisation as complete */ - global_init_done = 1; - } - - /* Initialise structure */ - memset ( deflate, 0, sizeof ( *deflate ) ); - deflate->format = format; -} diff --git a/qemu/roms/ipxe/src/crypto/drbg.c b/qemu/roms/ipxe/src/crypto/drbg.c deleted file mode 100644 index 5c8b5e612..000000000 --- a/qemu/roms/ipxe/src/crypto/drbg.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * DRBG mechanism - * - * This mechanism is designed to comply with ANS X9.82 Part 3-2007 - * Section 9. This standard is not freely available, but most of the - * text appears to be shared with NIST SP 800-90, which can be - * downloaded from - * - * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf - * - * Where possible, references are given to both documents. In the - * case of any disagreement, ANS X9.82 takes priority over NIST SP - * 800-90. (In particular, note that some algorithms that are - * Approved by NIST SP 800-90 are not Approved by ANS X9.82.) - */ - -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/entropy.h> -#include <ipxe/drbg.h> - -/** - * Instantiate DRBG - * - * @v state Algorithm state to be initialised - * @v personal Personalisation string - * @v personal_len Length of personalisation string - * @ret rc Return status code - * - * This is the Instantiate_function defined in ANS X9.82 Part 3-2007 - * Section 9.2 (NIST SP 800-90 Section 9.1). - * - * Only a single security strength is supported, and prediction - * resistance is always enabled. The nonce is accounted for by - * increasing the entropy input, as per ANS X9.82 Part 3-2007 Section - * 8.4.2 (NIST SP 800-90 Section 8.6.7). - */ -int drbg_instantiate ( struct drbg_state *state, const void *personal, - size_t personal_len ) { - unsigned int entropy_bits = ( ( 3 * DRBG_SECURITY_STRENGTH + 1 ) / 2 ); - size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES; - size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES; - uint8_t data[max_len]; - int len; - int rc; - - DBGC ( state, "DRBG %p instantiate\n", state ); - - /* Sanity checks */ - assert ( state != NULL ); - - /* 1. If requested_instantiation_security_strength > - * highest_supported_security_strength, then return an - * ERROR_FLAG - */ - if ( DRBG_SECURITY_STRENGTH > DRBG_MAX_SECURITY_STRENGTH ) { - DBGC ( state, "DRBG %p cannot support security strength %d\n", - state, DRBG_SECURITY_STRENGTH ); - return -ENOTSUP; - } - - /* 2. If prediction_resistance_flag is set, and prediction - * resistance is not supported, then return an ERROR_FLAG - * - * (Nothing to do since prediction resistance is always - * supported.) - */ - - /* 3. If the length of the personalization_string > - * max_personalization_string_length, return an ERROR_FLAG - */ - if ( personal_len > DRBG_MAX_PERSONAL_LEN_BYTES ) { - DBGC ( state, "DRBG %p personalisation string too long (%zd " - "bytes)\n", state, personal_len ); - return -ERANGE; - } - - /* 4. Set security_strength to the nearest security strength - * greater than or equal to - * requested_instantiation_security_strength. - * - * (Nothing to do since we support only a single security - * strength.) - */ - - /* 5. Using the security_strength, select appropriate DRBG - * mechanism parameters. - * - * (Nothing to do since we support only a single security - * strength.) - */ - - /* 6. ( status, entropy_input ) = Get_entropy_input ( - * security_strength, min_length, max_length, - * prediction_resistance_request ) - * 7. If an ERROR is returned in step 6, return a - * CATASTROPHIC_ERROR_FLAG. - * 8. Obtain a nonce. - */ - len = get_entropy_input ( entropy_bits, data, min_len, - sizeof ( data ) ); - if ( len < 0 ) { - rc = len; - DBGC ( state, "DRBG %p could not get entropy input: %s\n", - state, strerror ( rc ) ); - return rc; - } - assert ( len >= ( int ) min_len ); - assert ( len <= ( int ) sizeof ( data ) ); - - /* 9. initial_working_state = Instantiate_algorithm ( - * entropy_input, nonce, personalization_string ). - */ - drbg_instantiate_algorithm ( state, data, len, personal, personal_len ); - - /* 10. Get a state_handle for a currently empty state. If an - * empty internal state cannot be found, return an - * ERROR_FLAG. - * 11. Set the internal state indicated by state_handle to - * the initial values for the internal state (i.e. set - * the working_state to the values returned as - * initial_working_state in step 9 and any other values - * required for the working_state, and set the - * administrative information to the appropriate values. - * - * (Almost nothing to do since the memory to hold the state - * was passed in by the caller and has already been updated - * in-situ.) - */ - state->reseed_required = 0; - state->valid = 1; - - /* 12. Return SUCCESS and state_handle. */ - return 0; -} - -/** - * Reseed DRBG - * - * @v state Algorithm state - * @v additional Additional input - * @v additional_len Length of additional input - * @ret rc Return status code - * - * This is the Reseed_function defined in ANS X9.82 Part 3-2007 - * Section 9.3 (NIST SP 800-90 Section 9.2). - * - * Prediction resistance is always enabled. - */ -int drbg_reseed ( struct drbg_state *state, const void *additional, - size_t additional_len ) { - unsigned int entropy_bits = DRBG_SECURITY_STRENGTH; - size_t min_len = DRBG_MIN_ENTROPY_LEN_BYTES; - size_t max_len = DRBG_MAX_ENTROPY_LEN_BYTES; - uint8_t data[max_len]; - int len; - int rc; - - DBGC ( state, "DRBG %p reseed\n", state ); - - /* Sanity checks */ - assert ( state != NULL ); - - /* 1. Using state_handle, obtain the current internal state. - * If state_handle indicates an invalid or empty internal - * state, return an ERROR_FLAG. - * - * (Almost nothing to do since the memory holding the internal - * state was passed in by the caller.) - */ - if ( ! state->valid ) { - DBGC ( state, "DRBG %p not valid\n", state ); - return -EINVAL; - } - - /* 2. If prediction_resistance_request is set, and - * prediction_resistance_flag is not set, then return an - * ERROR_FLAG. - * - * (Nothing to do since prediction resistance is always - * supported.) - */ - - /* 3. If the length of the additional_input > - * max_additional_input_length, return an ERROR_FLAG. - */ - if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) { - DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n", - state, additional_len ); - return -ERANGE; - } - - /* 4. ( status, entropy_input ) = Get_entropy_input ( - * security_strength, min_length, max_length, - * prediction_resistance_request ). - * - * 5. If an ERROR is returned in step 4, return a - * CATASTROPHIC_ERROR_FLAG. - */ - len = get_entropy_input ( entropy_bits, data, min_len, - sizeof ( data ) ); - if ( len < 0 ) { - rc = len; - DBGC ( state, "DRBG %p could not get entropy input: %s\n", - state, strerror ( rc ) ); - return rc; - } - - /* 6. new_working_state = Reseed_algorithm ( working_state, - * entropy_input, additional_input ). - */ - drbg_reseed_algorithm ( state, data, len, additional, additional_len ); - - /* 7. Replace the working_state in the internal state - * indicated by state_handle with the values of - * new_working_state obtained in step 6. - * - * (Nothing to do since the state has already been updated in-situ.) - */ - - /* 8. Return SUCCESS. */ - return 0; -} - -/** - * Generate pseudorandom bits using DRBG - * - * @v state Algorithm state - * @v additional Additional input - * @v additional_len Length of additional input - * @v prediction_resist Prediction resistance is required - * @v data Output buffer - * @v len Length of output buffer - * @ret rc Return status code - * - * This is the Generate_function defined in ANS X9.82 Part 3-2007 - * Section 9.4 (NIST SP 800-90 Section 9.3). - * - * Requests must be for an integral number of bytes. Only a single - * security strength is supported. Prediction resistance is supported - * if requested. - */ -int drbg_generate ( struct drbg_state *state, const void *additional, - size_t additional_len, int prediction_resist, - void *data, size_t len ) { - int rc; - - DBGC ( state, "DRBG %p generate\n", state ); - - /* Sanity checks */ - assert ( state != NULL ); - assert ( data != NULL ); - - /* 1. Using state_handle, obtain the current internal state - * for the instantiation. If state_handle indicates an - * invalid or empty internal state, then return an ERROR_FLAG. - * - * (Almost nothing to do since the memory holding the internal - * state was passed in by the caller.) - */ - if ( ! state->valid ) { - DBGC ( state, "DRBG %p not valid\n", state ); - return -EINVAL; - } - - /* 2. If requested_number_of_bits > - * max_number_of_bits_per_request, then return an - * ERROR_FLAG. - */ - if ( len > DRBG_MAX_GENERATED_LEN_BYTES ) { - DBGC ( state, "DRBG %p request too long (%zd bytes)\n", - state, len ); - return -ERANGE; - } - - /* 3. If requested_security_strength > the security_strength - * indicated in the internal state, then return an - * ERROR_FLAG. - * - * (Nothing to do since only a single security strength is - * supported.) - */ - - /* 4. If the length of the additional_input > - * max_additional_input_length, then return an ERROR_FLAG. - */ - if ( additional_len > DRBG_MAX_ADDITIONAL_LEN_BYTES ) { - DBGC ( state, "DRBG %p additional input too long (%zd bytes)\n", - state, additional_len ); - return -ERANGE; - } - - /* 5. If prediction_resistance_request is set, and - * prediction_resistance_flag is not set, then return an - * ERROR_FLAG. - * - * (Nothing to do since prediction resistance is always - * supported.) - */ - - /* 6. Clear the reseed_required_flag. */ - state->reseed_required = 0; - - step_7: - /* 7. If reseed_required_flag is set, or if - * prediction_resistance_request is set, then - */ - if ( state->reseed_required || prediction_resist ) { - - /* 7.1 status = Reseed_function ( state_handle, - * prediction_resistance_request, - * additional_input ) - * 7.2 If status indicates an ERROR, then return - * status. - */ - if ( ( rc = drbg_reseed ( state, additional, - additional_len ) ) != 0 ) { - DBGC ( state, "DRBG %p could not reseed: %s\n", - state, strerror ( rc ) ); - return rc; - } - - /* 7.3 Using state_handle, obtain the new internal - * state. - * - * (Nothing to do since the internal state has been - * updated in-situ.) - */ - - /* 7.4 additional_input = the Null string. */ - additional = NULL; - additional_len = 0; - - /* 7.5 Clear the reseed_required_flag. */ - state->reseed_required = 0; - } - - /* 8. ( status, pseudorandom_bits, new_working_state ) = - * Generate_algorithm ( working_state, - * requested_number_of_bits, additional_input ). - */ - rc = drbg_generate_algorithm ( state, additional, additional_len, - data, len ); - - /* 9. If status indicates that a reseed is required before - * the requested bits can be generated, then - */ - if ( rc != 0 ) { - - /* 9.1 Set the reseed_required_flag. */ - state->reseed_required = 1; - - /* 9.2 If the prediction_resistance_flag is set, then - * set the prediction_resistance_request - * indication. - */ - prediction_resist = 1; - - /* 9.3 Go to step 7. */ - goto step_7; - } - - /* 10. Replace the old working_state in the internal state - * indicated by state_handle with the values of - * new_working_state. - * - * (Nothing to do since the working state has already been - * updated in-situ.) - */ - - /* 11. Return SUCCESS and pseudorandom_bits. */ - return 0; -} - -/** - * Uninstantiate DRBG - * - * @v state Algorithm state - * - * This is the Uninstantiate_function defined in ANS X9.82 Part 3-2007 - * Section 9.5 (NIST SP 800-90 Section 9.4). - */ -void drbg_uninstantiate ( struct drbg_state *state ) { - - DBGC ( state, "DRBG %p uninstantiate\n", state ); - - /* Sanity checks */ - assert ( state != NULL ); - - /* 1. If state_handle indicates an invalid state, then return - * an ERROR_FLAG. - * - * (Nothing to do since the memory holding the internal state - * was passed in by the caller.) - */ - - /* 2. Erase the contents of the internal state indicated by - * state_handle. - */ - memset ( state, 0, sizeof ( *state ) ); - - /* 3. Return SUCCESS. */ -} diff --git a/qemu/roms/ipxe/src/crypto/ecb.c b/qemu/roms/ipxe/src/crypto/ecb.c deleted file mode 100644 index 3c9cf340c..000000000 --- a/qemu/roms/ipxe/src/crypto/ecb.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <assert.h> -#include <ipxe/crypto.h> -#include <ipxe/ecb.h> - -/** @file - * - * Electronic codebook (ECB) - * - */ - -/** - * Encrypt data - * - * @v ctx Context - * @v src Data to encrypt - * @v dst Buffer for encrypted data - * @v len Length of data - * @v raw_cipher Underlying cipher algorithm - */ -void ecb_encrypt ( void *ctx, const void *src, void *dst, size_t len, - struct cipher_algorithm *raw_cipher ) { - size_t blocksize = raw_cipher->blocksize; - - assert ( ( len % blocksize ) == 0 ); - - while ( len ) { - cipher_encrypt ( raw_cipher, ctx, src, dst, blocksize ); - dst += blocksize; - src += blocksize; - len -= blocksize; - } -} - -/** - * Decrypt data - * - * @v ctx Context - * @v src Data to decrypt - * @v dst Buffer for decrypted data - * @v len Length of data - * @v raw_cipher Underlying cipher algorithm - */ -void ecb_decrypt ( void *ctx, const void *src, void *dst, size_t len, - struct cipher_algorithm *raw_cipher ) { - size_t blocksize = raw_cipher->blocksize; - - assert ( ( len % blocksize ) == 0 ); - - while ( len ) { - cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize ); - dst += blocksize; - src += blocksize; - len -= blocksize; - } -} diff --git a/qemu/roms/ipxe/src/crypto/entropy.c b/qemu/roms/ipxe/src/crypto/entropy.c deleted file mode 100644 index 5acbc0258..000000000 --- a/qemu/roms/ipxe/src/crypto/entropy.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Entropy source - * - * This algorithm is designed to comply with ANS X9.82 Part 4 (April - * 2011 Draft) Section 13.3. This standard is unfortunately not - * freely available. - */ - -#include <stdint.h> -#include <assert.h> -#include <string.h> -#include <errno.h> -#include <ipxe/crypto.h> -#include <ipxe/hash_df.h> -#include <ipxe/entropy.h> - -/* Disambiguate the various error causes */ -#define EPIPE_REPETITION_COUNT_TEST \ - __einfo_error ( EINFO_EPIPE_REPETITION_COUNT_TEST ) -#define EINFO_EPIPE_REPETITION_COUNT_TEST \ - __einfo_uniqify ( EINFO_EPIPE, 0x01, "Repetition count test failed" ) -#define EPIPE_ADAPTIVE_PROPORTION_TEST \ - __einfo_error ( EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST ) -#define EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST \ - __einfo_uniqify ( EINFO_EPIPE, 0x02, "Adaptive proportion test failed" ) - -/** - * Calculate cutoff value for the repetition count test - * - * @ret cutoff Cutoff value - * - * This is the cutoff value for the Repetition Count Test defined in - * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.2. - */ -static inline __attribute__ (( always_inline )) unsigned int -repetition_count_cutoff ( void ) { - double max_repetitions; - unsigned int cutoff; - - /* The cutoff formula for the repetition test is: - * - * C = ( 1 + ( -log2(W) / H_min ) ) - * - * where W is set at 2^(-30) (in ANS X9.82 Part 2 (October - * 2011 Draft) Section 8.5.2.1.3.1). - */ - max_repetitions = ( 1 + ( 30 / min_entropy_per_sample() ) ); - - /* Round up to a whole number of repetitions. We don't have - * the ceil() function available, so do the rounding by hand. - */ - cutoff = max_repetitions; - if ( cutoff < max_repetitions ) - cutoff++; - linker_assert ( ( cutoff >= max_repetitions ), rounding_error ); - - /* Floating-point operations are not allowed in iPXE since we - * never set up a suitable environment. Abort the build - * unless the calculated number of repetitions is a - * compile-time constant. - */ - linker_assert ( __builtin_constant_p ( cutoff ), - repetition_count_cutoff_not_constant ); - - return cutoff; -} - -/** - * Perform repetition count test - * - * @v sample Noise sample - * @ret rc Return status code - * - * This is the Repetition Count Test defined in ANS X9.82 Part 2 - * (October 2011 Draft) Section 8.5.2.1.2. - */ -static int repetition_count_test ( noise_sample_t sample ) { - static noise_sample_t most_recent_sample; - static unsigned int repetition_count = 0; - - /* A = the most recently seen sample value - * B = the number of times that value A has been seen in a row - * C = the cutoff value above which the repetition test should fail - */ - - /* 1. For each new sample processed: - * - * (Note that the test for "repetition_count > 0" ensures that - * the initial value of most_recent_sample is treated as being - * undefined.) - */ - if ( ( sample == most_recent_sample ) && ( repetition_count > 0 ) ) { - - /* a) If the new sample = A, then B is incremented by one. */ - repetition_count++; - - /* i. If B >= C, then an error condition is raised - * due to a failure of the test - */ - if ( repetition_count >= repetition_count_cutoff() ) - return -EPIPE_REPETITION_COUNT_TEST; - - } else { - - /* b) Else: - * i. A = new sample - */ - most_recent_sample = sample; - - /* ii. B = 1 */ - repetition_count = 1; - } - - return 0; -} - -/** - * Window size for the adaptive proportion test - * - * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.1 allows - * five possible window sizes: 16, 64, 256, 4096 and 65536. - * - * We expect to generate relatively few (<256) entropy samples during - * a typical iPXE run; the use of a large window size would mean that - * the test would never complete a single cycle. We use a window size - * of 64, which is the smallest window size that permits values of - * H_min down to one bit per sample. - */ -#define ADAPTIVE_PROPORTION_WINDOW_SIZE 64 - -/** - * Combine adaptive proportion test window size and min-entropy - * - * @v n N (window size) - * @v h H (min-entropy) - * @ret n_h (N,H) combined value - */ -#define APC_N_H( n, h ) ( ( (n) << 8 ) | (h) ) - -/** - * Define a row of the adaptive proportion cutoff table - * - * @v h H (min-entropy) - * @v c16 Cutoff for N=16 - * @v c64 Cutoff for N=64 - * @v c256 Cutoff for N=256 - * @v c4096 Cutoff for N=4096 - * @v c65536 Cutoff for N=65536 - */ -#define APC_TABLE_ROW( h, c16, c64, c256, c4096, c65536) \ - case APC_N_H ( 16, h ) : return c16; \ - case APC_N_H ( 64, h ) : return c64; \ - case APC_N_H ( 256, h ) : return c256; \ - case APC_N_H ( 4096, h ) : return c4096; \ - case APC_N_H ( 65536, h ) : return c65536; - -/** Value used to represent "N/A" in adaptive proportion cutoff table */ -#define APC_NA 0 - -/** - * Look up value in adaptive proportion test cutoff table - * - * @v n N (window size) - * @v h H (min-entropy) - * @ret cutoff Cutoff - * - * This is the table of cutoff values defined in ANS X9.82 Part 2 - * (October 2011 Draft) Section 8.5.2.1.3.1.2. - */ -static inline __attribute__ (( always_inline )) unsigned int -adaptive_proportion_cutoff_lookup ( unsigned int n, unsigned int h ) { - switch ( APC_N_H ( n, h ) ) { - APC_TABLE_ROW ( 1, APC_NA, 51, 168, 2240, 33537 ); - APC_TABLE_ROW ( 2, APC_NA, 35, 100, 1193, 17053 ); - APC_TABLE_ROW ( 3, 10, 24, 61, 643, 8705 ); - APC_TABLE_ROW ( 4, 8, 16, 38, 354, 4473 ); - APC_TABLE_ROW ( 5, 6, 12, 25, 200, 2321 ); - APC_TABLE_ROW ( 6, 5, 9, 17, 117, 1220 ); - APC_TABLE_ROW ( 7, 4, 7, 15, 71, 653 ); - APC_TABLE_ROW ( 8, 4, 5, 9, 45, 358 ); - APC_TABLE_ROW ( 9, 3, 4, 7, 30, 202 ); - APC_TABLE_ROW ( 10, 3, 4, 5, 21, 118 ); - APC_TABLE_ROW ( 11, 2, 3, 4, 15, 71 ); - APC_TABLE_ROW ( 12, 2, 3, 4, 11, 45 ); - APC_TABLE_ROW ( 13, 2, 2, 3, 9, 30 ); - APC_TABLE_ROW ( 14, 2, 2, 3, 7, 21 ); - APC_TABLE_ROW ( 15, 1, 2, 2, 6, 15 ); - APC_TABLE_ROW ( 16, 1, 2, 2, 5, 11 ); - APC_TABLE_ROW ( 17, 1, 1, 2, 4, 9 ); - APC_TABLE_ROW ( 18, 1, 1, 2, 4, 7 ); - APC_TABLE_ROW ( 19, 1, 1, 1, 3, 6 ); - APC_TABLE_ROW ( 20, 1, 1, 1, 3, 5 ); - default: - return APC_NA; - } -} - -/** - * Calculate cutoff value for the adaptive proportion test - * - * @ret cutoff Cutoff value - * - * This is the cutoff value for the Adaptive Proportion Test defined - * in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.2. - */ -static inline __attribute__ (( always_inline )) unsigned int -adaptive_proportion_cutoff ( void ) { - unsigned int h; - unsigned int n; - unsigned int cutoff; - - /* Look up cutoff value in cutoff table */ - n = ADAPTIVE_PROPORTION_WINDOW_SIZE; - h = min_entropy_per_sample(); - cutoff = adaptive_proportion_cutoff_lookup ( n, h ); - - /* Fail unless cutoff value is a build-time constant */ - linker_assert ( __builtin_constant_p ( cutoff ), - adaptive_proportion_cutoff_not_constant ); - - /* Fail if cutoff value is N/A */ - linker_assert ( ( cutoff != APC_NA ), - adaptive_proportion_cutoff_not_applicable ); - - return cutoff; -} - -/** - * Perform adaptive proportion test - * - * @v sample Noise sample - * @ret rc Return status code - * - * This is the Adaptive Proportion Test for the Most Common Value - * defined in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3. - */ -static int adaptive_proportion_test ( noise_sample_t sample ) { - static noise_sample_t current_counted_sample; - static unsigned int sample_count = ADAPTIVE_PROPORTION_WINDOW_SIZE; - static unsigned int repetition_count; - - /* A = the sample value currently being counted - * B = the number of samples examined in this run of the test so far - * N = the total number of samples that must be observed in - * one run of the test, also known as the "window size" of - * the test - * B = the current number of times that S (sic) has been seen - * in the W (sic) samples examined so far - * C = the cutoff value above which the repetition test should fail - * W = the probability of a false positive: 2^-30 - */ - - /* 1. The entropy source draws the current sample from the - * noise source. - * - * (Nothing to do; we already have the current sample.) - */ - - /* 2. If S = N, then a new run of the test begins: */ - if ( sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) { - - /* a. A = the current sample */ - current_counted_sample = sample; - - /* b. S = 0 */ - sample_count = 0; - - /* c. B = 0 */ - repetition_count = 0; - - } else { - - /* Else: (the test is already running) - * a. S = S + 1 - */ - sample_count++; - - /* b. If A = the current sample, then: */ - if ( sample == current_counted_sample ) { - - /* i. B = B + 1 */ - repetition_count++; - - /* ii. If S (sic) > C then raise an error - * condition, because the test has - * detected a failure - */ - if ( repetition_count > adaptive_proportion_cutoff() ) - return -EPIPE_ADAPTIVE_PROPORTION_TEST; - - } - } - - return 0; -} - -/** - * Get entropy sample - * - * @ret entropy Entropy sample - * @ret rc Return status code - * - * This is the GetEntropy function defined in ANS X9.82 Part 2 - * (October 2011 Draft) Section 6.5.1. - */ -static int get_entropy ( entropy_sample_t *entropy ) { - static int rc = 0; - noise_sample_t noise; - - /* Any failure is permanent */ - if ( rc != 0 ) - return rc; - - /* Get noise sample */ - if ( ( rc = get_noise ( &noise ) ) != 0 ) - return rc; - - /* Perform Repetition Count Test and Adaptive Proportion Test - * as mandated by ANS X9.82 Part 2 (October 2011 Draft) - * Section 8.5.2.1.1. - */ - if ( ( rc = repetition_count_test ( noise ) ) != 0 ) - return rc; - if ( ( rc = adaptive_proportion_test ( noise ) ) != 0 ) - return rc; - - /* We do not use any optional conditioning component */ - *entropy = noise; - - return 0; -} - -/** - * Calculate number of samples required for startup tests - * - * @ret num_samples Number of samples required - * - * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.5 requires - * that at least one full cycle of the continuous tests must be - * performed at start-up. - */ -static inline __attribute__ (( always_inline )) unsigned int -startup_test_count ( void ) { - unsigned int num_samples; - - /* At least max(N,C) samples shall be generated by the noise - * source for start-up testing. - */ - num_samples = repetition_count_cutoff(); - if ( num_samples < adaptive_proportion_cutoff() ) - num_samples = adaptive_proportion_cutoff(); - linker_assert ( __builtin_constant_p ( num_samples ), - startup_test_count_not_constant ); - - return num_samples; -} - -/** - * Create next nonce value - * - * @ret nonce Nonce - * - * This is the MakeNextNonce function defined in ANS X9.82 Part 4 - * (April 2011 Draft) Section 13.3.4.2. - */ -static uint32_t make_next_nonce ( void ) { - static uint32_t nonce; - - /* The simplest implementation of a nonce uses a large counter */ - nonce++; - - return nonce; -} - -/** - * Obtain entropy input temporary buffer - * - * @v num_samples Number of entropy samples - * @v tmp Temporary buffer - * @v tmp_len Length of temporary buffer - * @ret rc Return status code - * - * This is (part of) the implementation of the Get_entropy_input - * function (using an entropy source as the source of entropy input - * and condensing each entropy source output after each GetEntropy - * call) as defined in ANS X9.82 Part 4 (April 2011 Draft) Section - * 13.3.4.2. - * - * To minimise code size, the number of samples required is calculated - * at compilation time. - */ -int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp, - size_t tmp_len ) { - static unsigned int startup_tested = 0; - struct { - uint32_t nonce; - entropy_sample_t sample; - } __attribute__ (( packed )) data;; - uint8_t df_buf[tmp_len]; - unsigned int i; - int rc; - - /* Enable entropy gathering */ - if ( ( rc = entropy_enable() ) != 0 ) - return rc; - - /* Perform mandatory startup tests, if not yet performed */ - for ( ; startup_tested < startup_test_count() ; startup_tested++ ) { - if ( ( rc = get_entropy ( &data.sample ) ) != 0 ) - goto err_get_entropy; - } - - /* 3. entropy_total = 0 - * - * (Nothing to do; the number of entropy samples required has - * already been precalculated.) - */ - - /* 4. tmp = a fixed n-bit value, such as 0^n */ - memset ( tmp, 0, tmp_len ); - - /* 5. While ( entropy_total < min_entropy ) */ - while ( num_samples-- ) { - /* 5.1. ( status, entropy_bitstring, assessed_entropy ) - * = GetEntropy() - * 5.2. If status indicates an error, return ( status, Null ) - */ - if ( ( rc = get_entropy ( &data.sample ) ) != 0 ) - goto err_get_entropy; - - /* 5.3. nonce = MakeNextNonce() */ - data.nonce = make_next_nonce(); - - /* 5.4. tmp = tmp XOR - * df ( ( nonce || entropy_bitstring ), n ) - */ - hash_df ( &entropy_hash_df_algorithm, &data, sizeof ( data ), - df_buf, sizeof ( df_buf ) ); - for ( i = 0 ; i < tmp_len ; i++ ) - tmp[i] ^= df_buf[i]; - - /* 5.5. entropy_total = entropy_total + assessed_entropy - * - * (Nothing to do; the number of entropy samples - * required has already been precalculated.) - */ - } - - /* Disable entropy gathering */ - entropy_disable(); - - return 0; - - err_get_entropy: - entropy_disable(); - return rc; -} diff --git a/qemu/roms/ipxe/src/crypto/hash_df.c b/qemu/roms/ipxe/src/crypto/hash_df.c deleted file mode 100644 index c1417e683..000000000 --- a/qemu/roms/ipxe/src/crypto/hash_df.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Hash-based derivation function (Hash_df) - * - * This algorithm is designed to comply with ANS X9.82 Part 3-2007 - * Section 10.5.2. This standard is not freely available, but most of - * the text appears to be shared with NIST SP 800-90, which can be - * downloaded from - * - * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf - * - * Where possible, references are given to both documents. In the - * case of any disagreement, ANS X9.82 takes priority over NIST SP - * 800-90. (In particular, note that some algorithms that are - * Approved by NIST SP 800-90 are not Approved by ANS X9.82.) - */ - -#include <stdint.h> -#include <string.h> -#include <assert.h> -#include <byteswap.h> -#include <ipxe/crypto.h> -#include <ipxe/hash_df.h> - -/** - * Distribute entropy throughout a buffer - * - * @v hash Underlying hash algorithm - * @v input Input data - * @v input_len Length of input data, in bytes - * @v output Output buffer - * @v output_len Length of output buffer, in bytes - * - * This is the Hash_df function defined in ANS X9.82 Part 3-2007 - * Section 10.5.2 (NIST SP 800-90 Section 10.4.1). - * - * The number of bits requested is implicit in the length of the - * output buffer. Requests must be for an integral number of bytes. - * - * The output buffer is filled incrementally with each iteration of - * the central loop, rather than constructing an overall "temp" and - * then taking the leftmost(no_of_bits_to_return) bits. - * - * There is no way for the Hash_df function to fail. The returned - * status SUCCESS is implicit. - */ -void hash_df ( struct digest_algorithm *hash, const void *input, - size_t input_len, void *output, size_t output_len ) { - uint8_t context[hash->ctxsize]; - uint8_t digest[hash->digestsize]; - size_t frag_len; - struct { - uint8_t pad[3]; - uint8_t counter; - uint32_t no_of_bits_to_return; - } __attribute__ (( packed )) prefix; - void *temp; - size_t remaining; - - DBGC ( &hash_df, "HASH_DF input:\n" ); - DBGC_HDA ( &hash_df, 0, input, input_len ); - - /* Sanity checks */ - assert ( input != NULL ); - assert ( output != NULL ); - - /* 1. temp = the Null string - * 2. len = ceil ( no_of_bits_to_return / outlen ) - * - * (Nothing to do. We fill the output buffer incrementally, - * rather than constructing the complete "temp" in-memory. - * "len" is implicit in the number of iterations required to - * fill the output buffer, and so is not calculated - * explicitly.) - */ - - /* 3. counter = an 8-bit binary value representing the integer "1" */ - prefix.counter = 1; - - /* 4. For i = 1 to len do */ - for ( temp = output, remaining = output_len ; remaining > 0 ; ) { - - /* Comment: in step 5.1 (sic), no_of_bits_to_return is - * used as a 32-bit string. - * - * 4.1 temp = temp || Hash ( counter || no_of_bits_to_return - * || input_string ) - */ - prefix.no_of_bits_to_return = htonl ( output_len * 8 ); - digest_init ( hash, context ); - digest_update ( hash, context, &prefix.counter, - ( sizeof ( prefix ) - - offsetof ( typeof ( prefix ), counter ) ) ); - digest_update ( hash, context, input, input_len ); - digest_final ( hash, context, digest ); - - /* 4.2 counter = counter + 1 */ - prefix.counter++; - - /* 5. requested_bits = Leftmost ( no_of_bits_to_return ) - * of temp - * - * (We fill the output buffer incrementally.) - */ - frag_len = sizeof ( digest ); - if ( frag_len > remaining ) - frag_len = remaining; - memcpy ( temp, digest, frag_len ); - temp += frag_len; - remaining -= frag_len; - } - - /* 6. Return SUCCESS and requested_bits */ - DBGC ( &hash_df, "HASH_DF output:\n" ); - DBGC_HDA ( &hash_df, 0, output, output_len ); - return; -} diff --git a/qemu/roms/ipxe/src/crypto/hmac.c b/qemu/roms/ipxe/src/crypto/hmac.c deleted file mode 100644 index 95a46195c..000000000 --- a/qemu/roms/ipxe/src/crypto/hmac.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** - * @file - * - * Keyed-Hashing for Message Authentication - */ - -#include <string.h> -#include <assert.h> -#include <ipxe/crypto.h> -#include <ipxe/hmac.h> - -/** - * Reduce HMAC key length - * - * @v digest Digest algorithm to use - * @v digest_ctx Digest context - * @v key Key - * @v key_len Length of key - */ -static void hmac_reduce_key ( struct digest_algorithm *digest, - void *key, size_t *key_len ) { - uint8_t digest_ctx[digest->ctxsize]; - - digest_init ( digest, digest_ctx ); - digest_update ( digest, digest_ctx, key, *key_len ); - digest_final ( digest, digest_ctx, key ); - *key_len = digest->digestsize; -} - -/** - * Initialise HMAC - * - * @v digest Digest algorithm to use - * @v digest_ctx Digest context - * @v key Key - * @v key_len Length of key - * - * The length of the key should be less than the block size of the - * digest algorithm being used. (If the key length is greater, it - * will be replaced with its own digest, and key_len will be updated - * accordingly). - */ -void hmac_init ( struct digest_algorithm *digest, void *digest_ctx, - void *key, size_t *key_len ) { - unsigned char k_ipad[digest->blocksize]; - unsigned int i; - - /* Reduce key if necessary */ - if ( *key_len > sizeof ( k_ipad ) ) - hmac_reduce_key ( digest, key, key_len ); - - /* Construct input pad */ - memset ( k_ipad, 0, sizeof ( k_ipad ) ); - memcpy ( k_ipad, key, *key_len ); - for ( i = 0 ; i < sizeof ( k_ipad ) ; i++ ) { - k_ipad[i] ^= 0x36; - } - - /* Start inner hash */ - digest_init ( digest, digest_ctx ); - digest_update ( digest, digest_ctx, k_ipad, sizeof ( k_ipad ) ); -} - -/** - * Finalise HMAC - * - * @v digest Digest algorithm to use - * @v digest_ctx Digest context - * @v key Key - * @v key_len Length of key - * @v hmac HMAC digest to fill in - * - * The length of the key should be less than the block size of the - * digest algorithm being used. (If the key length is greater, it - * will be replaced with its own digest, and key_len will be updated - * accordingly). - */ -void hmac_final ( struct digest_algorithm *digest, void *digest_ctx, - void *key, size_t *key_len, void *hmac ) { - unsigned char k_opad[digest->blocksize]; - unsigned int i; - - /* Reduce key if necessary */ - if ( *key_len > sizeof ( k_opad ) ) - hmac_reduce_key ( digest, key, key_len ); - - /* Construct output pad */ - memset ( k_opad, 0, sizeof ( k_opad ) ); - memcpy ( k_opad, key, *key_len ); - for ( i = 0 ; i < sizeof ( k_opad ) ; i++ ) { - k_opad[i] ^= 0x5c; - } - - /* Finish inner hash */ - digest_final ( digest, digest_ctx, hmac ); - - /* Perform outer hash */ - digest_init ( digest, digest_ctx ); - digest_update ( digest, digest_ctx, k_opad, sizeof ( k_opad ) ); - digest_update ( digest, digest_ctx, hmac, digest->digestsize ); - digest_final ( digest, digest_ctx, hmac ); -} diff --git a/qemu/roms/ipxe/src/crypto/hmac_drbg.c b/qemu/roms/ipxe/src/crypto/hmac_drbg.c deleted file mode 100644 index 6c1d5deb2..000000000 --- a/qemu/roms/ipxe/src/crypto/hmac_drbg.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * HMAC_DRBG algorithm - * - * This algorithm is designed to comply with ANS X9.82 Part 3-2007 - * Section 10.2.2.2. This standard is not freely available, but most - * of the text appears to be shared with NIST SP 800-90, which can be - * downloaded from - * - * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf - * - * Where possible, references are given to both documents. In the - * case of any disagreement, ANS X9.82 takes priority over NIST SP - * 800-90. (In particular, note that some algorithms that are - * Approved by NIST SP 800-90 are not Approved by ANS X9.82.) - */ - -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/crypto.h> -#include <ipxe/hmac.h> -#include <ipxe/hmac_drbg.h> - -/** - * Update the HMAC_DRBG key - * - * @v hash Underlying hash algorithm - * @v state HMAC_DRBG internal state - * @v data Provided data - * @v len Length of provided data - * @v single Single byte used in concatenation - * - * This function carries out the operation - * - * K = HMAC ( K, V || single || provided_data ) - * - * as used by hmac_drbg_update() - */ -static void hmac_drbg_update_key ( struct digest_algorithm *hash, - struct hmac_drbg_state *state, - const void *data, size_t len, - const uint8_t single ) { - uint8_t context[ hash->ctxsize ]; - size_t out_len = hash->digestsize; - - DBGC ( state, "HMAC_DRBG_%s %p provided data :\n", hash->name, state ); - DBGC_HDA ( state, 0, data, len ); - - /* Sanity checks */ - assert ( hash != NULL ); - assert ( state != NULL ); - assert ( ( data != NULL ) || ( len == 0 ) ); - assert ( ( single == 0x00 ) || ( single == 0x01 ) ); - - /* K = HMAC ( K, V || single || provided_data ) */ - hmac_init ( hash, context, state->key, &out_len ); - assert ( out_len == hash->digestsize ); - hmac_update ( hash, context, state->value, out_len ); - hmac_update ( hash, context, &single, sizeof ( single ) ); - hmac_update ( hash, context, data, len ); - hmac_final ( hash, context, state->key, &out_len, state->key ); - assert ( out_len == hash->digestsize ); - - DBGC ( state, "HMAC_DRBG_%s %p K = HMAC ( K, V || %#02x || " - "provided_data ) :\n", hash->name, state, single ); - DBGC_HDA ( state, 0, state->key, out_len ); -} - -/** - * Update the HMAC_DRBG value - * - * @v hash Underlying hash algorithm - * @v state HMAC_DRBG internal state - * @v data Provided data - * @v len Length of provided data - * @v single Single byte used in concatenation - * - * This function carries out the operation - * - * V = HMAC ( K, V ) - * - * as used by hmac_drbg_update() and hmac_drbg_generate() - */ -static void hmac_drbg_update_value ( struct digest_algorithm *hash, - struct hmac_drbg_state *state ) { - uint8_t context[ hash->ctxsize ]; - size_t out_len = hash->digestsize; - - /* Sanity checks */ - assert ( hash != NULL ); - assert ( state != NULL ); - - /* V = HMAC ( K, V ) */ - hmac_init ( hash, context, state->key, &out_len ); - assert ( out_len == hash->digestsize ); - hmac_update ( hash, context, state->value, out_len ); - hmac_final ( hash, context, state->key, &out_len, state->value ); - assert ( out_len == hash->digestsize ); - - DBGC ( state, "HMAC_DRBG_%s %p V = HMAC ( K, V ) :\n", - hash->name, state ); - DBGC_HDA ( state, 0, state->value, out_len ); -} - -/** - * Update HMAC_DRBG internal state - * - * @v hash Underlying hash algorithm - * @v state HMAC_DRBG internal state - * @v data Provided data - * @v len Length of provided data - * - * This is the HMAC_DRBG_Update function defined in ANS X9.82 Part - * 3-2007 Section 10.2.2.2.2 (NIST SP 800-90 Section 10.1.2.2). - * - * The key and value are updated in-place within the HMAC_DRBG - * internal state. - */ -static void hmac_drbg_update ( struct digest_algorithm *hash, - struct hmac_drbg_state *state, - const void *data, size_t len ) { - - DBGC ( state, "HMAC_DRBG_%s %p update\n", hash->name, state ); - - /* Sanity checks */ - assert ( hash != NULL ); - assert ( state != NULL ); - assert ( ( data != NULL ) || ( len == 0 ) ); - - /* 1. K = HMAC ( K, V || 0x00 || provided_data ) */ - hmac_drbg_update_key ( hash, state, data, len, 0x00 ); - - /* 2. V = HMAC ( K, V ) */ - hmac_drbg_update_value ( hash, state ); - - /* 3. If ( provided_data = Null ), then return K and V */ - if ( ! len ) - return; - - /* 4. K = HMAC ( K, V || 0x01 || provided_data ) */ - hmac_drbg_update_key ( hash, state, data, len, 0x01 ); - - /* 5. V = HMAC ( K, V ) */ - hmac_drbg_update_value ( hash, state ); - - /* 6. Return K and V */ -} - -/** - * Instantiate HMAC_DRBG - * - * @v hash Underlying hash algorithm - * @v state HMAC_DRBG internal state to be initialised - * @v entropy Entropy input - * @v entropy_len Length of entropy input - * @v personal Personalisation string - * @v personal_len Length of personalisation string - * - * This is the HMAC_DRBG_Instantiate_algorithm function defined in ANS - * X9.82 Part 3-2007 Section 10.2.2.2.3 (NIST SP 800-90 Section - * 10.1.2.3). - * - * The nonce must be included within the entropy input (i.e. the - * entropy input must contain at least 3/2 * security_strength bits of - * entropy, as per ANS X9.82 Part 3-2007 Section 8.4.2 (NIST SP 800-90 - * Section 8.6.7). - * - * The key, value and reseed counter are updated in-place within the - * HMAC_DRBG internal state. - */ -void hmac_drbg_instantiate ( struct digest_algorithm *hash, - struct hmac_drbg_state *state, - const void *entropy, size_t entropy_len, - const void *personal, size_t personal_len ){ - size_t out_len = hash->digestsize; - - DBGC ( state, "HMAC_DRBG_%s %p instantiate\n", hash->name, state ); - - /* Sanity checks */ - assert ( hash != NULL ); - assert ( state != NULL ); - assert ( entropy != NULL ); - assert ( ( personal != NULL ) || ( personal_len == 0 ) ); - - /* 1. seed_material = entropy_input || nonce || - * personalisation_string - */ - - /* 2. Key = 0x00 00..00 */ - memset ( state->key, 0x00, out_len ); - - /* 3. V = 0x01 01...01 */ - memset ( state->value, 0x01, out_len ); - - /* 4. ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V ) - * 5. reseed_counter = 1 - * 6. Return V, Key and reseed_counter as the - * initial_working_state - */ - hmac_drbg_reseed ( hash, state, entropy, entropy_len, - personal, personal_len ); -} - -/** - * Reseed HMAC_DRBG - * - * @v hash Underlying hash algorithm - * @v state HMAC_DRBG internal state - * @v entropy Entropy input - * @v entropy_len Length of entropy input - * @v additional Additional input - * @v additional_len Length of additional input - * - * This is the HMAC_DRBG_Reseed_algorithm function defined in ANS X9.82 - * Part 3-2007 Section 10.2.2.2.4 (NIST SP 800-90 Section 10.1.2.4). - * - * The key, value and reseed counter are updated in-place within the - * HMAC_DRBG internal state. - */ -void hmac_drbg_reseed ( struct digest_algorithm *hash, - struct hmac_drbg_state *state, - const void *entropy, size_t entropy_len, - const void *additional, size_t additional_len ) { - uint8_t seed_material[ entropy_len + additional_len ]; - - DBGC ( state, "HMAC_DRBG_%s %p (re)seed\n", hash->name, state ); - - /* Sanity checks */ - assert ( hash != NULL ); - assert ( state != NULL ); - assert ( entropy != NULL ); - assert ( ( additional != NULL ) || ( additional_len == 0 ) ); - - /* 1. seed_material = entropy_input || additional_input */ - memcpy ( seed_material, entropy, entropy_len ); - memcpy ( ( seed_material + entropy_len ), additional, additional_len ); - DBGC ( state, "HMAC_DRBG_%s %p seed material :\n", hash->name, state ); - DBGC_HDA ( state, 0, seed_material, sizeof ( seed_material ) ); - - /* 2. ( Key, V ) = HMAC_DBRG_Update ( seed_material, Key, V ) */ - hmac_drbg_update ( hash, state, seed_material, - sizeof ( seed_material ) ); - - /* 3. reseed_counter = 1 */ - state->reseed_counter = 1; - - /* 4. Return V, Key and reseed_counter as the new_working_state */ -} - -/** - * Generate pseudorandom bits using HMAC_DRBG - * - * @v hash Underlying hash algorithm - * @v state HMAC_DRBG internal state - * @v additional Additional input - * @v additional_len Length of additional input - * @v data Output buffer - * @v len Length of output buffer - * @ret rc Return status code - * - * This is the HMAC_DRBG_Generate_algorithm function defined in ANS X9.82 - * Part 3-2007 Section 10.2.2.2.5 (NIST SP 800-90 Section 10.1.2.5). - * - * Requests must be for an integral number of bytes. - * - * The key, value and reseed counter are updated in-place within the - * HMAC_DRBG internal state. - * - * Note that the only permitted error is "reseed required". - */ -int hmac_drbg_generate ( struct digest_algorithm *hash, - struct hmac_drbg_state *state, - const void *additional, size_t additional_len, - void *data, size_t len ) { - size_t out_len = hash->digestsize; - void *orig_data = data; - size_t orig_len = len; - size_t frag_len; - - DBGC ( state, "HMAC_DRBG_%s %p generate\n", hash->name, state ); - - /* Sanity checks */ - assert ( hash != NULL ); - assert ( state != NULL ); - assert ( data != NULL ); - assert ( ( additional != NULL ) || ( additional_len == 0 ) ); - - /* 1. If reseed_counter > reseed_interval, then return an - * indication that a reseed is required - */ - if ( state->reseed_counter > HMAC_DRBG_RESEED_INTERVAL ) { - DBGC ( state, "HMAC_DRBG_%s %p reseed interval exceeded\n", - hash->name, state ); - return -ESTALE; - } - - /* 2. If additional_input != Null, then - * ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V ) - */ - if ( additional_len ) - hmac_drbg_update ( hash, state, additional, additional_len ); - - /* 3. temp = Null - * 4. While ( len ( temp ) < requested_number_of_bits ) do: - */ - while ( len ) { - - /* 4.1 V = HMAC ( Key, V ) */ - hmac_drbg_update_value ( hash, state ); - - /* 4.2. temp = temp || V - * 5. returned_bits = Leftmost requested_number_of_bits - * of temp - */ - frag_len = len; - if ( frag_len > out_len ) - frag_len = out_len; - memcpy ( data, state->value, frag_len ); - data += frag_len; - len -= frag_len; - } - - /* 6. ( Key, V ) = HMAC_DRBG_Update ( additional_input, Key, V ) */ - hmac_drbg_update ( hash, state, additional, additional_len ); - - /* 7. reseed_counter = reseed_counter + 1 */ - state->reseed_counter++; - - DBGC ( state, "HMAC_DRBG_%s %p generated :\n", hash->name, state ); - DBGC_HDA ( state, 0, orig_data, orig_len ); - - /* 8. Return SUCCESS, returned_bits, and the new values of - * Key, V and reseed_counter as the new_working_state - */ - return 0; -} diff --git a/qemu/roms/ipxe/src/crypto/md5.c b/qemu/roms/ipxe/src/crypto/md5.c deleted file mode 100644 index f9738b0ac..000000000 --- a/qemu/roms/ipxe/src/crypto/md5.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * MD5 algorithm - * - */ - -#include <stdint.h> -#include <string.h> -#include <byteswap.h> -#include <assert.h> -#include <ipxe/rotate.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/md5.h> - -/** MD5 variables */ -struct md5_variables { - /* This layout matches that of struct md5_digest_data, - * allowing for efficient endianness-conversion, - */ - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - uint32_t w[16]; -} __attribute__ (( packed )); - -/** MD5 constants */ -static const uint32_t k[64] = { - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, - 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, - 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, - 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, - 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, - 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 -}; - -/** MD5 shift amounts */ -static const uint8_t r[64] = { - 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 -}; - -/** - * f(b,c,d) for steps 0 to 15 - * - * @v v MD5 variables - * @ret f f(b,c,d) - */ -static uint32_t md5_f_0_15 ( struct md5_variables *v ) { - return ( v->d ^ ( v->b & ( v->c ^ v->d ) ) ); -} - -/** - * f(b,c,d) for steps 16 to 31 - * - * @v v MD5 variables - * @ret f f(b,c,d) - */ -static uint32_t md5_f_16_31 ( struct md5_variables *v ) { - return ( v->c ^ ( v->d & ( v->b ^ v->c ) ) ); -} - -/** - * f(b,c,d) for steps 32 to 47 - * - * @v v MD5 variables - * @ret f f(b,c,d) - */ -static uint32_t md5_f_32_47 ( struct md5_variables *v ) { - return ( v->b ^ v->c ^ v->d ); -} - -/** - * f(b,c,d) for steps 48 to 63 - * - * @v v MD5 variables - * @ret f f(b,c,d) - */ -static uint32_t md5_f_48_63 ( struct md5_variables *v ) { - return ( v->c ^ ( v->b | (~v->d) ) ); -} - -/** An MD5 step function */ -struct md5_step { - /** - * Calculate f(b,c,d) - * - * @v v MD5 variables - * @ret f f(b,c,d) - */ - uint32_t ( * f ) ( struct md5_variables *v ); - /** Coefficient of i in g=ni+m */ - uint8_t coefficient; - /** Constant term in g=ni+m */ - uint8_t constant; -}; - -/** MD5 steps */ -static struct md5_step md5_steps[4] = { - /** 0 to 15 */ - { .f = md5_f_0_15, .coefficient = 1, .constant = 0 }, - /** 16 to 31 */ - { .f = md5_f_16_31, .coefficient = 5, .constant = 1 }, - /** 32 to 47 */ - { .f = md5_f_32_47, .coefficient = 3, .constant = 5 }, - /** 48 to 63 */ - { .f = md5_f_48_63, .coefficient = 7, .constant = 0 }, -}; - -/** - * Initialise MD5 algorithm - * - * @v ctx MD5 context - */ -static void md5_init ( void *ctx ) { - struct md5_context *context = ctx; - - context->ddd.dd.digest.h[0] = cpu_to_le32 ( 0x67452301 ); - context->ddd.dd.digest.h[1] = cpu_to_le32 ( 0xefcdab89 ); - context->ddd.dd.digest.h[2] = cpu_to_le32 ( 0x98badcfe ); - context->ddd.dd.digest.h[3] = cpu_to_le32 ( 0x10325476 ); - context->len = 0; -} - -/** - * Calculate MD5 digest of accumulated data - * - * @v context MD5 context - */ -static void md5_digest ( struct md5_context *context ) { - union { - union md5_digest_data_dwords ddd; - struct md5_variables v; - } u; - uint32_t *a = &u.v.a; - uint32_t *b = &u.v.b; - uint32_t *c = &u.v.c; - uint32_t *d = &u.v.d; - uint32_t *w = u.v.w; - uint32_t f; - uint32_t g; - uint32_t temp; - struct md5_step *step; - unsigned int i; - - /* Sanity checks */ - assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); - linker_assert ( &u.ddd.dd.digest.h[0] == a, md5_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[1] == b, md5_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[2] == c, md5_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[3] == d, md5_bad_layout ); - linker_assert ( &u.ddd.dd.data.dword[0] == w, md5_bad_layout ); - - DBGC ( context, "MD5 digesting:\n" ); - DBGC_HDA ( context, 0, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); - DBGC_HDA ( context, context->len, &context->ddd.dd.data, - sizeof ( context->ddd.dd.data ) ); - - /* Convert h[0..3] to host-endian, and initialise a, b, c, d, - * and w[0..15] - */ - for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) / - sizeof ( u.ddd.dword[0] ) ) ; i++ ) { - le32_to_cpus ( &context->ddd.dword[i] ); - u.ddd.dword[i] = context->ddd.dword[i]; - } - - /* Main loop */ - for ( i = 0 ; i < 64 ; i++ ) { - step = &md5_steps[ i / 16 ]; - f = step->f ( &u.v ); - g = ( ( ( step->coefficient * i ) + step->constant ) % 16 ); - temp = *d; - *d = *c; - *c = *b; - *b = ( *b + rol32 ( ( *a + f + k[i] + w[g] ), r[i] ) ); - *a = temp; - DBGC2 ( context, "%2d : %08x %08x %08x %08x\n", - i, *a, *b, *c, *d ); - } - - /* Add chunk to hash and convert back to big-endian */ - for ( i = 0 ; i < 4 ; i++ ) { - context->ddd.dd.digest.h[i] = - cpu_to_le32 ( context->ddd.dd.digest.h[i] + - u.ddd.dd.digest.h[i] ); - } - - DBGC ( context, "MD5 digested:\n" ); - DBGC_HDA ( context, 0, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); -} - -/** - * Accumulate data with MD5 algorithm - * - * @v ctx MD5 context - * @v data Data - * @v len Length of data - */ -static void md5_update ( void *ctx, const void *data, size_t len ) { - struct md5_context *context = ctx; - const uint8_t *byte = data; - size_t offset; - - /* Accumulate data a byte at a time, performing the digest - * whenever we fill the data buffer - */ - while ( len-- ) { - offset = ( context->len % sizeof ( context->ddd.dd.data ) ); - context->ddd.dd.data.byte[offset] = *(byte++); - context->len++; - if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ) - md5_digest ( context ); - } -} - -/** - * Generate MD5 digest - * - * @v ctx MD5 context - * @v out Output buffer - */ -static void md5_final ( void *ctx, void *out ) { - struct md5_context *context = ctx; - uint64_t len_bits; - uint8_t pad; - - /* Record length before pre-processing */ - len_bits = cpu_to_le64 ( ( ( uint64_t ) context->len ) * 8 ); - - /* Pad with a single "1" bit followed by as many "0" bits as required */ - pad = 0x80; - do { - md5_update ( ctx, &pad, sizeof ( pad ) ); - pad = 0x00; - } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) != - offsetof ( typeof ( context->ddd.dd.data ), final.len ) ); - - /* Append length (in bits) */ - md5_update ( ctx, &len_bits, sizeof ( len_bits ) ); - assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); - - /* Copy out final digest */ - memcpy ( out, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); -} - -/** MD5 algorithm */ -struct digest_algorithm md5_algorithm = { - .name = "md5", - .ctxsize = sizeof ( struct md5_context ), - .blocksize = sizeof ( union md5_block ), - .digestsize = sizeof ( struct md5_digest ), - .init = md5_init, - .update = md5_update, - .final = md5_final, -}; - -/** "md5" object identifier */ -static uint8_t oid_md5[] = { ASN1_OID_MD5 }; - -/** "md5" OID-identified algorithm */ -struct asn1_algorithm oid_md5_algorithm __asn1_algorithm = { - .name = "md5", - .digest = &md5_algorithm, - .oid = ASN1_OID_CURSOR ( oid_md5 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_aes_cbc_sha1.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_aes_cbc_sha1.c deleted file mode 100644 index 06722c0e1..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_aes_cbc_sha1.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <byteswap.h> -#include <ipxe/rsa.h> -#include <ipxe/aes.h> -#include <ipxe/sha1.h> -#include <ipxe/tls.h> - -/** TLS_RSA_WITH_AES_128_CBC_SHA cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite (03) = { - .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ), - .key_len = ( 128 / 8 ), - .pubkey = &rsa_algorithm, - .cipher = &aes_cbc_algorithm, - .digest = &sha1_algorithm, -}; - -/** TLS_RSA_WITH_AES_256_CBC_SHA cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite (04) = { - .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ), - .key_len = ( 256 / 8 ), - .pubkey = &rsa_algorithm, - .cipher = &aes_cbc_algorithm, - .digest = &sha1_algorithm, -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_aes_cbc_sha256.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_aes_cbc_sha256.c deleted file mode 100644 index c609eacea..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_aes_cbc_sha256.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <byteswap.h> -#include <ipxe/rsa.h> -#include <ipxe/aes.h> -#include <ipxe/sha256.h> -#include <ipxe/tls.h> - -/** TLS_RSA_WITH_AES_128_CBC_SHA256 cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite(01)={ - .code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ), - .key_len = ( 128 / 8 ), - .pubkey = &rsa_algorithm, - .cipher = &aes_cbc_algorithm, - .digest = &sha256_algorithm, -}; - -/** TLS_RSA_WITH_AES_256_CBC_SHA256 cipher suite */ -struct tls_cipher_suite tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite(02)={ - .code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ), - .key_len = ( 256 / 8 ), - .pubkey = &rsa_algorithm, - .cipher = &aes_cbc_algorithm, - .digest = &sha256_algorithm, -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_md5.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_md5.c deleted file mode 100644 index ac828ac11..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_md5.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/rsa.h> -#include <ipxe/md5.h> -#include <ipxe/asn1.h> - -/** "md5WithRSAEncryption" object identifier */ -static uint8_t oid_md5_with_rsa_encryption[] = - { ASN1_OID_MD5WITHRSAENCRYPTION }; - -/** "md5WithRSAEncryption" OID-identified algorithm */ -struct asn1_algorithm md5_with_rsa_encryption_algorithm __asn1_algorithm = { - .name = "md5WithRSAEncryption", - .pubkey = &rsa_algorithm, - .digest = &md5_algorithm, - .oid = ASN1_OID_CURSOR ( oid_md5_with_rsa_encryption ), -}; - -/** MD5 digestInfo prefix */ -static const uint8_t rsa_md5_prefix_data[] = - { RSA_DIGESTINFO_PREFIX ( MD5_DIGEST_SIZE, ASN1_OID_MD5 ) }; - -/** MD5 digestInfo prefix */ -struct rsa_digestinfo_prefix rsa_md5_prefix __rsa_digestinfo_prefix = { - .digest = &md5_algorithm, - .data = rsa_md5_prefix_data, - .len = sizeof ( rsa_md5_prefix_data ), -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha1.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha1.c deleted file mode 100644 index 39424bf2d..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha1.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/rsa.h> -#include <ipxe/sha1.h> -#include <ipxe/asn1.h> -#include <ipxe/tls.h> - -/** "sha1WithRSAEncryption" object identifier */ -static uint8_t oid_sha1_with_rsa_encryption[] = - { ASN1_OID_SHA1WITHRSAENCRYPTION }; - -/** "sha1WithRSAEncryption" OID-identified algorithm */ -struct asn1_algorithm sha1_with_rsa_encryption_algorithm __asn1_algorithm = { - .name = "sha1WithRSAEncryption", - .pubkey = &rsa_algorithm, - .digest = &sha1_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha1_with_rsa_encryption ), -}; - -/** SHA-1 digestInfo prefix */ -static const uint8_t rsa_sha1_prefix_data[] = - { RSA_DIGESTINFO_PREFIX ( SHA1_DIGEST_SIZE, ASN1_OID_SHA1 ) }; - -/** SHA-1 digestInfo prefix */ -struct rsa_digestinfo_prefix rsa_sha1_prefix __rsa_digestinfo_prefix = { - .digest = &sha1_algorithm, - .data = rsa_sha1_prefix_data, - .len = sizeof ( rsa_sha1_prefix_data ), -}; - -/** RSA with SHA-1 signature hash algorithm */ -struct tls_signature_hash_algorithm tls_rsa_sha1 __tls_sig_hash_algorithm = { - .code = { - .signature = TLS_RSA_ALGORITHM, - .hash = TLS_SHA1_ALGORITHM, - }, - .pubkey = &rsa_algorithm, - .digest = &sha1_algorithm, -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha224.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha224.c deleted file mode 100644 index 5e8755aab..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha224.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/rsa.h> -#include <ipxe/sha256.h> -#include <ipxe/asn1.h> -#include <ipxe/tls.h> - -/** "sha224WithRSAEncryption" object identifier */ -static uint8_t oid_sha224_with_rsa_encryption[] = - { ASN1_OID_SHA224WITHRSAENCRYPTION }; - -/** "sha224WithRSAEncryption" OID-identified algorithm */ -struct asn1_algorithm sha224_with_rsa_encryption_algorithm __asn1_algorithm = { - .name = "sha224WithRSAEncryption", - .pubkey = &rsa_algorithm, - .digest = &sha224_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha224_with_rsa_encryption ), -}; - -/** SHA-224 digestInfo prefix */ -static const uint8_t rsa_sha224_prefix_data[] = - { RSA_DIGESTINFO_PREFIX ( SHA224_DIGEST_SIZE, ASN1_OID_SHA224 ) }; - -/** SHA-224 digestInfo prefix */ -struct rsa_digestinfo_prefix rsa_sha224_prefix __rsa_digestinfo_prefix = { - .digest = &sha224_algorithm, - .data = rsa_sha224_prefix_data, - .len = sizeof ( rsa_sha224_prefix_data ), -}; - -/** RSA with SHA-224 signature hash algorithm */ -struct tls_signature_hash_algorithm tls_rsa_sha224 __tls_sig_hash_algorithm = { - .code = { - .signature = TLS_RSA_ALGORITHM, - .hash = TLS_SHA224_ALGORITHM, - }, - .pubkey = &rsa_algorithm, - .digest = &sha224_algorithm, -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha256.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha256.c deleted file mode 100644 index b44af5f19..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha256.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/rsa.h> -#include <ipxe/sha256.h> -#include <ipxe/asn1.h> -#include <ipxe/tls.h> - -/** "sha256WithRSAEncryption" object identifier */ -static uint8_t oid_sha256_with_rsa_encryption[] = - { ASN1_OID_SHA256WITHRSAENCRYPTION }; - -/** "sha256WithRSAEncryption" OID-identified algorithm */ -struct asn1_algorithm sha256_with_rsa_encryption_algorithm __asn1_algorithm = { - .name = "sha256WithRSAEncryption", - .pubkey = &rsa_algorithm, - .digest = &sha256_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha256_with_rsa_encryption ), -}; - -/** SHA-256 digestInfo prefix */ -static const uint8_t rsa_sha256_prefix_data[] = - { RSA_DIGESTINFO_PREFIX ( SHA256_DIGEST_SIZE, ASN1_OID_SHA256 ) }; - -/** SHA-256 digestInfo prefix */ -struct rsa_digestinfo_prefix rsa_sha256_prefix __rsa_digestinfo_prefix = { - .digest = &sha256_algorithm, - .data = rsa_sha256_prefix_data, - .len = sizeof ( rsa_sha256_prefix_data ), -}; - -/** RSA with SHA-256 signature hash algorithm */ -struct tls_signature_hash_algorithm tls_rsa_sha256 __tls_sig_hash_algorithm = { - .code = { - .signature = TLS_RSA_ALGORITHM, - .hash = TLS_SHA256_ALGORITHM, - }, - .pubkey = &rsa_algorithm, - .digest = &sha256_algorithm, -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha384.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha384.c deleted file mode 100644 index af22a2bf0..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha384.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/rsa.h> -#include <ipxe/sha512.h> -#include <ipxe/asn1.h> -#include <ipxe/tls.h> - -/** "sha384WithRSAEncryption" object identifier */ -static uint8_t oid_sha384_with_rsa_encryption[] = - { ASN1_OID_SHA384WITHRSAENCRYPTION }; - -/** "sha384WithRSAEncryption" OID-identified algorithm */ -struct asn1_algorithm sha384_with_rsa_encryption_algorithm __asn1_algorithm = { - .name = "sha384WithRSAEncryption", - .pubkey = &rsa_algorithm, - .digest = &sha384_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha384_with_rsa_encryption ), -}; - -/** SHA-384 digestInfo prefix */ -static const uint8_t rsa_sha384_prefix_data[] = - { RSA_DIGESTINFO_PREFIX ( SHA384_DIGEST_SIZE, ASN1_OID_SHA384 ) }; - -/** SHA-384 digestInfo prefix */ -struct rsa_digestinfo_prefix rsa_sha384_prefix __rsa_digestinfo_prefix = { - .digest = &sha384_algorithm, - .data = rsa_sha384_prefix_data, - .len = sizeof ( rsa_sha384_prefix_data ), -}; - -/** RSA with SHA-384 signature hash algorithm */ -struct tls_signature_hash_algorithm tls_rsa_sha384 __tls_sig_hash_algorithm = { - .code = { - .signature = TLS_RSA_ALGORITHM, - .hash = TLS_SHA384_ALGORITHM, - }, - .pubkey = &rsa_algorithm, - .digest = &sha384_algorithm, -}; diff --git a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha512.c b/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha512.c deleted file mode 100644 index 29ee15493..000000000 --- a/qemu/roms/ipxe/src/crypto/mishmash/rsa_sha512.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/rsa.h> -#include <ipxe/sha512.h> -#include <ipxe/asn1.h> -#include <ipxe/tls.h> - -/** "sha512WithRSAEncryption" object identifier */ -static uint8_t oid_sha512_with_rsa_encryption[] = - { ASN1_OID_SHA512WITHRSAENCRYPTION }; - -/** "sha512WithRSAEncryption" OID-identified algorithm */ -struct asn1_algorithm sha512_with_rsa_encryption_algorithm __asn1_algorithm = { - .name = "sha512WithRSAEncryption", - .pubkey = &rsa_algorithm, - .digest = &sha512_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha512_with_rsa_encryption ), -}; - -/** SHA-512 digestInfo prefix */ -static const uint8_t rsa_sha512_prefix_data[] = - { RSA_DIGESTINFO_PREFIX ( SHA512_DIGEST_SIZE, ASN1_OID_SHA512 ) }; - -/** SHA-512 digestInfo prefix */ -struct rsa_digestinfo_prefix rsa_sha512_prefix __rsa_digestinfo_prefix = { - .digest = &sha512_algorithm, - .data = rsa_sha512_prefix_data, - .len = sizeof ( rsa_sha512_prefix_data ), -}; - -/** RSA with SHA-512 signature hash algorithm */ -struct tls_signature_hash_algorithm tls_rsa_sha512 __tls_sig_hash_algorithm = { - .code = { - .signature = TLS_RSA_ALGORITHM, - .hash = TLS_SHA512_ALGORITHM, - }, - .pubkey = &rsa_algorithm, - .digest = &sha512_algorithm, -}; diff --git a/qemu/roms/ipxe/src/crypto/null_entropy.c b/qemu/roms/ipxe/src/crypto/null_entropy.c deleted file mode 100644 index d1e1a6f73..000000000 --- a/qemu/roms/ipxe/src/crypto/null_entropy.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Nonexistent entropy source - * - * - * This source provides no entropy and must NOT be used in a - * security-sensitive environment. - */ - -#include <ipxe/entropy.h> - -PROVIDE_ENTROPY_INLINE ( null, min_entropy_per_sample ); -PROVIDE_ENTROPY_INLINE ( null, entropy_enable ); -PROVIDE_ENTROPY_INLINE ( null, entropy_disable ); -PROVIDE_ENTROPY_INLINE ( null, get_noise ); diff --git a/qemu/roms/ipxe/src/crypto/ocsp.c b/qemu/roms/ipxe/src/crypto/ocsp.c deleted file mode 100644 index 5df55bc96..000000000 --- a/qemu/roms/ipxe/src/crypto/ocsp.c +++ /dev/null @@ -1,960 +0,0 @@ -/* - * 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdint.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <ipxe/asn1.h> -#include <ipxe/x509.h> -#include <ipxe/sha1.h> -#include <ipxe/base64.h> -#include <ipxe/uri.h> -#include <ipxe/ocsp.h> -#include <config/crypto.h> - -/** @file - * - * Online Certificate Status Protocol - * - */ - -/* Disambiguate the various error causes */ -#define EACCES_CERT_STATUS \ - __einfo_error ( EINFO_EACCES_CERT_STATUS ) -#define EINFO_EACCES_CERT_STATUS \ - __einfo_uniqify ( EINFO_EACCES, 0x01, \ - "Certificate status not good" ) -#define EACCES_CERT_MISMATCH \ - __einfo_error ( EINFO_EACCES_CERT_MISMATCH ) -#define EINFO_EACCES_CERT_MISMATCH \ - __einfo_uniqify ( EINFO_EACCES, 0x02, \ - "Certificate ID mismatch" ) -#define EACCES_NON_OCSP_SIGNING \ - __einfo_error ( EINFO_EACCES_NON_OCSP_SIGNING ) -#define EINFO_EACCES_NON_OCSP_SIGNING \ - __einfo_uniqify ( EINFO_EACCES, 0x03, \ - "Not an OCSP signing certificate" ) -#define EACCES_STALE \ - __einfo_error ( EINFO_EACCES_STALE ) -#define EINFO_EACCES_STALE \ - __einfo_uniqify ( EINFO_EACCES, 0x04, \ - "Stale (or premature) OCSP repsonse" ) -#define EACCES_NO_RESPONDER \ - __einfo_error ( EINFO_EACCES_NO_RESPONDER ) -#define EINFO_EACCES_NO_RESPONDER \ - __einfo_uniqify ( EINFO_EACCES, 0x05, \ - "Missing OCSP responder certificate" ) -#define ENOTSUP_RESPONSE_TYPE \ - __einfo_error ( EINFO_ENOTSUP_RESPONSE_TYPE ) -#define EINFO_ENOTSUP_RESPONSE_TYPE \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \ - "Unsupported OCSP response type" ) -#define ENOTSUP_RESPONDER_ID \ - __einfo_error ( EINFO_ENOTSUP_RESPONDER_ID ) -#define EINFO_ENOTSUP_RESPONDER_ID \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \ - "Unsupported OCSP responder ID" ) -#define EPROTO_MALFORMED_REQUEST \ - __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST ) -#define EINFO_EPROTO_MALFORMED_REQUEST \ - __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_MALFORMED_REQUEST, \ - "Illegal confirmation request" ) -#define EPROTO_INTERNAL_ERROR \ - __einfo_error ( EINFO_EPROTO_INTERNAL_ERROR ) -#define EINFO_EPROTO_INTERNAL_ERROR \ - __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_INTERNAL_ERROR, \ - "Internal error in issuer" ) -#define EPROTO_TRY_LATER \ - __einfo_error ( EINFO_EPROTO_TRY_LATER ) -#define EINFO_EPROTO_TRY_LATER \ - __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_TRY_LATER, \ - "Try again later" ) -#define EPROTO_SIG_REQUIRED \ - __einfo_error ( EINFO_EPROTO_SIG_REQUIRED ) -#define EINFO_EPROTO_SIG_REQUIRED \ - __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_SIG_REQUIRED, \ - "Must sign the request" ) -#define EPROTO_UNAUTHORIZED \ - __einfo_error ( EINFO_EPROTO_UNAUTHORIZED ) -#define EINFO_EPROTO_UNAUTHORIZED \ - __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_UNAUTHORIZED, \ - "Request unauthorized" ) -#define EPROTO_STATUS( status ) \ - EUNIQ ( EINFO_EPROTO, (status), EPROTO_MALFORMED_REQUEST, \ - EPROTO_INTERNAL_ERROR, EPROTO_TRY_LATER, \ - EPROTO_SIG_REQUIRED, EPROTO_UNAUTHORIZED ) - -/** OCSP digest algorithm */ -#define ocsp_digest_algorithm sha1_algorithm - -/** OCSP digest algorithm identifier */ -static const uint8_t ocsp_algorithm_id[] = - { OCSP_ALGORITHM_IDENTIFIER ( ASN1_OID_SHA1 ) }; - -/** OCSP basic response type */ -static const uint8_t oid_basic_response_type[] = { ASN1_OID_OCSP_BASIC }; - -/** OCSP basic response type cursor */ -static struct asn1_cursor oid_basic_response_type_cursor = - ASN1_OID_CURSOR ( oid_basic_response_type ); - -/** - * Free OCSP check - * - * @v refcnt Reference count - */ -static void ocsp_free ( struct refcnt *refcnt ) { - struct ocsp_check *ocsp = - container_of ( refcnt, struct ocsp_check, refcnt ); - - x509_put ( ocsp->cert ); - x509_put ( ocsp->issuer ); - free ( ocsp->uri_string ); - free ( ocsp->request.builder.data ); - free ( ocsp->response.data ); - x509_put ( ocsp->response.signer ); - free ( ocsp ); -} - -/** - * Build OCSP request - * - * @v ocsp OCSP check - * @ret rc Return status code - */ -static int ocsp_request ( struct ocsp_check *ocsp ) { - struct digest_algorithm *digest = &ocsp_digest_algorithm; - struct asn1_builder *builder = &ocsp->request.builder; - struct asn1_cursor *cert_id = &ocsp->request.cert_id; - uint8_t digest_ctx[digest->ctxsize]; - uint8_t name_digest[digest->digestsize]; - uint8_t pubkey_digest[digest->digestsize]; - int rc; - - /* Generate digests */ - digest_init ( digest, digest_ctx ); - digest_update ( digest, digest_ctx, ocsp->cert->issuer.raw.data, - ocsp->cert->issuer.raw.len ); - digest_final ( digest, digest_ctx, name_digest ); - digest_init ( digest, digest_ctx ); - digest_update ( digest, digest_ctx, - ocsp->issuer->subject.public_key.raw_bits.data, - ocsp->issuer->subject.public_key.raw_bits.len ); - digest_final ( digest, digest_ctx, pubkey_digest ); - - /* Construct request */ - if ( ( rc = ( asn1_prepend_raw ( builder, ocsp->cert->serial.raw.data, - ocsp->cert->serial.raw.len ), - asn1_prepend ( builder, ASN1_OCTET_STRING, - pubkey_digest, sizeof ( pubkey_digest ) ), - asn1_prepend ( builder, ASN1_OCTET_STRING, - name_digest, sizeof ( name_digest ) ), - asn1_prepend ( builder, ASN1_SEQUENCE, - ocsp_algorithm_id, - sizeof ( ocsp_algorithm_id ) ), - asn1_wrap ( builder, ASN1_SEQUENCE ), - asn1_wrap ( builder, ASN1_SEQUENCE ), - asn1_wrap ( builder, ASN1_SEQUENCE ), - asn1_wrap ( builder, ASN1_SEQUENCE ), - asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n", - ocsp, x509_name ( ocsp->cert ), strerror ( rc ) ); - return rc; - } - DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n", - ocsp, x509_name ( ocsp->cert ) ); - DBGC2_HDA ( ocsp, 0, builder->data, builder->len ); - - /* Parse certificate ID for comparison with response */ - cert_id->data = builder->data; - cert_id->len = builder->len; - if ( ( rc = ( asn1_enter ( cert_id, ASN1_SEQUENCE ), - asn1_enter ( cert_id, ASN1_SEQUENCE ), - asn1_enter ( cert_id, ASN1_SEQUENCE ), - asn1_enter ( cert_id, ASN1_SEQUENCE ) ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n", - ocsp, x509_name ( ocsp->cert ), strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Build OCSP URI string - * - * @v ocsp OCSP check - * @ret rc Return status code - */ -static int ocsp_uri_string ( struct ocsp_check *ocsp ) { - struct x509_ocsp_responder *responder = - &ocsp->cert->extensions.auth_info.ocsp; - struct uri path_uri; - char *path_base64_string; - char *path_uri_string; - size_t path_len; - size_t len; - int rc; - - /* Sanity check */ - if ( ! responder->uri.len ) { - DBGC ( ocsp, "OCSP %p \"%s\" has no OCSP URI\n", - ocsp, x509_name ( ocsp->cert ) ); - rc = -ENOTTY; - goto err_no_uri; - } - - /* Base64-encode the request as the URI path */ - path_len = ( base64_encoded_len ( ocsp->request.builder.len ) - + 1 /* NUL */ ); - path_base64_string = malloc ( path_len ); - if ( ! path_base64_string ) { - rc = -ENOMEM; - goto err_path_base64; - } - base64_encode ( ocsp->request.builder.data, ocsp->request.builder.len, - path_base64_string, path_len ); - - /* URI-encode the Base64-encoded request */ - memset ( &path_uri, 0, sizeof ( path_uri ) ); - path_uri.path = path_base64_string; - path_uri_string = format_uri_alloc ( &path_uri ); - if ( ! path_uri_string ) { - rc = -ENOMEM; - goto err_path_uri; - } - - /* Construct URI string */ - len = ( responder->uri.len + strlen ( path_uri_string ) + 1 /* NUL */ ); - ocsp->uri_string = zalloc ( len ); - if ( ! ocsp->uri_string ) { - rc = -ENOMEM; - goto err_ocsp_uri; - } - memcpy ( ocsp->uri_string, responder->uri.data, responder->uri.len ); - strcpy ( &ocsp->uri_string[responder->uri.len], path_uri_string ); - DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n", - ocsp, x509_name ( ocsp->cert ), ocsp->uri_string ); - - /* Success */ - rc = 0; - - err_ocsp_uri: - free ( path_uri_string ); - err_path_uri: - free ( path_base64_string ); - err_path_base64: - err_no_uri: - return rc; -} - -/** - * Create OCSP check - * - * @v cert Certificate to check - * @v issuer Issuing certificate - * @ret ocsp OCSP check - * @ret rc Return status code - */ -int ocsp_check ( struct x509_certificate *cert, - struct x509_certificate *issuer, - struct ocsp_check **ocsp ) { - int rc; - - /* Sanity checks */ - assert ( cert != NULL ); - assert ( issuer != NULL ); - assert ( issuer->valid ); - - /* Allocate and initialise check */ - *ocsp = zalloc ( sizeof ( **ocsp ) ); - if ( ! *ocsp ) { - rc = -ENOMEM; - goto err_alloc; - } - ref_init ( &(*ocsp)->refcnt, ocsp_free ); - (*ocsp)->cert = x509_get ( cert ); - (*ocsp)->issuer = x509_get ( issuer ); - - /* Build request */ - if ( ( rc = ocsp_request ( *ocsp ) ) != 0 ) - goto err_request; - - /* Build URI string */ - if ( ( rc = ocsp_uri_string ( *ocsp ) ) != 0 ) - goto err_uri_string; - - return 0; - - err_uri_string: - err_request: - ocsp_put ( *ocsp ); - err_alloc: - *ocsp = NULL; - return rc; -} - -/** - * Parse OCSP response status - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_response_status ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - uint8_t status; - int rc; - - /* Enter responseStatus */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: " - "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc )); - return rc; - } - - /* Extract response status */ - if ( cursor.len != sizeof ( status ) ) { - DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n", - ocsp, x509_name ( ocsp->cert ) ); - DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return -EINVAL; - } - memcpy ( &status, cursor.data, sizeof ( status ) ); - - /* Check response status */ - if ( status != OCSP_STATUS_SUCCESSFUL ) { - DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n", - ocsp, x509_name ( ocsp->cert ), status ); - return EPROTO_STATUS ( status ); - } - - return 0; -} - -/** - * Parse OCSP response type - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_response_type ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - - /* Enter responseType */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_OID ); - - /* Check responseType is "basic" */ - if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n", - ocsp, x509_name ( ocsp->cert ) ); - DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return -ENOTSUP_RESPONSE_TYPE; - } - - return 0; -} - -/** - * Compare responder's certificate name - * - * @v ocsp OCSP check - * @v cert Certificate - * @ret difference Difference as returned by memcmp() - */ -static int ocsp_compare_responder_name ( struct ocsp_check *ocsp, - struct x509_certificate *cert ) { - struct ocsp_responder *responder = &ocsp->response.responder; - - /* Compare responder ID with certificate's subject */ - return asn1_compare ( &responder->id, &cert->subject.raw ); -} - -/** - * Compare responder's certificate public key hash - * - * @v ocsp OCSP check - * @v cert Certificate - * @ret difference Difference as returned by memcmp() - */ -static int ocsp_compare_responder_key_hash ( struct ocsp_check *ocsp, - struct x509_certificate *cert ) { - struct ocsp_responder *responder = &ocsp->response.responder; - struct asn1_cursor key_hash; - uint8_t ctx[SHA1_CTX_SIZE]; - uint8_t digest[SHA1_DIGEST_SIZE]; - int difference; - - /* Enter responder key hash */ - memcpy ( &key_hash, &responder->id, sizeof ( key_hash ) ); - asn1_enter ( &key_hash, ASN1_OCTET_STRING ); - - /* Sanity check */ - difference = ( sizeof ( digest ) - key_hash.len ); - if ( difference ) - return difference; - - /* Generate SHA1 hash of certificate's public key */ - digest_init ( &sha1_algorithm, ctx ); - digest_update ( &sha1_algorithm, ctx, - cert->subject.public_key.raw_bits.data, - cert->subject.public_key.raw_bits.len ); - digest_final ( &sha1_algorithm, ctx, digest ); - - /* Compare responder key hash with hash of certificate's public key */ - return memcmp ( digest, key_hash.data, sizeof ( digest ) ); -} - -/** - * Parse OCSP responder ID - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_responder_id ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct ocsp_responder *responder = &ocsp->response.responder; - struct asn1_cursor *responder_id = &responder->id; - unsigned int type; - - /* Enter responder ID */ - memcpy ( responder_id, raw, sizeof ( *responder_id ) ); - type = asn1_type ( responder_id ); - asn1_enter_any ( responder_id ); - - /* Identify responder ID type */ - switch ( type ) { - case ASN1_EXPLICIT_TAG ( 1 ) : - DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by name\n", - ocsp, x509_name ( ocsp->cert ) ); - responder->compare = ocsp_compare_responder_name; - return 0; - case ASN1_EXPLICIT_TAG ( 2 ) : - DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by key " - "hash\n", ocsp, x509_name ( ocsp->cert ) ); - responder->compare = ocsp_compare_responder_key_hash; - return 0; - default: - DBGC ( ocsp, "OCSP %p \"%s\" unsupported responder ID type " - "%d\n", ocsp, x509_name ( ocsp->cert ), type ); - return -ENOTSUP_RESPONDER_ID; - } -} - -/** - * Parse OCSP certificate ID - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_cert_id ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - - /* Check certID matches request */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_shrink_any ( &cursor ); - if ( asn1_compare ( &cursor, &ocsp->request.cert_id ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n", - ocsp, x509_name ( ocsp->cert ) ); - DBGC_HDA ( ocsp, 0, ocsp->request.cert_id.data, - ocsp->request.cert_id.len ); - DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return -EACCES_CERT_MISMATCH; - } - - return 0; -} - -/** - * Parse OCSP responses - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_responses ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct ocsp_response *response = &ocsp->response; - struct asn1_cursor cursor; - int rc; - - /* Enter responses */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Enter first singleResponse */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse certID */ - if ( ( rc = ocsp_parse_cert_id ( ocsp, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Check certStatus */ - if ( asn1_type ( &cursor ) != ASN1_IMPLICIT_TAG ( 0 ) ) { - DBGC ( ocsp, "OCSP %p \"%s\" non-good certStatus:\n", - ocsp, x509_name ( ocsp->cert ) ); - DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return -EACCES_CERT_STATUS; - } - asn1_skip_any ( &cursor ); - - /* Parse thisUpdate */ - if ( ( rc = asn1_generalized_time ( &cursor, - &response->this_update ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not parse thisUpdate: %s\n", - ocsp, x509_name ( ocsp->cert ), strerror ( rc ) ); - return rc; - } - DBGC2 ( ocsp, "OCSP %p \"%s\" this update was at time %lld\n", - ocsp, x509_name ( ocsp->cert ), response->this_update ); - asn1_skip_any ( &cursor ); - - /* Parse nextUpdate, if present */ - if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) { - asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - if ( ( rc = asn1_generalized_time ( &cursor, - &response->next_update ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not parse " - "nextUpdate: %s\n", ocsp, - x509_name ( ocsp->cert ), strerror ( rc ) ); - return rc; - } - DBGC2 ( ocsp, "OCSP %p \"%s\" next update is at time %lld\n", - ocsp, x509_name ( ocsp->cert ), response->next_update ); - } else { - /* If no nextUpdate is present, this indicates that - * "newer revocation information is available all the - * time". Actually, this indicates that there is no - * point to performing the OCSP check, since an - * attacker could replay the response at any future - * time and it would still be valid. - */ - DBGC ( ocsp, "OCSP %p \"%s\" responder is a moron\n", - ocsp, x509_name ( ocsp->cert ) ); - response->next_update = time ( NULL ); - } - - return 0; -} - -/** - * Parse OCSP response data - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_tbs_response_data ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct ocsp_response *response = &ocsp->response; - struct asn1_cursor cursor; - int rc; - - /* Record raw tbsResponseData */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_shrink_any ( &cursor ); - memcpy ( &response->tbs, &cursor, sizeof ( response->tbs ) ); - - /* Enter tbsResponseData */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Skip version, if present */ - asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - - /* Parse responderID */ - if ( ( rc = ocsp_parse_responder_id ( ocsp, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Skip producedAt */ - asn1_skip_any ( &cursor ); - - /* Parse responses */ - if ( ( rc = ocsp_parse_responses ( ocsp, &cursor ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Parse OCSP certificates - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_certs ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct ocsp_response *response = &ocsp->response; - struct asn1_cursor cursor; - struct x509_certificate *cert; - int rc; - - /* Enter certs */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse certificate, if present. The data structure permits - * multiple certificates, but the protocol requires that the - * OCSP signing certificate must either be the issuer itself, - * or must be directly issued by the issuer (see RFC2560 - * section 4.2.2.2 "Authorized Responders"). We therefore - * need to identify only the single certificate matching the - * Responder ID. - */ - while ( cursor.len ) { - - /* Parse certificate */ - if ( ( rc = x509_certificate ( cursor.data, cursor.len, - &cert ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not parse " - "certificate: %s\n", ocsp, - x509_name ( ocsp->cert ), strerror ( rc ) ); - DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return rc; - } - - /* Use if this certificate matches the responder ID */ - if ( response->responder.compare ( ocsp, cert ) == 0 ) { - response->signer = cert; - DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by ", - ocsp, x509_name ( ocsp->cert ) ); - DBGC2 ( ocsp, "\"%s\"\n", - x509_name ( response->signer ) ); - return 0; - } - - /* Otherwise, discard this certificate */ - x509_put ( cert ); - asn1_skip_any ( &cursor ); - } - - DBGC ( ocsp, "OCSP %p \"%s\" missing responder certificate\n", - ocsp, x509_name ( ocsp->cert ) ); - return -EACCES_NO_RESPONDER; -} - -/** - * Parse OCSP basic response - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_basic_response ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct ocsp_response *response = &ocsp->response; - struct asn1_algorithm **algorithm = &response->algorithm; - struct asn1_bit_string *signature = &response->signature; - struct asn1_cursor cursor; - int rc; - - /* Enter BasicOCSPResponse */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse tbsResponseData */ - if ( ( rc = ocsp_parse_tbs_response_data ( ocsp, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse signatureAlgorithm */ - if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature " - "algorithm: %s\n", - ocsp, x509_name ( ocsp->cert ), strerror ( rc ) ); - return rc; - } - DBGC2 ( ocsp, "OCSP %p \"%s\" signature algorithm is %s\n", - ocsp, x509_name ( ocsp->cert ), (*algorithm)->name ); - asn1_skip_any ( &cursor ); - - /* Parse signature */ - if ( ( rc = asn1_integral_bit_string ( &cursor, signature ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n", - ocsp, x509_name ( ocsp->cert ), strerror ( rc ) ); - return rc; - } - asn1_skip_any ( &cursor ); - - /* Parse certs, if present */ - if ( ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) && - ( ( rc = ocsp_parse_certs ( ocsp, &cursor ) ) != 0 ) ) - return rc; - - return 0; -} - -/** - * Parse OCSP response bytes - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_response_bytes ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int rc; - - /* Enter responseBytes */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse responseType */ - if ( ( rc = ocsp_parse_response_type ( ocsp, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Enter response */ - asn1_enter ( &cursor, ASN1_OCTET_STRING ); - - /* Parse response */ - if ( ( rc = ocsp_parse_basic_response ( ocsp, &cursor ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Parse OCSP response - * - * @v ocsp OCSP check - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int ocsp_parse_response ( struct ocsp_check *ocsp, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int rc; - - /* Enter OCSPResponse */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse responseStatus */ - if ( ( rc = ocsp_parse_response_status ( ocsp, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse responseBytes */ - if ( ( rc = ocsp_parse_response_bytes ( ocsp, &cursor ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Receive OCSP response - * - * @v ocsp OCSP check - * @v data Response data - * @v len Length of response data - * @ret rc Return status code - */ -int ocsp_response ( struct ocsp_check *ocsp, const void *data, size_t len ) { - struct ocsp_response *response = &ocsp->response; - struct asn1_cursor cursor; - int rc; - - /* Duplicate data */ - x509_put ( response->signer ); - response->signer = NULL; - free ( response->data ); - response->data = malloc ( len ); - if ( ! response->data ) - return -ENOMEM; - memcpy ( response->data, data, len ); - cursor.data = response->data; - cursor.len = len; - - /* Parse response */ - if ( ( rc = ocsp_parse_response ( ocsp, &cursor ) ) != 0 ) - return rc; - - return 0; -} - -/** - * OCSP dummy root certificate store - * - * OCSP validation uses no root certificates, since it takes place - * only when there already exists a validated issuer certificate. - */ -static struct x509_root ocsp_root = { - .digest = &ocsp_digest_algorithm, - .count = 0, - .fingerprints = NULL, -}; - -/** - * Check OCSP response signature - * - * @v ocsp OCSP check - * @v signer Signing certificate - * @ret rc Return status code - */ -static int ocsp_check_signature ( struct ocsp_check *ocsp, - struct x509_certificate *signer ) { - struct ocsp_response *response = &ocsp->response; - struct digest_algorithm *digest = response->algorithm->digest; - struct pubkey_algorithm *pubkey = response->algorithm->pubkey; - struct x509_public_key *public_key = &signer->subject.public_key; - uint8_t digest_ctx[ digest->ctxsize ]; - uint8_t digest_out[ digest->digestsize ]; - uint8_t pubkey_ctx[ pubkey->ctxsize ]; - int rc; - - /* Generate digest */ - digest_init ( digest, digest_ctx ); - digest_update ( digest, digest_ctx, response->tbs.data, - response->tbs.len ); - digest_final ( digest, digest_ctx, digest_out ); - - /* Initialise public-key algorithm */ - if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data, - public_key->raw.len ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not initialise public key: " - "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc )); - goto err_init; - } - - /* Verify digest */ - if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out, - response->signature.data, - response->signature.len ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: " - "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc )); - goto err_verify; - } - - DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n", - ocsp, x509_name ( ocsp->cert ) ); - - err_verify: - pubkey_final ( pubkey, pubkey_ctx ); - err_init: - return rc; -} - -/** - * Validate OCSP response - * - * @v ocsp OCSP check - * @v time Time at which to validate response - * @ret rc Return status code - */ -int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) { - struct ocsp_response *response = &ocsp->response; - struct x509_certificate *signer; - int rc; - - /* Sanity checks */ - assert ( response->data != NULL ); - - /* The response may include a signer certificate; if this is - * not present then the response must have been signed - * directly by the issuer. - */ - signer = ( response->signer ? response->signer : ocsp->issuer ); - - /* Validate signer, if applicable. If the signer is not the - * issuer, then it must be signed directly by the issuer. - */ - if ( signer != ocsp->issuer ) { - /* Forcibly invalidate the signer, since we need to - * ensure that it was signed by our issuer (and not - * some other issuer). This prevents a sub-CA's OCSP - * certificate from fraudulently signing OCSP - * responses from the parent CA. - */ - x509_invalidate ( signer ); - if ( ( rc = x509_validate ( signer, ocsp->issuer, time, - &ocsp_root ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not validate ", - ocsp, x509_name ( ocsp->cert ) ); - DBGC ( ocsp, "signer \"%s\": %s\n", - x509_name ( signer ), strerror ( rc ) ); - return rc; - } - - /* If signer is not the issuer, then it must have the - * extendedKeyUsage id-kp-OCSPSigning. - */ - if ( ! ( signer->extensions.ext_usage.bits & - X509_OCSP_SIGNING ) ) { - DBGC ( ocsp, "OCSP %p \"%s\" ", - ocsp, x509_name ( ocsp->cert ) ); - DBGC ( ocsp, "signer \"%s\" is not an OCSP-signing " - "certificate\n", x509_name ( signer ) ); - return -EACCES_NON_OCSP_SIGNING; - } - } - - /* Check OCSP response signature */ - if ( ( rc = ocsp_check_signature ( ocsp, signer ) ) != 0 ) - return rc; - - /* Check OCSP response is valid at the specified time - * (allowing for some margin of error). - */ - if ( response->this_update > ( time + TIMESTAMP_ERROR_MARGIN ) ) { - DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at " - "time %lld)\n", ocsp, x509_name ( ocsp->cert ), time ); - return -EACCES_STALE; - } - if ( response->next_update < ( time - TIMESTAMP_ERROR_MARGIN ) ) { - DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time " - "%lld)\n", ocsp, x509_name ( ocsp->cert ), time ); - return -EACCES_STALE; - } - DBGC2 ( ocsp, "OCSP %p \"%s\" response is valid (at time %lld)\n", - ocsp, x509_name ( ocsp->cert ), time ); - - /* Mark certificate as passing OCSP verification */ - ocsp->cert->extensions.auth_info.ocsp.good = 1; - - /* Validate certificate against issuer */ - if ( ( rc = x509_validate ( ocsp->cert, ocsp->issuer, time, - &ocsp_root ) ) != 0 ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not validate certificate: " - "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc )); - return rc; - } - DBGC ( ocsp, "OCSP %p \"%s\" successfully validated ", - ocsp, x509_name ( ocsp->cert ) ); - DBGC ( ocsp, "using \"%s\"\n", x509_name ( signer ) ); - - return 0; -} diff --git a/qemu/roms/ipxe/src/crypto/privkey.c b/qemu/roms/ipxe/src/crypto/privkey.c deleted file mode 100644 index a6043bd1e..000000000 --- a/qemu/roms/ipxe/src/crypto/privkey.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <ipxe/dhcp.h> -#include <ipxe/settings.h> -#include <ipxe/x509.h> -#include <ipxe/privkey.h> - -/** @file - * - * Private key - * - * Life would in theory be easier if we could use a single file to - * hold both the certificate and corresponding private key. - * Unfortunately, the only common format which supports this is - * PKCS#12 (aka PFX), which is too ugly to be allowed anywhere near my - * codebase. See, for reference and amusement: - * - * http://www.cs.auckland.ac.nz/~pgut001/pubs/pfx.html - */ - -/* Allow private key to be overridden if not explicitly specified */ -#ifdef PRIVATE_KEY -#define ALLOW_KEY_OVERRIDE 0 -#else -#define ALLOW_KEY_OVERRIDE 1 -#endif - -/* Raw private key data */ -extern char private_key_data[]; -extern char private_key_len[]; -__asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" - "\nprivate_key_data:\n\t" -#ifdef PRIVATE_KEY - ".incbin \"" PRIVATE_KEY "\"\n\t" -#endif /* PRIVATE_KEY */ - ".size private_key_data, ( . - private_key_data )\n\t" - ".equ private_key_len, ( . - private_key_data )\n\t" - ".previous\n\t" ); - -/** Private key */ -struct asn1_cursor private_key = { - .data = private_key_data, - .len = ( ( size_t ) private_key_len ), -}; - -/** Private key setting */ -static struct setting privkey_setting __setting ( SETTING_CRYPTO, privkey ) = { - .name = "privkey", - .description = "Private key", - .tag = DHCP_EB_KEY, - .type = &setting_type_hex, -}; - -/** - * Apply private key configuration settings - * - * @ret rc Return status code - */ -static int privkey_apply_settings ( void ) { - static void *key_data = NULL; - int len; - - /* Allow private key to be overridden only if not explicitly - * specified at build time. - */ - if ( ALLOW_KEY_OVERRIDE ) { - - /* Restore default private key */ - private_key.data = private_key_data; - private_key.len = ( ( size_t ) private_key_len ); - - /* Fetch new private key, if any */ - free ( key_data ); - if ( ( len = fetch_raw_setting_copy ( NULL, &privkey_setting, - &key_data ) ) >= 0 ) { - private_key.data = key_data; - private_key.len = len; - } - } - - /* Debug */ - if ( private_key.len ) { - DBGC ( &private_key, "PRIVKEY using %s private key:\n", - ( key_data ? "external" : "built-in" ) ); - DBGC_HDA ( &private_key, 0, private_key.data, private_key.len ); - } else { - DBGC ( &private_key, "PRIVKEY has no private key\n" ); - } - - return 0; -} - -/** Private key settings applicator */ -struct settings_applicator privkey_applicator __settings_applicator = { - .apply = privkey_apply_settings, -}; diff --git a/qemu/roms/ipxe/src/crypto/random_nz.c b/qemu/roms/ipxe/src/crypto/random_nz.c deleted file mode 100644 index 5fe576e05..000000000 --- a/qemu/roms/ipxe/src/crypto/random_nz.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * Random non-zero bytes - * - * The RSA algorithm requires the generation of random non-zero bytes, - * i.e. bytes in the range [0x01,0xff]. - * - * This algorithm is designed to comply with ANS X9.82 Part 1-2006 - * Section 9.2.1. This standard is not freely available, but most of - * the text appears to be shared with NIST SP 800-90, which can be - * downloaded from - * - * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf - * - * Where possible, references are given to both documents. In the - * case of any disagreement, ANS X9.82 takes priority over NIST SP - * 800-90. (In particular, note that some algorithms that are - * Approved by NIST SP 800-90 are not Approved by ANS X9.82.) - */ - -#include <stddef.h> -#include <stdint.h> -#include <ipxe/rbg.h> -#include <ipxe/random_nz.h> - -/** - * Get random non-zero bytes - * - * @v data Output buffer - * @v len Length of output buffer - * @ret rc Return status code - * - * This algorithm is designed to be isomorphic to the Simple Discard - * Method described in ANS X9.82 Part 1-2006 Section 9.2.1 (NIST SP - * 800-90 Section B.5.1.1). - */ -int get_random_nz ( void *data, size_t len ) { - uint8_t *bytes = data; - int rc; - - while ( len ) { - - /* Generate random byte */ - if ( ( rc = rbg_generate ( NULL, 0, 0, bytes, 1 ) ) != 0 ) - return rc; - - /* Move to next byte if this byte is acceptable */ - if ( *bytes != 0 ) { - bytes++; - len--; - } - } - - return 0; -} diff --git a/qemu/roms/ipxe/src/crypto/rbg.c b/qemu/roms/ipxe/src/crypto/rbg.c deleted file mode 100644 index 943b288c3..000000000 --- a/qemu/roms/ipxe/src/crypto/rbg.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * RBG mechanism - * - * This mechanism is designed to comply with ANS X9.82 Part 4 (April - * 2011 Draft) Section 10. This standard is unfortunately not freely - * available. - * - * The chosen RBG design is that of a DRBG with a live entropy source - * with no conditioning function. Only a single security strength is - * supported. No seedfile is used since there may be no non-volatile - * storage available. The system UUID is used as the personalisation - * string. - */ - -#include <stdint.h> -#include <string.h> -#include <ipxe/init.h> -#include <ipxe/settings.h> -#include <ipxe/uuid.h> -#include <ipxe/crypto.h> -#include <ipxe/drbg.h> -#include <ipxe/rbg.h> - -/** The RBG */ -struct random_bit_generator rbg; - -/** - * Start up RBG - * - * @ret rc Return status code - * - * This is the RBG_Startup function defined in ANS X9.82 Part 4 (April - * 2011 Draft) Section 9.1.2.2. - */ -static int rbg_startup ( void ) { - union uuid uuid; - int len; - int rc; - - /* Try to obtain system UUID for use as personalisation - * string, in accordance with ANS X9.82 Part 3-2007 Section - * 8.5.2. If no UUID is available, proceed without a - * personalisation string. - */ - if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting, &uuid ) ) < 0 ) { - rc = len; - DBGC ( &rbg, "RBG could not fetch personalisation string: " - "%s\n", strerror ( rc ) ); - len = 0; - } - - /* Instantiate DRBG */ - if ( ( rc = drbg_instantiate ( &rbg.state, &uuid, len ) ) != 0 ) { - DBGC ( &rbg, "RBG could not instantiate DRBG: %s\n", - strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Shut down RBG - * - */ -static void rbg_shutdown ( void ) { - - /* Uninstantiate DRBG */ - drbg_uninstantiate ( &rbg.state ); -} - -/** RBG startup function */ -static void rbg_startup_fn ( void ) { - - /* Start up RBG. There is no way to report an error at this - * stage, but a failed startup will result in an invalid DRBG - * that refuses to generate bits. - */ - rbg_startup(); -} - -/** RBG shutdown function */ -static void rbg_shutdown_fn ( int booting __unused ) { - - /* Shut down RBG */ - rbg_shutdown(); -} - -/** RBG startup table entry */ -struct startup_fn startup_rbg __startup_fn ( STARTUP_NORMAL ) = { - .startup = rbg_startup_fn, - .shutdown = rbg_shutdown_fn, -}; diff --git a/qemu/roms/ipxe/src/crypto/rootcert.c b/qemu/roms/ipxe/src/crypto/rootcert.c deleted file mode 100644 index 00ea1647e..000000000 --- a/qemu/roms/ipxe/src/crypto/rootcert.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdlib.h> -#include <ipxe/crypto.h> -#include <ipxe/sha256.h> -#include <ipxe/x509.h> -#include <ipxe/settings.h> -#include <ipxe/dhcp.h> -#include <ipxe/init.h> -#include <ipxe/rootcert.h> - -/** @file - * - * Root certificate store - * - */ - -/** Length of a root certificate fingerprint */ -#define FINGERPRINT_LEN SHA256_DIGEST_SIZE - -/* Allow trusted certificates to be overridden if not explicitly specified */ -#ifdef TRUSTED -#define ALLOW_TRUST_OVERRIDE 0 -#else -#define ALLOW_TRUST_OVERRIDE 1 -#endif - -/* Use iPXE root CA if no trusted certificates are explicitly specified */ -#ifndef TRUSTED -#define TRUSTED \ - /* iPXE root CA */ \ - 0x9f, 0xaf, 0x71, 0x7b, 0x7f, 0x8c, 0xa2, 0xf9, 0x3c, 0x25, \ - 0x6c, 0x79, 0xf8, 0xac, 0x55, 0x91, 0x89, 0x5d, 0x66, 0xd1, \ - 0xff, 0x3b, 0xee, 0x63, 0x97, 0xa7, 0x0d, 0x29, 0xc6, 0x5e, \ - 0xed, 0x1a, -#endif - -/** Root certificate fingerprints */ -static const uint8_t fingerprints[] = { TRUSTED }; - -/** Root certificate fingerprint setting */ -static struct setting trust_setting __setting ( SETTING_CRYPTO, trust ) = { - .name = "trust", - .description = "Trusted root certificate fingerprints", - .tag = DHCP_EB_TRUST, - .type = &setting_type_hex, -}; - -/** Root certificates */ -struct x509_root root_certificates = { - .digest = &sha256_algorithm, - .count = ( sizeof ( fingerprints ) / FINGERPRINT_LEN ), - .fingerprints = fingerprints, -}; - -/** - * Initialise root certificate - * - * The list of trusted root certificates can be specified at build - * time using the TRUST= build parameter. If no certificates are - * specified, then the default iPXE root CA certificate is trusted. - * - * If no certificates were explicitly specified, then we allow the - * list of trusted root certificate fingerprints to be overridden - * using the "trust" setting, but only at the point of iPXE - * initialisation. This prevents untrusted sources of settings - * (e.g. DHCP) from subverting the chain of trust, while allowing - * trustworthy sources (e.g. VMware GuestInfo or non-volatile stored - * options) to specify the trusted root certificate without requiring - * a rebuild. - */ -static void rootcert_init ( void ) { - void *external = NULL; - int len; - - /* Allow trusted root certificates to be overridden only if - * not explicitly specified at build time. - */ - if ( ALLOW_TRUST_OVERRIDE ) { - - /* Fetch copy of "trust" setting, if it exists. This - * memory will never be freed. - */ - if ( ( len = fetch_raw_setting_copy ( NULL, &trust_setting, - &external ) ) >= 0 ) { - root_certificates.fingerprints = external; - root_certificates.count = ( len / FINGERPRINT_LEN ); - } - } - - DBGC ( &root_certificates, "ROOTCERT using %d %s certificate(s):\n", - root_certificates.count, ( external ? "external" : "built-in" )); - DBGC_HDA ( &root_certificates, 0, root_certificates.fingerprints, - ( root_certificates.count * FINGERPRINT_LEN ) ); -} - -/** Root certificate initialiser */ -struct init_fn rootcert_init_fn __init_fn ( INIT_LATE ) = { - .initialise = rootcert_init, -}; diff --git a/qemu/roms/ipxe/src/crypto/rsa.c b/qemu/roms/ipxe/src/crypto/rsa.c deleted file mode 100644 index 36109280d..000000000 --- a/qemu/roms/ipxe/src/crypto/rsa.c +++ /dev/null @@ -1,637 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#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/rsa.h> - -/** @file - * - * RSA public-key cryptography - * - * RSA is documented in RFC 3447. - */ - -/* Disambiguate the various error causes */ -#define EACCES_VERIFY \ - __einfo_error ( EINFO_EACCES_VERIFY ) -#define EINFO_EACCES_VERIFY \ - __einfo_uniqify ( EINFO_EACCES, 0x01, "RSA signature incorrect" ) - -/** "rsaEncryption" object identifier */ -static uint8_t oid_rsa_encryption[] = { ASN1_OID_RSAENCRYPTION }; - -/** "rsaEncryption" OID-identified algorithm */ -struct asn1_algorithm rsa_encryption_algorithm __asn1_algorithm = { - .name = "rsaEncryption", - .pubkey = &rsa_algorithm, - .digest = NULL, - .oid = ASN1_OID_CURSOR ( oid_rsa_encryption ), -}; - -/** - * 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; - - for_each_table_entry ( prefix, RSA_DIGESTINFO_PREFIXES ) { - 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 ); - bigint_t ( size ) *modulus; - bigint_t ( exponent_size ) *exponent; - size_t tmp_len = bigint_mod_exp_tmp_len ( modulus, exponent ); - struct { - bigint_t ( size ) modulus; - bigint_t ( exponent_size ) exponent; - bigint_t ( size ) input; - bigint_t ( size ) output; - uint8_t tmp[tmp_len]; - } __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]; - context->tmp = &dynamic->tmp; - - return 0; -} - -/** - * Parse RSA integer - * - * @v integer Integer to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int rsa_parse_integer ( 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 ) - return -EINVAL; - - return 0; -} - -/** - * Parse RSA modulus and exponent - * - * @v modulus Modulus to fill in - * @v exponent Exponent to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int rsa_parse_mod_exp ( struct asn1_cursor *modulus, - struct asn1_cursor *exponent, - const struct asn1_cursor *raw ) { - struct asn1_bit_string bits; - struct asn1_cursor cursor; - int is_private; - int rc; - - /* Enter subjectPublicKeyInfo/RSAPrivateKey */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - 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 */ - if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 ) - return rc; - cursor.data = bits.data; - cursor.len = bits.len; - - /* Enter RSAPublicKey */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - } - - /* Extract modulus */ - if ( ( rc = rsa_parse_integer ( modulus, &cursor ) ) != 0 ) - return rc; - 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 ( exponent, &cursor ) ) != 0 ) - return rc; - - 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; - struct asn1_cursor modulus; - struct asn1_cursor exponent; - struct asn1_cursor cursor; - int rc; - - /* Initialise context */ - memset ( context, 0, sizeof ( *context ) ); - - /* Initialise cursor */ - cursor.data = key; - cursor.len = key_len; - - /* Parse modulus and exponent */ - if ( ( rc = rsa_parse_mod_exp ( &modulus, &exponent, &cursor ) ) != 0 ){ - DBGC ( context, "RSA %p invalid modulus/exponent:\n", context ); - DBGC_HDA ( context, 0, cursor.data, cursor.len ); - 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, context->tmp ); - - /* 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_VERIFY; - } - - 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 ); -} - -/** - * Check for matching RSA public/private key pair - * - * @v private_key Private key - * @v private_key_len Private key length - * @v public_key Public key - * @v public_key_len Public key length - * @ret rc Return status code - */ -static int rsa_match ( const void *private_key, size_t private_key_len, - const void *public_key, size_t public_key_len ) { - struct asn1_cursor private_modulus; - struct asn1_cursor private_exponent; - struct asn1_cursor private_cursor; - struct asn1_cursor public_modulus; - struct asn1_cursor public_exponent; - struct asn1_cursor public_cursor; - int rc; - - /* Initialise cursors */ - private_cursor.data = private_key; - private_cursor.len = private_key_len; - public_cursor.data = public_key; - public_cursor.len = public_key_len; - - /* Parse moduli and exponents */ - if ( ( rc = rsa_parse_mod_exp ( &private_modulus, &private_exponent, - &private_cursor ) ) != 0 ) - return rc; - if ( ( rc = rsa_parse_mod_exp ( &public_modulus, &public_exponent, - &public_cursor ) ) != 0 ) - return rc; - - /* Compare moduli */ - if ( asn1_compare ( &private_modulus, &public_modulus ) != 0 ) - return -ENOTTY; - - return 0; -} - -/** 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, - .match = rsa_match, -}; diff --git a/qemu/roms/ipxe/src/crypto/sha1.c b/qemu/roms/ipxe/src/crypto/sha1.c deleted file mode 100644 index 51866f4b7..000000000 --- a/qemu/roms/ipxe/src/crypto/sha1.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * SHA-1 algorithm - * - */ - -#include <stdint.h> -#include <string.h> -#include <byteswap.h> -#include <assert.h> -#include <ipxe/rotate.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/sha1.h> - -/** SHA-1 variables */ -struct sha1_variables { - /* This layout matches that of struct sha1_digest_data, - * allowing for efficient endianness-conversion, - */ - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - uint32_t e; - uint32_t w[80]; -} __attribute__ (( packed )); - -/** - * f(a,b,c,d) for steps 0 to 19 - * - * @v v SHA-1 variables - * @ret f f(a,b,c,d) - */ -static uint32_t sha1_f_0_19 ( struct sha1_variables *v ) { - return ( ( v->b & v->c ) | ( (~v->b) & v->d ) ); -} - -/** - * f(a,b,c,d) for steps 20 to 39 and 60 to 79 - * - * @v v SHA-1 variables - * @ret f f(a,b,c,d) - */ -static uint32_t sha1_f_20_39_60_79 ( struct sha1_variables *v ) { - return ( v->b ^ v->c ^ v->d ); -} - -/** - * f(a,b,c,d) for steps 40 to 59 - * - * @v v SHA-1 variables - * @ret f f(a,b,c,d) - */ -static uint32_t sha1_f_40_59 ( struct sha1_variables *v ) { - return ( ( v->b & v->c ) | ( v->b & v->d ) | ( v->c & v->d ) ); -} - -/** An SHA-1 step function */ -struct sha1_step { - /** - * Calculate f(a,b,c,d) - * - * @v v SHA-1 variables - * @ret f f(a,b,c,d) - */ - uint32_t ( * f ) ( struct sha1_variables *v ); - /** Constant k */ - uint32_t k; -}; - -/** SHA-1 steps */ -static struct sha1_step sha1_steps[4] = { - /** 0 to 19 */ - { .f = sha1_f_0_19, .k = 0x5a827999 }, - /** 20 to 39 */ - { .f = sha1_f_20_39_60_79, .k = 0x6ed9eba1 }, - /** 40 to 59 */ - { .f = sha1_f_40_59, .k = 0x8f1bbcdc }, - /** 60 to 79 */ - { .f = sha1_f_20_39_60_79, .k = 0xca62c1d6 }, -}; - -/** - * Initialise SHA-1 algorithm - * - * @v ctx SHA-1 context - */ -static void sha1_init ( void *ctx ) { - struct sha1_context *context = ctx; - - context->ddd.dd.digest.h[0] = cpu_to_be32 ( 0x67452301 ); - context->ddd.dd.digest.h[1] = cpu_to_be32 ( 0xefcdab89 ); - context->ddd.dd.digest.h[2] = cpu_to_be32 ( 0x98badcfe ); - context->ddd.dd.digest.h[3] = cpu_to_be32 ( 0x10325476 ); - context->ddd.dd.digest.h[4] = cpu_to_be32 ( 0xc3d2e1f0 ); - context->len = 0; -} - -/** - * Calculate SHA-1 digest of accumulated data - * - * @v context SHA-1 context - */ -static void sha1_digest ( struct sha1_context *context ) { - union { - union sha1_digest_data_dwords ddd; - struct sha1_variables v; - } u; - uint32_t *a = &u.v.a; - uint32_t *b = &u.v.b; - uint32_t *c = &u.v.c; - uint32_t *d = &u.v.d; - uint32_t *e = &u.v.e; - uint32_t *w = u.v.w; - uint32_t f; - uint32_t k; - uint32_t temp; - struct sha1_step *step; - unsigned int i; - - /* Sanity checks */ - assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); - linker_assert ( &u.ddd.dd.digest.h[0] == a, sha1_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[1] == b, sha1_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[2] == c, sha1_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[3] == d, sha1_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[4] == e, sha1_bad_layout ); - linker_assert ( &u.ddd.dd.data.dword[0] == w, sha1_bad_layout ); - - DBGC ( context, "SHA1 digesting:\n" ); - DBGC_HDA ( context, 0, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); - DBGC_HDA ( context, context->len, &context->ddd.dd.data, - sizeof ( context->ddd.dd.data ) ); - - /* Convert h[0..4] to host-endian, and initialise a, b, c, d, - * e, and w[0..15] - */ - for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) / - sizeof ( u.ddd.dword[0] ) ) ; i++ ) { - be32_to_cpus ( &context->ddd.dword[i] ); - u.ddd.dword[i] = context->ddd.dword[i]; - } - - /* Initialise w[16..79] */ - for ( i = 16 ; i < 80 ; i++ ) - w[i] = rol32 ( ( w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16] ), 1 ); - - /* Main loop */ - for ( i = 0 ; i < 80 ; i++ ) { - step = &sha1_steps[ i / 20 ]; - f = step->f ( &u.v ); - k = step->k; - temp = ( rol32 ( *a, 5 ) + f + *e + k + w[i] ); - *e = *d; - *d = *c; - *c = rol32 ( *b, 30 ); - *b = *a; - *a = temp; - DBGC2 ( context, "%2d : %08x %08x %08x %08x %08x\n", - i, *a, *b, *c, *d, *e ); - } - - /* Add chunk to hash and convert back to big-endian */ - for ( i = 0 ; i < 5 ; i++ ) { - context->ddd.dd.digest.h[i] = - cpu_to_be32 ( context->ddd.dd.digest.h[i] + - u.ddd.dd.digest.h[i] ); - } - - DBGC ( context, "SHA1 digested:\n" ); - DBGC_HDA ( context, 0, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); -} - -/** - * Accumulate data with SHA-1 algorithm - * - * @v ctx SHA-1 context - * @v data Data - * @v len Length of data - */ -static void sha1_update ( void *ctx, const void *data, size_t len ) { - struct sha1_context *context = ctx; - const uint8_t *byte = data; - size_t offset; - - /* Accumulate data a byte at a time, performing the digest - * whenever we fill the data buffer - */ - while ( len-- ) { - offset = ( context->len % sizeof ( context->ddd.dd.data ) ); - context->ddd.dd.data.byte[offset] = *(byte++); - context->len++; - if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ) - sha1_digest ( context ); - } -} - -/** - * Generate SHA-1 digest - * - * @v ctx SHA-1 context - * @v out Output buffer - */ -static void sha1_final ( void *ctx, void *out ) { - struct sha1_context *context = ctx; - uint64_t len_bits; - uint8_t pad; - - /* Record length before pre-processing */ - len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 ); - - /* Pad with a single "1" bit followed by as many "0" bits as required */ - pad = 0x80; - do { - sha1_update ( ctx, &pad, sizeof ( pad ) ); - pad = 0x00; - } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) != - offsetof ( typeof ( context->ddd.dd.data ), final.len ) ); - - /* Append length (in bits) */ - sha1_update ( ctx, &len_bits, sizeof ( len_bits ) ); - assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); - - /* Copy out final digest */ - memcpy ( out, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); -} - -/** SHA-1 algorithm */ -struct digest_algorithm sha1_algorithm = { - .name = "sha1", - .ctxsize = sizeof ( struct sha1_context ), - .blocksize = sizeof ( union sha1_block ), - .digestsize = sizeof ( struct sha1_digest ), - .init = sha1_init, - .update = sha1_update, - .final = sha1_final, -}; - -/** "sha1" object identifier */ -static uint8_t oid_sha1[] = { ASN1_OID_SHA1 }; - -/** "sha1" OID-identified algorithm */ -struct asn1_algorithm oid_sha1_algorithm __asn1_algorithm = { - .name = "sha1", - .digest = &sha1_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha1 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/sha1extra.c b/qemu/roms/ipxe/src/crypto/sha1extra.c deleted file mode 100644 index cec0d35e5..000000000 --- a/qemu/roms/ipxe/src/crypto/sha1extra.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <string.h> -#include <ipxe/crypto.h> -#include <ipxe/sha1.h> -#include <ipxe/hmac.h> -#include <stdint.h> -#include <byteswap.h> - -/** - * SHA1 pseudorandom function for creating derived keys - * - * @v key Master key with which this call is associated - * @v key_len Length of key - * @v label NUL-terminated ASCII string describing purpose of PRF data - * @v data Further data that should be included in the PRF - * @v data_len Length of further PRF data - * @v prf_len Bytes of PRF to generate - * @ret prf Pseudorandom function bytes - * - * This is the PRF variant used by 802.11, defined in IEEE 802.11-2007 - * 8.5.5.1. EAP-FAST uses a different SHA1-based PRF, and TLS uses an - * MD5-based PRF. - */ -void prf_sha1 ( const void *key, size_t key_len, const char *label, - const void *data, size_t data_len, void *prf, size_t prf_len ) -{ - u32 blk; - u8 keym[key_len]; /* modifiable copy of key */ - u8 in[strlen ( label ) + 1 + data_len + 1]; /* message to HMAC */ - u8 *in_blknr; /* pointer to last byte of in, block number */ - u8 out[SHA1_DIGEST_SIZE]; /* HMAC-SHA1 result */ - u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */ - const size_t label_len = strlen ( label ); - - /* The HMAC-SHA-1 is calculated using the given key on the - message text `label', followed by a NUL, followed by one - byte indicating the block number (0 for first). */ - - memcpy ( keym, key, key_len ); - - memcpy ( in, label, strlen ( label ) + 1 ); - memcpy ( in + label_len + 1, data, data_len ); - in_blknr = in + label_len + 1 + data_len; - - for ( blk = 0 ;; blk++ ) { - *in_blknr = blk; - - hmac_init ( &sha1_algorithm, sha1_ctx, keym, &key_len ); - hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) ); - hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out ); - - if ( prf_len <= sizeof ( out ) ) { - memcpy ( prf, out, prf_len ); - break; - } - - memcpy ( prf, out, sizeof ( out ) ); - prf_len -= sizeof ( out ); - prf += sizeof ( out ); - } -} - -/** - * PBKDF2 key derivation function inner block operation - * - * @v passphrase Passphrase from which to derive key - * @v pass_len Length of passphrase - * @v salt Salt to include in key - * @v salt_len Length of salt - * @v iterations Number of iterations of SHA1 to perform - * @v blocknr Index of this block, starting at 1 - * @ret block SHA1_SIZE bytes of PBKDF2 data - * - * The operation of this function is described in RFC 2898. - */ -static void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len, - const void *salt, size_t salt_len, - int iterations, u32 blocknr, u8 *block ) -{ - u8 pass[pass_len]; /* modifiable passphrase */ - u8 in[salt_len + 4]; /* input buffer to first round */ - u8 last[SHA1_DIGEST_SIZE]; /* output of round N, input of N+1 */ - u8 sha1_ctx[SHA1_CTX_SIZE]; - u8 *next_in = in; /* changed to `last' after first round */ - int next_size = sizeof ( in ); - int i; - unsigned int j; - - blocknr = htonl ( blocknr ); - - memcpy ( pass, passphrase, pass_len ); - memcpy ( in, salt, salt_len ); - memcpy ( in + salt_len, &blocknr, 4 ); - memset ( block, 0, sizeof ( last ) ); - - for ( i = 0; i < iterations; i++ ) { - hmac_init ( &sha1_algorithm, sha1_ctx, pass, &pass_len ); - hmac_update ( &sha1_algorithm, sha1_ctx, next_in, next_size ); - hmac_final ( &sha1_algorithm, sha1_ctx, pass, &pass_len, last ); - - for ( j = 0; j < sizeof ( last ); j++ ) { - block[j] ^= last[j]; - } - - next_in = last; - next_size = sizeof ( last ); - } -} - -/** - * PBKDF2 key derivation function using SHA1 - * - * @v passphrase Passphrase from which to derive key - * @v pass_len Length of passphrase - * @v salt Salt to include in key - * @v salt_len Length of salt - * @v iterations Number of iterations of SHA1 to perform - * @v key_len Length of key to generate - * @ret key Generated key bytes - * - * This is used most notably in 802.11 WPA passphrase hashing, in - * which case the salt is the SSID, 4096 iterations are used, and a - * 32-byte key is generated that serves as the Pairwise Master Key for - * EAPOL authentication. - * - * The operation of this function is further described in RFC 2898. - */ -void pbkdf2_sha1 ( const void *passphrase, size_t pass_len, - const void *salt, size_t salt_len, - int iterations, void *key, size_t key_len ) -{ - u32 blocks = ( key_len + SHA1_DIGEST_SIZE - 1 ) / SHA1_DIGEST_SIZE; - u32 blk; - u8 buf[SHA1_DIGEST_SIZE]; - - for ( blk = 1; blk <= blocks; blk++ ) { - pbkdf2_sha1_f ( passphrase, pass_len, salt, salt_len, - iterations, blk, buf ); - if ( key_len <= sizeof ( buf ) ) { - memcpy ( key, buf, key_len ); - break; - } - - memcpy ( key, buf, sizeof ( buf ) ); - key_len -= sizeof ( buf ); - key += sizeof ( buf ); - } -} diff --git a/qemu/roms/ipxe/src/crypto/sha224.c b/qemu/roms/ipxe/src/crypto/sha224.c deleted file mode 100644 index be25f24e9..000000000 --- a/qemu/roms/ipxe/src/crypto/sha224.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * SHA-224 algorithm - * - */ - -#include <stdint.h> -#include <byteswap.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/sha256.h> - -/** SHA-224 initial digest values */ -static const struct sha256_digest sha224_init_digest = { - .h = { - cpu_to_be32 ( 0xc1059ed8 ), - cpu_to_be32 ( 0x367cd507 ), - cpu_to_be32 ( 0x3070dd17 ), - cpu_to_be32 ( 0xf70e5939 ), - cpu_to_be32 ( 0xffc00b31 ), - cpu_to_be32 ( 0x68581511 ), - cpu_to_be32 ( 0x64f98fa7 ), - cpu_to_be32 ( 0xbefa4fa4 ), - }, -}; - -/** - * Initialise SHA-224 algorithm - * - * @v ctx SHA-224 context - */ -static void sha224_init ( void *ctx ) { - struct sha256_context *context = ctx; - - sha256_family_init ( context, &sha224_init_digest, SHA224_DIGEST_SIZE ); -} - -/** SHA-224 algorithm */ -struct digest_algorithm sha224_algorithm = { - .name = "sha224", - .ctxsize = sizeof ( struct sha256_context ), - .blocksize = sizeof ( union sha256_block ), - .digestsize = SHA224_DIGEST_SIZE, - .init = sha224_init, - .update = sha256_update, - .final = sha256_final, -}; - -/** "sha224" object identifier */ -static uint8_t oid_sha224[] = { ASN1_OID_SHA224 }; - -/** "sha224" OID-identified algorithm */ -struct asn1_algorithm oid_sha224_algorithm __asn1_algorithm = { - .name = "sha224", - .digest = &sha224_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha224 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/sha256.c b/qemu/roms/ipxe/src/crypto/sha256.c deleted file mode 100644 index 0360d8d16..000000000 --- a/qemu/roms/ipxe/src/crypto/sha256.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * SHA-256 algorithm - * - */ - -#include <stdint.h> -#include <string.h> -#include <byteswap.h> -#include <assert.h> -#include <ipxe/rotate.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/sha256.h> - -/** SHA-256 variables */ -struct sha256_variables { - /* This layout matches that of struct sha256_digest_data, - * allowing for efficient endianness-conversion, - */ - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - uint32_t e; - uint32_t f; - uint32_t g; - uint32_t h; - uint32_t w[SHA256_ROUNDS]; -} __attribute__ (( packed )); - -/** SHA-256 constants */ -static const uint32_t k[SHA256_ROUNDS] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, - 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, - 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, - 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -/** SHA-256 initial digest values */ -static const struct sha256_digest sha256_init_digest = { - .h = { - cpu_to_be32 ( 0x6a09e667 ), - cpu_to_be32 ( 0xbb67ae85 ), - cpu_to_be32 ( 0x3c6ef372 ), - cpu_to_be32 ( 0xa54ff53a ), - cpu_to_be32 ( 0x510e527f ), - cpu_to_be32 ( 0x9b05688c ), - cpu_to_be32 ( 0x1f83d9ab ), - cpu_to_be32 ( 0x5be0cd19 ), - }, -}; - -/** - * Initialise SHA-256 family algorithm - * - * @v context SHA-256 context - * @v init Initial digest values - * @v digestsize Digest size - */ -void sha256_family_init ( struct sha256_context *context, - const struct sha256_digest *init, - size_t digestsize ) { - - context->len = 0; - context->digestsize = digestsize; - memcpy ( &context->ddd.dd.digest, init, - sizeof ( context->ddd.dd.digest ) ); -} - -/** - * Initialise SHA-256 algorithm - * - * @v ctx SHA-256 context - */ -static void sha256_init ( void *ctx ) { - struct sha256_context *context = ctx; - - sha256_family_init ( context, &sha256_init_digest, - sizeof ( struct sha256_digest ) ); -} - -/** - * Calculate SHA-256 digest of accumulated data - * - * @v context SHA-256 context - */ -static void sha256_digest ( struct sha256_context *context ) { - union { - union sha256_digest_data_dwords ddd; - struct sha256_variables v; - } u; - uint32_t *a = &u.v.a; - uint32_t *b = &u.v.b; - uint32_t *c = &u.v.c; - uint32_t *d = &u.v.d; - uint32_t *e = &u.v.e; - uint32_t *f = &u.v.f; - uint32_t *g = &u.v.g; - uint32_t *h = &u.v.h; - uint32_t *w = u.v.w; - uint32_t s0; - uint32_t s1; - uint32_t maj; - uint32_t t1; - uint32_t t2; - uint32_t ch; - unsigned int i; - - /* Sanity checks */ - assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); - linker_assert ( &u.ddd.dd.digest.h[0] == a, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[1] == b, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[2] == c, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[3] == d, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[4] == e, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[5] == f, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[6] == g, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.digest.h[7] == h, sha256_bad_layout ); - linker_assert ( &u.ddd.dd.data.dword[0] == w, sha256_bad_layout ); - - DBGC ( context, "SHA256 digesting:\n" ); - DBGC_HDA ( context, 0, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); - DBGC_HDA ( context, context->len, &context->ddd.dd.data, - sizeof ( context->ddd.dd.data ) ); - - /* Convert h[0..7] to host-endian, and initialise a, b, c, d, - * e, f, g, h, and w[0..15] - */ - for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) / - sizeof ( u.ddd.dword[0] ) ) ; i++ ) { - be32_to_cpus ( &context->ddd.dword[i] ); - u.ddd.dword[i] = context->ddd.dword[i]; - } - - /* Initialise w[16..63] */ - for ( i = 16 ; i < SHA256_ROUNDS ; i++ ) { - s0 = ( ror32 ( w[i-15], 7 ) ^ ror32 ( w[i-15], 18 ) ^ - ( w[i-15] >> 3 ) ); - s1 = ( ror32 ( w[i-2], 17 ) ^ ror32 ( w[i-2], 19 ) ^ - ( w[i-2] >> 10 ) ); - w[i] = ( w[i-16] + s0 + w[i-7] + s1 ); - } - - /* Main loop */ - for ( i = 0 ; i < SHA256_ROUNDS ; i++ ) { - s0 = ( ror32 ( *a, 2 ) ^ ror32 ( *a, 13 ) ^ ror32 ( *a, 22 ) ); - maj = ( ( *a & *b ) ^ ( *a & *c ) ^ ( *b & *c ) ); - t2 = ( s0 + maj ); - s1 = ( ror32 ( *e, 6 ) ^ ror32 ( *e, 11 ) ^ ror32 ( *e, 25 ) ); - ch = ( ( *e & *f ) ^ ( (~*e) & *g ) ); - t1 = ( *h + s1 + ch + k[i] + w[i] ); - *h = *g; - *g = *f; - *f = *e; - *e = ( *d + t1 ); - *d = *c; - *c = *b; - *b = *a; - *a = ( t1 + t2 ); - DBGC2 ( context, "%2d : %08x %08x %08x %08x %08x %08x %08x " - "%08x\n", i, *a, *b, *c, *d, *e, *f, *g, *h ); - } - - /* Add chunk to hash and convert back to big-endian */ - for ( i = 0 ; i < 8 ; i++ ) { - context->ddd.dd.digest.h[i] = - cpu_to_be32 ( context->ddd.dd.digest.h[i] + - u.ddd.dd.digest.h[i] ); - } - - DBGC ( context, "SHA256 digested:\n" ); - DBGC_HDA ( context, 0, &context->ddd.dd.digest, - sizeof ( context->ddd.dd.digest ) ); -} - -/** - * Accumulate data with SHA-256 algorithm - * - * @v ctx SHA-256 context - * @v data Data - * @v len Length of data - */ -void sha256_update ( void *ctx, const void *data, size_t len ) { - struct sha256_context *context = ctx; - const uint8_t *byte = data; - size_t offset; - - /* Accumulate data a byte at a time, performing the digest - * whenever we fill the data buffer - */ - while ( len-- ) { - offset = ( context->len % sizeof ( context->ddd.dd.data ) ); - context->ddd.dd.data.byte[offset] = *(byte++); - context->len++; - if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ) - sha256_digest ( context ); - } -} - -/** - * Generate SHA-256 digest - * - * @v ctx SHA-256 context - * @v out Output buffer - */ -void sha256_final ( void *ctx, void *out ) { - struct sha256_context *context = ctx; - uint64_t len_bits; - uint8_t pad; - - /* Record length before pre-processing */ - len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 ); - - /* Pad with a single "1" bit followed by as many "0" bits as required */ - pad = 0x80; - do { - sha256_update ( ctx, &pad, sizeof ( pad ) ); - pad = 0x00; - } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) != - offsetof ( typeof ( context->ddd.dd.data ), final.len ) ); - - /* Append length (in bits) */ - sha256_update ( ctx, &len_bits, sizeof ( len_bits ) ); - assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 ); - - /* Copy out final digest */ - memcpy ( out, &context->ddd.dd.digest, context->digestsize ); -} - -/** SHA-256 algorithm */ -struct digest_algorithm sha256_algorithm = { - .name = "sha256", - .ctxsize = sizeof ( struct sha256_context ), - .blocksize = sizeof ( union sha256_block ), - .digestsize = sizeof ( struct sha256_digest ), - .init = sha256_init, - .update = sha256_update, - .final = sha256_final, -}; - -/** "sha256" object identifier */ -static uint8_t oid_sha256[] = { ASN1_OID_SHA256 }; - -/** "sha256" OID-identified algorithm */ -struct asn1_algorithm oid_sha256_algorithm __asn1_algorithm = { - .name = "sha256", - .digest = &sha256_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha256 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/sha384.c b/qemu/roms/ipxe/src/crypto/sha384.c deleted file mode 100644 index 017751826..000000000 --- a/qemu/roms/ipxe/src/crypto/sha384.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * SHA-384 algorithm - * - */ - -#include <stdint.h> -#include <byteswap.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/sha512.h> - -/** SHA-384 initial digest values */ -static const struct sha512_digest sha384_init_digest = { - .h = { - cpu_to_be64 ( 0xcbbb9d5dc1059ed8ULL ), - cpu_to_be64 ( 0x629a292a367cd507ULL ), - cpu_to_be64 ( 0x9159015a3070dd17ULL ), - cpu_to_be64 ( 0x152fecd8f70e5939ULL ), - cpu_to_be64 ( 0x67332667ffc00b31ULL ), - cpu_to_be64 ( 0x8eb44a8768581511ULL ), - cpu_to_be64 ( 0xdb0c2e0d64f98fa7ULL ), - cpu_to_be64 ( 0x47b5481dbefa4fa4ULL ), - }, -}; - -/** - * Initialise SHA-384 algorithm - * - * @v ctx SHA-384 context - */ -static void sha384_init ( void *ctx ) { - struct sha512_context *context = ctx; - - sha512_family_init ( context, &sha384_init_digest, SHA384_DIGEST_SIZE ); -} - -/** SHA-384 algorithm */ -struct digest_algorithm sha384_algorithm = { - .name = "sha384", - .ctxsize = sizeof ( struct sha512_context ), - .blocksize = sizeof ( union sha512_block ), - .digestsize = SHA384_DIGEST_SIZE, - .init = sha384_init, - .update = sha512_update, - .final = sha512_final, -}; - -/** "sha384" object identifier */ -static uint8_t oid_sha384[] = { ASN1_OID_SHA384 }; - -/** "sha384" OID-identified algorithm */ -struct asn1_algorithm oid_sha384_algorithm __asn1_algorithm = { - .name = "sha384", - .digest = &sha384_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha384 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/sha512.c b/qemu/roms/ipxe/src/crypto/sha512.c deleted file mode 100644 index 814f44563..000000000 --- a/qemu/roms/ipxe/src/crypto/sha512.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * SHA-512 algorithm - * - */ - -#include <stdint.h> -#include <string.h> -#include <byteswap.h> -#include <assert.h> -#include <ipxe/rotate.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/sha512.h> - -/** SHA-512 variables */ -struct sha512_variables { - /* This layout matches that of struct sha512_digest_data, - * allowing for efficient endianness-conversion, - */ - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; - uint64_t e; - uint64_t f; - uint64_t g; - uint64_t h; - uint64_t w[SHA512_ROUNDS]; -} __attribute__ (( packed )); - -/** SHA-512 constants */ -static const uint64_t k[SHA512_ROUNDS] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, - 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, - 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, - 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, - 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, - 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, - 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, - 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, - 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, - 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, - 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, - 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, - 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, - 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL -}; - -/** SHA-512 initial digest values */ -static const struct sha512_digest sha512_init_digest = { - .h = { - cpu_to_be64 ( 0x6a09e667f3bcc908ULL ), - cpu_to_be64 ( 0xbb67ae8584caa73bULL ), - cpu_to_be64 ( 0x3c6ef372fe94f82bULL ), - cpu_to_be64 ( 0xa54ff53a5f1d36f1ULL ), - cpu_to_be64 ( 0x510e527fade682d1ULL ), - cpu_to_be64 ( 0x9b05688c2b3e6c1fULL ), - cpu_to_be64 ( 0x1f83d9abfb41bd6bULL ), - cpu_to_be64 ( 0x5be0cd19137e2179ULL ), - }, -}; - -/** - * Initialise SHA-512 family algorithm - * - * @v context SHA-512 context - * @v init Initial digest values - * @v digestsize Digest size - */ -void sha512_family_init ( struct sha512_context *context, - const struct sha512_digest *init, - size_t digestsize ) { - - context->len = 0; - context->digestsize = digestsize; - memcpy ( &context->ddq.dd.digest, init, - sizeof ( context->ddq.dd.digest ) ); -} - -/** - * Initialise SHA-512 algorithm - * - * @v ctx SHA-512 context - */ -static void sha512_init ( void *ctx ) { - struct sha512_context *context = ctx; - - sha512_family_init ( context, &sha512_init_digest, - sizeof ( struct sha512_digest ) ); -} - -/** - * Calculate SHA-512 digest of accumulated data - * - * @v context SHA-512 context - */ -static void sha512_digest ( struct sha512_context *context ) { - union { - union sha512_digest_data_qwords ddq; - struct sha512_variables v; - } u; - uint64_t *a = &u.v.a; - uint64_t *b = &u.v.b; - uint64_t *c = &u.v.c; - uint64_t *d = &u.v.d; - uint64_t *e = &u.v.e; - uint64_t *f = &u.v.f; - uint64_t *g = &u.v.g; - uint64_t *h = &u.v.h; - uint64_t *w = u.v.w; - uint64_t s0; - uint64_t s1; - uint64_t maj; - uint64_t t1; - uint64_t t2; - uint64_t ch; - unsigned int i; - - /* Sanity checks */ - assert ( ( context->len % sizeof ( context->ddq.dd.data ) ) == 0 ); - linker_assert ( &u.ddq.dd.digest.h[0] == a, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.digest.h[1] == b, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.digest.h[2] == c, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.digest.h[3] == d, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.digest.h[4] == e, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.digest.h[5] == f, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.digest.h[6] == g, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.digest.h[7] == h, sha512_bad_layout ); - linker_assert ( &u.ddq.dd.data.qword[0] == w, sha512_bad_layout ); - - DBGC ( context, "SHA512 digesting:\n" ); - DBGC_HDA ( context, 0, &context->ddq.dd.digest, - sizeof ( context->ddq.dd.digest ) ); - DBGC_HDA ( context, context->len, &context->ddq.dd.data, - sizeof ( context->ddq.dd.data ) ); - - /* Convert h[0..7] to host-endian, and initialise a, b, c, d, - * e, f, g, h, and w[0..15] - */ - for ( i = 0 ; i < ( sizeof ( u.ddq.qword ) / - sizeof ( u.ddq.qword[0] ) ) ; i++ ) { - be64_to_cpus ( &context->ddq.qword[i] ); - u.ddq.qword[i] = context->ddq.qword[i]; - } - - /* Initialise w[16..79] */ - for ( i = 16 ; i < SHA512_ROUNDS ; i++ ) { - s0 = ( ror64 ( w[i-15], 1 ) ^ ror64 ( w[i-15], 8 ) ^ - ( w[i-15] >> 7 ) ); - s1 = ( ror64 ( w[i-2], 19 ) ^ ror64 ( w[i-2], 61 ) ^ - ( w[i-2] >> 6 ) ); - w[i] = ( w[i-16] + s0 + w[i-7] + s1 ); - } - - /* Main loop */ - for ( i = 0 ; i < SHA512_ROUNDS ; i++ ) { - s0 = ( ror64 ( *a, 28 ) ^ ror64 ( *a, 34 ) ^ ror64 ( *a, 39 ) ); - maj = ( ( *a & *b ) ^ ( *a & *c ) ^ ( *b & *c ) ); - t2 = ( s0 + maj ); - s1 = ( ror64 ( *e, 14 ) ^ ror64 ( *e, 18 ) ^ ror64 ( *e, 41 ) ); - ch = ( ( *e & *f ) ^ ( (~*e) & *g ) ); - t1 = ( *h + s1 + ch + k[i] + w[i] ); - *h = *g; - *g = *f; - *f = *e; - *e = ( *d + t1 ); - *d = *c; - *c = *b; - *b = *a; - *a = ( t1 + t2 ); - DBGC2 ( context, "%2d : %016llx %016llx %016llx %016llx " - "%016llx %016llx %016llx %016llx\n", - i, *a, *b, *c, *d, *e, *f, *g, *h ); - } - - /* Add chunk to hash and convert back to big-endian */ - for ( i = 0 ; i < 8 ; i++ ) { - context->ddq.dd.digest.h[i] = - cpu_to_be64 ( context->ddq.dd.digest.h[i] + - u.ddq.dd.digest.h[i] ); - } - - DBGC ( context, "SHA512 digested:\n" ); - DBGC_HDA ( context, 0, &context->ddq.dd.digest, - sizeof ( context->ddq.dd.digest ) ); -} - -/** - * Accumulate data with SHA-512 algorithm - * - * @v ctx SHA-512 context - * @v data Data - * @v len Length of data - */ -void sha512_update ( void *ctx, const void *data, size_t len ) { - struct sha512_context *context = ctx; - const uint8_t *byte = data; - size_t offset; - - /* Accumulate data a byte at a time, performing the digest - * whenever we fill the data buffer - */ - while ( len-- ) { - offset = ( context->len % sizeof ( context->ddq.dd.data ) ); - context->ddq.dd.data.byte[offset] = *(byte++); - context->len++; - if ( ( context->len % sizeof ( context->ddq.dd.data ) ) == 0 ) - sha512_digest ( context ); - } -} - -/** - * Generate SHA-512 digest - * - * @v ctx SHA-512 context - * @v out Output buffer - */ -void sha512_final ( void *ctx, void *out ) { - struct sha512_context *context = ctx; - uint64_t len_bits_hi; - uint64_t len_bits_lo; - uint8_t pad; - - /* Record length before pre-processing */ - len_bits_hi = 0; - len_bits_lo = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 ); - - /* Pad with a single "1" bit followed by as many "0" bits as required */ - pad = 0x80; - do { - sha512_update ( ctx, &pad, sizeof ( pad ) ); - pad = 0x00; - } while ( ( context->len % sizeof ( context->ddq.dd.data ) ) != - offsetof ( typeof ( context->ddq.dd.data ), final.len_hi ) ); - - /* Append length (in bits) */ - sha512_update ( ctx, &len_bits_hi, sizeof ( len_bits_hi ) ); - sha512_update ( ctx, &len_bits_lo, sizeof ( len_bits_lo ) ); - assert ( ( context->len % sizeof ( context->ddq.dd.data ) ) == 0 ); - - /* Copy out final digest */ - memcpy ( out, &context->ddq.dd.digest, context->digestsize ); -} - -/** SHA-512 algorithm */ -struct digest_algorithm sha512_algorithm = { - .name = "sha512", - .ctxsize = sizeof ( struct sha512_context ), - .blocksize = sizeof ( union sha512_block ), - .digestsize = sizeof ( struct sha512_digest ), - .init = sha512_init, - .update = sha512_update, - .final = sha512_final, -}; - -/** "sha512" object identifier */ -static uint8_t oid_sha512[] = { ASN1_OID_SHA512 }; - -/** "sha512" OID-identified algorithm */ -struct asn1_algorithm oid_sha512_algorithm __asn1_algorithm = { - .name = "sha512", - .digest = &sha512_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha512 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/sha512_224.c b/qemu/roms/ipxe/src/crypto/sha512_224.c deleted file mode 100644 index 8c37b566b..000000000 --- a/qemu/roms/ipxe/src/crypto/sha512_224.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * SHA-512/224 algorithm - * - */ - -#include <stdint.h> -#include <byteswap.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/sha512.h> - -/** SHA-512/224 initial digest values */ -static const struct sha512_digest sha512_224_init_digest = { - .h = { - cpu_to_be64 ( 0x8c3d37c819544da2ULL ), - cpu_to_be64 ( 0x73e1996689dcd4d6ULL ), - cpu_to_be64 ( 0x1dfab7ae32ff9c82ULL ), - cpu_to_be64 ( 0x679dd514582f9fcfULL ), - cpu_to_be64 ( 0x0f6d2b697bd44da8ULL ), - cpu_to_be64 ( 0x77e36f7304c48942ULL ), - cpu_to_be64 ( 0x3f9d85a86a1d36c8ULL ), - cpu_to_be64 ( 0x1112e6ad91d692a1ULL ), - }, -}; - -/** - * Initialise SHA-512/224 algorithm - * - * @v ctx SHA-512/224 context - */ -static void sha512_224_init ( void *ctx ) { - struct sha512_context *context = ctx; - - sha512_family_init ( context, &sha512_224_init_digest, - SHA512_224_DIGEST_SIZE ); -} - -/** SHA-512/224 algorithm */ -struct digest_algorithm sha512_224_algorithm = { - .name = "sha512/224", - .ctxsize = sizeof ( struct sha512_context ), - .blocksize = sizeof ( union sha512_block ), - .digestsize = SHA512_224_DIGEST_SIZE, - .init = sha512_224_init, - .update = sha512_update, - .final = sha512_final, -}; - -/** "sha512_224" object identifier */ -static uint8_t oid_sha512_224[] = { ASN1_OID_SHA512_224 }; - -/** "sha512_224" OID-identified algorithm */ -struct asn1_algorithm oid_sha512_224_algorithm __asn1_algorithm = { - .name = "sha512/224", - .digest = &sha512_224_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha512_224 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/sha512_256.c b/qemu/roms/ipxe/src/crypto/sha512_256.c deleted file mode 100644 index f8afaf3e3..000000000 --- a/qemu/roms/ipxe/src/crypto/sha512_256.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -/** @file - * - * SHA-512/256 algorithm - * - */ - -#include <stdint.h> -#include <byteswap.h> -#include <ipxe/crypto.h> -#include <ipxe/asn1.h> -#include <ipxe/sha512.h> - -/** SHA-512/256 initial digest values */ -static const struct sha512_digest sha512_256_init_digest = { - .h = { - cpu_to_be64 ( 0x22312194fc2bf72cULL ), - cpu_to_be64 ( 0x9f555fa3c84c64c2ULL ), - cpu_to_be64 ( 0x2393b86b6f53b151ULL ), - cpu_to_be64 ( 0x963877195940eabdULL ), - cpu_to_be64 ( 0x96283ee2a88effe3ULL ), - cpu_to_be64 ( 0xbe5e1e2553863992ULL ), - cpu_to_be64 ( 0x2b0199fc2c85b8aaULL ), - cpu_to_be64 ( 0x0eb72ddc81c52ca2ULL ), - }, -}; - -/** - * Initialise SHA-512/256 algorithm - * - * @v ctx SHA-512/256 context - */ -static void sha512_256_init ( void *ctx ) { - struct sha512_context *context = ctx; - - sha512_family_init ( context, &sha512_256_init_digest, - SHA512_256_DIGEST_SIZE ); -} - -/** SHA-512/256 algorithm */ -struct digest_algorithm sha512_256_algorithm = { - .name = "sha512/256", - .ctxsize = sizeof ( struct sha512_context ), - .blocksize = sizeof ( union sha512_block ), - .digestsize = SHA512_256_DIGEST_SIZE, - .init = sha512_256_init, - .update = sha512_update, - .final = sha512_final, -}; - -/** "sha512_256" object identifier */ -static uint8_t oid_sha512_256[] = { ASN1_OID_SHA512_256 }; - -/** "sha512_256" OID-identified algorithm */ -struct asn1_algorithm oid_sha512_256_algorithm __asn1_algorithm = { - .name = "sha512/256", - .digest = &sha512_256_algorithm, - .oid = ASN1_OID_CURSOR ( oid_sha512_256 ), -}; diff --git a/qemu/roms/ipxe/src/crypto/x509.c b/qemu/roms/ipxe/src/crypto/x509.c deleted file mode 100644 index 43a4ca17a..000000000 --- a/qemu/roms/ipxe/src/crypto/x509.c +++ /dev/null @@ -1,1776 +0,0 @@ -/* - * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/list.h> -#include <ipxe/base16.h> -#include <ipxe/asn1.h> -#include <ipxe/crypto.h> -#include <ipxe/md5.h> -#include <ipxe/sha1.h> -#include <ipxe/sha256.h> -#include <ipxe/rsa.h> -#include <ipxe/rootcert.h> -#include <ipxe/certstore.h> -#include <ipxe/socket.h> -#include <ipxe/in.h> -#include <ipxe/x509.h> -#include <config/crypto.h> - -/** @file - * - * X.509 certificates - * - * The structure of X.509v3 certificates is documented in RFC 5280 - * section 4.1. - */ - -/* Disambiguate the various error causes */ -#define ENOTSUP_ALGORITHM \ - __einfo_error ( EINFO_ENOTSUP_ALGORITHM ) -#define EINFO_ENOTSUP_ALGORITHM \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" ) -#define ENOTSUP_EXTENSION \ - __einfo_error ( EINFO_ENOTSUP_EXTENSION ) -#define EINFO_ENOTSUP_EXTENSION \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" ) -#define EINVAL_ALGORITHM \ - __einfo_error ( EINFO_EINVAL_ALGORITHM ) -#define EINFO_EINVAL_ALGORITHM \ - __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" ) -#define EINVAL_ALGORITHM_MISMATCH \ - __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH ) -#define EINFO_EINVAL_ALGORITHM_MISMATCH \ - __einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" ) -#define EINVAL_PATH_LEN \ - __einfo_error ( EINFO_EINVAL_PATH_LEN ) -#define EINFO_EINVAL_PATH_LEN \ - __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" ) -#define EINVAL_VERSION \ - __einfo_error ( EINFO_EINVAL_VERSION ) -#define EINFO_EINVAL_VERSION \ - __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" ) -#define EACCES_WRONG_ISSUER \ - __einfo_error ( EINFO_EACCES_WRONG_ISSUER ) -#define EINFO_EACCES_WRONG_ISSUER \ - __einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" ) -#define EACCES_NOT_CA \ - __einfo_error ( EINFO_EACCES_NOT_CA ) -#define EINFO_EACCES_NOT_CA \ - __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" ) -#define EACCES_KEY_USAGE \ - __einfo_error ( EINFO_EACCES_KEY_USAGE ) -#define EINFO_EACCES_KEY_USAGE \ - __einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" ) -#define EACCES_EXPIRED \ - __einfo_error ( EINFO_EACCES_EXPIRED ) -#define EINFO_EACCES_EXPIRED \ - __einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" ) -#define EACCES_PATH_LEN \ - __einfo_error ( EINFO_EACCES_PATH_LEN ) -#define EINFO_EACCES_PATH_LEN \ - __einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" ) -#define EACCES_UNTRUSTED \ - __einfo_error ( EINFO_EACCES_UNTRUSTED ) -#define EINFO_EACCES_UNTRUSTED \ - __einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" ) -#define EACCES_OUT_OF_ORDER \ - __einfo_error ( EINFO_EACCES_OUT_OF_ORDER ) -#define EINFO_EACCES_OUT_OF_ORDER \ - __einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" ) -#define EACCES_EMPTY \ - __einfo_error ( EINFO_EACCES_EMPTY ) -#define EINFO_EACCES_EMPTY \ - __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" ) -#define EACCES_OCSP_REQUIRED \ - __einfo_error ( EINFO_EACCES_OCSP_REQUIRED ) -#define EINFO_EACCES_OCSP_REQUIRED \ - __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" ) -#define EACCES_WRONG_NAME \ - __einfo_error ( EINFO_EACCES_WRONG_NAME ) -#define EINFO_EACCES_WRONG_NAME \ - __einfo_uniqify ( EINFO_EACCES, 0x0a, "Incorrect certificate name" ) -#define EACCES_USELESS \ - __einfo_error ( EINFO_EACCES_USELESS ) -#define EINFO_EACCES_USELESS \ - __einfo_uniqify ( EINFO_EACCES, 0x0b, "No usable certificates" ) - -/** - * Get X.509 certificate name (for debugging) - * - * @v cert X.509 certificate - * @ret name Name (for debugging) - */ -const char * x509_name ( struct x509_certificate *cert ) { - struct asn1_cursor *common_name = &cert->subject.common_name; - struct digest_algorithm *digest = &sha1_algorithm; - static char buf[64]; - uint8_t fingerprint[ digest->digestsize ]; - size_t len; - - len = common_name->len; - if ( len ) { - /* Certificate has a commonName: use that */ - if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) ) - len = ( sizeof ( buf ) - 1 /* NUL */ ); - memcpy ( buf, common_name->data, len ); - buf[len] = '\0'; - } else { - /* Certificate has no commonName: use SHA-1 fingerprint */ - x509_fingerprint ( cert, digest, fingerprint ); - base16_encode ( fingerprint, sizeof ( fingerprint ), - buf, sizeof ( buf ) ); - } - return buf; -} - -/** "commonName" object identifier */ -static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME }; - -/** "commonName" object identifier cursor */ -static struct asn1_cursor oid_common_name_cursor = - ASN1_OID_CURSOR ( oid_common_name ); - -/** - * Parse X.509 certificate version - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_version ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int version; - int rc; - - /* Enter version */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - - /* Parse integer */ - if ( ( rc = asn1_integer ( &cursor, &version ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot parse version: %s\n", - cert, strerror ( rc ) ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - - /* Sanity check */ - if ( version < 0 ) { - DBGC ( cert, "X509 %p invalid version %d\n", cert, version ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_VERSION; - } - - /* Record version */ - cert->version = version; - DBGC2 ( cert, "X509 %p is a version %d certificate\n", - cert, ( cert->version + 1 ) ); - - return 0; -} - -/** - * Parse X.509 certificate serial number - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_serial ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_serial *serial = &cert->serial; - int rc; - - /* Record raw serial number */ - memcpy ( &serial->raw, raw, sizeof ( serial->raw ) ); - if ( ( rc = asn1_shrink ( &serial->raw, ASN1_INTEGER ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot shrink serialNumber: %s\n", - cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p issuer is:\n", cert ); - DBGC2_HDA ( cert, 0, serial->raw.data, serial->raw.len ); - - return 0; -} - -/** - * Parse X.509 certificate issuer - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_issuer ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_issuer *issuer = &cert->issuer; - int rc; - - /* Record raw issuer */ - memcpy ( &issuer->raw, raw, sizeof ( issuer->raw ) ); - if ( ( rc = asn1_shrink ( &issuer->raw, ASN1_SEQUENCE ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot shrink issuer: %s\n", - cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p issuer is:\n", cert ); - DBGC2_HDA ( cert, 0, issuer->raw.data, issuer->raw.len ); - - return 0; -} - -/** - * Parse X.509 certificate validity - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_validity ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_validity *validity = &cert->validity; - struct x509_time *not_before = &validity->not_before; - struct x509_time *not_after = &validity->not_after; - struct asn1_cursor cursor; - int rc; - - /* Enter validity */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse notBefore */ - if ( ( rc = asn1_generalized_time ( &cursor, - ¬_before->time ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot parse notBefore: %s\n", - cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p valid from time %lld\n", - cert, not_before->time ); - asn1_skip_any ( &cursor ); - - /* Parse notAfter */ - if ( ( rc = asn1_generalized_time ( &cursor, - ¬_after->time ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot parse notAfter: %s\n", - cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p valid until time %lld\n", - cert, not_after->time ); - - return 0; -} - -/** - * Parse X.509 certificate common name - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_common_name ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - struct asn1_cursor oid_cursor; - struct asn1_cursor name_cursor; - int rc; - - /* Enter name */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Scan through name list */ - for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) { - - /* Check for "commonName" OID */ - memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) ); - asn1_enter ( &oid_cursor, ASN1_SET ); - asn1_enter ( &oid_cursor, ASN1_SEQUENCE ); - memcpy ( &name_cursor, &oid_cursor, sizeof ( name_cursor ) ); - asn1_enter ( &oid_cursor, ASN1_OID ); - if ( asn1_compare ( &oid_common_name_cursor, &oid_cursor ) != 0) - continue; - asn1_skip_any ( &name_cursor ); - if ( ( rc = asn1_enter_any ( &name_cursor ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot locate name:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - - /* Record common name */ - memcpy ( &cert->subject.common_name, &name_cursor, - sizeof ( cert->subject.common_name ) ); - - return 0; - } - - /* Certificates may not have a commonName */ - DBGC2 ( cert, "X509 %p no commonName found:\n", cert ); - return 0; -} - -/** - * Parse X.509 certificate subject - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_subject ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_subject *subject = &cert->subject; - int rc; - - /* Record raw subject */ - memcpy ( &subject->raw, raw, sizeof ( subject->raw ) ); - asn1_shrink_any ( &subject->raw ); - DBGC2 ( cert, "X509 %p subject is:\n", cert ); - DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len ); - - /* Parse common name */ - if ( ( rc = x509_parse_common_name ( cert, raw ) ) != 0 ) - return rc; - DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert, - x509_name ( cert ) ); - - return 0; -} - -/** - * Parse X.509 certificate public key information - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_public_key ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_public_key *public_key = &cert->subject.public_key; - struct asn1_algorithm **algorithm = &public_key->algorithm; - struct asn1_bit_string *raw_bits = &public_key->raw_bits; - struct asn1_cursor cursor; - int rc; - - /* Record raw subjectPublicKeyInfo */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_shrink_any ( &cursor ); - memcpy ( &public_key->raw, &cursor, sizeof ( public_key->raw ) ); - DBGC2 ( cert, "X509 %p public key is:\n", cert ); - DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len ); - - /* Enter subjectPublicKeyInfo */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse algorithm */ - if ( ( rc = asn1_pubkey_algorithm ( &cursor, algorithm ) ) != 0 ) { - DBGC ( cert, "X509 %p could not parse public key algorithm: " - "%s\n", cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p public key algorithm is %s\n", - cert, (*algorithm)->name ); - asn1_skip_any ( &cursor ); - - /* Parse bit string */ - if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) { - DBGC ( cert, "X509 %p could not parse public key bits: %s\n", - cert, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Parse X.509 certificate basic constraints - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_basic_constraints ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_basic_constraints *basic = &cert->extensions.basic; - struct asn1_cursor cursor; - int ca = 0; - int path_len; - int rc; - - /* Enter basicConstraints */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse "cA", if present */ - if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) { - ca = asn1_boolean ( &cursor ); - if ( ca < 0 ) { - rc = ca; - DBGC ( cert, "X509 %p cannot parse cA: %s\n", - cert, strerror ( rc ) ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - asn1_skip_any ( &cursor ); - } - basic->ca = ca; - DBGC2 ( cert, "X509 %p is %sa CA certificate\n", - cert, ( basic->ca ? "" : "not " ) ); - - /* Ignore everything else unless "cA" is true */ - if ( ! ca ) - return 0; - - /* Parse "pathLenConstraint", if present and applicable */ - basic->path_len = X509_PATH_LEN_UNLIMITED; - if ( asn1_type ( &cursor ) == ASN1_INTEGER ) { - if ( ( rc = asn1_integer ( &cursor, &path_len ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot parse pathLenConstraint: " - "%s\n", cert, strerror ( rc ) ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - if ( path_len < 0 ) { - DBGC ( cert, "X509 %p invalid pathLenConstraint %d\n", - cert, path_len ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL; - } - basic->path_len = path_len; - DBGC2 ( cert, "X509 %p path length constraint is %d\n", - cert, basic->path_len ); - } - - return 0; -} - -/** - * Parse X.509 certificate key usage - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_key_usage ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_key_usage *usage = &cert->extensions.usage; - struct asn1_bit_string bit_string; - const uint8_t *bytes; - size_t len; - unsigned int i; - int rc; - - /* Mark extension as present */ - usage->present = 1; - - /* Parse bit string */ - if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) { - DBGC ( cert, "X509 %p could not parse key usage: %s\n", - cert, strerror ( rc ) ); - return rc; - } - - /* Parse key usage bits */ - bytes = bit_string.data; - len = bit_string.len; - if ( len > sizeof ( usage->bits ) ) - len = sizeof ( usage->bits ); - for ( i = 0 ; i < len ; i++ ) { - usage->bits |= ( *(bytes++) << ( 8 * i ) ); - } - DBGC2 ( cert, "X509 %p key usage is %08x\n", cert, usage->bits ); - - return 0; -} - -/** "id-kp-codeSigning" object identifier */ -static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING }; - -/** "id-kp-OCSPSigning" object identifier */ -static uint8_t oid_ocsp_signing[] = { ASN1_OID_OCSPSIGNING }; - -/** Supported key purposes */ -static struct x509_key_purpose x509_key_purposes[] = { - { - .name = "codeSigning", - .bits = X509_CODE_SIGNING, - .oid = ASN1_OID_CURSOR ( oid_code_signing ), - }, - { - .name = "ocspSigning", - .bits = X509_OCSP_SIGNING, - .oid = ASN1_OID_CURSOR ( oid_ocsp_signing ), - }, -}; - -/** - * Parse X.509 certificate key purpose identifier - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_key_purpose ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage; - struct x509_key_purpose *purpose; - struct asn1_cursor cursor; - unsigned int i; - int rc; - - /* Enter keyPurposeId */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) { - DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - - /* Identify key purpose */ - for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) / - sizeof ( x509_key_purposes[0] ) ) ; i++ ) { - purpose = &x509_key_purposes[i]; - if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) { - DBGC2 ( cert, "X509 %p has key purpose %s\n", - cert, purpose->name ); - ext_usage->bits |= purpose->bits; - return 0; - } - } - - /* Ignore unrecognised key purposes */ - return 0; -} - -/** - * Parse X.509 certificate extended key usage - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_extended_key_usage ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int rc; - - /* Enter extKeyUsage */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse each extended key usage in turn */ - while ( cursor.len ) { - if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - } - - return 0; -} - -/** - * Parse X.509 certificate OCSP access method - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_ocsp ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp; - struct asn1_cursor *uri = &ocsp->uri; - int rc; - - /* Enter accessLocation */ - memcpy ( uri, raw, sizeof ( *uri ) ); - if ( ( rc = asn1_enter ( uri, X509_GENERAL_NAME_URI ) ) != 0 ) { - DBGC ( cert, "X509 %p OCSP does not contain " - "uniformResourceIdentifier:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - DBGC2 ( cert, "X509 %p OCSP URI is:\n", cert ); - DBGC2_HDA ( cert, 0, uri->data, uri->len ); - - return 0; -} - -/** "id-ad-ocsp" object identifier */ -static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP }; - -/** Supported access methods */ -static struct x509_access_method x509_access_methods[] = { - { - .name = "OCSP", - .oid = ASN1_OID_CURSOR ( oid_ad_ocsp ), - .parse = x509_parse_ocsp, - }, -}; - -/** - * Identify X.509 access method by OID - * - * @v oid OID - * @ret method Access method, or NULL - */ -static struct x509_access_method * -x509_find_access_method ( const struct asn1_cursor *oid ) { - struct x509_access_method *method; - unsigned int i; - - for ( i = 0 ; i < ( sizeof ( x509_access_methods ) / - sizeof ( x509_access_methods[0] ) ) ; i++ ) { - method = &x509_access_methods[i]; - if ( asn1_compare ( &method->oid, oid ) == 0 ) - return method; - } - - return NULL; -} - -/** - * Parse X.509 certificate access description - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_access_description ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - struct asn1_cursor subcursor; - struct x509_access_method *method; - int rc; - - /* Enter keyPurposeId */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Try to identify access method */ - memcpy ( &subcursor, &cursor, sizeof ( subcursor ) ); - asn1_enter ( &subcursor, ASN1_OID ); - method = x509_find_access_method ( &subcursor ); - asn1_skip_any ( &cursor ); - DBGC2 ( cert, "X509 %p found access method %s\n", - cert, ( method ? method->name : "<unknown>" ) ); - - /* Parse access location, if applicable */ - if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) ) - return rc; - - return 0; -} - -/** - * Parse X.509 certificate authority information access - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_authority_info_access ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int rc; - - /* Enter authorityInfoAccess */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse each access description in turn */ - while ( cursor.len ) { - if ( ( rc = x509_parse_access_description ( cert, - &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - } - - return 0; -} - -/** - * Parse X.509 certificate subject alternative name - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_subject_alt_name ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_subject_alt_name *alt_name = &cert->extensions.alt_name; - struct asn1_cursor *names = &alt_name->names; - int rc; - - /* Enter subjectAltName */ - memcpy ( names, raw, sizeof ( *names ) ); - if ( ( rc = asn1_enter ( names, ASN1_SEQUENCE ) ) != 0 ) { - DBGC ( cert, "X509 %p invalid subjectAltName: %s\n", - cert, strerror ( rc ) ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - DBGC2 ( cert, "X509 %p has subjectAltName:\n", cert ); - DBGC2_HDA ( cert, 0, names->data, names->len ); - - return 0; -} - -/** "id-ce-basicConstraints" object identifier */ -static uint8_t oid_ce_basic_constraints[] = - { ASN1_OID_BASICCONSTRAINTS }; - -/** "id-ce-keyUsage" object identifier */ -static uint8_t oid_ce_key_usage[] = - { ASN1_OID_KEYUSAGE }; - -/** "id-ce-extKeyUsage" object identifier */ -static uint8_t oid_ce_ext_key_usage[] = - { ASN1_OID_EXTKEYUSAGE }; - -/** "id-pe-authorityInfoAccess" object identifier */ -static uint8_t oid_pe_authority_info_access[] = - { ASN1_OID_AUTHORITYINFOACCESS }; - -/** "id-ce-subjectAltName" object identifier */ -static uint8_t oid_ce_subject_alt_name[] = - { ASN1_OID_SUBJECTALTNAME }; - -/** Supported certificate extensions */ -static struct x509_extension x509_extensions[] = { - { - .name = "basicConstraints", - .oid = ASN1_OID_CURSOR ( oid_ce_basic_constraints ), - .parse = x509_parse_basic_constraints, - }, - { - .name = "keyUsage", - .oid = ASN1_OID_CURSOR ( oid_ce_key_usage ), - .parse = x509_parse_key_usage, - }, - { - .name = "extKeyUsage", - .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ), - .parse = x509_parse_extended_key_usage, - }, - { - .name = "authorityInfoAccess", - .oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ), - .parse = x509_parse_authority_info_access, - }, - { - .name = "subjectAltName", - .oid = ASN1_OID_CURSOR ( oid_ce_subject_alt_name ), - .parse = x509_parse_subject_alt_name, - }, -}; - -/** - * Identify X.509 extension by OID - * - * @v oid OID - * @ret extension Extension, or NULL - */ -static struct x509_extension * -x509_find_extension ( const struct asn1_cursor *oid ) { - struct x509_extension *extension; - unsigned int i; - - for ( i = 0 ; i < ( sizeof ( x509_extensions ) / - sizeof ( x509_extensions[0] ) ) ; i++ ) { - extension = &x509_extensions[i]; - if ( asn1_compare ( &extension->oid, oid ) == 0 ) - return extension; - } - - return NULL; -} - -/** - * Parse X.509 certificate extension - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_extension ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - struct asn1_cursor subcursor; - struct x509_extension *extension; - int is_critical = 0; - int rc; - - /* Enter extension */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Try to identify extension */ - memcpy ( &subcursor, &cursor, sizeof ( subcursor ) ); - asn1_enter ( &subcursor, ASN1_OID ); - extension = x509_find_extension ( &subcursor ); - asn1_skip_any ( &cursor ); - DBGC2 ( cert, "X509 %p found extension %s\n", - cert, ( extension ? extension->name : "<unknown>" ) ); - - /* Identify criticality */ - if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) { - is_critical = asn1_boolean ( &cursor ); - if ( is_critical < 0 ) { - rc = is_critical; - DBGC ( cert, "X509 %p cannot parse extension " - "criticality: %s\n", cert, strerror ( rc ) ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - asn1_skip_any ( &cursor ); - } - - /* Handle unknown extensions */ - if ( ! extension ) { - if ( is_critical ) { - /* Fail if we cannot handle a critical extension */ - DBGC ( cert, "X509 %p cannot handle critical " - "extension:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -ENOTSUP_EXTENSION; - } else { - /* Ignore unknown non-critical extensions */ - return 0; - } - }; - - /* Extract extnValue */ - if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) { - DBGC ( cert, "X509 %p extension missing extnValue:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - - /* Parse extension */ - if ( ( rc = extension->parse ( cert, &cursor ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Parse X.509 certificate extensions, if present - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_extensions ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - int rc; - - /* Enter extensions, if present */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 3 ) ); - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse each extension in turn */ - while ( cursor.len ) { - if ( ( rc = x509_parse_extension ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - } - - return 0; -} - -/** - * Parse X.509 certificate tbsCertificate - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_tbscertificate ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct asn1_algorithm **algorithm = &cert->signature_algorithm; - struct asn1_cursor cursor; - int rc; - - /* Record raw tbsCertificate */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - asn1_shrink_any ( &cursor ); - memcpy ( &cert->tbs, &cursor, sizeof ( cert->tbs ) ); - - /* Enter tbsCertificate */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse version, if present */ - if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) { - if ( ( rc = x509_parse_version ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - } - - /* Parse serialNumber */ - if ( ( rc = x509_parse_serial ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse signature */ - if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) { - DBGC ( cert, "X509 %p could not parse signature algorithm: " - "%s\n", cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n", - cert, (*algorithm)->name ); - asn1_skip_any ( &cursor ); - - /* Parse issuer */ - if ( ( rc = x509_parse_issuer ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse validity */ - if ( ( rc = x509_parse_validity ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse subject */ - if ( ( rc = x509_parse_subject ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse subjectPublicKeyInfo */ - if ( ( rc = x509_parse_public_key ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse extensions, if present */ - if ( ( rc = x509_parse_extensions ( cert, &cursor ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Parse X.509 certificate from ASN.1 data - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -int x509_parse ( struct x509_certificate *cert, - const struct asn1_cursor *raw ) { - struct x509_signature *signature = &cert->signature; - struct asn1_algorithm **signature_algorithm = &signature->algorithm; - struct asn1_bit_string *signature_value = &signature->value; - struct asn1_cursor cursor; - int rc; - - /* Record raw certificate */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - memcpy ( &cert->raw, &cursor, sizeof ( cert->raw ) ); - - /* Enter certificate */ - asn1_enter ( &cursor, ASN1_SEQUENCE ); - - /* Parse tbsCertificate */ - if ( ( rc = x509_parse_tbscertificate ( cert, &cursor ) ) != 0 ) - return rc; - asn1_skip_any ( &cursor ); - - /* Parse signatureAlgorithm */ - if ( ( rc = asn1_signature_algorithm ( &cursor, - signature_algorithm ) ) != 0 ) { - DBGC ( cert, "X509 %p could not parse signature algorithm: " - "%s\n", cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n", - cert, (*signature_algorithm)->name ); - asn1_skip_any ( &cursor ); - - /* Parse signatureValue */ - if ( ( rc = asn1_integral_bit_string ( &cursor, - signature_value ) ) != 0 ) { - DBGC ( cert, "X509 %p could not parse signature value: %s\n", - cert, strerror ( rc ) ); - return rc; - } - DBGC2 ( cert, "X509 %p signatureValue is:\n", cert ); - DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len ); - - /* Check that algorithm in tbsCertificate matches algorithm in - * signature - */ - if ( signature->algorithm != (*signature_algorithm) ) { - DBGC ( cert, "X509 %p signature algorithm %s does not match " - "signatureAlgorithm %s\n", - cert, signature->algorithm->name, - (*signature_algorithm)->name ); - return -EINVAL_ALGORITHM_MISMATCH; - } - - return 0; -} - -/** - * Create X.509 certificate - * - * @v data Raw certificate data - * @v len Length of raw data - * @ret cert X.509 certificate - * @ret rc Return status code - * - * On success, the caller holds a reference to the X.509 certificate, - * and is responsible for ultimately calling x509_put(). - */ -int x509_certificate ( const void *data, size_t len, - struct x509_certificate **cert ) { - struct asn1_cursor cursor; - void *raw; - int rc; - - /* Initialise cursor */ - cursor.data = data; - cursor.len = len; - asn1_shrink_any ( &cursor ); - - /* Return stored certificate, if present */ - if ( ( *cert = certstore_find ( &cursor ) ) != NULL ) { - - /* Add caller's reference */ - x509_get ( *cert ); - return 0; - } - - /* Allocate and initialise certificate */ - *cert = zalloc ( sizeof ( **cert ) + cursor.len ); - if ( ! *cert ) - return -ENOMEM; - ref_init ( &(*cert)->refcnt, NULL ); - raw = ( *cert + 1 ); - - /* Copy raw data */ - memcpy ( raw, cursor.data, cursor.len ); - cursor.data = raw; - - /* Parse certificate */ - if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) { - x509_put ( *cert ); - *cert = NULL; - return rc; - } - - /* Add certificate to store */ - certstore_add ( *cert ); - - return 0; -} - -/** - * Check X.509 certificate signature - * - * @v cert X.509 certificate - * @v public_key X.509 public key - * @ret rc Return status code - */ -static int x509_check_signature ( struct x509_certificate *cert, - struct x509_public_key *public_key ) { - struct x509_signature *signature = &cert->signature; - struct asn1_algorithm *algorithm = signature->algorithm; - struct digest_algorithm *digest = algorithm->digest; - struct pubkey_algorithm *pubkey = algorithm->pubkey; - uint8_t digest_ctx[ digest->ctxsize ]; - uint8_t digest_out[ digest->digestsize ]; - uint8_t pubkey_ctx[ pubkey->ctxsize ]; - int rc; - - /* Sanity check */ - assert ( cert->signature_algorithm == cert->signature.algorithm ); - - /* Calculate certificate digest */ - digest_init ( digest, digest_ctx ); - digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len ); - digest_final ( digest, digest_ctx, digest_out ); - DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, x509_name ( cert ) ); - DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) ); - - /* Check that signature public key algorithm matches signer */ - if ( public_key->algorithm->pubkey != pubkey ) { - DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not " - "match signer's algorithm %s\n", - cert, x509_name ( cert ), algorithm->name, - public_key->algorithm->name ); - rc = -EINVAL_ALGORITHM_MISMATCH; - goto err_mismatch; - } - - /* Verify signature using signer's public key */ - if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data, - public_key->raw.len ) ) != 0 ) { - DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: " - "%s\n", cert, x509_name ( cert ), strerror ( rc ) ); - goto err_pubkey_init; - } - if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out, - signature->value.data, - signature->value.len ) ) != 0 ) { - DBGC ( cert, "X509 %p \"%s\" signature verification failed: " - "%s\n", cert, x509_name ( cert ), strerror ( rc ) ); - goto err_pubkey_verify; - } - - /* Success */ - rc = 0; - - err_pubkey_verify: - pubkey_final ( pubkey, pubkey_ctx ); - err_pubkey_init: - err_mismatch: - return rc; -} - -/** - * Check X.509 certificate against issuer certificate - * - * @v cert X.509 certificate - * @v issuer X.509 issuer certificate - * @ret rc Return status code - */ -int x509_check_issuer ( struct x509_certificate *cert, - struct x509_certificate *issuer ) { - struct x509_public_key *public_key = &issuer->subject.public_key; - int rc; - - /* Check issuer. In theory, this should be a full X.500 DN - * comparison, which would require support for a plethora of - * abominations such as TeletexString (which allows the - * character set to be changed mid-string using escape codes). - * In practice, we assume that anyone who deliberately changes - * the encoding of the issuer DN is probably a masochist who - * will rather enjoy the process of figuring out exactly why - * their certificate doesn't work. - * - * See http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt - * for some enjoyable ranting on this subject. - */ - if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) { - DBGC ( cert, "X509 %p \"%s\" issuer does not match ", - cert, x509_name ( cert ) ); - DBGC ( cert, "X509 %p \"%s\" subject\n", - issuer, x509_name ( issuer ) ); - DBGC_HDA ( cert, 0, cert->issuer.raw.data, - cert->issuer.raw.len ); - DBGC_HDA ( issuer, 0, issuer->subject.raw.data, - issuer->subject.raw.len ); - return -EACCES_WRONG_ISSUER; - } - - /* Check that issuer is allowed to sign certificates */ - if ( ! issuer->extensions.basic.ca ) { - DBGC ( issuer, "X509 %p \"%s\" cannot sign ", - issuer, x509_name ( issuer ) ); - DBGC ( issuer, "X509 %p \"%s\": not a CA certificate\n", - cert, x509_name ( cert ) ); - return -EACCES_NOT_CA; - } - if ( issuer->extensions.usage.present && - ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) { - DBGC ( issuer, "X509 %p \"%s\" cannot sign ", - issuer, x509_name ( issuer ) ); - DBGC ( issuer, "X509 %p \"%s\": no keyCertSign usage\n", - cert, x509_name ( cert ) ); - return -EACCES_KEY_USAGE; - } - - /* Check signature */ - if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Calculate X.509 certificate fingerprint - * - * @v cert X.509 certificate - * @v digest Digest algorithm - * @v fingerprint Fingerprint buffer - */ -void x509_fingerprint ( struct x509_certificate *cert, - struct digest_algorithm *digest, - void *fingerprint ) { - uint8_t ctx[ digest->ctxsize ]; - - /* Calculate fingerprint */ - digest_init ( digest, ctx ); - digest_update ( digest, ctx, cert->raw.data, cert->raw.len ); - digest_final ( digest, ctx, fingerprint ); -} - -/** - * Check X.509 root certificate - * - * @v cert X.509 certificate - * @v root X.509 root certificate list - * @ret rc Return status code - */ -int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) { - struct digest_algorithm *digest = root->digest; - uint8_t fingerprint[ digest->digestsize ]; - const uint8_t *root_fingerprint = root->fingerprints; - unsigned int i; - - /* Calculate certificate fingerprint */ - x509_fingerprint ( cert, digest, fingerprint ); - - /* Check fingerprint against all root certificates */ - for ( i = 0 ; i < root->count ; i++ ) { - if ( memcmp ( fingerprint, root_fingerprint, - sizeof ( fingerprint ) ) == 0 ) { - DBGC ( cert, "X509 %p \"%s\" is a root certificate\n", - cert, x509_name ( cert ) ); - return 0; - } - root_fingerprint += sizeof ( fingerprint ); - } - - DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n", - cert, x509_name ( cert ) ); - return -ENOENT; -} - -/** - * Check X.509 certificate validity period - * - * @v cert X.509 certificate - * @v time Time at which to check certificate - * @ret rc Return status code - */ -int x509_check_time ( struct x509_certificate *cert, time_t time ) { - struct x509_validity *validity = &cert->validity; - - /* Check validity period */ - if ( validity->not_before.time > ( time + TIMESTAMP_ERROR_MARGIN ) ) { - DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n", - cert, x509_name ( cert ), time ); - return -EACCES_EXPIRED; - } - if ( validity->not_after.time < ( time - TIMESTAMP_ERROR_MARGIN ) ) { - DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n", - cert, x509_name ( cert ), time ); - return -EACCES_EXPIRED; - } - - DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n", - cert, x509_name ( cert ), time ); - return 0; -} - -/** - * Validate X.509 certificate - * - * @v cert X.509 certificate - * @v issuer Issuing X.509 certificate (or NULL) - * @v time Time at which to validate certificate - * @v root Root certificate list, or NULL to use default - * @ret rc Return status code - * - * The issuing certificate must have already been validated. - * - * Validation results are cached: if a certificate has already been - * successfully validated then @c issuer, @c time, and @c root will be - * ignored. - */ -int x509_validate ( struct x509_certificate *cert, - struct x509_certificate *issuer, - time_t time, struct x509_root *root ) { - unsigned int max_path_remaining; - int rc; - - /* Use default root certificate store if none specified */ - if ( ! root ) - root = &root_certificates; - - /* Return success if certificate has already been validated */ - if ( cert->valid ) - return 0; - - /* Fail if certificate is invalid at specified time */ - if ( ( rc = x509_check_time ( cert, time ) ) != 0 ) - return rc; - - /* Succeed if certificate is a trusted root certificate */ - if ( x509_check_root ( cert, root ) == 0 ) { - cert->valid = 1; - cert->path_remaining = ( cert->extensions.basic.path_len + 1 ); - return 0; - } - - /* Fail unless we have an issuer */ - if ( ! issuer ) { - DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n", - cert, x509_name ( cert ) ); - return -EACCES_UNTRUSTED; - } - - /* Fail unless issuer has already been validated */ - if ( ! issuer->valid ) { - DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) ); - DBGC ( cert, "issuer %p \"%s\" has not yet been validated\n", - issuer, x509_name ( issuer ) ); - return -EACCES_OUT_OF_ORDER; - } - - /* Fail if issuing certificate cannot validate this certificate */ - if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 ) - return rc; - - /* Fail if path length constraint is violated */ - if ( issuer->path_remaining == 0 ) { - DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) ); - DBGC ( cert, "issuer %p \"%s\" path length exceeded\n", - issuer, x509_name ( issuer ) ); - return -EACCES_PATH_LEN; - } - - /* Fail if OCSP is required */ - if ( cert->extensions.auth_info.ocsp.uri.len && - ( ! cert->extensions.auth_info.ocsp.good ) ) { - DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n", - cert, x509_name ( cert ) ); - return -EACCES_OCSP_REQUIRED; - } - - /* Calculate effective path length */ - cert->path_remaining = ( issuer->path_remaining - 1 ); - max_path_remaining = ( cert->extensions.basic.path_len + 1 ); - if ( cert->path_remaining > max_path_remaining ) - cert->path_remaining = max_path_remaining; - - /* Mark certificate as valid */ - cert->valid = 1; - - DBGC ( cert, "X509 %p \"%s\" successfully validated using ", - cert, x509_name ( cert ) ); - DBGC ( cert, "issuer %p \"%s\"\n", issuer, x509_name ( issuer ) ); - return 0; -} - -/** - * Check X.509 certificate alternative dNSName - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @v name Name - * @ret rc Return status code - */ -static int x509_check_dnsname ( struct x509_certificate *cert, - const struct asn1_cursor *raw, - const char *name ) { - const char *fullname = name; - const char *dnsname = raw->data; - size_t len = raw->len; - - /* Check for wildcards */ - if ( ( len >= 2 ) && ( dnsname[0] == '*' ) && ( dnsname[1] == '.' ) ) { - - /* Skip initial "*." */ - dnsname += 2; - len -= 2; - - /* Skip initial portion of name to be tested */ - name = strchr ( name, '.' ); - if ( ! name ) - return -ENOENT; - name++; - } - - /* Compare names */ - if ( ! ( ( strlen ( name ) == len ) && - ( memcmp ( name, dnsname, len ) == 0 ) ) ) - return -ENOENT; - - if ( name != fullname ) { - DBGC2 ( cert, "X509 %p \"%s\" found wildcard match for " - "\"*.%s\"\n", cert, x509_name ( cert ), name ); - } - return 0; -} - -/** - * Check X.509 certificate alternative iPAddress - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @v name Name - * @ret rc Return status code - */ -static int x509_check_ipaddress ( struct x509_certificate *cert, - const struct asn1_cursor *raw, - const char *name ) { - struct sockaddr sa; - sa_family_t family; - const void *address; - int rc; - - /* Determine address family */ - if ( raw->len == sizeof ( struct in_addr ) ) { - struct sockaddr_in *sin = ( ( struct sockaddr_in * ) &sa ); - family = AF_INET; - address = &sin->sin_addr; - } else if ( raw->len == sizeof ( struct in6_addr ) ) { - struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) &sa ); - family = AF_INET6; - address = &sin6->sin6_addr; - } else { - DBGC ( cert, "X509 %p \"%s\" has iPAddress with unexpected " - "length %zd\n", cert, x509_name ( cert ), raw->len ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL; - } - - /* Attempt to convert name to a socket address */ - if ( ( rc = sock_aton ( name, &sa ) ) != 0 ) { - DBGC2 ( cert, "X509 %p \"%s\" cannot parse \"%s\" as " - "iPAddress: %s\n", cert, x509_name ( cert ), name, - strerror ( rc ) ); - return rc; - } - if ( sa.sa_family != family ) - return -ENOENT; - - /* Compare addresses */ - if ( memcmp ( address, raw->data, raw->len ) != 0 ) - return -ENOENT; - - DBGC2 ( cert, "X509 %p \"%s\" found iPAddress match for \"%s\"\n", - cert, x509_name ( cert ), sock_ntoa ( &sa ) ); - return 0; -} - -/** - * Check X.509 certificate alternative name - * - * @v cert X.509 certificate - * @v raw ASN.1 cursor - * @v name Name - * @ret rc Return status code - */ -static int x509_check_alt_name ( struct x509_certificate *cert, - const struct asn1_cursor *raw, - const char *name ) { - struct asn1_cursor alt_name; - unsigned int type; - - /* Enter generalName */ - memcpy ( &alt_name, raw, sizeof ( alt_name ) ); - type = asn1_type ( &alt_name ); - asn1_enter_any ( &alt_name ); - - /* Check this name */ - switch ( type ) { - case X509_GENERAL_NAME_DNS : - return x509_check_dnsname ( cert, &alt_name, name ); - case X509_GENERAL_NAME_IP : - return x509_check_ipaddress ( cert, &alt_name, name ); - default: - DBGC2 ( cert, "X509 %p \"%s\" unknown name of type %#02x:\n", - cert, x509_name ( cert ), type ); - DBGC2_HDA ( cert, 0, alt_name.data, alt_name.len ); - return -ENOTSUP; - } -} - -/** - * Check X.509 certificate name - * - * @v cert X.509 certificate - * @v name Name - * @ret rc Return status code - */ -int x509_check_name ( struct x509_certificate *cert, const char *name ) { - struct asn1_cursor *common_name = &cert->subject.common_name; - struct asn1_cursor alt_name; - int rc; - - /* Check commonName */ - if ( x509_check_dnsname ( cert, common_name, name ) == 0 ) { - DBGC2 ( cert, "X509 %p \"%s\" commonName matches \"%s\"\n", - cert, x509_name ( cert ), name ); - return 0; - } - - /* Check any subjectAlternativeNames */ - memcpy ( &alt_name, &cert->extensions.alt_name.names, - sizeof ( alt_name ) ); - for ( ; alt_name.len ; asn1_skip_any ( &alt_name ) ) { - if ( ( rc = x509_check_alt_name ( cert, &alt_name, - name ) ) == 0 ) { - DBGC2 ( cert, "X509 %p \"%s\" subjectAltName matches " - "\"%s\"\n", cert, x509_name ( cert ), name ); - return 0; - } - } - - DBGC ( cert, "X509 %p \"%s\" does not match name \"%s\"\n", - cert, x509_name ( cert ), name ); - return -EACCES_WRONG_NAME; -} - -/** - * Free X.509 certificate chain - * - * @v refcnt Reference count - */ -static void x509_free_chain ( struct refcnt *refcnt ) { - struct x509_chain *chain = - container_of ( refcnt, struct x509_chain, refcnt ); - struct x509_link *link; - struct x509_link *tmp; - - DBGC2 ( chain, "X509 chain %p freed\n", chain ); - - /* Free each link in the chain */ - list_for_each_entry_safe ( link, tmp, &chain->links, list ) { - x509_put ( link->cert ); - list_del ( &link->list ); - free ( link ); - } - - /* Free chain */ - free ( chain ); -} - -/** - * Allocate X.509 certificate chain - * - * @ret chain X.509 certificate chain, or NULL - */ -struct x509_chain * x509_alloc_chain ( void ) { - struct x509_chain *chain; - - /* Allocate chain */ - chain = zalloc ( sizeof ( *chain ) ); - if ( ! chain ) - return NULL; - - /* Initialise chain */ - ref_init ( &chain->refcnt, x509_free_chain ); - INIT_LIST_HEAD ( &chain->links ); - - DBGC2 ( chain, "X509 chain %p allocated\n", chain ); - return chain; -} - -/** - * Append X.509 certificate to X.509 certificate chain - * - * @v chain X.509 certificate chain - * @v cert X.509 certificate - * @ret rc Return status code - */ -int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) { - struct x509_link *link; - - /* Allocate link */ - link = zalloc ( sizeof ( *link ) ); - if ( ! link ) - return -ENOMEM; - - /* Add link to chain */ - link->cert = x509_get ( cert ); - list_add_tail ( &link->list, &chain->links ); - DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n", - chain, cert, x509_name ( cert ) ); - - return 0; -} - -/** - * Append X.509 certificate to X.509 certificate chain - * - * @v chain X.509 certificate chain - * @v data Raw certificate data - * @v len Length of raw data - * @ret rc Return status code - */ -int x509_append_raw ( struct x509_chain *chain, const void *data, - size_t len ) { - struct x509_certificate *cert; - int rc; - - /* Parse certificate */ - if ( ( rc = x509_certificate ( data, len, &cert ) ) != 0 ) - goto err_parse; - - /* Append certificate to chain */ - if ( ( rc = x509_append ( chain, cert ) ) != 0 ) - goto err_append; - - /* Drop reference to certificate */ - x509_put ( cert ); - - return 0; - - err_append: - x509_put ( cert ); - err_parse: - return rc; -} - -/** - * Identify X.509 certificate by subject - * - * @v certs X.509 certificate list - * @v subject Subject - * @ret cert X.509 certificate, or NULL if not found - */ -static struct x509_certificate * -x509_find_subject ( struct x509_chain *certs, - const struct asn1_cursor *subject ) { - struct x509_link *link; - struct x509_certificate *cert; - - /* Scan through certificate list */ - list_for_each_entry ( link, &certs->links, list ) { - - /* Check subject */ - cert = link->cert; - if ( asn1_compare ( subject, &cert->subject.raw ) == 0 ) - return cert; - } - - return NULL; -} - -/** - * Append X.509 certificates to X.509 certificate chain - * - * @v chain X.509 certificate chain - * @v certs X.509 certificate list - * @ret rc Return status code - * - * Certificates will be automatically appended to the chain based upon - * the subject and issuer names. - */ -int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) { - struct x509_certificate *cert; - struct x509_certificate *previous; - int rc; - - /* Get current certificate */ - cert = x509_last ( chain ); - if ( ! cert ) { - DBGC ( chain, "X509 chain %p has no certificates\n", chain ); - return -EACCES_EMPTY; - } - - /* Append certificates, in order */ - while ( 1 ) { - - /* Find issuing certificate */ - previous = cert; - cert = x509_find_subject ( certs, &cert->issuer.raw ); - if ( ! cert ) - break; - if ( cert == previous ) - break; - - /* Append certificate to chain */ - if ( ( rc = x509_append ( chain, cert ) ) != 0 ) - return rc; - } - - return 0; -} - -/** - * Validate X.509 certificate chain - * - * @v chain X.509 certificate chain - * @v time Time at which to validate certificates - * @v store Certificate store, or NULL to use default - * @v root Root certificate list, or NULL to use default - * @ret rc Return status code - */ -int x509_validate_chain ( struct x509_chain *chain, time_t time, - struct x509_chain *store, struct x509_root *root ) { - struct x509_certificate *issuer = NULL; - struct x509_link *link; - int rc; - - /* Use default certificate store if none specified */ - if ( ! store ) - store = &certstore; - - /* Append any applicable certificates from the certificate store */ - if ( ( rc = x509_auto_append ( chain, store ) ) != 0 ) - return rc; - - /* Find first certificate that can be validated as a - * standalone (i.e. is already valid, or can be validated as - * a trusted root certificate). - */ - list_for_each_entry ( link, &chain->links, list ) { - - /* Try validating this certificate as a standalone */ - if ( ( rc = x509_validate ( link->cert, NULL, time, - root ) ) != 0 ) - continue; - - /* Work back up to start of chain, performing pairwise - * validation. - */ - issuer = link->cert; - list_for_each_entry_continue_reverse ( link, &chain->links, - list ) { - - /* Validate this certificate against its issuer */ - if ( ( rc = x509_validate ( link->cert, issuer, time, - root ) ) != 0 ) - return rc; - issuer = link->cert; - } - - return 0; - } - - DBGC ( chain, "X509 chain %p found no usable certificates\n", chain ); - return -EACCES_USELESS; -} - -/* Drag in objects via x509_validate() */ -REQUIRING_SYMBOL ( x509_validate ); - -/* Drag in certificate store */ -REQUIRE_OBJECT ( certstore ); - -/* Drag in crypto configuration */ -REQUIRE_OBJECT ( config_crypto ); |