summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/gpxe/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux-4.02/gpxe/src/crypto')
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/aes_wrap.c123
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/arc4.c131
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/asn1.c166
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/aes.c476
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.c1496
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.h91
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint_impl.h105
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/crypto.h300
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/os_port.h61
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/rsa.c332
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls/sha1.c240
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls_aes.c158
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/axtls_sha1.c25
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/cbc.c101
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/chap.c124
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/crandom.c55
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/crc32.c54
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/crypto_null.c87
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/hmac.c122
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/md5.c234
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/sha1extra.c165
-rw-r--r--contrib/syslinux-4.02/gpxe/src/crypto/x509.c183
22 files changed, 4829 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/aes_wrap.c b/contrib/syslinux-4.02/gpxe/src/crypto/aes_wrap.c
new file mode 100644
index 0000000..d7f94af
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/aes_wrap.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <gpxe/crypto.h>
+#include <gpxe/aes.h>
+
+/**
+ * Wrap a key or other data using AES Key Wrap (RFC 3394)
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v src Data to encrypt
+ * @v nblk Number of 8-byte blocks in @a data
+ * @ret dest Encrypted data (8 bytes longer than input)
+ *
+ * The algorithm is implemented such that @a src and @a dest may point
+ * to the same buffer.
+ */
+int aes_wrap ( const void *kek, const void *src, void *dest, int nblk )
+{
+ u8 *A = dest;
+ u8 B[16];
+ u8 *R;
+ int i, j;
+ void *aes_ctx = malloc ( AES_CTX_SIZE );
+
+ if ( ! aes_ctx )
+ return -1;
+
+ cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
+
+ /* Set up */
+ memset ( A, 0xA6, sizeof ( A ) );
+ memmove ( dest + 8, src, nblk * 8 );
+
+ /* Wrap */
+ for ( j = 0; j < 6; j++ ) {
+ R = dest + 8;
+ for ( i = 1; i <= nblk; i++ ) {
+ memcpy ( B, A, 8 );
+ memcpy ( B + 8, R, 8 );
+ cipher_encrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
+ memcpy ( A, B, 8 );
+ A[7] ^= ( nblk * j ) + i;
+ memcpy ( R, B + 8, 8 );
+ R += 8;
+ }
+ }
+
+ free ( aes_ctx );
+ return 0;
+}
+
+/**
+ * Unwrap a key or other data using AES Key Wrap (RFC 3394)
+ *
+ * @v kek Key Encryption Key, 16 bytes
+ * @v src Data to decrypt
+ * @v nblk Number of 8-byte blocks in @e plaintext key
+ * @ret dest Decrypted data (8 bytes shorter than input)
+ * @ret rc Zero on success, nonzero on IV mismatch
+ *
+ * The algorithm is implemented such that @a src and @a dest may point
+ * to the same buffer.
+ */
+int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk )
+{
+ u8 A[8], B[16];
+ u8 *R;
+ int i, j;
+ void *aes_ctx = malloc ( AES_CTX_SIZE );
+
+ if ( ! aes_ctx )
+ return -1;
+
+ cipher_setkey ( &aes_algorithm, aes_ctx, kek, 16 );
+
+ /* Set up */
+ memcpy ( A, src, 8 );
+ memmove ( dest, src + 8, nblk * 8 );
+
+ /* Unwrap */
+ for ( j = 5; j >= 0; j-- ) {
+ R = dest + ( nblk - 1 ) * 8;
+ for ( i = nblk; i >= 1; i-- ) {
+ memcpy ( B, A, 8 );
+ memcpy ( B + 8, R, 8 );
+ B[7] ^= ( nblk * j ) + i;
+ cipher_decrypt ( &aes_algorithm, aes_ctx, B, B, 16 );
+ memcpy ( A, B, 8 );
+ memcpy ( R, B + 8, 8 );
+ R -= 8;
+ }
+ }
+
+ free ( aes_ctx );
+
+ /* Check IV */
+ for ( i = 0; i < 8; i++ ) {
+ if ( A[i] != 0xA6 )
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/arc4.c b/contrib/syslinux-4.02/gpxe/src/crypto/arc4.c
new file mode 100644
index 0000000..e58fba7
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/arc4.c
@@ -0,0 +1,131 @@
+/*
+ * The ARC4 stream cipher.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crypto.h>
+#include <gpxe/arc4.h>
+
+#define SWAP( ary, i, j ) \
+ ({ u8 temp = ary[i]; ary[i] = ary[j]; ary[j] = temp; })
+
+/**
+ * Set ARC4 key
+ *
+ * @v ctxv ARC4 encryption context
+ * @v keyv Key to set
+ * @v keylen Length of key
+ *
+ * If an initialisation vector is to be used, it should be prepended
+ * to the key; ARC4 does not implement the @c setiv function because
+ * there is no standard length for an initialisation vector in the
+ * cipher.
+ */
+static int arc4_setkey ( void *ctxv, const void *keyv, size_t keylen )
+{
+ struct arc4_ctx *ctx = ctxv;
+ const u8 *key = keyv;
+ u8 *S = ctx->state;
+ int i, j;
+
+ for ( i = 0; i < 256; i++ ) {
+ S[i] = i;
+ }
+
+ for ( i = j = 0; i < 256; i++ ) {
+ j = ( j + S[i] + key[i % keylen] ) & 0xff;
+ SWAP ( S, i, j );
+ }
+
+ ctx->i = ctx->j = 0;
+ return 0;
+}
+
+/**
+ * Perform ARC4 encryption or decryption
+ *
+ * @v ctxv ARC4 encryption context
+ * @v srcv Data to encrypt or decrypt
+ * @v dstv Location to store encrypted or decrypted data
+ * @v len Length of data to operate on
+ *
+ * ARC4 is a stream cipher that works by generating a stream of PRNG
+ * data based on the key, and XOR'ing it with the data to be
+ * encrypted. Since XOR is symmetric, encryption and decryption in
+ * ARC4 are the same operation.
+ *
+ * If you pass a @c NULL source or destination pointer, @a len
+ * keystream bytes will be consumed without encrypting any data.
+ */
+static void arc4_xor ( void *ctxv, const void *srcv, void *dstv,
+ size_t len )
+{
+ struct arc4_ctx *ctx = ctxv;
+ const u8 *src = srcv;
+ u8 *dst = dstv;
+ u8 *S = ctx->state;
+ int i = ctx->i, j = ctx->j;
+
+ while ( len-- ) {
+ i = ( i + 1 ) & 0xff;
+ j = ( j + S[i] ) & 0xff;
+ SWAP ( S, i, j );
+ if ( srcv && dstv )
+ *dst++ = *src++ ^ S[(S[i] + S[j]) & 0xff];
+ }
+
+ ctx->i = i;
+ ctx->j = j;
+}
+
+static void arc4_setiv ( void *ctx __unused, const void *iv __unused )
+{
+ /* ARC4 does not use a fixed-length IV */
+}
+
+
+/**
+ * Perform ARC4 encryption or decryption, skipping initial keystream bytes
+ *
+ * @v key ARC4 encryption key
+ * @v keylen Key length
+ * @v skip Number of bytes of keystream to skip
+ * @v src Message to encrypt or decrypt
+ * @v msglen Length of message
+ * @ret dst Encrypted or decrypted message
+ */
+void arc4_skip ( const void *key, size_t keylen, size_t skip,
+ const void *src, void *dst, size_t msglen )
+{
+ struct arc4_ctx ctx;
+ arc4_setkey ( &ctx, key, keylen );
+ arc4_xor ( &ctx, NULL, NULL, skip );
+ arc4_xor ( &ctx, src, dst, msglen );
+}
+
+struct cipher_algorithm arc4_algorithm = {
+ .name = "ARC4",
+ .ctxsize = ARC4_CTX_SIZE,
+ .blocksize = 1,
+ .setkey = arc4_setkey,
+ .setiv = arc4_setiv,
+ .encrypt = arc4_xor,
+ .decrypt = arc4_xor,
+};
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/asn1.c b/contrib/syslinux-4.02/gpxe/src/crypto/asn1.c
new file mode 100644
index 0000000..154a8a8
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/asn1.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <stddef.h>
+#include <errno.h>
+#include <gpxe/asn1.h>
+
+/** @file
+ *
+ * ASN.1 encoding
+ *
+ */
+
+/**
+ * Start parsing ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type
+ * @ret len Length of object body, or negative error
+ *
+ * The object cursor will be updated to point to the start of the
+ * object body (i.e. the first byte following the length byte(s)), and
+ * the length of the object body (i.e. the number of bytes until the
+ * following object tag, if any) is returned.
+ *
+ * If any error occurs (i.e. if the object is not of the expected
+ * type, or if we overflow beyond the end of the ASN.1 object), then
+ * the cursor will be invalidated and a negative value will be
+ * returned.
+ */
+static int asn1_start ( struct asn1_cursor *cursor,
+ unsigned int type ) {
+ unsigned int len_len;
+ unsigned int len;
+ int rc;
+
+ /* Sanity check */
+ if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
+ if ( cursor->len )
+ DBGC ( cursor, "ASN1 %p too short\n", cursor );
+ rc = -EINVAL;
+ goto notfound;
+ }
+
+ /* Check the tag byte */
+ if ( *( ( uint8_t * ) cursor->data ) != type ) {
+ DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
+ cursor, type, *( ( uint8_t * ) cursor->data ) );
+ rc = -ENXIO;
+ goto notfound;
+ }
+ cursor->data++;
+ cursor->len--;
+
+ /* Extract length of the length field and sanity check */
+ len_len = *( ( uint8_t * ) cursor->data );
+ if ( len_len & 0x80 ) {
+ len_len = ( len_len & 0x7f );
+ cursor->data++;
+ cursor->len--;
+ } else {
+ len_len = 1;
+ }
+ if ( cursor->len < len_len ) {
+ DBGC ( cursor, "ASN1 %p bad length field length %d (max "
+ "%zd)\n", cursor, len_len, cursor->len );
+ rc = -EINVAL;
+ goto notfound;
+ }
+
+ /* Extract the length and sanity check */
+ for ( len = 0 ; len_len ; len_len-- ) {
+ len <<= 8;
+ len |= *( ( uint8_t * ) cursor->data );
+ cursor->data++;
+ cursor->len--;
+ }
+ if ( cursor->len < len ) {
+ DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
+ cursor, len, cursor->len );
+ rc = -EINVAL;
+ goto notfound;
+ }
+
+ return len;
+
+ notfound:
+ cursor->data = NULL;
+ cursor->len = 0;
+ return rc;
+}
+
+/**
+ * Enter ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type
+ * @ret rc Return status code
+ *
+ * The object cursor will be updated to point to the body of the
+ * current ASN.1 object. If any error occurs, the object cursor will
+ * be invalidated.
+ */
+int asn1_enter ( struct asn1_cursor *cursor, unsigned int type ) {
+ int len;
+
+ len = asn1_start ( cursor, type );
+ if ( len < 0 )
+ return len;
+
+ cursor->len = len;
+ DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
+ cursor, type, len );
+
+ return 0;
+}
+
+/**
+ * Skip ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type
+ * @ret rc Return status code
+ *
+ * The object cursor will be updated to point to the next ASN.1
+ * object. If any error occurs, the object cursor will be
+ * invalidated.
+ */
+int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
+ int len;
+
+ len = asn1_start ( cursor, type );
+ if ( len < 0 )
+ return len;
+
+ cursor->data += len;
+ cursor->len -= len;
+ DBGC ( cursor, "ASN1 %p skipped object type %02x (len %x)\n",
+ cursor, type, len );
+
+ if ( ! cursor->len ) {
+ DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
+ cursor->data = NULL;
+ return -ENOENT;
+ }
+
+ return 0;
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/aes.c b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/aes.c
new file mode 100644
index 0000000..0c0d724
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/aes.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright(C) 2006 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.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+/**
+ * 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
+ * submix tables).
+ */
+
+#include <string.h>
+#include "crypto.h"
+
+/* all commented out in skeleton mode */
+#ifndef CONFIG_SSL_SKELETON_MODE
+
+#define rot1(x) (((x) << 24) | ((x) >> 8))
+#define rot2(x) (((x) << 16) | ((x) >> 16))
+#define rot3(x) (((x) << 8) | ((x) >> 24))
+
+/*
+ * This cute trick does 4 'mul by two' at once. Stolen from
+ * Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
+ * a standard graphics trick
+ * The key to this is that we need to xor with 0x1b if the top bit is set.
+ * a 1xxx xxxx 0xxx 0xxx First we mask the 7bit,
+ * b 1000 0000 0000 0000 then we shift right by 7 putting the 7bit in 0bit,
+ * c 0000 0001 0000 0000 we then subtract (c) from (b)
+ * d 0111 1111 0000 0000 and now we and with our mask
+ * e 0001 1011 0000 0000
+ */
+#define mt 0x80808080
+#define ml 0x7f7f7f7f
+#define mh 0xfefefefe
+#define mm 0x1b1b1b1b
+#define mul2(x,t) ((t)=((x)&mt), \
+ ((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
+
+#define inv_mix_col(x,f2,f4,f8,f9) (\
+ (f2)=mul2(x,f2), \
+ (f4)=mul2(f2,f4), \
+ (f8)=mul2(f4,f8), \
+ (f9)=(x)^(f8), \
+ (f8)=((f2)^(f4)^(f8)), \
+ (f2)^=(f9), \
+ (f4)^=(f9), \
+ (f8)^=rot3(f2), \
+ (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
+ */
+static const uint8_t aes_sbox[256] =
+{
+ 0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
+ 0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
+ 0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
+ 0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
+ 0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
+ 0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
+ 0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
+ 0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
+ 0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
+ 0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
+ 0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
+ 0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
+ 0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
+ 0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
+ 0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
+ 0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
+ 0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
+ 0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
+ 0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
+ 0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
+ 0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
+ 0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
+ 0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
+ 0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
+ 0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
+ 0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
+ 0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
+ 0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
+ 0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
+ 0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
+ 0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
+ 0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
+};
+
+/*
+ * AES is-box
+ */
+static const uint8_t aes_isbox[256] =
+{
+ 0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
+ 0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
+ 0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
+ 0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
+ 0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
+ 0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
+ 0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
+ 0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
+ 0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
+ 0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
+ 0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
+ 0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
+ 0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
+ 0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
+ 0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
+ 0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
+ 0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
+ 0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
+ 0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
+ 0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
+ 0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
+ 0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
+ 0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
+ 0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
+ 0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
+ 0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
+ 0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
+ 0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
+ 0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
+ 0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
+ 0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
+ 0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+};
+
+static const unsigned char Rcon[30]=
+{
+ 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
+ 0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
+ 0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
+ 0xb3,0x7d,0xfa,0xef,0xc5,0x91,
+};
+
+/* 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;
+}
+
+/**
+ * Set up AES with the key/iv and cipher size.
+ */
+void AES_set_key(AES_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, AES_MODE mode)
+{
+ int i, ii;
+ uint32_t *W, tmp, tmp2;
+ const unsigned char *ip;
+ int words;
+
+ switch (mode)
+ {
+ case AES_MODE_128:
+ i = 10;
+ words = 4;
+ break;
+
+ case AES_MODE_256:
+ i = 14;
+ words = 8;
+ break;
+
+ default: /* fail silently */
+ return;
+ }
+
+ ctx->rounds = i;
+ ctx->key_size = words;
+ W = ctx->ks;
+ for (i = 0; i < words; i+=2)
+ {
+ W[i+0]= ((uint32_t)key[ 0]<<24)|
+ ((uint32_t)key[ 1]<<16)|
+ ((uint32_t)key[ 2]<< 8)|
+ ((uint32_t)key[ 3] );
+ W[i+1]= ((uint32_t)key[ 4]<<24)|
+ ((uint32_t)key[ 5]<<16)|
+ ((uint32_t)key[ 6]<< 8)|
+ ((uint32_t)key[ 7] );
+ key += 8;
+ }
+
+ ip = Rcon;
+ ii = 4 * (ctx->rounds+1);
+ for (i = words; i<ii; i++)
+ {
+ tmp = W[i-1];
+
+ if ((i % words) == 0)
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ];
+ tmp=tmp2^(((unsigned int)*ip)<<24);
+ ip++;
+ }
+
+ if ((words == 8) && ((i % words) == 4))
+ {
+ tmp2 =(uint32_t)aes_sbox[(tmp )&0xff] ;
+ tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
+ tmp2|=(uint32_t)aes_sbox[(tmp>>24) ]<<24;
+ tmp=tmp2;
+ }
+
+ W[i]=W[i-words]^tmp;
+ }
+
+ /* copy the iv across */
+ memcpy(ctx->iv, iv, 16);
+}
+
+/**
+ * Change a key for decryption.
+ */
+void AES_convert_key(AES_CTX *ctx)
+{
+ int i;
+ uint32_t *k,w,t1,t2,t3,t4;
+
+ k = ctx->ks;
+ k += 4;
+
+ for (i=ctx->rounds*4; i>4; i--)
+ {
+ w= *k;
+ w = inv_mix_col(w,t1,t2,t3,t4);
+ *k++ =w;
+ }
+}
+
+#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;
+
+ for (length -= 16; length >= 0; length -= 16)
+ {
+ 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;
+
+ 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);
+ }
+
+ l2n(tout0, iv);
+ l2n(tout1, iv);
+ l2n(tout2, iv);
+ l2n(tout3, iv);
+}
+
+/**
+ * Decrypt a byte sequence (with a block size 16) using the AES cipher.
+ */
+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)
+ {
+ n2l(msg_32, tin0);
+ n2l(msg_32, tin1);
+ n2l(msg_32, tin2);
+ n2l(msg_32, tin3);
+
+ data[0] = tin0;
+ data[1] = tin1;
+ data[2] = tin2;
+ data[3] = tin3;
+
+ 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;
+
+ l2n(tout0, out_32);
+ l2n(tout1, out_32);
+ l2n(tout2, out_32);
+ l2n(tout3, out_32);
+ }
+
+ l2n(xor0, iv);
+ l2n(xor1, iv);
+ l2n(xor2, iv);
+ l2n(xor3, iv);
+}
+#endif
+
+/**
+ * Encrypt a single block (16 bytes) of data
+ */
+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.
+ */
+ uint32_t tmp[4];
+ uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
+ int curr_rnd;
+ int rounds = ctx->rounds;
+ const uint32_t *k = ctx->ks;
+
+ /* 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++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 0; row < 4; row++)
+ {
+ a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
+ a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
+ a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF];
+ a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd < (rounds - 1))
+ {
+ 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)
+{
+ 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);
+
+ /* 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++)
+ {
+ /* Perform ByteSub and ShiftRow operations together */
+ for (row = 4; row > 0; row--)
+ {
+ a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
+ a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
+ a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
+ a3 = aes_isbox[(data[row%4])&0xFF];
+
+ /* Perform MixColumn iff not last round */
+ if (curr_rnd<(rounds-1))
+ {
+ /* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
+ are quite large compared to encryption; this
+ operation slows decryption down noticeably. */
+ xt0 = AES_xtime(a0^a1);
+ xt1 = AES_xtime(a1^a2);
+ xt2 = AES_xtime(a2^a3);
+ xt3 = AES_xtime(a3^a0);
+ xt4 = AES_xtime(xt0^xt1);
+ xt5 = AES_xtime(xt1^xt2);
+ xt6 = AES_xtime(xt4^xt5);
+
+ xt0 ^= a1^a2^a3^xt4^xt6;
+ xt1 ^= a0^a2^a3^xt5^xt6;
+ xt2 ^= a0^a1^a3^xt4^xt6;
+ xt3 ^= a0^a1^a2^xt5^xt6;
+ tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
+ }
+ else
+ tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
+ }
+
+ for (row = 4; row > 0; row--)
+ {
+ data[row-1] = tmp[row-1] ^ *(--k);
+ }
+ }
+}
+
+#endif
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.c b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.c
new file mode 100644
index 0000000..49cad97
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.c
@@ -0,0 +1,1496 @@
+/*
+ * Copyright(C) 2006 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.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+/**
+ * @defgroup bigint_api Big Integer API
+ * @brief The bigint implementation as used by the axTLS project.
+ *
+ * The bigint library is for RSA encryption/decryption as well as signing.
+ * This code tries to minimise use of malloc/free by maintaining a small
+ * cache. A bigint context may maintain state by being made "permanent".
+ * It be be later released with a bi_depermanent() and bi_free() call.
+ *
+ * It supports the following reduction techniques:
+ * - Classical
+ * - Barrett
+ * - Montgomery
+ *
+ * It also implements the following:
+ * - Karatsuba multiplication
+ * - Squaring
+ * - Sliding window exponentiation
+ * - Chinese Remainder Theorem (implemented in rsa.c).
+ *
+ * All the algorithms used are pretty standard, and designed for different
+ * data bus sizes. Negative numbers are not dealt with at all, so a subtraction
+ * may need to be tested for negativity.
+ *
+ * This library steals some ideas from Jef Poskanzer
+ * <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>
+ * and GMP <http://www.swox.com/gmp>. It gets most of its implementation
+ * detail from "The Handbook of Applied Cryptography"
+ * <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>
+ * @{
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include "bigint.h"
+#include "crypto.h"
+
+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 *trim(bigint *bi);
+static void more_comps(bigint *bi, int n);
+#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
+ defined(CONFIG_BIGINT_MONTGOMERY)
+static bigint *comp_right_shift(bigint *biR, int num_shifts);
+static bigint *comp_left_shift(bigint *biR, int num_shifts);
+#endif
+
+#ifdef CONFIG_BIGINT_CHECK_ON
+static void check(const bigint *bi);
+#endif
+
+/**
+ * @brief Start a new bigint context.
+ * @return A bigint context.
+ */
+BI_CTX *bi_initialize(void)
+{
+ /* calloc() sets everything to zero */
+ BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX));
+
+ /* the radix */
+ ctx->bi_radix = alloc(ctx, 2);
+ ctx->bi_radix->comps[0] = 0;
+ ctx->bi_radix->comps[1] = 1;
+ bi_permanent(ctx->bi_radix);
+ return ctx;
+}
+
+/**
+ * @brief Close the bigint context and free any resources.
+ *
+ * Free up any used memory - a check is done if all objects were not
+ * properly freed.
+ * @param ctx [in] The bigint session context.
+ */
+void bi_terminate(BI_CTX *ctx)
+{
+ bigint *p, *pn;
+
+ bi_depermanent(ctx->bi_radix);
+ bi_free(ctx, ctx->bi_radix);
+
+ if (ctx->active_count != 0)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_terminate: there were %d un-freed bigints\n",
+ ctx->active_count);
+#endif
+ abort();
+ }
+
+ for (p = ctx->free_list; p != NULL; p = pn)
+ {
+ pn = p->next;
+ free(p->comps);
+ free(p);
+ }
+
+ free(ctx);
+}
+
+/**
+ * @brief Increment the number of references to this object.
+ * It does not do a full copy.
+ * @param bi [in] The bigint to copy.
+ * @return A reference to the same bigint.
+ */
+bigint *bi_copy(bigint *bi)
+{
+ check(bi);
+ if (bi->refs != PERMANENT)
+ bi->refs++;
+ return bi;
+}
+
+/**
+ * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.
+ *
+ * For this object to be freed, bi_depermanent() must be called.
+ * @param bi [in] The bigint to be made permanent.
+ */
+void bi_permanent(bigint *bi)
+{
+ check(bi);
+ if (bi->refs != 1)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_permanent: refs was not 1\n");
+#endif
+ abort();
+ }
+
+ bi->refs = PERMANENT;
+}
+
+/**
+ * @brief Take a permanent object and make it eligible for freedom.
+ * @param bi [in] The bigint to be made back to temporary.
+ */
+void bi_depermanent(bigint *bi)
+{
+ check(bi);
+ if (bi->refs != PERMANENT)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_depermanent: bigint was not permanent\n");
+#endif
+ abort();
+ }
+
+ bi->refs = 1;
+}
+
+/**
+ * @brief Free a bigint object so it can be used again.
+ *
+ * The memory itself it not actually freed, just tagged as being available
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint to be freed.
+ */
+void bi_free(BI_CTX *ctx, bigint *bi)
+{
+ check(bi);
+ if (bi->refs == PERMANENT)
+ {
+ return;
+ }
+
+ if (--bi->refs > 0)
+ {
+ return;
+ }
+
+ bi->next = ctx->free_list;
+ ctx->free_list = bi;
+ ctx->free_count++;
+
+ if (--ctx->active_count < 0)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("bi_free: active_count went negative "
+ "- double-freed bigint?\n");
+#endif
+ abort();
+ }
+}
+
+/**
+ * @brief Convert an (unsigned) integer into a bigint.
+ * @param ctx [in] The bigint session context.
+ * @param i [in] The (unsigned) integer to be converted.
+ *
+ */
+bigint *int_to_bi(BI_CTX *ctx, comp i)
+{
+ bigint *biR = alloc(ctx, 1);
+ biR->comps[0] = i;
+ return biR;
+}
+
+/**
+ * @brief Do a full copy of the bigint object.
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint object to be copied.
+ */
+bigint *bi_clone(BI_CTX *ctx, const bigint *bi)
+{
+ bigint *biR = alloc(ctx, bi->size);
+ check(bi);
+ memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE);
+ return biR;
+}
+
+/**
+ * @brief Perform an addition operation between two bigints.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @return The result of the addition.
+ */
+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+ int n;
+ comp carry = 0;
+ comp *pa, *pb;
+
+ check(bia);
+ check(bib);
+
+ n = max(bia->size, bib->size);
+ more_comps(bia, n+1);
+ more_comps(bib, n);
+ pa = bia->comps;
+ pb = bib->comps;
+
+ do
+ {
+ comp sl, rl, cy1;
+ sl = *pa + *pb++;
+ rl = sl + carry;
+ cy1 = sl < *pa;
+ carry = cy1 | (rl < sl);
+ *pa++ = rl;
+ } while (--n != 0);
+
+ *pa = carry; /* do overflow */
+ bi_free(ctx, bib);
+ return trim(bia);
+}
+
+/**
+ * @brief Perform a subtraction operation between two bigints.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @param is_negative [out] If defined, indicates that the result was negative.
+ * is_negative may be null.
+ * @return The result of the subtraction. The result is always positive.
+ */
+bigint *bi_subtract(BI_CTX *ctx,
+ bigint *bia, bigint *bib, int *is_negative)
+{
+ int n = bia->size;
+ comp *pa, *pb, carry = 0;
+
+ check(bia);
+ check(bib);
+
+ more_comps(bib, n);
+ pa = bia->comps;
+ pb = bib->comps;
+
+ do
+ {
+ comp sl, rl, cy1;
+ sl = *pa - *pb++;
+ rl = sl - carry;
+ cy1 = sl > *pa;
+ carry = cy1 | (rl > sl);
+ *pa++ = rl;
+ } while (--n != 0);
+
+ if (is_negative) /* indicate a negative result */
+ {
+ *is_negative = carry;
+ }
+
+ bi_free(ctx, trim(bib)); /* put bib back to the way it was */
+ return trim(bia);
+}
+
+/**
+ * Perform a multiply between a bigint an an (unsigned) integer
+ */
+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)
+{
+ int j = 0, n = bia->size;
+ bigint *biR = alloc(ctx, n + 1);
+ comp carry = 0;
+ comp *r = biR->comps;
+ comp *a = bia->comps;
+
+ check(bia);
+
+ /* clear things to start with */
+ memset(r, 0, ((n+1)*COMP_BYTE_SIZE));
+
+ do
+ {
+ long_comp tmp = *r + (long_comp)a[j]*b + carry;
+ *r++ = (comp)tmp; /* downsize */
+ carry = (comp)(tmp >> COMP_BIT_SIZE);
+ } while (++j < n);
+
+ *r = carry;
+ bi_free(ctx, bia);
+ return trim(biR);
+}
+
+/**
+ * @brief Does both division and modulo calculations.
+ *
+ * Used extensively when doing classical reduction.
+ * @param ctx [in] The bigint session context.
+ * @param u [in] A bigint which is the numerator.
+ * @param v [in] Either the denominator or the modulus depending on the mode.
+ * @param is_mod [n] Determines if this is a normal division (0) or a reduction
+ * (1).
+ * @return The result of the division/reduction.
+ */
+bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod)
+{
+ int n = v->size, m = u->size-n;
+ int j = 0, orig_u_size = u->size;
+ uint8_t mod_offset = ctx->mod_offset;
+ comp d;
+ bigint *quotient, *tmp_u;
+ comp q_dash;
+
+ check(u);
+ check(v);
+
+ /* if doing reduction and we are < mod, then return mod */
+ if (is_mod && bi_compare(v, u) > 0)
+ {
+ bi_free(ctx, v);
+ return u;
+ }
+
+ quotient = alloc(ctx, m+1);
+ tmp_u = alloc(ctx, n+1);
+ v = trim(v); /* make sure we have no leading 0's */
+ d = (comp)((long_comp)COMP_RADIX/(V1+1));
+
+ /* clear things to start with */
+ memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE));
+
+ /* normalise */
+ if (d > 1)
+ {
+ u = bi_int_multiply(ctx, u, d);
+
+ if (is_mod)
+ {
+ v = ctx->bi_normalised_mod[mod_offset];
+ }
+ else
+ {
+ v = bi_int_multiply(ctx, v, d);
+ }
+ }
+
+ if (orig_u_size == u->size) /* new digit position u0 */
+ {
+ more_comps(u, orig_u_size + 1);
+ }
+
+ do
+ {
+ /* get a temporary short version of u */
+ memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE);
+
+ /* calculate q' */
+ if (U(0) == V1)
+ {
+ q_dash = COMP_RADIX-1;
+ }
+ 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))
+ {
+ q_dash--;
+ }
+ }
+
+ /* multiply and subtract */
+ if (q_dash)
+ {
+ int is_negative;
+ tmp_u = bi_subtract(ctx, tmp_u,
+ bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative);
+ more_comps(tmp_u, n+1);
+
+ Q(j) = q_dash;
+
+ /* add back */
+ if (is_negative)
+ {
+ Q(j)--;
+ tmp_u = bi_add(ctx, tmp_u, bi_copy(v));
+
+ /* lop off the carry */
+ tmp_u->size--;
+ v->size--;
+ }
+ }
+ else
+ {
+ Q(j) = 0;
+ }
+
+ /* copy back to u */
+ memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE);
+ } while (++j <= m);
+
+ bi_free(ctx, tmp_u);
+ bi_free(ctx, v);
+
+ if (is_mod) /* get the remainder */
+ {
+ bi_free(ctx, quotient);
+ return bi_int_divide(ctx, trim(u), d);
+ }
+ else /* get the quotient */
+ {
+ bi_free(ctx, u);
+ return trim(quotient);
+ }
+}
+
+/*
+ * Perform an integer divide on a bigint.
+ */
+static bigint *bi_int_divide(BI_CTX *ctx __unused, bigint *biR, comp denom)
+{
+ int i = biR->size - 1;
+ long_comp r = 0;
+
+ check(biR);
+
+ do
+ {
+ r = (r<<COMP_BIT_SIZE) + biR->comps[i];
+ biR->comps[i] = (comp)(r / denom);
+ r %= denom;
+ } while (--i != 0);
+
+ return trim(biR);
+}
+
+#ifdef CONFIG_BIGINT_MONTGOMERY
+/**
+ * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
+ * where B^-1(B-1) mod N=1. Actually, only the least significant part of
+ * N' is needed, hence the definition N0'=N' mod b. We reproduce below the
+ * simple algorithm from an article by Dusse and Kaliski to efficiently
+ * find N0' from N0 and b */
+static comp modular_inverse(bigint *bim)
+{
+ int i;
+ comp t = 1;
+ comp two_2_i_minus_1 = 2; /* 2^(i-1) */
+ long_comp two_2_i = 4; /* 2^i */
+ comp N = bim->comps[0];
+
+ for (i = 2; i <= COMP_BIT_SIZE; i++)
+ {
+ if ((long_comp)N*t%two_2_i >= two_2_i_minus_1)
+ {
+ t += two_2_i_minus_1;
+ }
+
+ two_2_i_minus_1 <<= 1;
+ two_2_i <<= 1;
+ }
+
+ return (comp)(COMP_RADIX-t);
+}
+#endif
+
+#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
+ defined(CONFIG_BIGINT_MONTGOMERY)
+/**
+ * Take each component and shift down (in terms of components)
+ */
+static bigint *comp_right_shift(bigint *biR, int num_shifts)
+{
+ int i = biR->size-num_shifts;
+ comp *x = biR->comps;
+ comp *y = &biR->comps[num_shifts];
+
+ check(biR);
+
+ if (i <= 0) /* have we completely right shifted? */
+ {
+ biR->comps[0] = 0; /* return 0 */
+ biR->size = 1;
+ return biR;
+ }
+
+ do
+ {
+ *x++ = *y++;
+ } while (--i > 0);
+
+ biR->size -= num_shifts;
+ return biR;
+}
+
+/**
+ * Take each component and shift it up (in terms of components)
+ */
+static bigint *comp_left_shift(bigint *biR, int num_shifts)
+{
+ int i = biR->size-1;
+ comp *x, *y;
+
+ check(biR);
+
+ if (num_shifts <= 0)
+ {
+ return biR;
+ }
+
+ more_comps(biR, biR->size + num_shifts);
+
+ x = &biR->comps[i+num_shifts];
+ y = &biR->comps[i];
+
+ do
+ {
+ *x-- = *y--;
+ } while (i--);
+
+ memset(biR->comps, 0, num_shifts*COMP_BYTE_SIZE); /* zero LS comps */
+ return biR;
+}
+#endif
+
+/**
+ * @brief Allow a binary sequence to be imported as a bigint.
+ * @param ctx [in] The bigint session context.
+ * @param data [in] The data to be converted.
+ * @param size [in] The number of bytes of data.
+ * @return A bigint representing this data.
+ */
+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size)
+{
+ bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE);
+ int i, j = 0, offset = 0;
+
+ memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
+
+ for (i = size-1; i >= 0; i--)
+ {
+ biR->comps[offset] += data[i] << (j*8);
+
+ if (++j == COMP_BYTE_SIZE)
+ {
+ j = 0;
+ offset ++;
+ }
+ }
+
+ return trim(biR);
+}
+
+#ifdef CONFIG_SSL_FULL_MODE
+/**
+ * @brief The testharness uses this code to import text hex-streams and
+ * convert them into bigints.
+ * @param ctx [in] The bigint session context.
+ * @param data [in] A string consisting of hex characters. The characters must
+ * be in upper case.
+ * @return A bigint representing this data.
+ */
+bigint *bi_str_import(BI_CTX *ctx, const char *data)
+{
+ int size = strlen(data);
+ bigint *biR = alloc(ctx, (size+COMP_NUM_NIBBLES-1)/COMP_NUM_NIBBLES);
+ int i, j = 0, offset = 0;
+ memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
+
+ for (i = size-1; i >= 0; i--)
+ {
+ int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10);
+ biR->comps[offset] += num << (j*4);
+
+ if (++j == COMP_NUM_NIBBLES)
+ {
+ j = 0;
+ offset ++;
+ }
+ }
+
+ return biR;
+}
+
+void bi_print(const char *label, bigint *x)
+{
+ int i, j;
+
+ if (x == NULL)
+ {
+ printf("%s: (null)\n", label);
+ return;
+ }
+
+ printf("%s: (size %d)\n", label, x->size);
+ for (i = x->size-1; i >= 0; i--)
+ {
+ for (j = COMP_NUM_NIBBLES-1; j >= 0; j--)
+ {
+ comp mask = 0x0f << (j*4);
+ comp num = (x->comps[i] & mask) >> (j*4);
+ putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout);
+ }
+ }
+
+ printf("\n");
+}
+#endif
+
+/**
+ * @brief Take a bigint and convert it into a byte sequence.
+ *
+ * This is useful after a decrypt operation.
+ * @param ctx [in] The bigint session context.
+ * @param x [in] The bigint to be converted.
+ * @param data [out] The converted data as a byte stream.
+ * @param size [in] The maximum size of the byte stream. Unused bytes will be
+ * zeroed.
+ */
+void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size)
+{
+ int i, j, k = size-1;
+
+ check(x);
+ memset(data, 0, size); /* ensure all leading 0's are cleared */
+
+ for (i = 0; i < x->size; i++)
+ {
+ for (j = 0; j < COMP_BYTE_SIZE; j++)
+ {
+ comp mask = 0xff << (j*8);
+ int num = (x->comps[i] & mask) >> (j*8);
+ data[k--] = num;
+
+ if (k < 0)
+ {
+ break;
+ }
+ }
+ }
+
+ bi_free(ctx, x);
+}
+
+/**
+ * @brief Pre-calculate some of the expensive steps in reduction.
+ *
+ * This function should only be called once (normally when a session starts).
+ * When the session is over, bi_free_mod() should be called. bi_mod_power()
+ * relies on this function being called.
+ * @param ctx [in] The bigint session context.
+ * @param bim [in] The bigint modulus that will be used.
+ * @param mod_offset [in] There are three moduluii that can be stored - the
+ * standard modulus, and its two primes p and q. This offset refers to which
+ * modulus we are referring to.
+ * @see bi_free_mod(), bi_mod_power().
+ */
+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset)
+{
+ int k = bim->size;
+ comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1));
+#ifdef CONFIG_BIGINT_MONTGOMERY
+ bigint *R, *R2;
+#endif
+
+ ctx->bi_mod[mod_offset] = bim;
+ bi_permanent(ctx->bi_mod[mod_offset]);
+ ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);
+ bi_permanent(ctx->bi_normalised_mod[mod_offset]);
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+ /* set montgomery variables */
+ R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1); /* R */
+ R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1); /* R^2 */
+ ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2); /* R^2 mod m */
+ ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R); /* R mod m */
+
+ bi_permanent(ctx->bi_RR_mod_m[mod_offset]);
+ bi_permanent(ctx->bi_R_mod_m[mod_offset]);
+
+ ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);
+
+#elif defined (CONFIG_BIGINT_BARRETT)
+ ctx->bi_mu[mod_offset] =
+ bi_divide(ctx, comp_left_shift(
+ bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0);
+ bi_permanent(ctx->bi_mu[mod_offset]);
+#endif
+}
+
+/**
+ * @brief Used when cleaning various bigints at the end of a session.
+ * @param ctx [in] The bigint session context.
+ * @param mod_offset [in] The offset to use.
+ * @see bi_set_mod().
+ */
+void bi_free_mod(BI_CTX *ctx, int mod_offset)
+{
+ bi_depermanent(ctx->bi_mod[mod_offset]);
+ bi_free(ctx, ctx->bi_mod[mod_offset]);
+#if defined (CONFIG_BIGINT_MONTGOMERY)
+ bi_depermanent(ctx->bi_RR_mod_m[mod_offset]);
+ bi_depermanent(ctx->bi_R_mod_m[mod_offset]);
+ bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]);
+ bi_free(ctx, ctx->bi_R_mod_m[mod_offset]);
+#elif defined(CONFIG_BIGINT_BARRETT)
+ bi_depermanent(ctx->bi_mu[mod_offset]);
+ bi_free(ctx, ctx->bi_mu[mod_offset]);
+#endif
+ bi_depermanent(ctx->bi_normalised_mod[mod_offset]);
+ bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
+}
+
+/**
+ * Perform a standard multiplication between two bigints.
+ */
+static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+ int i, j, i_plus_j;
+ int n = bia->size;
+ int t = bib->size;
+ bigint *biR = alloc(ctx, n + t);
+ comp *sr = biR->comps;
+ comp *sa = bia->comps;
+ comp *sb = bib->comps;
+
+ check(bia);
+ check(bib);
+
+ /* clear things to start with */
+ memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE));
+ i = 0;
+
+ do
+ {
+ comp carry = 0;
+ comp b = *sb++;
+ i_plus_j = i;
+ j = 0;
+
+ 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);
+ } while (++j < n);
+
+ sr[i_plus_j] = carry;
+ } while (++i < t);
+
+ bi_free(ctx, bia);
+ bi_free(ctx, bib);
+ return trim(biR);
+}
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+/*
+ * Karatsuba improves on regular multiplication due to only 3 multiplications
+ * being done instead of 4. The additional additions/subtractions are O(N)
+ * rather than O(N^2) and so for big numbers it saves on a few operations
+ */
+static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square)
+{
+ bigint *x0, *x1;
+ bigint *p0, *p1, *p2;
+ int m;
+
+ if (is_square)
+ {
+ m = (bia->size + 1)/2;
+ }
+ else
+ {
+ m = (max(bia->size, bib->size) + 1)/2;
+ }
+
+ x0 = bi_clone(ctx, bia);
+ x0->size = m;
+ x1 = bi_clone(ctx, bia);
+ comp_right_shift(x1, m);
+ bi_free(ctx, bia);
+
+ /* work out the 3 partial products */
+ if (is_square)
+ {
+ p0 = bi_square(ctx, bi_copy(x0));
+ p2 = bi_square(ctx, bi_copy(x1));
+ p1 = bi_square(ctx, bi_add(ctx, x0, x1));
+ }
+ else /* normal multiply */
+ {
+ bigint *y0, *y1;
+ y0 = bi_clone(ctx, bib);
+ y0->size = m;
+ y1 = bi_clone(ctx, bib);
+ comp_right_shift(y1, m);
+ bi_free(ctx, bib);
+
+ p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0));
+ p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1));
+ p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1));
+ }
+
+ p1 = bi_subtract(ctx,
+ bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL);
+
+ comp_left_shift(p1, m);
+ comp_left_shift(p2, 2*m);
+ return bi_add(ctx, p1, bi_add(ctx, p0, p2));
+}
+#endif
+
+/**
+ * @brief Perform a multiplication operation between two bigints.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @return The result of the multiplication.
+ */
+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
+{
+ check(bia);
+ check(bib);
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+ if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH)
+ {
+ return regular_multiply(ctx, bia, bib);
+ }
+
+ return karatsuba(ctx, bia, bib, 0);
+#else
+ return regular_multiply(ctx, bia, bib);
+#endif
+}
+
+#ifdef CONFIG_BIGINT_SQUARE
+/*
+ * Perform the actual square operion. It takes into account overflow.
+ */
+static bigint *regular_square(BI_CTX *ctx, bigint *bi)
+{
+ int t = bi->size;
+ int i = 0, j;
+ bigint *biR = alloc(ctx, t*2);
+ comp *w = biR->comps;
+ comp *x = bi->comps;
+ 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);
+
+ for (j = i+1; j < t; j++)
+ {
+ long_comp xx = (long_comp)x[i]*x[j];
+ long_comp blob = (long_comp)w[i+j]+carry;
+
+ if (u) /* previous overflow */
+ {
+ blob += COMP_RADIX;
+ }
+
+ u = 0;
+ if (xx & COMP_BIG_MSB) /* check for overflow */
+ {
+ u = 1;
+ }
+
+ tmp = 2*xx + blob;
+ w[i+j] = (comp)tmp;
+ carry = (comp)(tmp >> COMP_BIT_SIZE);
+ }
+
+ w[i+t] += carry;
+
+ if (u)
+ {
+ w[i+t+1] = 1; /* add carry */
+ }
+ } while (++i < t);
+
+ bi_free(ctx, bi);
+ return trim(biR);
+}
+
+/**
+ * @brief Perform a square operation on a bigint.
+ * @param ctx [in] The bigint session context.
+ * @param bia [in] A bigint.
+ * @return The result of the multiplication.
+ */
+bigint *bi_square(BI_CTX *ctx, bigint *bia)
+{
+ check(bia);
+
+#ifdef CONFIG_BIGINT_KARATSUBA
+ if (bia->size < SQU_KARATSUBA_THRESH)
+ {
+ return regular_square(ctx, bia);
+ }
+
+ return karatsuba(ctx, bia, NULL, 1);
+#else
+ return regular_square(ctx, bia);
+#endif
+}
+#endif
+
+/**
+ * @brief Compare two bigints.
+ * @param bia [in] A bigint.
+ * @param bib [in] Another bigint.
+ * @return -1 if smaller, 1 if larger and 0 if equal.
+ */
+int bi_compare(bigint *bia, bigint *bib)
+{
+ int r, i;
+
+ check(bia);
+ check(bib);
+
+ if (bia->size > bib->size)
+ r = 1;
+ else if (bia->size < bib->size)
+ r = -1;
+ else
+ {
+ comp *a = bia->comps;
+ comp *b = bib->comps;
+
+ /* Same number of components. Compare starting from the high end
+ * and working down. */
+ r = 0;
+ i = bia->size - 1;
+
+ do
+ {
+ if (a[i] > b[i])
+ {
+ r = 1;
+ break;
+ }
+ else if (a[i] < b[i])
+ {
+ r = -1;
+ break;
+ }
+ } while (--i >= 0);
+ }
+
+ return r;
+}
+
+/*
+ * Allocate and zero more components. Does not consume bi.
+ */
+static void more_comps(bigint *bi, int n)
+{
+ if (n > bi->max_comps)
+ {
+ bi->max_comps = max(bi->max_comps * 2, n);
+ bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE);
+ }
+
+ if (n > bi->size)
+ {
+ memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE);
+ }
+
+ bi->size = n;
+}
+
+/*
+ * Make a new empty bigint. It may just use an old one if one is available.
+ * Otherwise get one off the heap.
+ */
+static bigint *alloc(BI_CTX *ctx, int size)
+{
+ bigint *biR;
+
+ /* Can we recycle an old bigint? */
+ if (ctx->free_list != NULL)
+ {
+ biR = ctx->free_list;
+ ctx->free_list = biR->next;
+ ctx->free_count--;
+
+ if (biR->refs != 0)
+ {
+#ifdef CONFIG_SSL_FULL_MODE
+ printf("alloc: refs was not 0\n");
+#endif
+ abort(); /* create a stack trace from a core dump */
+ }
+
+ more_comps(biR, size);
+ }
+ else
+ {
+ /* No free bigints available - create a new one. */
+ biR = (bigint *)malloc(sizeof(bigint));
+ biR->comps = (comp*)malloc(size * COMP_BYTE_SIZE);
+ biR->max_comps = size; /* give some space to spare */
+ }
+
+ biR->size = size;
+ biR->refs = 1;
+ biR->next = NULL;
+ ctx->active_count++;
+ return biR;
+}
+
+/*
+ * Work out the highest '1' bit in an exponent. Used when doing sliding-window
+ * exponentiation.
+ */
+static int find_max_exp_index(bigint *biexp)
+{
+ int i = COMP_BIT_SIZE-1;
+ comp shift = COMP_RADIX/2;
+ comp test = biexp->comps[biexp->size-1]; /* assume no leading zeroes */
+
+ check(biexp);
+
+ do
+ {
+ if (test & shift)
+ {
+ return i+(biexp->size-1)*COMP_BIT_SIZE;
+ }
+
+ shift >>= 1;
+ } while (--i != 0);
+
+ return -1; /* error - must have been a leading 0 */
+}
+
+/*
+ * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window
+ * exponentiation.
+ */
+static int exp_bit_is_one(bigint *biexp, int offset)
+{
+ comp test = biexp->comps[offset / COMP_BIT_SIZE];
+ int num_shifts = offset % COMP_BIT_SIZE;
+ comp shift = 1;
+ int i;
+
+ check(biexp);
+
+ for (i = 0; i < num_shifts; i++)
+ {
+ shift <<= 1;
+ }
+
+ return test & shift;
+}
+
+#ifdef CONFIG_BIGINT_CHECK_ON
+/*
+ * Perform a sanity check on bi.
+ */
+static void check(const bigint *bi)
+{
+ if (bi->refs <= 0)
+ {
+ printf("check: zero or negative refs in bigint\n");
+ abort();
+ }
+
+ if (bi->next != NULL)
+ {
+ printf("check: attempt to use a bigint from "
+ "the free list\n");
+ abort();
+ }
+}
+#endif
+
+/*
+ * Delete any leading 0's (and allow for 0).
+ */
+static bigint *trim(bigint *bi)
+{
+ check(bi);
+
+ while (bi->comps[bi->size-1] == 0 && bi->size > 1)
+ {
+ bi->size--;
+ }
+
+ return bi;
+}
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+/**
+ * @brief Perform a single montgomery reduction.
+ * @param ctx [in] The bigint session context.
+ * @param bixy [in] A bigint.
+ * @return The result of the montgomery reduction.
+ */
+bigint *bi_mont(BI_CTX *ctx, bigint *bixy)
+{
+ int i = 0, n;
+ uint8_t mod_offset = ctx->mod_offset;
+ bigint *bim = ctx->bi_mod[mod_offset];
+ comp mod_inv = ctx->N0_dash[mod_offset];
+
+ check(bixy);
+
+ if (ctx->use_classical) /* just use classical instead */
+ {
+ return bi_mod(ctx, bixy);
+ }
+
+ n = bim->size;
+
+ do
+ {
+ bixy = bi_add(ctx, bixy, comp_left_shift(
+ bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i));
+ } while (++i < n);
+
+ comp_right_shift(bixy, n);
+
+ if (bi_compare(bixy, bim) >= 0)
+ {
+ bixy = bi_subtract(ctx, bixy, bim, NULL);
+ }
+
+ return bixy;
+}
+
+#elif defined(CONFIG_BIGINT_BARRETT)
+/*
+ * Stomp on the most significant components to give the illusion of a "mod base
+ * radix" operation
+ */
+static bigint *comp_mod(bigint *bi, int mod)
+{
+ check(bi);
+
+ if (bi->size > mod)
+ {
+ bi->size = 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.
+ * @param bi [in] A bigint.
+ * @return The result of the Barrett reduction.
+ */
+bigint *bi_barrett(BI_CTX *ctx, bigint *bi)
+{
+ bigint *q1, *q2, *q3, *r1, *r2, *r;
+ uint8_t mod_offset = ctx->mod_offset;
+ bigint *bim = ctx->bi_mod[mod_offset];
+ int k = bim->size;
+
+ check(bi);
+ check(bim);
+
+ /* use Classical method instead - Barrett cannot help here */
+ if (bi->size > k*2)
+ {
+ return bi_mod(ctx, 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);
+ 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);
+ r = bi_subtract(ctx, r1, r2, NULL);
+
+ /* if (r >= m) r = r - m; */
+ if (bi_compare(r, bim) >= 0)
+ {
+ r = bi_subtract(ctx, r, bim, NULL);
+ }
+
+ return r;
+}
+#endif /* CONFIG_BIGINT_BARRETT */
+
+#ifdef CONFIG_BIGINT_SLIDING_WINDOW
+/*
+ * Work out g1, g3, g5, g7... etc for the sliding-window algorithm
+ */
+static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1)
+{
+ int k = 1, i;
+ bigint *g2;
+
+ for (i = 0; i < window-1; i++) /* compute 2^(window-1) */
+ {
+ k <<= 1;
+ }
+
+ ctx->g = (bigint **)malloc(k*sizeof(bigint *));
+ ctx->g[0] = bi_clone(ctx, g1);
+ bi_permanent(ctx->g[0]);
+ g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */
+
+ for (i = 1; i < k; i++)
+ {
+ ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2)));
+ bi_permanent(ctx->g[i]);
+ }
+
+ bi_free(ctx, g2);
+ ctx->window = k;
+}
+#endif
+
+/**
+ * @brief Perform a modular exponentiation.
+ *
+ * This function requires bi_set_mod() to have been called previously. This is
+ * one of the optimisations used for performance.
+ * @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.
+ * @see bi_set_mod().
+ */
+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)
+{
+ int i = find_max_exp_index(biexp), j, window_size = 1;
+ bigint *biR = int_to_bi(ctx, 1);
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+ uint8_t mod_offset = ctx->mod_offset;
+ if (!ctx->use_classical)
+ {
+ /* preconvert */
+ bi = bi_mont(ctx,
+ bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset])); /* x' */
+ bi_free(ctx, biR);
+ biR = ctx->bi_R_mod_m[mod_offset]; /* A */
+ }
+#endif
+
+ check(bi);
+ check(biexp);
+
+#ifdef CONFIG_BIGINT_SLIDING_WINDOW
+ for (j = i; j > 32; j /= 5) /* work out an optimum size */
+ window_size++;
+
+ /* work out the slide constants */
+ precompute_slide_window(ctx, window_size, bi);
+#else /* just one constant */
+ ctx->g = (bigint **)malloc(sizeof(bigint *));
+ ctx->g[0] = bi_clone(ctx, bi);
+ ctx->window = 1;
+ bi_permanent(ctx->g[0]);
+#endif
+
+ /* if sliding-window is off, then only one bit will be done at a time and
+ * will reduce to standard left-to-right exponentiation */
+ do
+ {
+ if (exp_bit_is_one(biexp, i))
+ {
+ int l = i-window_size+1;
+ int part_exp = 0;
+
+ if (l < 0) /* LSB of exponent will always be 1 */
+ l = 0;
+ else
+ {
+ while (exp_bit_is_one(biexp, l) == 0)
+ l++; /* go back up */
+ }
+
+ /* build up the section of the exponent */
+ for (j = i; j >= l; j--)
+ {
+ biR = bi_residue(ctx, bi_square(ctx, biR));
+ if (exp_bit_is_one(biexp, j))
+ part_exp++;
+
+ if (j != l)
+ part_exp <<= 1;
+ }
+
+ part_exp = (part_exp-1)/2; /* adjust for array */
+ biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp]));
+ i = l-1;
+ }
+ else /* square it */
+ {
+ biR = bi_residue(ctx, bi_square(ctx, biR));
+ i--;
+ }
+ } while (i >= 0);
+
+ /* cleanup */
+ for (i = 0; i < ctx->window; i++)
+ {
+ bi_depermanent(ctx->g[i]);
+ bi_free(ctx, ctx->g[i]);
+ }
+
+ free(ctx->g);
+ bi_free(ctx, bi);
+ bi_free(ctx, biexp);
+#if defined CONFIG_BIGINT_MONTGOMERY
+ return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */
+#else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */
+ return biR;
+#endif
+}
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * @brief Perform a modular exponentiation using a temporary modulus.
+ *
+ * We need this function to check the signatures of certificates. The modulus
+ * of this function is temporary as it's just used for authentication.
+ * @param ctx [in] The bigint session context.
+ * @param bi [in] The bigint to perform the exp/mod.
+ * @param bim [in] The temporary modulus.
+ * @param biexp [in] The bigint exponent.
+ * @see bi_set_mod().
+ */
+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp)
+{
+ bigint *biR, *tmp_biR;
+
+ /* Set up a temporary bigint context and transfer what we need between
+ * them. We need to do this since we want to keep the original modulus
+ * which is already in this context. This operation is only called when
+ * doing peer verification, and so is not expensive :-) */
+ BI_CTX *tmp_ctx = bi_initialize();
+ bi_set_mod(tmp_ctx, bi_clone(tmp_ctx, bim), BIGINT_M_OFFSET);
+ tmp_biR = bi_mod_power(tmp_ctx,
+ bi_clone(tmp_ctx, bi),
+ bi_clone(tmp_ctx, biexp));
+ biR = bi_clone(ctx, tmp_biR);
+ bi_free(tmp_ctx, tmp_biR);
+ bi_free_mod(tmp_ctx, BIGINT_M_OFFSET);
+ bi_terminate(tmp_ctx);
+
+ bi_free(ctx, bi);
+ bi_free(ctx, bim);
+ bi_free(ctx, biexp);
+ return biR;
+}
+#endif
+/** @} */
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.h b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.h
new file mode 100644
index 0000000..f9a3c70
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright(C) 2006 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.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+#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"
+
+#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_free(BI_CTX *ctx, bigint *bi);
+bigint *bi_copy(bigint *bi);
+bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
+void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
+bigint *int_to_bi(BI_CTX *ctx, comp i);
+
+/* the functions that actually do something interesting */
+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_subtract(BI_CTX *ctx, bigint *bia,
+ bigint *bib, int *is_negative);
+bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);
+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);
+int bi_compare(bigint *bia, bigint *bib);
+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
+void bi_free_mod(BI_CTX *ctx, int mod_offset);
+
+#ifdef CONFIG_SSL_FULL_MODE
+void bi_print(const char *label, bigint *bi);
+bigint *bi_str_import(BI_CTX *ctx, const char *data);
+#endif
+
+/**
+ * @def bi_mod
+ * Find the residue of B. bi_set_mod() must be called before hand.
+ */
+#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
+
+/**
+ * bi_residue() is technically the same as bi_mod(), but it uses the
+ * appropriate reduction technique (which is bi_mod() when doing classical
+ * reduction).
+ */
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+#define bi_residue(A, B) bi_mont(A, B)
+bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
+#elif defined(CONFIG_BIGINT_BARRETT)
+#define bi_residue(A, B) bi_barrett(A, B)
+bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
+#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
+#define bi_residue(A, B) bi_mod(A, B)
+#endif
+
+#ifdef CONFIG_BIGINT_SQUARE
+bigint *bi_square(BI_CTX *ctx, bigint *bi);
+#else
+#define bi_square(A, B) bi_multiply(A, bi_copy(B), B)
+#endif
+
+#endif
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint_impl.h b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint_impl.h
new file mode 100644
index 0000000..762a7cc
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/bigint_impl.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright(C) 2006 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.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+#ifndef BIGINT_IMPL_HEADER
+#define BIGINT_IMPL_HEADER
+
+/* Maintain a number of precomputed variables when doing reduction */
+#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */
+#ifdef CONFIG_BIGINT_CRT
+#define BIGINT_P_OFFSET 1 /**< p modulo offset. */
+#define BIGINT_Q_OFFSET 2 /**< q module offset. */
+#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */
+#else
+#define BIGINT_NUM_MODS 1
+#endif
+
+/* Architecture specific functions for big ints */
+#ifdef WIN32
+#define COMP_RADIX 4294967296i64
+#define COMP_BIG_MSB 0x8000000000000000i64
+#else
+#define COMP_RADIX 4294967296ULL /**< Max component + 1 */
+#define COMP_BIG_MSB 0x8000000000000000ULL /**< (Max dbl comp + 1)/ 2 */
+#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. */
+
+/**
+ * @struct _bigint
+ * @brief A big integer basic object
+ */
+struct _bigint
+{
+ struct _bigint* next; /**< The next bigint in the cache. */
+ short size; /**< The number of components in this bigint. */
+ short max_comps; /**< The heapsize allocated for this bigint */
+ int refs; /**< An internal reference count. */
+ comp* comps; /**< A ptr to the actual component data */
+};
+
+typedef struct _bigint bigint; /**< An alias for _bigint */
+
+/**
+ * Maintains the state of the cache, and a number of variables used in
+ * reduction.
+ */
+typedef struct /**< A big integer "session" context. */
+{
+ bigint *active_list; /**< Bigints currently used. */
+ bigint *free_list; /**< Bigints not used. */
+ bigint *bi_radix; /**< The radix used. */
+ bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */
+
+#if defined(CONFIG_BIGINT_MONTGOMERY)
+ bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */
+ bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */
+ comp N0_dash[BIGINT_NUM_MODS];
+#elif defined(CONFIG_BIGINT_BARRETT)
+ bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */
+#endif
+ bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
+ bigint **g; /**< Used by sliding-window. */
+ int window; /**< The size of the sliding window */
+ int active_count; /**< Number of active bigints. */
+ int free_count; /**< Number of free bigints. */
+
+#ifdef CONFIG_BIGINT_MONTGOMERY
+ uint8_t use_classical; /**< Use classical reduction. */
+#endif
+ uint8_t mod_offset; /**< The mod offset we are using */
+} BI_CTX;
+
+#ifndef WIN32
+#define max(a,b) ((a)>(b)?(a):(b)) /**< Find the maximum of 2 numbers. */
+#define min(a,b) ((a)<(b)?(a):(b)) /**< Find the minimum of 2 numbers. */
+#endif
+
+#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */
+
+#define V1 v->comps[v->size-1] /**< v1 for division */
+#define V2 v->comps[v->size-2] /**< v2 for division */
+#define U(j) tmp_u->comps[tmp_u->size-j-1] /**< uj for division */
+#define Q(j) quotient->comps[quotient->size-j-1] /**< qj for division */
+
+#endif
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/crypto.h b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/crypto.h
new file mode 100644
index 0000000..12acb27
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/crypto.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright(C) 2006 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.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+/**
+ * @file crypto.h
+ */
+
+#ifndef HEADER_CRYPTO_H
+#define HEADER_CRYPTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bigint.h"
+
+/**************************************************************************
+ * AES declarations
+ **************************************************************************/
+
+#define AES_MAXROUNDS 14
+
+typedef struct aes_key_st
+{
+ uint16_t rounds;
+ uint16_t key_size;
+ uint32_t ks[(AES_MAXROUNDS+1)*8];
+ uint8_t iv[16];
+} AES_CTX;
+
+typedef enum
+{
+ AES_MODE_128,
+ AES_MODE_256
+} AES_MODE;
+
+void AES_set_key(AES_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, AES_MODE mode);
+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
+ **************************************************************************/
+
+typedef struct
+{
+ int x, y, m[256];
+} RC4_CTX;
+
+void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);
+void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);
+
+/**************************************************************************
+ * SHA1 declarations
+ **************************************************************************/
+
+#define SHA1_SIZE 20
+
+/*
+ * This structure will hold context information for the SHA-1
+ * hashing operation
+ */
+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 */
+ uint16_t Message_Block_Index; /* Index into message block array */
+ 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);
+
+/**************************************************************************
+ * MD5 declarations
+ **************************************************************************/
+
+/* MD5 context. */
+
+#define MD5_SIZE 16
+
+typedef struct
+{
+ uint32_t state[4]; /* state (ABCD) */
+ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ 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);
+
+/**************************************************************************
+ * HMAC declarations
+ **************************************************************************/
+void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
+ int key_len, uint8_t *digest);
+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 <string.h>
+static inline void get_random_NZ(int num_rand_bytes, uint8_t *rand_data) {
+ memset ( rand_data, 0x01, num_rand_bytes );
+}
+
+/**************************************************************************
+ * RSA declarations
+ **************************************************************************/
+
+typedef struct
+{
+ bigint *m; /* modulus */
+ bigint *e; /* public exponent */
+ bigint *d; /* private exponent */
+#ifdef CONFIG_BIGINT_CRT
+ bigint *p; /* p as in m = pq */
+ bigint *q; /* q as in m = pq */
+ bigint *dP; /* d mod (p-1) */
+ bigint *dQ; /* d mod (q-1) */
+ bigint *qInv; /* q^-1 mod p */
+#endif
+ int num_octets;
+ bigint *sig_m; /* signature modulus */
+ BI_CTX *bi_ctx;
+} RSA_CTX;
+
+void RSA_priv_key_new(RSA_CTX **rsa_ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len,
+ const uint8_t *priv_exp, int priv_len
+#ifdef CONFIG_BIGINT_CRT
+ , const uint8_t *p, int p_len,
+ const uint8_t *q, int q_len,
+ const uint8_t *dP, int dP_len,
+ const uint8_t *dQ, int dQ_len,
+ const uint8_t *qInv, int qInv_len
+#endif
+ );
+void RSA_pub_key_new(RSA_CTX **rsa_ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len);
+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);
+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);
+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
+ **************************************************************************/
+
+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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/os_port.h b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/os_port.h
new file mode 100644
index 0000000..babdbfa
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/os_port.h
@@ -0,0 +1,61 @@
+/**
+ * @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()
+
+/** 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 */
+}
+
+typedef void FILE;
+
+static inline FILE * fopen ( const char *filename __unused,
+ const char *mode __unused ) {
+ return NULL;
+}
+
+static inline int fseek ( FILE *stream __unused, long offset __unused,
+ int whence __unused ) {
+ return -1;
+}
+
+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
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/rsa.c b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/rsa.c
new file mode 100644
index 0000000..389eda5
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/rsa.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright(C) 2006 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.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+/**
+ * Implements the RSA public encryption algorithm. Uses the bigint library to
+ * perform its calculations.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <stdlib.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 *priv_exp, int priv_len
+#if CONFIG_BIGINT_CRT
+ , const uint8_t *p, int p_len,
+ const uint8_t *q, int q_len,
+ const uint8_t *dP, int dP_len,
+ const uint8_t *dQ, int dQ_len,
+ const uint8_t *qInv, int qInv_len
+#endif
+ )
+{
+ RSA_CTX *rsa_ctx;
+ BI_CTX *bi_ctx;
+ RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len);
+ rsa_ctx = *ctx;
+ bi_ctx = rsa_ctx->bi_ctx;
+ rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len);
+ bi_permanent(rsa_ctx->d);
+
+#ifdef CONFIG_BIGINT_CRT
+ rsa_ctx->p = bi_import(bi_ctx, p, p_len);
+ rsa_ctx->q = bi_import(bi_ctx, q, q_len);
+ rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len);
+ rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len);
+ rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len);
+ bi_permanent(rsa_ctx->dP);
+ bi_permanent(rsa_ctx->dQ);
+ bi_permanent(rsa_ctx->qInv);
+ bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET);
+ bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET);
+#endif
+}
+
+void RSA_pub_key_new(RSA_CTX **ctx,
+ const uint8_t *modulus, int mod_len,
+ const uint8_t *pub_exp, int pub_len)
+{
+ RSA_CTX *rsa_ctx;
+ BI_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->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);
+ bi_permanent(rsa_ctx->e);
+}
+
+/**
+ * Free up any RSA context resources.
+ */
+void RSA_free(RSA_CTX *rsa_ctx)
+{
+ BI_CTX *bi_ctx;
+ if (rsa_ctx == NULL) /* deal with ptrs that are null */
+ return;
+
+ bi_ctx = rsa_ctx->bi_ctx;
+
+ bi_depermanent(rsa_ctx->e);
+ bi_free(bi_ctx, rsa_ctx->e);
+ bi_free_mod(rsa_ctx->bi_ctx, BIGINT_M_OFFSET);
+
+ if (rsa_ctx->d)
+ {
+ bi_depermanent(rsa_ctx->d);
+ bi_free(bi_ctx, rsa_ctx->d);
+#ifdef CONFIG_BIGINT_CRT
+ bi_depermanent(rsa_ctx->dP);
+ bi_depermanent(rsa_ctx->dQ);
+ bi_depermanent(rsa_ctx->qInv);
+ bi_free(bi_ctx, rsa_ctx->dP);
+ bi_free(bi_ctx, rsa_ctx->dQ);
+ bi_free(bi_ctx, rsa_ctx->qInv);
+ bi_free_mod(rsa_ctx->bi_ctx, BIGINT_P_OFFSET);
+ bi_free_mod(rsa_ctx->bi_ctx, BIGINT_Q_OFFSET);
+#endif
+ }
+
+ bi_terminate(bi_ctx);
+ free(rsa_ctx);
+}
+
+/**
+ * @brief Use PKCS1.5 for decryption/verification.
+ * @param ctx [in] The context
+ * @param in_data [in] The data to encrypt (must be < modulus size-11)
+ * @param out_data [out] The encrypted data.
+ * @param is_decryption [in] Decryption or verify operation.
+ * @return The number of bytes that were originally encrypted. -1 on error.
+ * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
+ */
+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;
+ int i, size;
+ bigint *decrypted_bi, *dat_bi;
+
+ memset(out_data, 0, byte_size); /* initialise */
+
+ /* decrypt */
+ dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size);
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+ decrypted_bi = is_decryption ? /* decrypt or verify? */
+ RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi);
+#else /* always a decryption */
+ decrypted_bi = RSA_private(ctx, dat_bi);
+#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 */
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+ if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */
+ {
+ while (block[i++] == 0xff && i < byte_size);
+
+ if (block[i-2] != 0xff)
+ i = byte_size; /*ensure size is 0 */
+ }
+ else /* PKCS1.5 encryption padding is random */
+#endif
+ {
+ while (block[i++] && i < byte_size);
+ }
+ size = byte_size - i;
+
+ /* get only the bit we want */
+ if (size > 0)
+ memcpy(out_data, &block[i], size);
+
+ free(block);
+ return size ? size : -1;
+}
+
+/**
+ * Performs m = c^d mod n
+ */
+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)
+{
+#ifdef CONFIG_BIGINT_CRT
+ return bi_crt(c, bi_msg);
+#else
+ BI_CTX *ctx = c->bi_ctx;
+ ctx->mod_offset = BIGINT_M_OFFSET;
+ return bi_mod_power(ctx, bi_msg, c->d);
+#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.
+ */
+void RSA_print(const RSA_CTX *rsa_ctx)
+{
+ if (rsa_ctx == NULL)
+ return;
+
+ printf("----------------- RSA DEBUG ----------------\n");
+ printf("Size:\t%d\n", rsa_ctx->num_octets);
+ bi_print("Modulus", rsa_ctx->m);
+ bi_print("Public Key", rsa_ctx->e);
+ bi_print("Private Key", rsa_ctx->d);
+}
+#endif
+
+#ifdef CONFIG_SSL_CERT_VERIFICATION
+/**
+ * Performs c = m^e mod n
+ */
+bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg)
+{
+ c->bi_ctx->mod_offset = BIGINT_M_OFFSET;
+ return bi_mod_power(c->bi_ctx, bi_msg, c->e);
+}
+
+/**
+ * Use PKCS1.5 for encryption/signing.
+ * see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
+ */
+int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
+ uint8_t *out_data, int is_signing)
+{
+ int byte_size = ctx->num_octets;
+ int num_pads_needed = byte_size-in_len-3;
+ bigint *dat_bi, *encrypt_bi;
+
+ /* note: in_len+11 must be > byte_size */
+ out_data[0] = 0; /* ensure encryption block is < modulus */
+
+ if (is_signing)
+ {
+ out_data[1] = 1; /* PKCS1.5 signing pads with "0xff"'s */
+ memset(&out_data[2], 0xff, num_pads_needed);
+ }
+ else /* randomize the encryption padding with non-zero bytes */
+ {
+ out_data[1] = 2;
+ get_random_NZ(num_pads_needed, &out_data[2]);
+ }
+
+ out_data[2+num_pads_needed] = 0;
+ memcpy(&out_data[3+num_pads_needed], in_data, 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);
+ 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;
+}
+#endif
+
+#endif /* CONFIG_SSL_CERT_VERIFICATION */
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls/sha1.c b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/sha1.c
new file mode 100644
index 0000000..9a42801
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls/sha1.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright(C) 2006 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.
+ *
+ * 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.
+ *
+ * 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
+ */
+
+/**
+ * SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995.
+ * This code was originally taken from RFC3174
+ */
+
+#include <string.h>
+#include "crypto.h"
+
+/*
+ * Define the SHA1 circular left shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/* ----- static functions ----- */
+static void SHA1PadMessage(SHA1_CTX *ctx);
+static void SHA1ProcessMessageBlock(SHA1_CTX *ctx);
+
+/**
+ * Initialize the SHA1 context
+ */
+void SHA1Init(SHA1_CTX *ctx)
+{
+ ctx->Length_Low = 0;
+ ctx->Length_High = 0;
+ ctx->Message_Block_Index = 0;
+ ctx->Intermediate_Hash[0] = 0x67452301;
+ ctx->Intermediate_Hash[1] = 0xEFCDAB89;
+ ctx->Intermediate_Hash[2] = 0x98BADCFE;
+ ctx->Intermediate_Hash[3] = 0x10325476;
+ ctx->Intermediate_Hash[4] = 0xC3D2E1F0;
+}
+
+/**
+ * Accepts an array of octets as the next portion of the message.
+ */
+void SHA1Update(SHA1_CTX *ctx, const uint8_t *msg, int len)
+{
+ while (len--)
+ {
+ ctx->Message_Block[ctx->Message_Block_Index++] = (*msg & 0xFF);
+
+ ctx->Length_Low += 8;
+ if (ctx->Length_Low == 0)
+ {
+ ctx->Length_High++;
+ }
+
+ if (ctx->Message_Block_Index == 64)
+ {
+ SHA1ProcessMessageBlock(ctx);
+ }
+
+ msg++;
+ }
+}
+
+/**
+ * Return the 160-bit message digest into the user's array
+ */
+void SHA1Final(SHA1_CTX *ctx, uint8_t *digest)
+{
+ int i;
+
+ SHA1PadMessage(ctx);
+ memset(ctx->Message_Block, 0, 64);
+ ctx->Length_Low = 0; /* and clear length */
+ ctx->Length_High = 0;
+
+ for (i = 0; i < SHA1_SIZE; i++)
+ {
+ digest[i] = ctx->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) );
+ }
+}
+
+/**
+ * Process the next 512 bits of the message stored in the array.
+ */
+static void SHA1ProcessMessageBlock(SHA1_CTX *ctx)
+{
+ const uint32_t K[] = { /* Constants defined in SHA-1 */
+ 0x5A827999,
+ 0x6ED9EBA1,
+ 0x8F1BBCDC,
+ 0xCA62C1D6
+ };
+ int t; /* Loop counter */
+ uint32_t temp; /* Temporary word value */
+ uint32_t W[80]; /* Word sequence */
+ uint32_t A, B, C, D, E; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for (t = 0; t < 16; t++)
+ {
+ W[t] = ctx->Message_Block[t * 4] << 24;
+ W[t] |= ctx->Message_Block[t * 4 + 1] << 16;
+ W[t] |= ctx->Message_Block[t * 4 + 2] << 8;
+ W[t] |= ctx->Message_Block[t * 4 + 3];
+ }
+
+ for (t = 16; t < 80; t++)
+ {
+ W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = ctx->Intermediate_Hash[0];
+ B = ctx->Intermediate_Hash[1];
+ C = ctx->Intermediate_Hash[2];
+ D = ctx->Intermediate_Hash[3];
+ E = ctx->Intermediate_Hash[4];
+
+ for (t = 0; t < 20; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+
+ B = A;
+ A = temp;
+ }
+
+ for (t = 20; t < 40; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for (t = 40; t < 60; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for (t = 60; t < 80; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ ctx->Intermediate_Hash[0] += A;
+ ctx->Intermediate_Hash[1] += B;
+ ctx->Intermediate_Hash[2] += C;
+ ctx->Intermediate_Hash[3] += D;
+ ctx->Intermediate_Hash[4] += E;
+ ctx->Message_Block_Index = 0;
+}
+
+/*
+ * According to the standard, the message must be padded to an even
+ * 512 bits. The first padding bit must be a '1'. The last 64
+ * bits represent the length of the original message. All bits in
+ * between should be 0. This function will pad the message
+ * according to those rules by filling the Message_Block array
+ * accordingly. It will also call the ProcessMessageBlock function
+ * provided appropriately. When it returns, it can be assumed that
+ * the message digest has been computed.
+ *
+ * @param ctx [in, out] The SHA1 context
+ */
+static void SHA1PadMessage(SHA1_CTX *ctx)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (ctx->Message_Block_Index > 55)
+ {
+ ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
+ while(ctx->Message_Block_Index < 64)
+ {
+ ctx->Message_Block[ctx->Message_Block_Index++] = 0;
+ }
+
+ SHA1ProcessMessageBlock(ctx);
+
+ while (ctx->Message_Block_Index < 56)
+ {
+ ctx->Message_Block[ctx->Message_Block_Index++] = 0;
+ }
+ }
+ else
+ {
+ ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
+ while(ctx->Message_Block_Index < 56)
+ {
+
+ ctx->Message_Block[ctx->Message_Block_Index++] = 0;
+ }
+ }
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ ctx->Message_Block[56] = ctx->Length_High >> 24;
+ ctx->Message_Block[57] = ctx->Length_High >> 16;
+ ctx->Message_Block[58] = ctx->Length_High >> 8;
+ ctx->Message_Block[59] = ctx->Length_High;
+ ctx->Message_Block[60] = ctx->Length_Low >> 24;
+ ctx->Message_Block[61] = ctx->Length_Low >> 16;
+ ctx->Message_Block[62] = ctx->Length_Low >> 8;
+ ctx->Message_Block[63] = ctx->Length_Low;
+ SHA1ProcessMessageBlock(ctx);
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls_aes.c b/contrib/syslinux-4.02/gpxe/src/crypto/axtls_aes.c
new file mode 100644
index 0000000..8bd3758
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls_aes.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <gpxe/crypto.h>
+#include <gpxe/cbc.h>
+#include <gpxe/aes.h>
+#include "crypto/axtls/crypto.h"
+
+/** @file
+ *
+ * AES algorithm
+ *
+ */
+
+/**
+ * Set key
+ *
+ * @v ctx Context
+ * @v key Key
+ * @v keylen Key length
+ * @ret rc Return status code
+ */
+static int aes_setkey ( void *ctx, const void *key, size_t keylen ) {
+ struct aes_context *aes_ctx = ctx;
+ AES_MODE mode;
+ void *iv;
+
+ switch ( keylen ) {
+ case ( 128 / 8 ):
+ mode = AES_MODE_128;
+ break;
+ case ( 256 / 8 ):
+ mode = AES_MODE_256;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* IV is not a relevant concept at this stage; use a dummy
+ * value that will have no side-effects.
+ */
+ iv = &aes_ctx->axtls_ctx.iv;
+
+ AES_set_key ( &aes_ctx->axtls_ctx, key, iv, mode );
+
+ aes_ctx->decrypting = 0;
+
+ return 0;
+}
+
+/**
+ * Set initialisation vector
+ *
+ * @v ctx Context
+ * @v iv Initialisation vector
+ */
+static void aes_setiv ( void *ctx __unused, const void *iv __unused ) {
+ /* Nothing to do */
+}
+
+/**
+ * Call AXTLS' AES_encrypt() or AES_decrypt() functions
+ *
+ * @v axtls_ctx AXTLS AES context
+ * @v src Data to process
+ * @v dst Buffer for output
+ * @v func AXTLS AES function to call
+ */
+static void aes_call_axtls ( AES_CTX *axtls_ctx, const void *src, void *dst,
+ void ( * func ) ( const AES_CTX *axtls_ctx,
+ uint32_t *data ) ){
+ const uint32_t *srcl = src;
+ uint32_t *dstl = dst;
+ unsigned int i;
+
+ /* AXTLS' AES_encrypt() and AES_decrypt() functions both
+ * expect to deal with an array of four dwords in host-endian
+ * order.
+ */
+ for ( i = 0 ; i < 4 ; i++ )
+ dstl[i] = ntohl ( srcl[i] );
+ func ( axtls_ctx, dstl );
+ for ( i = 0 ; i < 4 ; i++ )
+ dstl[i] = htonl ( dstl[i] );
+}
+
+/**
+ * Encrypt data
+ *
+ * @v ctx Context
+ * @v src Data to encrypt
+ * @v dst Buffer for encrypted data
+ * @v len Length of data
+ */
+static void aes_encrypt ( void *ctx, const void *src, void *dst,
+ size_t len ) {
+ struct aes_context *aes_ctx = ctx;
+
+ assert ( len == AES_BLOCKSIZE );
+ if ( aes_ctx->decrypting )
+ assert ( 0 );
+ aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_encrypt );
+}
+
+/**
+ * Decrypt data
+ *
+ * @v ctx Context
+ * @v src Data to decrypt
+ * @v dst Buffer for decrypted data
+ * @v len Length of data
+ */
+static void aes_decrypt ( void *ctx, const void *src, void *dst,
+ size_t len ) {
+ struct aes_context *aes_ctx = ctx;
+
+ assert ( len == AES_BLOCKSIZE );
+ if ( ! aes_ctx->decrypting ) {
+ AES_convert_key ( &aes_ctx->axtls_ctx );
+ aes_ctx->decrypting = 1;
+ }
+ aes_call_axtls ( &aes_ctx->axtls_ctx, src, dst, AES_decrypt );
+}
+
+/** Basic AES algorithm */
+struct cipher_algorithm aes_algorithm = {
+ .name = "aes",
+ .ctxsize = sizeof ( struct aes_context ),
+ .blocksize = AES_BLOCKSIZE,
+ .setkey = aes_setkey,
+ .setiv = aes_setiv,
+ .encrypt = aes_encrypt,
+ .decrypt = aes_decrypt,
+};
+
+/* AES with cipher-block chaining */
+CBC_CIPHER ( aes_cbc, aes_cbc_algorithm,
+ aes_algorithm, struct aes_context, AES_BLOCKSIZE );
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/axtls_sha1.c b/contrib/syslinux-4.02/gpxe/src/crypto/axtls_sha1.c
new file mode 100644
index 0000000..841e193
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/axtls_sha1.c
@@ -0,0 +1,25 @@
+#include "crypto/axtls/crypto.h"
+#include <gpxe/crypto.h>
+#include <gpxe/sha1.h>
+
+static void sha1_init ( void *ctx ) {
+ SHA1Init ( ctx );
+}
+
+static void sha1_update ( void *ctx, const void *data, size_t len ) {
+ SHA1Update ( ctx, data, len );
+}
+
+static void sha1_final ( void *ctx, void *out ) {
+ SHA1Final ( ctx, out );
+}
+
+struct digest_algorithm sha1_algorithm = {
+ .name = "sha1",
+ .ctxsize = SHA1_CTX_SIZE,
+ .blocksize = 64,
+ .digestsize = SHA1_DIGEST_SIZE,
+ .init = sha1_init,
+ .update = sha1_update,
+ .final = sha1_final,
+};
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/cbc.c b/contrib/syslinux-4.02/gpxe/src/crypto/cbc.c
new file mode 100644
index 0000000..1710203
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/cbc.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <assert.h>
+#include <gpxe/crypto.h>
+#include <gpxe/cbc.h>
+
+/** @file
+ *
+ * Cipher-block chaining
+ *
+ */
+
+/**
+ * XOR data blocks
+ *
+ * @v src Input data
+ * @v dst Second input data and output data buffer
+ * @v len Length of data
+ */
+static void cbc_xor ( const void *src, void *dst, size_t len ) {
+ const uint32_t *srcl = src;
+ uint32_t *dstl = dst;
+ unsigned int i;
+
+ /* Assume that block sizes will always be dword-aligned, for speed */
+ assert ( ( len % sizeof ( *srcl ) ) == 0 );
+
+ for ( i = 0 ; i < ( len / sizeof ( *srcl ) ) ; i++ )
+ dstl[i] ^= srcl[i];
+}
+
+/**
+ * Encrypt data
+ *
+ * @v ctx Context
+ * @v src Data to encrypt
+ * @v dst Buffer for encrypted data
+ * @v len Length of data
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ */
+void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len,
+ struct cipher_algorithm *raw_cipher, void *cbc_ctx ) {
+ size_t blocksize = raw_cipher->blocksize;
+
+ assert ( ( len % blocksize ) == 0 );
+
+ while ( len ) {
+ cbc_xor ( src, cbc_ctx, blocksize );
+ cipher_encrypt ( raw_cipher, ctx, cbc_ctx, dst, blocksize );
+ memcpy ( cbc_ctx, dst, blocksize );
+ dst += blocksize;
+ src += blocksize;
+ len -= blocksize;
+ }
+}
+
+/**
+ * Decrypt data
+ *
+ * @v ctx Context
+ * @v src Data to decrypt
+ * @v dst Buffer for decrypted data
+ * @v len Length of data
+ * @v raw_cipher Underlying cipher algorithm
+ * @v cbc_ctx CBC context
+ */
+void cbc_decrypt ( void *ctx, const void *src, void *dst, size_t len,
+ struct cipher_algorithm *raw_cipher, void *cbc_ctx ) {
+ size_t blocksize = raw_cipher->blocksize;
+
+ assert ( ( len % blocksize ) == 0 );
+
+ while ( len ) {
+ cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize );
+ cbc_xor ( cbc_ctx, dst, blocksize );
+ memcpy ( cbc_ctx, src, blocksize );
+ dst += blocksize;
+ src += blocksize;
+ len -= blocksize;
+ }
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/chap.c b/contrib/syslinux-4.02/gpxe/src/crypto/chap.c
new file mode 100644
index 0000000..8aa224c
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/chap.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <gpxe/crypto.h>
+#include <gpxe/chap.h>
+
+/** @file
+ *
+ * CHAP protocol
+ *
+ */
+
+/**
+ * Initialise CHAP challenge/response
+ *
+ * @v chap CHAP challenge/response
+ * @v digest Digest algorithm to use
+ * @ret rc Return status code
+ *
+ * Initialises a CHAP challenge/response structure. This routine
+ * allocates memory, and so may fail. The allocated memory must
+ * eventually be freed by a call to chap_finish().
+ */
+int chap_init ( struct chap_response *chap,
+ struct digest_algorithm *digest ) {
+ size_t state_len;
+ void *state;
+
+ assert ( chap->digest == NULL );
+ assert ( chap->digest_context == NULL );
+ assert ( chap->response == NULL );
+
+ DBG ( "CHAP %p initialising with %s digest\n", chap, digest->name );
+
+ state_len = ( digest->ctxsize + digest->digestsize );
+ state = malloc ( state_len );
+ if ( ! state ) {
+ DBG ( "CHAP %p could not allocate %zd bytes for state\n",
+ chap, state_len );
+ return -ENOMEM;
+ }
+
+ chap->digest = digest;
+ chap->digest_context = state;
+ chap->response = ( state + digest->ctxsize );
+ chap->response_len = digest->digestsize;
+ digest_init ( chap->digest, chap->digest_context );
+ return 0;
+}
+
+/**
+ * Add data to the CHAP challenge
+ *
+ * @v chap CHAP response
+ * @v data Data to add
+ * @v len Length of data to add
+ */
+void chap_update ( struct chap_response *chap, const void *data,
+ size_t len ) {
+ assert ( chap->digest != NULL );
+ assert ( chap->digest_context != NULL );
+
+ if ( ! chap->digest )
+ return;
+
+ digest_update ( chap->digest, chap->digest_context, data, len );
+}
+
+/**
+ * Respond to the CHAP challenge
+ *
+ * @v chap CHAP response
+ *
+ * Calculates the final CHAP response value, and places it in @c
+ * chap->response, with a length of @c chap->response_len.
+ */
+void chap_respond ( struct chap_response *chap ) {
+ assert ( chap->digest != NULL );
+ assert ( chap->digest_context != NULL );
+ assert ( chap->response != NULL );
+
+ DBG ( "CHAP %p responding to challenge\n", chap );
+
+ if ( ! chap->digest )
+ return;
+
+ digest_final ( chap->digest, chap->digest_context, chap->response );
+}
+
+/**
+ * Free resources used by a CHAP response
+ *
+ * @v chap CHAP response
+ */
+void chap_finish ( struct chap_response *chap ) {
+ void *state = chap->digest_context;
+
+ DBG ( "CHAP %p finished\n", chap );
+
+ free ( state );
+ memset ( chap, 0, sizeof ( *chap ) );
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/crandom.c b/contrib/syslinux-4.02/gpxe/src/crypto/crandom.c
new file mode 100644
index 0000000..9828482
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/crandom.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/** @file
+ *
+ * Cryptographically strong random number generator
+ *
+ * Currently the cryptographic part is not implemented, and this just
+ * uses random().
+ */
+
+#include <gpxe/crypto.h>
+#include <stdlib.h>
+
+/**
+ * Get cryptographically strong random bytes
+ *
+ * @v buf Buffer in which to store random bytes
+ * @v len Number of random bytes to generate
+ *
+ * @b WARNING: This function is currently underimplemented, and does
+ * not give numbers any stronger than random()!
+ */
+void get_random_bytes ( void *buf, size_t len )
+{
+ u8 *bufp = buf;
+
+ /*
+ * Somewhat arbitrarily, choose the 0x00FF0000-masked byte
+ * returned by random() as having good entropy. PRNGs often
+ * don't provide good entropy in lower bits, and the top byte
+ * might show a pattern because of sign issues.
+ */
+
+ while ( len-- ) {
+ *bufp++ = ( random() >> 16 ) & 0xFF;
+ }
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/crc32.c b/contrib/syslinux-4.02/gpxe/src/crypto/crc32.c
new file mode 100644
index 0000000..0cc314e
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/crc32.c
@@ -0,0 +1,54 @@
+/*
+ * Little-endian CRC32 implementation.
+ *
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crc32.h>
+
+#define CRCPOLY 0xedb88320
+
+/**
+ * Calculate 32-bit little-endian CRC checksum
+ *
+ * @v seed Initial value
+ * @v data Data to checksum
+ * @v len Length of data
+ *
+ * Usually @a seed is initially zero or all one bits, depending on the
+ * protocol. To continue a CRC checksum over multiple calls, pass the
+ * return value from one call as the @a seed parameter to the next.
+ */
+u32 crc32_le ( u32 seed, const void *data, size_t len )
+{
+ u32 crc = seed;
+ const u8 *src = data;
+ u32 mult;
+ int i;
+
+ while ( len-- ) {
+ crc ^= *src++;
+ for ( i = 0; i < 8; i++ ) {
+ mult = ( crc & 1 ) ? CRCPOLY : 0;
+ crc = ( crc >> 1 ) ^ mult;
+ }
+ }
+
+ return crc;
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/crypto_null.c b/contrib/syslinux-4.02/gpxe/src/crypto/crypto_null.c
new file mode 100644
index 0000000..61efb34
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/crypto_null.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Null crypto algorithm
+ */
+
+#include <string.h>
+#include <gpxe/crypto.h>
+
+static void digest_null_init ( void *ctx __unused ) {
+ /* Do nothing */
+}
+
+static void digest_null_update ( void *ctx __unused, const void *src __unused,
+ size_t len __unused ) {
+ /* Do nothing */
+}
+
+static void digest_null_final ( void *ctx __unused, void *out __unused ) {
+ /* Do nothing */
+}
+
+struct digest_algorithm digest_null = {
+ .name = "null",
+ .ctxsize = 0,
+ .blocksize = 1,
+ .digestsize = 0,
+ .init = digest_null_init,
+ .update = digest_null_update,
+ .final = digest_null_final,
+};
+
+static int cipher_null_setkey ( void *ctx __unused, const void *key __unused,
+ size_t keylen __unused ) {
+ /* Do nothing */
+ return 0;
+}
+
+static void cipher_null_setiv ( void *ctx __unused,
+ const void *iv __unused ) {
+ /* Do nothing */
+}
+
+static void cipher_null_encrypt ( void *ctx __unused, const void *src,
+ void *dst, size_t len ) {
+ memcpy ( dst, src, len );
+}
+
+static void cipher_null_decrypt ( void *ctx __unused, const void *src,
+ void *dst, size_t len ) {
+ memcpy ( dst, src, len );
+}
+
+struct cipher_algorithm cipher_null = {
+ .name = "null",
+ .ctxsize = 0,
+ .blocksize = 1,
+ .setkey = cipher_null_setkey,
+ .setiv = cipher_null_setiv,
+ .encrypt = cipher_null_encrypt,
+ .decrypt = cipher_null_decrypt,
+};
+
+struct pubkey_algorithm pubkey_null = {
+ .name = "null",
+ .ctxsize = 0,
+};
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/hmac.c b/contrib/syslinux-4.02/gpxe/src/crypto/hmac.c
new file mode 100644
index 0000000..d64730c
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/hmac.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+/**
+ * @file
+ *
+ * Keyed-Hashing for Message Authentication
+ */
+
+#include <string.h>
+#include <assert.h>
+#include <gpxe/crypto.h>
+#include <gpxe/hmac.h>
+
+/**
+ * Reduce HMAC key length
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v key Key
+ * @v key_len Length of key
+ */
+static void hmac_reduce_key ( struct digest_algorithm *digest,
+ void *key, size_t *key_len ) {
+ uint8_t digest_ctx[digest->ctxsize];
+
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, key, *key_len );
+ digest_final ( digest, digest_ctx, key );
+ *key_len = digest->digestsize;
+}
+
+/**
+ * Initialise HMAC
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v key Key
+ * @v key_len Length of key
+ *
+ * The length of the key should be less than the block size of the
+ * digest algorithm being used. (If the key length is greater, it
+ * will be replaced with its own digest, and key_len will be updated
+ * accordingly).
+ */
+void hmac_init ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len ) {
+ unsigned char k_ipad[digest->blocksize];
+ unsigned int i;
+
+ /* Reduce key if necessary */
+ if ( *key_len > sizeof ( k_ipad ) )
+ hmac_reduce_key ( digest, key, key_len );
+
+ /* Construct input pad */
+ memset ( k_ipad, 0, sizeof ( k_ipad ) );
+ memcpy ( k_ipad, key, *key_len );
+ for ( i = 0 ; i < sizeof ( k_ipad ) ; i++ ) {
+ k_ipad[i] ^= 0x36;
+ }
+
+ /* Start inner hash */
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, k_ipad, sizeof ( k_ipad ) );
+}
+
+/**
+ * Finalise HMAC
+ *
+ * @v digest Digest algorithm to use
+ * @v digest_ctx Digest context
+ * @v key Key
+ * @v key_len Length of key
+ * @v hmac HMAC digest to fill in
+ *
+ * The length of the key should be less than the block size of the
+ * digest algorithm being used. (If the key length is greater, it
+ * will be replaced with its own digest, and key_len will be updated
+ * accordingly).
+ */
+void hmac_final ( struct digest_algorithm *digest, void *digest_ctx,
+ void *key, size_t *key_len, void *hmac ) {
+ unsigned char k_opad[digest->blocksize];
+ unsigned int i;
+
+ /* Reduce key if necessary */
+ if ( *key_len > sizeof ( k_opad ) )
+ hmac_reduce_key ( digest, key, key_len );
+
+ /* Construct output pad */
+ memset ( k_opad, 0, sizeof ( k_opad ) );
+ memcpy ( k_opad, key, *key_len );
+ for ( i = 0 ; i < sizeof ( k_opad ) ; i++ ) {
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* Finish inner hash */
+ digest_final ( digest, digest_ctx, hmac );
+
+ /* Perform outer hash */
+ digest_init ( digest, digest_ctx );
+ digest_update ( digest, digest_ctx, k_opad, sizeof ( k_opad ) );
+ digest_update ( digest, digest_ctx, hmac, digest->digestsize );
+ digest_final ( digest, digest_ctx, hmac );
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/md5.c b/contrib/syslinux-4.02/gpxe/src/crypto/md5.c
new file mode 100644
index 0000000..8c60639
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/md5.c
@@ -0,0 +1,234 @@
+/*
+ * Cryptographic API.
+ *
+ * MD5 Message Digest Algorithm (RFC1321).
+ *
+ * Derived from cryptoapi implementation, originally based on the
+ * public domain implementation written by Colin Plumb in 1993.
+ *
+ * Reduced object size by around 50% compared to the original Linux
+ * version for use in Etherboot by Michael Brown.
+ *
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2006 Michael Brown <mbrown@fensystems.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdint.h>
+#include <string.h>
+#include <byteswap.h>
+#include <gpxe/crypto.h>
+#include <gpxe/md5.h>
+
+struct md5_step {
+ u32 ( * f ) ( u32 b, u32 c, u32 d );
+ u8 coefficient;
+ u8 constant;
+};
+
+static u32 f1(u32 b, u32 c, u32 d)
+{
+ return ( d ^ ( b & ( c ^ d ) ) );
+}
+
+static u32 f2(u32 b, u32 c, u32 d)
+{
+ return ( c ^ ( d & ( b ^ c ) ) );
+}
+
+static u32 f3(u32 b, u32 c, u32 d)
+{
+ return ( b ^ c ^ d );
+}
+
+static u32 f4(u32 b, u32 c, u32 d)
+{
+ return ( c ^ ( b | ~d ) );
+}
+
+static struct md5_step md5_steps[4] = {
+ {
+ .f = f1,
+ .coefficient = 1,
+ .constant = 0,
+ },
+ {
+ .f = f2,
+ .coefficient = 5,
+ .constant = 1,
+ },
+ {
+ .f = f3,
+ .coefficient = 3,
+ .constant = 5,
+ },
+ {
+ .f = f4,
+ .coefficient = 7,
+ .constant = 0,
+ }
+};
+
+static const u8 r[64] = {
+ 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
+ 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
+ 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
+ 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
+};
+
+static const u32 k[64] = {
+ 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL,
+ 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
+ 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL,
+ 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
+ 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL,
+ 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
+ 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL,
+ 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
+ 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL,
+ 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
+ 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL,
+ 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
+ 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL,
+ 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
+ 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL,
+ 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL,
+};
+
+static void md5_transform(u32 *hash, const u32 *in)
+{
+ u32 a, b, c, d, f, g, temp;
+ int i;
+ struct md5_step *step;
+
+ a = hash[0];
+ b = hash[1];
+ c = hash[2];
+ d = hash[3];
+
+ for ( i = 0 ; i < 64 ; i++ ) {
+ step = &md5_steps[i >> 4];
+ f = step->f ( b, c, d );
+ g = ( ( i * step->coefficient + step->constant ) & 0xf );
+ temp = d;
+ d = c;
+ c = b;
+ a += ( f + k[i] + in[g] );
+ a = ( ( a << r[i] ) | ( a >> ( 32-r[i] ) ) );
+ b += a;
+ a = temp;
+ }
+
+ hash[0] += a;
+ hash[1] += b;
+ hash[2] += c;
+ hash[3] += d;
+}
+
+/* XXX: this stuff can be optimized */
+static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
+{
+ while (words--) {
+ le32_to_cpus(buf);
+ buf++;
+ }
+}
+
+static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
+{
+ while (words--) {
+ cpu_to_le32s(buf);
+ buf++;
+ }
+}
+
+static inline void md5_transform_helper(struct md5_ctx *ctx)
+{
+ le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32));
+ md5_transform(ctx->hash, ctx->block);
+}
+
+static void md5_init(void *context)
+{
+ struct md5_ctx *mctx = context;
+
+ mctx->hash[0] = 0x67452301;
+ mctx->hash[1] = 0xefcdab89;
+ mctx->hash[2] = 0x98badcfe;
+ mctx->hash[3] = 0x10325476;
+ mctx->byte_count = 0;
+}
+
+static void md5_update(void *context, const void *data, size_t len)
+{
+ struct md5_ctx *mctx = context;
+ const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
+
+ mctx->byte_count += len;
+
+ if (avail > len) {
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, len);
+ return;
+ }
+
+ memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
+ data, avail);
+
+ md5_transform_helper(mctx);
+ data += avail;
+ len -= avail;
+
+ while (len >= sizeof(mctx->block)) {
+ memcpy(mctx->block, data, sizeof(mctx->block));
+ md5_transform_helper(mctx);
+ data += sizeof(mctx->block);
+ len -= sizeof(mctx->block);
+ }
+
+ memcpy(mctx->block, data, len);
+}
+
+static void md5_final(void *context, void *out)
+{
+ struct md5_ctx *mctx = context;
+ const unsigned int offset = mctx->byte_count & 0x3f;
+ char *p = (char *)mctx->block + offset;
+ int padding = 56 - (offset + 1);
+
+ *p++ = 0x80;
+ if (padding < 0) {
+ memset(p, 0x00, padding + sizeof (u64));
+ md5_transform_helper(mctx);
+ p = (char *)mctx->block;
+ padding = 56;
+ }
+
+ memset(p, 0, padding);
+ mctx->block[14] = mctx->byte_count << 3;
+ mctx->block[15] = mctx->byte_count >> 29;
+ le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
+ sizeof(u64)) / sizeof(u32));
+ md5_transform(mctx->hash, mctx->block);
+ cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
+ memcpy(out, mctx->hash, sizeof(mctx->hash));
+ memset(mctx, 0, sizeof(*mctx));
+}
+
+struct digest_algorithm md5_algorithm = {
+ .name = "md5",
+ .ctxsize = MD5_CTX_SIZE,
+ .blocksize = ( MD5_BLOCK_WORDS * 4 ),
+ .digestsize = MD5_DIGEST_SIZE,
+ .init = md5_init,
+ .update = md5_update,
+ .final = md5_final,
+};
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/sha1extra.c b/contrib/syslinux-4.02/gpxe/src/crypto/sha1extra.c
new file mode 100644
index 0000000..c144a0f
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/sha1extra.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <gpxe/crypto.h>
+#include <gpxe/sha1.h>
+#include <gpxe/hmac.h>
+#include <stdint.h>
+#include <byteswap.h>
+
+/**
+ * SHA1 pseudorandom function for creating derived keys
+ *
+ * @v key Master key with which this call is associated
+ * @v key_len Length of key
+ * @v label NUL-terminated ASCII string describing purpose of PRF data
+ * @v data Further data that should be included in the PRF
+ * @v data_len Length of further PRF data
+ * @v prf_len Bytes of PRF to generate
+ * @ret prf Pseudorandom function bytes
+ *
+ * This is the PRF variant used by 802.11, defined in IEEE 802.11-2007
+ * 8.5.5.1. EAP-FAST uses a different SHA1-based PRF, and TLS uses an
+ * MD5-based PRF.
+ */
+void prf_sha1 ( const void *key, size_t key_len, const char *label,
+ const void *data, size_t data_len, void *prf, size_t prf_len )
+{
+ u32 blk;
+ u8 keym[key_len]; /* modifiable copy of key */
+ u8 in[strlen ( label ) + 1 + data_len + 1]; /* message to HMAC */
+ u8 *in_blknr; /* pointer to last byte of in, block number */
+ u8 out[SHA1_SIZE]; /* HMAC-SHA1 result */
+ u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */
+ const size_t label_len = strlen ( label );
+
+ /* The HMAC-SHA-1 is calculated using the given key on the
+ message text `label', followed by a NUL, followed by one
+ byte indicating the block number (0 for first). */
+
+ memcpy ( keym, key, key_len );
+
+ memcpy ( in, label, strlen ( label ) + 1 );
+ memcpy ( in + label_len + 1, data, data_len );
+ in_blknr = in + label_len + 1 + data_len;
+
+ for ( blk = 0 ;; blk++ ) {
+ *in_blknr = blk;
+
+ hmac_init ( &sha1_algorithm, sha1_ctx, keym, &key_len );
+ hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) );
+ hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out );
+
+ if ( prf_len <= SHA1_SIZE ) {
+ memcpy ( prf, out, prf_len );
+ break;
+ }
+
+ memcpy ( prf, out, SHA1_SIZE );
+ prf_len -= SHA1_SIZE;
+ prf += SHA1_SIZE;
+ }
+}
+
+/**
+ * PBKDF2 key derivation function inner block operation
+ *
+ * @v passphrase Passphrase from which to derive key
+ * @v pass_len Length of passphrase
+ * @v salt Salt to include in key
+ * @v salt_len Length of salt
+ * @v iterations Number of iterations of SHA1 to perform
+ * @v blocknr Index of this block, starting at 1
+ * @ret block SHA1_SIZE bytes of PBKDF2 data
+ *
+ * The operation of this function is described in RFC 2898.
+ */
+static void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len,
+ const void *salt, size_t salt_len,
+ int iterations, u32 blocknr, u8 *block )
+{
+ u8 pass[pass_len]; /* modifiable passphrase */
+ u8 in[salt_len + 4]; /* input buffer to first round */
+ u8 last[SHA1_SIZE]; /* output of round N, input of N+1 */
+ u8 sha1_ctx[SHA1_CTX_SIZE];
+ u8 *next_in = in; /* changed to `last' after first round */
+ int next_size = sizeof ( in );
+ int i, j;
+
+ blocknr = htonl ( blocknr );
+
+ memcpy ( pass, passphrase, pass_len );
+ memcpy ( in, salt, salt_len );
+ memcpy ( in + salt_len, &blocknr, 4 );
+ memset ( block, 0, SHA1_SIZE );
+
+ for ( i = 0; i < iterations; i++ ) {
+ hmac_init ( &sha1_algorithm, sha1_ctx, pass, &pass_len );
+ hmac_update ( &sha1_algorithm, sha1_ctx, next_in, next_size );
+ hmac_final ( &sha1_algorithm, sha1_ctx, pass, &pass_len, last );
+
+ for ( j = 0; j < SHA1_SIZE; j++ ) {
+ block[j] ^= last[j];
+ }
+
+ next_in = last;
+ next_size = SHA1_SIZE;
+ }
+}
+
+/**
+ * PBKDF2 key derivation function using SHA1
+ *
+ * @v passphrase Passphrase from which to derive key
+ * @v pass_len Length of passphrase
+ * @v salt Salt to include in key
+ * @v salt_len Length of salt
+ * @v iterations Number of iterations of SHA1 to perform
+ * @v key_len Length of key to generate
+ * @ret key Generated key bytes
+ *
+ * This is used most notably in 802.11 WPA passphrase hashing, in
+ * which case the salt is the SSID, 4096 iterations are used, and a
+ * 32-byte key is generated that serves as the Pairwise Master Key for
+ * EAPOL authentication.
+ *
+ * The operation of this function is further described in RFC 2898.
+ */
+void pbkdf2_sha1 ( const void *passphrase, size_t pass_len,
+ const void *salt, size_t salt_len,
+ int iterations, void *key, size_t key_len )
+{
+ u32 blocks = ( key_len + SHA1_SIZE - 1 ) / SHA1_SIZE;
+ u32 blk;
+ u8 buf[SHA1_SIZE];
+
+ for ( blk = 1; blk <= blocks; blk++ ) {
+ pbkdf2_sha1_f ( passphrase, pass_len, salt, salt_len,
+ iterations, blk, buf );
+ if ( key_len <= SHA1_SIZE ) {
+ memcpy ( key, buf, key_len );
+ break;
+ }
+
+ memcpy ( key, buf, SHA1_SIZE );
+ key_len -= SHA1_SIZE;
+ key += SHA1_SIZE;
+ }
+}
diff --git a/contrib/syslinux-4.02/gpxe/src/crypto/x509.c b/contrib/syslinux-4.02/gpxe/src/crypto/x509.c
new file mode 100644
index 0000000..31ed412
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/crypto/x509.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/asn1.h>
+#include <gpxe/x509.h>
+
+/** @file
+ *
+ * X.509 certificates
+ *
+ * The structure of X.509v3 certificates is concisely documented in
+ * RFC5280 section 4.1. The structure of RSA public keys is
+ * documented in RFC2313.
+ */
+
+/** Object Identifier for "rsaEncryption" (1.2.840.113549.1.1.1) */
+static const uint8_t oid_rsa_encryption[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01 };
+
+/**
+ * Identify X.509 certificate public key
+ *
+ * @v certificate Certificate
+ * @v algorithm Public key algorithm to fill in
+ * @v pubkey Public key value to fill in
+ * @ret rc Return status code
+ */
+static int x509_public_key ( const struct asn1_cursor *certificate,
+ struct asn1_cursor *algorithm,
+ struct asn1_cursor *pubkey ) {
+ struct asn1_cursor cursor;
+ int rc;
+
+ /* Locate subjectPublicKeyInfo */
+ memcpy ( &cursor, certificate, sizeof ( cursor ) );
+ rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */
+ asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */
+ asn1_skip ( &cursor, ASN1_EXPLICIT_TAG ), /* version */
+ asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* validity */
+ asn1_skip ( &cursor, ASN1_SEQUENCE ), /* name */
+ asn1_enter ( &cursor, ASN1_SEQUENCE )/* subjectPublicKeyInfo*/);
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate subjectPublicKeyInfo in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+
+ /* Locate algorithm */
+ memcpy ( algorithm, &cursor, sizeof ( *algorithm ) );
+ rc = ( asn1_enter ( algorithm, ASN1_SEQUENCE ) /* algorithm */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate algorithm in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+
+ /* Locate subjectPublicKey */
+ memcpy ( pubkey, &cursor, sizeof ( *pubkey ) );
+ rc = ( asn1_skip ( pubkey, ASN1_SEQUENCE ), /* algorithm */
+ asn1_enter ( pubkey, ASN1_BIT_STRING ) /* subjectPublicKey*/ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate subjectPublicKey in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Identify X.509 certificate RSA modulus and public exponent
+ *
+ * @v certificate Certificate
+ * @v rsa RSA public key to fill in
+ * @ret rc Return status code
+ *
+ * The caller is responsible for eventually calling
+ * x509_free_rsa_public_key() to free the storage allocated to hold
+ * the RSA modulus and exponent.
+ */
+int x509_rsa_public_key ( const struct asn1_cursor *certificate,
+ struct x509_rsa_public_key *rsa_pubkey ) {
+ struct asn1_cursor algorithm;
+ struct asn1_cursor pubkey;
+ struct asn1_cursor modulus;
+ struct asn1_cursor exponent;
+ int rc;
+
+ /* First, extract the public key algorithm and key data */
+ if ( ( rc = x509_public_key ( certificate, &algorithm,
+ &pubkey ) ) != 0 )
+ return rc;
+
+ /* Check that algorithm is RSA */
+ rc = ( asn1_enter ( &algorithm, ASN1_OID ) /* algorithm */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate algorithm:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return rc;
+ }
+ if ( ( algorithm.len != sizeof ( oid_rsa_encryption ) ) ||
+ ( memcmp ( algorithm.data, &oid_rsa_encryption,
+ sizeof ( oid_rsa_encryption ) ) != 0 ) ) {
+ DBG ( "algorithm is not rsaEncryption in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+
+ /* Check that public key is a byte string, i.e. that the
+ * "unused bits" byte contains zero.
+ */
+ if ( ( pubkey.len < 1 ) ||
+ ( ( *( uint8_t * ) pubkey.data ) != 0 ) ) {
+ DBG ( "subjectPublicKey is not a byte string in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+ pubkey.data++;
+ pubkey.len--;
+
+ /* Pick out the modulus and exponent */
+ rc = ( asn1_enter ( &pubkey, ASN1_SEQUENCE ) /* RSAPublicKey */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate RSAPublicKey in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+ memcpy ( &modulus, &pubkey, sizeof ( modulus ) );
+ rc = ( asn1_enter ( &modulus, ASN1_INTEGER ) /* modulus */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate modulus in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+ memcpy ( &exponent, &pubkey, sizeof ( exponent ) );
+ rc = ( asn1_skip ( &exponent, ASN1_INTEGER ), /* modulus */
+ asn1_enter ( &exponent, ASN1_INTEGER ) /* publicExponent */ );
+ if ( rc != 0 ) {
+ DBG ( "Cannot locate publicExponent in:\n" );
+ DBG_HDA ( 0, certificate->data, certificate->len );
+ return -ENOTSUP;
+ }
+
+ /* Allocate space and copy out modulus and exponent */
+ rsa_pubkey->modulus = malloc ( modulus.len + exponent.len );
+ if ( ! rsa_pubkey->modulus )
+ return -ENOMEM;
+ rsa_pubkey->exponent = ( rsa_pubkey->modulus + modulus.len );
+ memcpy ( rsa_pubkey->modulus, modulus.data, modulus.len );
+ rsa_pubkey->modulus_len = modulus.len;
+ memcpy ( rsa_pubkey->exponent, exponent.data, exponent.len );
+ rsa_pubkey->exponent_len = exponent.len;
+
+ DBG2 ( "RSA modulus:\n" );
+ DBG2_HDA ( 0, rsa_pubkey->modulus, rsa_pubkey->modulus_len );
+ DBG2 ( "RSA exponent:\n" );
+ DBG2_HDA ( 0, rsa_pubkey->exponent, rsa_pubkey->exponent_len );
+
+ return 0;
+}