/*
- * 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
*/
#include <string.h>
+#include "os_port.h"
#include "crypto.h"
/* all commented out in skeleton mode */
(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
*/
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;
}
/**
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);
}
}
-#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;
-
- n2l(iv, tout0);
- n2l(iv, tout1);
- n2l(iv, tout2);
- n2l(iv, tout3);
- iv -= 4;
+ int i;
+ uint32_t tin[4], tout[4], iv[4];
- for (length -= 16; length >= 0; length -= 16)
+ memcpy(iv, ctx->iv, AES_IV_SIZE);
+ for (i = 0; i < 4; i++)
+ tout[i] = ntohl(iv[i]);
+
+ 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);
}
/**
*/
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;
-
- n2l(iv ,xor0);
- n2l(iv, xor1);
- n2l(iv, xor2);
- n2l(iv, xor3);
- iv -= 4;
-
- for (length-=16; length >= 0; length -= 16)
+ int i;
+ uint32_t tin[4], xor[4], tout[4], data[4], 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)
{
- 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;
-
- xor0 = tin0;
- xor1 = tin1;
- xor2 = tin2;
- xor3 = tin3;
+ for (i = 0; i < 4; i++)
+ {
+ tout[i] = data[i]^xor[i];
+ xor[i] = tin[i];
+ out_32[i] = htonl(tout[i]);
+ }
- 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.
/* 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++)
{
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);
/* 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--)
}
for (row = 4; row > 0; row--)
- {
data[row-1] = tmp[row-1] ^ *(--k);
- }
}
}
/*
- * 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.
*/
/**
#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) || \
#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.
*/
void bi_terminate(BI_CTX *ctx)
{
- bigint *p, *pn;
-
bi_depermanent(ctx->bi_radix);
bi_free(ctx, ctx->bi_radix);
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;
free(p);
}
- free(ctx);
+ ctx->free_count = 0;
+ ctx->free_list = NULL;
}
/**
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--;
+ }
}
}
/*
* 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;
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);
}
if (k < 0)
{
- break;
+ goto buf_done;
}
}
}
+buf_done:
bi_free(ctx, x);
}
/**
* 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;
/* 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);
#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
}
{
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;
- w[i+j] = (comp)tmp;
- carry = (comp)(tmp >> COMP_BIT_SIZE);
- }
+ tmp += w[i+j];
- w[i+t] += carry;
+ if ((COMP_MAX-tmp) < carry)
+ c = 1;
- if (u)
- {
- w[i+t+1] = 1; /* add carry */
+ tmp += carry;
+ w[i+j] = (comp)tmp;
+ carry = tmp >> COMP_BIT_SIZE;
+
+ if (c)
+ carry += COMP_RADIX;
}
+
+ 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);
}
shift >>= 1;
- } while (--i != 0);
+ } while (i-- != 0);
return -1; /* error - must have been a leading 0 */
}
shift <<= 1;
}
- return test & shift;
+ return (test & shift) != 0;
}
#ifdef CONFIG_BIGINT_CHECK_ON
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.
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; */
* @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)
* @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)
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
/** @} */
/*
- * 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 "os_port.h"
-#include "bigint_impl.h"
+#include "crypto.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);
#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
/*
- * 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
#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
#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
--- /dev/null
+#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
/*
- * 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
*/
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
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
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);
*/
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
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
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
**************************************************************************/
bigint *qInv; /* q^-1 mod p */
#endif
int num_octets;
- bigint *sig_m; /* signature modulus */
BI_CTX *bi_ctx;
} RSA_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
- **************************************************************************/
-#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
+ * RNG 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
}
+#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;
-
-static inline FILE * fopen ( const char *filename __unused,
- const char *mode __unused ) {
- return NULL;
-}
+/* Expose AES_encrypt() and AES_decrypt() in aes.o */
+#define aes 1
+#if OBJECT
-static inline int fseek ( FILE *stream __unused, long offset __unused,
- int whence __unused ) {
- return -1;
-}
+/* AES_CTX is not defined at this point, so omit prototypes */
-static inline long ftell ( FILE *stream __unused ) {
- return -1;
-}
+static void AES_encrypt();
+static void AES_decrypt();
-static inline size_t fread ( void *ptr __unused, size_t size __unused,
- size_t nmemb __unused, FILE *stream __unused ) {
- return -1;
+void axtls_aes_encrypt ( void *ctx, uint32_t *data ) {
+ AES_encrypt ( ctx, data );
}
-static inline int fclose ( FILE *stream __unused ) {
- return -1;
+void axtls_aes_decrypt ( void *ctx, uint32_t *data ) {
+ AES_decrypt ( ctx, data );
}
-#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
/*
- * 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.
*/
/**
#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,
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);
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 */
#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 */
if (size > 0)
memcpy(out_data, &block[i], size);
- free(block);
return size ? size : -1;
}
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;
#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.
}
#endif
-#ifdef CONFIG_SSL_CERT_VERIFICATION
+#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)
/**
* Performs c = m^e mod n
*/
/* 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);
- 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;
+ /* save a few bytes of memory */
+ bi_clear_cache(ctx->bi_ctx);
+ return byte_size;
}
-#endif
#endif /* CONFIG_SSL_CERT_VERIFICATION */
#include <string.h>
#include <errno.h>
+#include <assert.h>
#include <byteswap.h>
#include <ipxe/crypto.h>
#include <ipxe/cbc.h>
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 );
}
/**
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 */
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 */ );
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 );
/** 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;
*/
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 {