From 1c29b4d979a9ea9be49bb942a2c41b7b6dc0dc9e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 9 Mar 2012 15:45:56 +0000 Subject: [PATCH] [crypto] Upgrade AES and RSA code to upstream axTLS version 1.4.5 All axTLS files are now vanilla versions of the upstream axTLS files, with one minor exception: the unused "ctx" parameter of bi_int_divide() has been marked with "__unused" to avoid a compilation error. Signed-off-by: Michael Brown --- src/crypto/axtls/aes.c | 191 +++++++++------------ src/crypto/axtls/bigint.c | 303 +++++++++++++++++---------------- src/crypto/axtls/bigint.h | 60 ++++--- src/crypto/axtls/bigint_impl.h | 66 ++++--- src/crypto/axtls/config.h | 13 ++ src/crypto/axtls/crypto.h | 242 +++++++++----------------- src/crypto/axtls/os_port.h | 71 ++++---- src/crypto/axtls/rsa.c | 143 +++++----------- src/crypto/axtls_aes.c | 5 +- src/crypto/x509.c | 10 ++ src/include/ipxe/aes.h | 4 + src/net/tls.c | 2 +- 12 files changed, 508 insertions(+), 602 deletions(-) create mode 100644 src/crypto/axtls/config.h diff --git a/src/crypto/axtls/aes.c b/src/crypto/axtls/aes.c index 87faaa1d..bd99a709 100644 --- a/src/crypto/axtls/aes.c +++ b/src/crypto/axtls/aes.c @@ -1,23 +1,33 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * All rights reserved. * - * This library 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 Lesser General Public License for more details. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -FILE_LICENCE ( GPL2_OR_LATER ); - /** * AES implementation - this is a small code version. There are much faster * versions around but they are much larger in size (i.e. they use large @@ -25,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #include +#include "os_port.h" #include "crypto.h" /* all commented out in skeleton mode */ @@ -64,10 +75,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); (f8)^=rot2(f4), \ (f8)^rot1(f9)) -/* some macros to do endian independent byte extraction */ -#define n2l(c,l) l=ntohl(*c); c++ -#define l2n(l,c) *c++=htonl(l) - /* * AES S-box */ @@ -154,11 +161,15 @@ static const unsigned char Rcon[30]= 0xb3,0x7d,0xfa,0xef,0xc5,0x91, }; +/* ----- static functions ----- */ +static void AES_encrypt(const AES_CTX *ctx, uint32_t *data); +static void AES_decrypt(const AES_CTX *ctx, uint32_t *data); + /* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial x^8+x^4+x^3+x+1 */ static unsigned char AES_xtime(uint32_t x) { - return x = (x&0x80) ? (x<<1)^0x1b : x<<1; + return (x&0x80) ? (x<<1)^0x1b : x<<1; } /** @@ -247,7 +258,7 @@ void AES_convert_key(AES_CTX *ctx) k = ctx->ks; k += 4; - for (i=ctx->rounds*4; i>4; i--) + for (i= ctx->rounds*4; i > 4; i--) { w= *k; w = inv_mix_col(w,t1,t2,t3,t4); @@ -255,52 +266,43 @@ void AES_convert_key(AES_CTX *ctx) } } -#if 0 /** * Encrypt a byte sequence (with a block size 16) using the AES cipher. */ void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) { - uint32_t tin0, tin1, tin2, tin3; - uint32_t tout0, tout1, tout2, tout3; - uint32_t tin[4]; - uint32_t *iv = (uint32_t *)ctx->iv; - uint32_t *msg_32 = (uint32_t *)msg; - uint32_t *out_32 = (uint32_t *)out; + int i; + uint32_t tin[4], tout[4], iv[4]; - n2l(iv, tout0); - n2l(iv, tout1); - n2l(iv, tout2); - n2l(iv, tout3); - iv -= 4; + memcpy(iv, ctx->iv, AES_IV_SIZE); + for (i = 0; i < 4; i++) + tout[i] = ntohl(iv[i]); - for (length -= 16; length >= 0; length -= 16) + for (length -= AES_BLOCKSIZE; length >= 0; length -= AES_BLOCKSIZE) { - n2l(msg_32, tin0); - n2l(msg_32, tin1); - n2l(msg_32, tin2); - n2l(msg_32, tin3); - tin[0] = tin0^tout0; - tin[1] = tin1^tout1; - tin[2] = tin2^tout2; - tin[3] = tin3^tout3; + uint32_t msg_32[4]; + uint32_t out_32[4]; + memcpy(msg_32, msg, AES_BLOCKSIZE); + msg += AES_BLOCKSIZE; + + for (i = 0; i < 4; i++) + tin[i] = ntohl(msg_32[i])^tout[i]; AES_encrypt(ctx, tin); - tout0 = tin[0]; - l2n(tout0, out_32); - tout1 = tin[1]; - l2n(tout1, out_32); - tout2 = tin[2]; - l2n(tout2, out_32); - tout3 = tin[3]; - l2n(tout3, out_32); + for (i = 0; i < 4; i++) + { + tout[i] = tin[i]; + out_32[i] = htonl(tout[i]); + } + + memcpy(out, out_32, AES_BLOCKSIZE); + out += AES_BLOCKSIZE; } - l2n(tout0, iv); - l2n(tout1, iv); - l2n(tout2, iv); - l2n(tout3, iv); + for (i = 0; i < 4; i++) + iv[i] = htonl(tout[i]); + memcpy(ctx->iv, iv, AES_IV_SIZE); } /** @@ -308,61 +310,48 @@ void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) */ void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) { - uint32_t tin0, tin1, tin2, tin3; - uint32_t xor0,xor1,xor2,xor3; - uint32_t tout0,tout1,tout2,tout3; - uint32_t data[4]; - uint32_t *iv = (uint32_t *)ctx->iv; - uint32_t *msg_32 = (uint32_t *)msg; - uint32_t *out_32 = (uint32_t *)out; + int i; + uint32_t tin[4], xor[4], tout[4], data[4], iv[4]; - n2l(iv ,xor0); - n2l(iv, xor1); - n2l(iv, xor2); - n2l(iv, xor3); - iv -= 4; + memcpy(iv, ctx->iv, AES_IV_SIZE); + for (i = 0; i < 4; i++) + xor[i] = ntohl(iv[i]); - for (length-=16; length >= 0; length -= 16) + for (length -= 16; length >= 0; length -= 16) { - n2l(msg_32, tin0); - n2l(msg_32, tin1); - n2l(msg_32, tin2); - n2l(msg_32, tin3); + uint32_t msg_32[4]; + uint32_t out_32[4]; + memcpy(msg_32, msg, AES_BLOCKSIZE); + msg += AES_BLOCKSIZE; - data[0] = tin0; - data[1] = tin1; - data[2] = tin2; - data[3] = tin3; + for (i = 0; i < 4; i++) + { + tin[i] = ntohl(msg_32[i]); + data[i] = tin[i]; + } AES_decrypt(ctx, data); - tout0 = data[0]^xor0; - tout1 = data[1]^xor1; - tout2 = data[2]^xor2; - tout3 = data[3]^xor3; + for (i = 0; i < 4; i++) + { + tout[i] = data[i]^xor[i]; + xor[i] = tin[i]; + out_32[i] = htonl(tout[i]); + } - xor0 = tin0; - xor1 = tin1; - xor2 = tin2; - xor3 = tin3; - - l2n(tout0, out_32); - l2n(tout1, out_32); - l2n(tout2, out_32); - l2n(tout3, out_32); + memcpy(out, out_32, AES_BLOCKSIZE); + out += AES_BLOCKSIZE; } - l2n(xor0, iv); - l2n(xor1, iv); - l2n(xor2, iv); - l2n(xor3, iv); + for (i = 0; i < 4; i++) + iv[i] = htonl(xor[i]); + memcpy(ctx->iv, iv, AES_IV_SIZE); } -#endif /** * Encrypt a single block (16 bytes) of data */ -void AES_encrypt(const AES_CTX *ctx, uint32_t *data) +static void AES_encrypt(const AES_CTX *ctx, uint32_t *data) { /* To make this code smaller, generate the sbox entries on the fly. * This will have a really heavy effect upon performance. @@ -375,9 +364,7 @@ void AES_encrypt(const AES_CTX *ctx, uint32_t *data) /* Pre-round key addition */ for (row = 0; row < 4; row++) - { data[row] ^= *(k++); - } /* Encrypt one block. */ for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++) @@ -395,12 +382,10 @@ void AES_encrypt(const AES_CTX *ctx, uint32_t *data) { tmp1 = a0 ^ a1 ^ a2 ^ a3; old_a0 = a0; - a0 ^= tmp1 ^ AES_xtime(a0 ^ a1); a1 ^= tmp1 ^ AES_xtime(a1 ^ a2); a2 ^= tmp1 ^ AES_xtime(a2 ^ a3); a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0); - } tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3); @@ -409,32 +394,28 @@ void AES_encrypt(const AES_CTX *ctx, uint32_t *data) /* KeyAddition - note that it is vital that this loop is separate from the MixColumn operation, which must be atomic...*/ for (row = 0; row < 4; row++) - { data[row] = tmp[row] ^ *(k++); - } } } /** * Decrypt a single block (16 bytes) of data */ -void AES_decrypt(const AES_CTX *ctx, uint32_t *data) +static void AES_decrypt(const AES_CTX *ctx, uint32_t *data) { uint32_t tmp[4]; uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6; uint32_t a0, a1, a2, a3, row; int curr_rnd; int rounds = ctx->rounds; - uint32_t *k = (uint32_t*)ctx->ks + ((rounds+1)*4); + const uint32_t *k = ctx->ks + ((rounds+1)*4); /* pre-round key addition */ for (row=4; row > 0;row--) - { data[row-1] ^= *(--k); - } /* Decrypt one block */ - for (curr_rnd=0; curr_rnd < rounds; curr_rnd++) + for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++) { /* Perform ByteSub and ShiftRow operations together */ for (row = 4; row > 0; row--) @@ -469,9 +450,7 @@ void AES_decrypt(const AES_CTX *ctx, uint32_t *data) } for (row = 4; row > 0; row--) - { data[row-1] = tmp[row-1] ^ *(--k); - } } } diff --git a/src/crypto/axtls/bigint.c b/src/crypto/axtls/bigint.c index 49cad971..e228a218 100644 --- a/src/crypto/axtls/bigint.c +++ b/src/crypto/axtls/bigint.c @@ -1,19 +1,31 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. + * All rights reserved. * - * This library 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 Lesser General Public License for more details. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -53,12 +65,17 @@ #include #include #include +#include "os_port.h" #include "bigint.h" -#include "crypto.h" + +#define V1 v->comps[v->size-1] /**< v1 for division */ +#define V2 v->comps[v->size-2] /**< v2 for division */ +#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */ +#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */ static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i); static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom); -static bigint __malloc *alloc(BI_CTX *ctx, int size); +static bigint *alloc(BI_CTX *ctx, int size); static bigint *trim(bigint *bi); static void more_comps(bigint *bi, int n); #if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \ @@ -69,8 +86,11 @@ static bigint *comp_left_shift(bigint *biR, int num_shifts); #ifdef CONFIG_BIGINT_CHECK_ON static void check(const bigint *bi); +#else +#define check(A) /**< disappears in normal production mode */ #endif + /** * @brief Start a new bigint context. * @return A bigint context. @@ -97,8 +117,6 @@ BI_CTX *bi_initialize(void) */ void bi_terminate(BI_CTX *ctx) { - bigint *p, *pn; - bi_depermanent(ctx->bi_radix); bi_free(ctx, ctx->bi_radix); @@ -111,6 +129,20 @@ void bi_terminate(BI_CTX *ctx) abort(); } + bi_clear_cache(ctx); + free(ctx); +} + +/** + *@brief Clear the memory cache. + */ +void bi_clear_cache(BI_CTX *ctx) +{ + bigint *p, *pn; + + if (ctx->free_list == NULL) + return; + for (p = ctx->free_list; p != NULL; p = pn) { pn = p->next; @@ -118,7 +150,8 @@ void bi_terminate(BI_CTX *ctx) free(p); } - free(ctx); + ctx->free_count = 0; + ctx->free_list = NULL; } /** @@ -410,18 +443,18 @@ bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) else { q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1); - } - if (v->size > 1 && V2) - { - /* we are implementing the following: - if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - - q_dash*V1)*COMP_RADIX) + U(2))) ... */ - comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - - (long_comp)q_dash*V1); - if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2)) + if (v->size > 1 && V2) { - q_dash--; + /* we are implementing the following: + if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - + q_dash*V1)*COMP_RADIX) + U(2))) ... */ + comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - + (long_comp)q_dash*V1); + if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2)) + { + q_dash--; + } } } @@ -473,6 +506,7 @@ bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) /* * Perform an integer divide on a bigint. */ +// mcb30 - mark ctx with __unused to avoid a compilation error static bigint *bi_int_divide(BI_CTX *ctx __unused, bigint *biR, comp denom) { int i = biR->size - 1; @@ -485,7 +519,7 @@ static bigint *bi_int_divide(BI_CTX *ctx __unused, bigint *biR, comp denom) r = (r<comps[i]; biR->comps[i] = (comp)(r / denom); r %= denom; - } while (--i != 0); + } while (--i >= 0); return trim(biR); } @@ -690,10 +724,11 @@ void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size) if (k < 0) { - break; + goto buf_done; } } } +buf_done: bi_free(ctx, x); } @@ -769,11 +804,16 @@ void bi_free_mod(BI_CTX *ctx, int mod_offset) /** * Perform a standard multiplication between two bigints. + * + * Barrett reduction has no need for some parts of the product, so ignore bits + * of the multiply. This routine gives Barrett its big performance + * improvements over Classical/Montgomery reduction methods. */ -static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) +static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib, + int inner_partial, int outer_partial) { - int i, j, i_plus_j; - int n = bia->size; + int i = 0, j; + int n = bia->size; int t = bib->size; bigint *biR = alloc(ctx, n + t); comp *sr = biR->comps; @@ -785,23 +825,33 @@ static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) /* clear things to start with */ memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE)); - i = 0; do { + long_comp tmp; comp carry = 0; - comp b = *sb++; - i_plus_j = i; + int r_index = i; j = 0; + if (outer_partial && outer_partial-i > 0 && outer_partial < n) + { + r_index = outer_partial-1; + j = outer_partial-i-1; + } + do { - long_comp tmp = sr[i_plus_j] + (long_comp)sa[j]*b + carry; - sr[i_plus_j++] = (comp)tmp; /* downsize */ - carry = (comp)(tmp >> COMP_BIT_SIZE); + if (inner_partial && r_index >= inner_partial) + { + break; + } + + tmp = sr[r_index] + ((long_comp)sa[j])*sb[i] + carry; + sr[r_index++] = (comp)tmp; /* downsize */ + carry = tmp >> COMP_BIT_SIZE; } while (++j < n); - sr[i_plus_j] = carry; + sr[r_index] = carry; } while (++i < t); bi_free(ctx, bia); @@ -881,12 +931,12 @@ bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) #ifdef CONFIG_BIGINT_KARATSUBA if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH) { - return regular_multiply(ctx, bia, bib); + return regular_multiply(ctx, bia, bib, 0, 0); } return karatsuba(ctx, bia, bib, 0); #else - return regular_multiply(ctx, bia, bib); + return regular_multiply(ctx, bia, bib, 0, 0); #endif } @@ -898,47 +948,46 @@ static bigint *regular_square(BI_CTX *ctx, bigint *bi) { int t = bi->size; int i = 0, j; - bigint *biR = alloc(ctx, t*2); + bigint *biR = alloc(ctx, t*2+1); comp *w = biR->comps; comp *x = bi->comps; - comp carry; - + long_comp carry; memset(w, 0, biR->size*COMP_BYTE_SIZE); do { long_comp tmp = w[2*i] + (long_comp)x[i]*x[i]; - comp u = 0; w[2*i] = (comp)tmp; - carry = (comp)(tmp >> COMP_BIT_SIZE); + carry = tmp >> COMP_BIT_SIZE; for (j = i+1; j < t; j++) { + uint8_t c = 0; long_comp xx = (long_comp)x[i]*x[j]; - long_comp blob = (long_comp)w[i+j]+carry; + if ((COMP_MAX-xx) < xx) + c = 1; - if (u) /* previous overflow */ - { - blob += COMP_RADIX; - } + tmp = (xx<<1); - u = 0; - if (xx & COMP_BIG_MSB) /* check for overflow */ - { - u = 1; - } + if ((COMP_MAX-tmp) < w[i+j]) + c = 1; - tmp = 2*xx + blob; + tmp += w[i+j]; + + if ((COMP_MAX-tmp) < carry) + c = 1; + + tmp += carry; w[i+j] = (comp)tmp; - carry = (comp)(tmp >> COMP_BIT_SIZE); + carry = tmp >> COMP_BIT_SIZE; + + if (c) + carry += COMP_RADIX; } - w[i+t] += carry; - - if (u) - { - w[i+t+1] = 1; /* add carry */ - } + tmp = w[i+t] + carry; + w[i+t] = (comp)tmp; + w[i+t+1] = tmp >> COMP_BIT_SIZE; } while (++i < t); bi_free(ctx, bi); @@ -1092,7 +1141,7 @@ static int find_max_exp_index(bigint *biexp) } shift >>= 1; - } while (--i != 0); + } while (i-- != 0); return -1; /* error - must have been a leading 0 */ } @@ -1115,7 +1164,7 @@ static int exp_bit_is_one(bigint *biexp, int offset) shift <<= 1; } - return test & shift; + return (test & shift) != 0; } #ifdef CONFIG_BIGINT_CHECK_ON @@ -1210,81 +1259,6 @@ static bigint *comp_mod(bigint *bi, int mod) return bi; } -/* - * Barrett reduction has no need for some parts of the product, so ignore bits - * of the multiply. This routine gives Barrett its big performance - * improvements over Classical/Montgomery reduction methods. - */ -static bigint *partial_multiply(BI_CTX *ctx, bigint *bia, bigint *bib, - int inner_partial, int outer_partial) -{ - int i = 0, j, n = bia->size, t = bib->size; - bigint *biR; - comp carry; - comp *sr, *sa, *sb; - - check(bia); - check(bib); - - biR = alloc(ctx, n + t); - sa = bia->comps; - sb = bib->comps; - sr = biR->comps; - - if (inner_partial) - { - memset(sr, 0, inner_partial*COMP_BYTE_SIZE); - } - else /* outer partial */ - { - if (n < outer_partial || t < outer_partial) /* should we bother? */ - { - bi_free(ctx, bia); - bi_free(ctx, bib); - biR->comps[0] = 0; /* return 0 */ - biR->size = 1; - return biR; - } - - memset(&sr[outer_partial], 0, (n+t-outer_partial)*COMP_BYTE_SIZE); - } - - do - { - comp *a = sa; - comp b = *sb++; - long_comp tmp; - int i_plus_j = i; - carry = 0; - j = n; - - if (outer_partial && i_plus_j < outer_partial) - { - i_plus_j = outer_partial; - a = &sa[outer_partial-i]; - j = n-(outer_partial-i); - } - - do - { - if (inner_partial && i_plus_j >= inner_partial) - { - break; - } - - tmp = sr[i_plus_j] + ((long_comp)*a++)*b + carry; - sr[i_plus_j++] = (comp)tmp; /* downsize */ - carry = (comp)(tmp >> COMP_BIT_SIZE); - } while (--j != 0); - - sr[i_plus_j] = carry; - } while (++i < t); - - bi_free(ctx, bia); - bi_free(ctx, bib); - return trim(biR); -} - /** * @brief Perform a single Barrett reduction. * @param ctx [in] The bigint session context. @@ -1310,12 +1284,12 @@ bigint *bi_barrett(BI_CTX *ctx, bigint *bi) q1 = comp_right_shift(bi_clone(ctx, bi), k-1); /* do outer partial multiply */ - q2 = partial_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1); + q2 = regular_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1); q3 = comp_right_shift(q2, k+1); r1 = comp_mod(bi, k+1); /* do inner partial multiply */ - r2 = comp_mod(partial_multiply(ctx, q3, bim, k+1, 0), k+1); + r2 = comp_mod(regular_multiply(ctx, q3, bim, k+1, 0), k+1); r = bi_subtract(ctx, r1, r2, NULL); /* if (r >= m) r = r - m; */ @@ -1366,6 +1340,7 @@ static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) * @param ctx [in] The bigint session context. * @param bi [in] The bigint on which to perform the mod power operation. * @param biexp [in] The bigint exponent. + * @return The result of the mod exponentiation operation * @see bi_set_mod(). */ bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) @@ -1467,6 +1442,7 @@ bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) * @param bi [in] The bigint to perform the exp/mod. * @param bim [in] The temporary modulus. * @param biexp [in] The bigint exponent. + * @return The result of the mod exponentiation operation * @see bi_set_mod(). */ bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp) @@ -1493,4 +1469,45 @@ bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp) return biR; } #endif + +#ifdef CONFIG_BIGINT_CRT +/** + * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts. + * + * @param ctx [in] The bigint session context. + * @param bi [in] The bigint to perform the exp/mod. + * @param dP [in] CRT's dP bigint + * @param dQ [in] CRT's dQ bigint + * @param p [in] CRT's p bigint + * @param q [in] CRT's q bigint + * @param qInv [in] CRT's qInv bigint + * @return The result of the CRT operation + */ +bigint *bi_crt(BI_CTX *ctx, bigint *bi, + bigint *dP, bigint *dQ, + bigint *p, bigint *q, bigint *qInv) +{ + bigint *m1, *m2, *h; + + /* Montgomery has a condition the 0 < x, y < m and these products violate + * that condition. So disable Montgomery when using CRT */ +#if defined(CONFIG_BIGINT_MONTGOMERY) + ctx->use_classical = 1; +#endif + ctx->mod_offset = BIGINT_P_OFFSET; + m1 = bi_mod_power(ctx, bi_copy(bi), dP); + + ctx->mod_offset = BIGINT_Q_OFFSET; + m2 = bi_mod_power(ctx, bi, dQ); + + h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL); + h = bi_multiply(ctx, h, qInv); + ctx->mod_offset = BIGINT_P_OFFSET; + h = bi_residue(ctx, h); +#if defined(CONFIG_BIGINT_MONTGOMERY) + ctx->use_classical = 0; /* reset for any further operation */ +#endif + return bi_add(ctx, m2, bi_multiply(ctx, q, h)); +} +#endif /** @} */ diff --git a/src/crypto/axtls/bigint.h b/src/crypto/axtls/bigint.h index f5f33531..1f38c53d 100644 --- a/src/crypto/axtls/bigint.h +++ b/src/crypto/axtls/bigint.h @@ -1,44 +1,43 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * All rights reserved. * - * This library 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 Lesser General Public License for more details. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -FILE_LICENCE ( GPL2_OR_LATER ); - #ifndef BIGINT_HEADER #define BIGINT_HEADER -/* enable features based on a 'super-set' capbaility. */ -#if defined(CONFIG_SSL_FULL_MODE) -#define CONFIG_SSL_ENABLE_CLIENT -#define CONFIG_SSL_CERT_VERIFICATION -#elif defined(CONFIG_SSL_ENABLE_CLIENT) -#define CONFIG_SSL_CERT_VERIFICATION -#endif +#include "crypto.h" -#include "os_port.h" -#include "bigint_impl.h" - -#ifndef CONFIG_BIGINT_CHECK_ON -#define check(A) /**< disappears in normal production mode */ -#endif BI_CTX *bi_initialize(void); void bi_terminate(BI_CTX *ctx); void bi_permanent(bigint *bi); void bi_depermanent(bigint *bi); +void bi_clear_cache(BI_CTX *ctx); void bi_free(BI_CTX *ctx, bigint *bi); bigint *bi_copy(bigint *bi); bigint *bi_clone(BI_CTX *ctx, const bigint *bi); @@ -90,4 +89,11 @@ bigint *bi_square(BI_CTX *ctx, bigint *bi); #define bi_square(A, B) bi_multiply(A, bi_copy(B), B) #endif +#ifdef CONFIG_BIGINT_CRT +bigint *bi_crt(BI_CTX *ctx, bigint *bi, + bigint *dP, bigint *dQ, + bigint *p, bigint *q, + bigint *qInv); +#endif + #endif diff --git a/src/crypto/axtls/bigint_impl.h b/src/crypto/axtls/bigint_impl.h index 762a7ccb..09d8550e 100644 --- a/src/crypto/axtls/bigint_impl.h +++ b/src/crypto/axtls/bigint_impl.h @@ -1,19 +1,31 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. + * All rights reserved. * - * This library 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 Lesser General Public License for more details. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef BIGINT_IMPL_HEADER @@ -30,20 +42,39 @@ #endif /* Architecture specific functions for big ints */ +#if defined(CONFIG_INTEGER_8BIT) +#define COMP_RADIX 256U /**< Max component + 1 */ +#define COMP_MAX 0xFFFFU/**< (Max dbl comp -1) */ +#define COMP_BIT_SIZE 8 /**< Number of bits in a component. */ +#define COMP_BYTE_SIZE 1 /**< Number of bytes in a component. */ +#define COMP_NUM_NIBBLES 2 /**< Used For diagnostics only. */ +typedef uint8_t comp; /**< A single precision component. */ +typedef uint16_t long_comp; /**< A double precision component. */ +typedef int16_t slong_comp; /**< A signed double precision component. */ +#elif defined(CONFIG_INTEGER_16BIT) +#define COMP_RADIX 65536U /**< Max component + 1 */ +#define COMP_MAX 0xFFFFFFFFU/**< (Max dbl comp -1) */ +#define COMP_BIT_SIZE 16 /**< Number of bits in a component. */ +#define COMP_BYTE_SIZE 2 /**< Number of bytes in a component. */ +#define COMP_NUM_NIBBLES 4 /**< Used For diagnostics only. */ +typedef uint16_t comp; /**< A single precision component. */ +typedef uint32_t long_comp; /**< A double precision component. */ +typedef int32_t slong_comp; /**< A signed double precision component. */ +#else /* regular 32 bit */ #ifdef WIN32 #define COMP_RADIX 4294967296i64 -#define COMP_BIG_MSB 0x8000000000000000i64 +#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64 #else #define COMP_RADIX 4294967296ULL /**< Max component + 1 */ -#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */ +#define COMP_MAX 0xFFFFFFFFFFFFFFFFULL/**< (Max dbl comp -1) */ #endif #define COMP_BIT_SIZE 32 /**< Number of bits in a component. */ #define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */ #define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */ - typedef uint32_t comp; /**< A single precision component. */ typedef uint64_t long_comp; /**< A double precision component. */ typedef int64_t slong_comp; /**< A signed double precision component. */ +#endif /** * @struct _bigint @@ -97,9 +128,4 @@ typedef struct /**< A big integer "session" context. */ #define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */ -#define V1 v->comps[v->size-1] /**< v1 for division */ -#define V2 v->comps[v->size-2] /**< v2 for division */ -#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */ -#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */ - #endif diff --git a/src/crypto/axtls/config.h b/src/crypto/axtls/config.h new file mode 100644 index 00000000..32fa3bf0 --- /dev/null +++ b/src/crypto/axtls/config.h @@ -0,0 +1,13 @@ +#ifndef AXTLS_CONFIG_H +#define AXTLS_CONFIG_H + +/** + * @file config.h + * + * Trick the axtls code into building within our build environment. + */ + +#define CONFIG_SSL_ENABLE_CLIENT 1 +#define CONFIG_BIGINT_CLASSICAL 1 + +#endif diff --git a/src/crypto/axtls/crypto.h b/src/crypto/axtls/crypto.h index b7af7c41..2c4cda4d 100644 --- a/src/crypto/axtls/crypto.h +++ b/src/crypto/axtls/crypto.h @@ -1,23 +1,33 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * All rights reserved. * - * This library 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 Lesser General Public License for more details. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -FILE_LICENCE ( GPL2_OR_LATER ); - /** * @file crypto.h */ @@ -29,20 +39,40 @@ FILE_LICENCE ( GPL2_OR_LATER ); extern "C" { #endif +#include "config.h" +#include "bigint_impl.h" #include "bigint.h" +#ifndef STDCALL +#define STDCALL +#endif +#ifndef EXP_FUNC +#define EXP_FUNC +#endif + + +/* enable features based on a 'super-set' capbaility. */ +#if defined(CONFIG_SSL_FULL_MODE) +#define CONFIG_SSL_ENABLE_CLIENT +#define CONFIG_SSL_CERT_VERIFICATION +#elif defined(CONFIG_SSL_ENABLE_CLIENT) +#define CONFIG_SSL_CERT_VERIFICATION +#endif + /************************************************************************** * AES declarations **************************************************************************/ #define AES_MAXROUNDS 14 +#define AES_BLOCKSIZE 16 +#define AES_IV_SIZE 16 typedef struct aes_key_st { uint16_t rounds; uint16_t key_size; uint32_t ks[(AES_MAXROUNDS+1)*8]; - uint8_t iv[16]; + uint8_t iv[AES_IV_SIZE]; } AES_CTX; typedef enum @@ -57,8 +87,6 @@ void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length); void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length); void AES_convert_key(AES_CTX *ctx); -void AES_encrypt(const AES_CTX *ctx, uint32_t *data); -void AES_decrypt(const AES_CTX *ctx, uint32_t *data); /************************************************************************** * RC4 declarations @@ -66,7 +94,7 @@ void AES_decrypt(const AES_CTX *ctx, uint32_t *data); typedef struct { - int x, y, m[256]; + uint8_t x, y, m[256]; } RC4_CTX; void RC4_setup(RC4_CTX *s, const uint8_t *key, int length); @@ -84,22 +112,38 @@ void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length); */ typedef struct { - uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */ - uint32_t Length_Low; /* Message length in bits */ - uint32_t Length_High; /* Message length in bits */ + uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */ + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ uint16_t Message_Block_Index; /* Index into message block array */ - uint8_t Message_Block[64]; /* 512-bit message blocks */ + uint8_t Message_Block[64]; /* 512-bit message blocks */ } SHA1_CTX; -void SHA1Init(SHA1_CTX *); -void SHA1Update(SHA1_CTX *, const uint8_t * msg, int len); -void SHA1Final(SHA1_CTX *, uint8_t *digest); +void SHA1_Init(SHA1_CTX *); +void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len); +void SHA1_Final(uint8_t *digest, SHA1_CTX *); /************************************************************************** - * MD5 declarations + * MD2 declarations **************************************************************************/ -/* MD5 context. */ +#define MD2_SIZE 16 + +typedef struct +{ + unsigned char cksum[16]; /* checksum of the data block */ + unsigned char state[48]; /* intermediate digest state */ + unsigned char buffer[16]; /* data block being processed */ + int left; /* amount of data in buffer */ +} MD2_CTX; + +EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx); +EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen); +EXP_FUNC void STDCALL MD2_Final(uint8_t *digest, MD2_CTX *ctx); + +/************************************************************************** + * MD5 declarations + **************************************************************************/ #define MD5_SIZE 16 @@ -110,9 +154,9 @@ typedef struct uint8_t buffer[64]; /* input buffer */ } MD5_CTX; -void MD5Init(MD5_CTX *); -void MD5Update(MD5_CTX *, const uint8_t *msg, int len); -void MD5Final(MD5_CTX *, uint8_t *digest); +EXP_FUNC void STDCALL MD5_Init(MD5_CTX *); +EXP_FUNC void STDCALL MD5_Update(MD5_CTX *, const uint8_t *msg, int len); +EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *); /************************************************************************** * HMAC declarations @@ -122,26 +166,6 @@ void hmac_md5(const uint8_t *msg, int length, const uint8_t *key, void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, int key_len, uint8_t *digest); -/************************************************************************** - * RNG declarations - **************************************************************************/ -void RNG_initialize(const uint8_t *seed_buf, int size); -void RNG_terminate(void); -void get_random(int num_rand_bytes, uint8_t *rand_data); -//void get_random_NZ(int num_rand_bytes, uint8_t *rand_data); - -#include -static inline void get_random_NZ(int num_rand_bytes, uint8_t *rand_data) { - /* AXTLS does not check for failures when generating random - * data. Rely on the fact that get_random_nz() does not - * request prediction resistance (and so cannot introduce new - * failures) and therefore any potential failure must already - * have been encountered by e.g. tls_generate_random(), which - * does check for failures. - */ - get_random_nz ( rand_data, num_rand_bytes ); -} - /************************************************************************** * RSA declarations **************************************************************************/ @@ -159,7 +183,6 @@ typedef struct bigint *qInv; /* q^-1 mod p */ #endif int num_octets; - bigint *sig_m; /* signature modulus */ BI_CTX *bi_ctx; } RSA_CTX; @@ -182,125 +205,22 @@ void RSA_free(RSA_CTX *ctx); int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, int is_decryption); bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg); -#ifdef CONFIG_SSL_CERT_VERIFICATION -bigint *RSA_raw_sign_verify(RSA_CTX *c, bigint *bi_msg); +#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT) bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, bigint *modulus, bigint *pub_exp); -bigint *RSA_public(const RSA_CTX *c, bigint *bi_msg); +bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg); int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, uint8_t *out_data, int is_signing); void RSA_print(const RSA_CTX *ctx); #endif /************************************************************************** - * ASN1 declarations + * RNG declarations **************************************************************************/ -#define X509_OK 0 -#define X509_NOT_OK -1 -#define X509_VFY_ERROR_NO_TRUSTED_CERT -2 -#define X509_VFY_ERROR_BAD_SIGNATURE -3 -#define X509_VFY_ERROR_NOT_YET_VALID -4 -#define X509_VFY_ERROR_EXPIRED -5 -#define X509_VFY_ERROR_SELF_SIGNED -6 -#define X509_VFY_ERROR_INVALID_CHAIN -7 -#define X509_VFY_ERROR_UNSUPPORTED_DIGEST -8 -#define X509_INVALID_PRIV_KEY -9 - -/* - * The Distinguished Name - */ -#define X509_NUM_DN_TYPES 3 -#define X509_COMMON_NAME 0 -#define X509_ORGANIZATION 1 -#define X509_ORGANIZATIONAL_TYPE 2 - -#define ASN1_INTEGER 0x02 -#define ASN1_BIT_STRING 0x03 -#define ASN1_OCTET_STRING 0x04 -#define ASN1_NULL 0x05 -#define ASN1_OID 0x06 -#define ASN1_PRINTABLE_STR 0x13 -#define ASN1_TELETEX_STR 0x14 -#define ASN1_IA5_STR 0x16 -#define ASN1_UTC_TIME 0x17 -#define ASN1_SEQUENCE 0x30 -#define ASN1_SET 0x31 -#define ASN1_IMPLICIT_TAG 0x80 -#define ASN1_EXPLICIT_TAG 0xa0 - -#define SALT_SIZE 8 - -struct _x509_ctx -{ - char *ca_cert_dn[X509_NUM_DN_TYPES]; - char *cert_dn[X509_NUM_DN_TYPES]; -#if defined(_WIN32_WCE) - long not_before; - long not_after; -#else - time_t not_before; - time_t not_after; -#endif - uint8_t *signature; - uint16_t sig_len; - uint8_t sig_type; - RSA_CTX *rsa_ctx; - bigint *digest; - struct _x509_ctx *next; -}; - -typedef struct _x509_ctx X509_CTX; - -#ifdef CONFIG_SSL_CERT_VERIFICATION -typedef struct -{ - X509_CTX *cert[CONFIG_X509_MAX_CA_CERTS]; -} CA_CERT_CTX; -#endif - -int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx); -int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type); -int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type); -int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object); -int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx); -void x509_free(X509_CTX *x509_ctx); -#ifdef CONFIG_SSL_CERT_VERIFICATION -int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert); -const uint8_t *x509_get_signature(const uint8_t *asn1_signature, int *len); -#endif -#ifdef CONFIG_SSL_FULL_MODE -void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert); -void x509_display_error(int error); -#endif - -/************************************************************************** - * MISC declarations - **************************************************************************/ - -extern const char * const unsupported_str; - -typedef void (*crypt_func)(void *, const uint8_t *, uint8_t *, int); -typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key, - int key_len, uint8_t *digest); - -typedef struct -{ - uint8_t *pre_data; /* include the ssl record bytes */ - uint8_t *data; /* the regular ssl data */ - int max_len; - int index; -} BUF_MEM; - -BUF_MEM buf_new(void); -void buf_grow(BUF_MEM *bm, int len); -void buf_free(BUF_MEM *bm); -int get_file(const char *filename, uint8_t **buf); - -#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG) -void print_blob(const char *format, const uint8_t *data, int size, ...); -#else - #define print_blob(...) -#endif +EXP_FUNC void STDCALL RNG_initialize(const uint8_t *seed_buf, int size); +EXP_FUNC void STDCALL RNG_terminate(void); +EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data); +void get_random_NZ(int num_rand_bytes, uint8_t *rand_data); #ifdef __cplusplus } diff --git a/src/crypto/axtls/os_port.h b/src/crypto/axtls/os_port.h index babdbfad..0a6ef54a 100644 --- a/src/crypto/axtls/os_port.h +++ b/src/crypto/axtls/os_port.h @@ -1,61 +1,54 @@ +#ifndef AXTLS_OS_PORT_H +#define AXTLS_OS_PORT_H + /** * @file os_port.h * * Trick the axtls code into building within our build environment. */ -#ifndef HEADER_OS_PORT_H -#define HEADER_OS_PORT_H - #include -#include -#include -#include -#include #include -#define STDCALL -#define EXP_FUNC -#define TTY_FLUSH() +/** All imported axTLS files are licensed using the three-clause BSD licence */ +FILE_LICENCE ( BSD3 ); /** We can't actually abort, since we are effectively a kernel... */ #define abort() assert ( 0 ) -/** crypto_misc.c has a bad #ifdef */ -static inline void close ( int fd __unused ) { - /* Do nothing */ +/** rsa.c uses alloca() */ +#define alloca( size ) __builtin_alloca ( size ) + +#include +static inline void get_random_NZ ( int num_rand_bytes, uint8_t *rand_data ) { + /* AXTLS does not check for failures when generating random + * data. Rely on the fact that get_random_nz() does not + * request prediction resistance (and so cannot introduce new + * failures) and therefore any potential failure must already + * have been encountered by e.g. tls_generate_random(), which + * does check for failures. + */ + get_random_nz ( rand_data, num_rand_bytes ); } -typedef void FILE; +/* Expose AES_encrypt() and AES_decrypt() in aes.o */ +#define aes 1 +#if OBJECT -static inline FILE * fopen ( const char *filename __unused, - const char *mode __unused ) { - return NULL; +/* AES_CTX is not defined at this point, so omit prototypes */ + +static void AES_encrypt(); +static void AES_decrypt(); + +void axtls_aes_encrypt ( void *ctx, uint32_t *data ) { + AES_encrypt ( ctx, data ); } -static inline int fseek ( FILE *stream __unused, long offset __unused, - int whence __unused ) { - return -1; +void axtls_aes_decrypt ( void *ctx, uint32_t *data ) { + AES_decrypt ( ctx, data ); } -static inline long ftell ( FILE *stream __unused ) { - return -1; -} - -static inline size_t fread ( void *ptr __unused, size_t size __unused, - size_t nmemb __unused, FILE *stream __unused ) { - return -1; -} - -static inline int fclose ( FILE *stream __unused ) { - return -1; -} - -#define CONFIG_SSL_CERT_VERIFICATION 1 -#define CONFIG_SSL_MAX_CERTS 1 -#define CONFIG_X509_MAX_CA_CERTS 1 -#define CONFIG_SSL_EXPIRY_TIME 24 -#define CONFIG_SSL_ENABLE_CLIENT 1 -#define CONFIG_BIGINT_CLASSICAL 1 +#endif +#undef aes #endif diff --git a/src/crypto/axtls/rsa.c b/src/crypto/axtls/rsa.c index 389eda57..f17500c3 100644 --- a/src/crypto/axtls/rsa.c +++ b/src/crypto/axtls/rsa.c @@ -1,19 +1,31 @@ /* - * Copyright(C) 2006 Cameron Rich + * Copyright (c) 2007, Cameron Rich * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. + * All rights reserved. * - * This library 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 Lesser General Public License for more details. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -25,12 +37,9 @@ #include #include #include +#include "os_port.h" #include "crypto.h" -#ifdef CONFIG_BIGINT_CRT -static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi); -#endif - void RSA_priv_key_new(RSA_CTX **ctx, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len, @@ -71,11 +80,16 @@ void RSA_pub_key_new(RSA_CTX **ctx, const uint8_t *pub_exp, int pub_len) { RSA_CTX *rsa_ctx; - BI_CTX *bi_ctx = bi_initialize(); + BI_CTX *bi_ctx; + + if (*ctx) /* if we load multiple certs, dump the old one */ + RSA_free(*ctx); + + bi_ctx = bi_initialize(); *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX)); rsa_ctx = *ctx; rsa_ctx->bi_ctx = bi_ctx; - rsa_ctx->num_octets = (mod_len & 0xFFF0); + rsa_ctx->num_octets = mod_len; rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len); bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET); rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len); @@ -129,10 +143,10 @@ void RSA_free(RSA_CTX *rsa_ctx) int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, int is_decryption) { - int byte_size = ctx->num_octets; - uint8_t *block; + const int byte_size = ctx->num_octets; int i, size; bigint *decrypted_bi, *dat_bi; + uint8_t *block = (uint8_t *)alloca(byte_size); memset(out_data, 0, byte_size); /* initialise */ @@ -146,7 +160,6 @@ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, #endif /* convert to a normal block */ - block = (uint8_t *)malloc(byte_size); bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size); i = 10; /* start at the first possible non-padded byte */ @@ -170,7 +183,6 @@ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, if (size > 0) memcpy(out_data, &block[i], size); - free(block); return size ? size : -1; } @@ -180,7 +192,7 @@ int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg) { #ifdef CONFIG_BIGINT_CRT - return bi_crt(c, bi_msg); + return bi_crt(c->bi_ctx, bi_msg, c->dP, c->dQ, c->p, c->q, c->qInv); #else BI_CTX *ctx = c->bi_ctx; ctx->mod_offset = BIGINT_M_OFFSET; @@ -188,39 +200,6 @@ bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg) #endif } -#ifdef CONFIG_BIGINT_CRT -/** - * Use the Chinese Remainder Theorem to quickly perform RSA decrypts. - * This should really be in bigint.c (and was at one stage), but needs - * access to the RSA_CTX context... - */ -static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi) -{ - BI_CTX *ctx = rsa->bi_ctx; - bigint *m1, *m2, *h; - - /* Montgomery has a condition the 0 < x, y < m and these products violate - * that condition. So disable Montgomery when using CRT */ -#if defined(CONFIG_BIGINT_MONTGOMERY) - ctx->use_classical = 1; -#endif - ctx->mod_offset = BIGINT_P_OFFSET; - m1 = bi_mod_power(ctx, bi_copy(bi), rsa->dP); - - ctx->mod_offset = BIGINT_Q_OFFSET; - m2 = bi_mod_power(ctx, bi, rsa->dQ); - - h = bi_subtract(ctx, bi_add(ctx, m1, rsa->p), bi_copy(m2), NULL); - h = bi_multiply(ctx, h, rsa->qInv); - ctx->mod_offset = BIGINT_P_OFFSET; - h = bi_residue(ctx, h); -#if defined(CONFIG_BIGINT_MONTGOMERY) - ctx->use_classical = 0; /* reset for any further operation */ -#endif - return bi_add(ctx, m2, bi_multiply(ctx, rsa->q, h)); -} -#endif - #ifdef CONFIG_SSL_FULL_MODE /** * Used for diagnostics. @@ -238,7 +217,7 @@ void RSA_print(const RSA_CTX *rsa_ctx) } #endif -#ifdef CONFIG_SSL_CERT_VERIFICATION +#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT) /** * Performs c = m^e mod n */ @@ -279,54 +258,12 @@ int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, /* now encrypt it */ dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size); encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) : - RSA_public(ctx, dat_bi); + RSA_public(ctx, dat_bi); bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size); + + /* save a few bytes of memory */ + bi_clear_cache(ctx->bi_ctx); return byte_size; } -#if 0 -/** - * Take a signature and decrypt it. - */ -bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, - bigint *modulus, bigint *pub_exp) -{ - uint8_t *block; - int i, size; - bigint *decrypted_bi, *dat_bi; - bigint *bir = NULL; - - block = (uint8_t *)malloc(sig_len); - - /* decrypt */ - dat_bi = bi_import(ctx, sig, sig_len); - ctx->mod_offset = BIGINT_M_OFFSET; - - /* convert to a normal block */ - decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp); - - bi_export(ctx, decrypted_bi, block, sig_len); - ctx->mod_offset = BIGINT_M_OFFSET; - - i = 10; /* start at the first possible non-padded byte */ - while (block[i++] && i < sig_len); - size = sig_len - i; - - /* get only the bit we want */ - if (size > 0) - { - int len; - const uint8_t *sig_ptr = x509_get_signature(&block[i], &len); - - if (sig_ptr) - { - bir = bi_import(ctx, sig_ptr, len); - } - } - - free(block); - return bir; -} -#endif - #endif /* CONFIG_SSL_CERT_VERIFICATION */ diff --git a/src/crypto/axtls_aes.c b/src/crypto/axtls_aes.c index b73a5725..3f1d668a 100644 --- a/src/crypto/axtls_aes.c +++ b/src/crypto/axtls_aes.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -119,7 +120,7 @@ static void aes_encrypt ( void *ctx, const void *src, void *dst, assert ( len == AES_BLOCKSIZE ); if ( aes_ctx->decrypting ) assert ( 0 ); - aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_encrypt ); + aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, axtls_aes_encrypt ); } /** @@ -139,7 +140,7 @@ static void aes_decrypt ( void *ctx, const void *src, void *dst, AES_convert_key ( &aes_ctx->axtls_ctx ); aes_ctx->decrypting = 1; } - aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_decrypt ); + aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, axtls_aes_decrypt ); } /** Basic AES algorithm */ diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 28d28fc1..50593bc6 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -155,6 +155,11 @@ int x509_rsa_public_key ( const struct asn1_cursor *certificate, DBG_HDA ( 0, certificate->data, certificate->len ); return -ENOTSUP; } + if ( modulus.len && ( ! *( ( uint8_t * ) modulus.data ) ) ) { + /* Skip positive sign byte */ + modulus.data++; + modulus.len--; + } memcpy ( &exponent, &pubkey, sizeof ( exponent ) ); rc = ( asn1_skip ( &exponent, ASN1_INTEGER ), /* modulus */ asn1_enter ( &exponent, ASN1_INTEGER ) /* publicExponent */ ); @@ -163,6 +168,11 @@ int x509_rsa_public_key ( const struct asn1_cursor *certificate, DBG_HDA ( 0, certificate->data, certificate->len ); return -ENOTSUP; } + if ( exponent.len && ( ! *( ( uint8_t * ) exponent.data ) ) ) { + /* Skip positive sign byte */ + exponent.data++; + exponent.len--; + } /* Allocate space and copy out modulus and exponent */ rsa_pubkey->modulus = malloc ( modulus.len + exponent.len ); diff --git a/src/include/ipxe/aes.h b/src/include/ipxe/aes.h index 5d645b20..4e44f985 100644 --- a/src/include/ipxe/aes.h +++ b/src/include/ipxe/aes.h @@ -21,6 +21,10 @@ struct aes_context { /** AES context size */ #define AES_CTX_SIZE sizeof ( struct aes_context ) +/* AXTLS functions */ +extern void axtls_aes_encrypt ( const AES_CTX *ctx, uint32_t *data ); +extern void axtls_aes_decrypt ( const AES_CTX *ctx, uint32_t *data ); + extern struct cipher_algorithm aes_algorithm; extern struct cipher_algorithm aes_cbc_algorithm; diff --git a/src/net/tls.c b/src/net/tls.c index 8940613c..90af1676 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -794,7 +794,7 @@ static int tls_send_certificate ( struct tls_session *tls ) { */ static int tls_send_client_key_exchange ( struct tls_session *tls ) { /* FIXME: Hack alert */ - RSA_CTX *rsa_ctx; + RSA_CTX *rsa_ctx = NULL; RSA_pub_key_new ( &rsa_ctx, tls->rsa.modulus, tls->rsa.modulus_len, tls->rsa.exponent, tls->rsa.exponent_len ); struct {