david/ipxe
Archived
1
0

[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 <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2012-03-09 15:45:56 +00:00
parent 74b1e706a8
commit 1c29b4d979
12 changed files with 508 additions and 602 deletions

View File

@ -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 <string.h>
#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);
}
}
}

View File

@ -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 <string.h>
#include <stdio.h>
#include <time.h>
#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<<COMP_BIT_SIZE) + biR->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
/** @} */

View File

@ -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

View File

@ -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

13
src/crypto/axtls/config.h Normal file
View File

@ -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

View File

@ -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 <ipxe/random_nz.h>
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
}

View File

@ -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 <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <byteswap.h>
#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 <ipxe/random_nz.h>
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

View File

@ -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 <string.h>
#include <time.h>
#include <stdlib.h>
#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 */

View File

@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/crypto.h>
#include <ipxe/cbc.h>
@ -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 */

View File

@ -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 );

View File

@ -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;

View File

@ -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 {