From 7c7e89b540304bfc0b62d6e8e760d0b426ba15c4 Mon Sep 17 00:00:00 2001 From: cameronrich Date: Sun, 16 Sep 2007 11:28:22 +0000 Subject: [PATCH] added md2 git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@125 9a5d90b5-6617-0410-8a86-bb477d3ed2e3 --- crypto/Makefile | 1 + crypto/crypto.h | 28 +++++++-- crypto/md2.c | 142 +++++++++++++++++++++++++++++++++++++++++++++ ssl/Makefile | 1 + ssl/test/ssltest.c | 4 +- ssl/x509.c | 9 +++ 6 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 crypto/md2.c diff --git a/crypto/Makefile b/crypto/Makefile index 2f69f1e49..b449a3f86 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -24,6 +24,7 @@ AXTLS_HOME=.. OBJ=\ aes.o \ hmac.o \ + md2.o \ md5.o \ rc4.o \ sha1.o diff --git a/crypto/crypto.h b/crypto/crypto.h index ad49646c0..e45c717b5 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -82,11 +82,11 @@ void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length); */ typedef struct { - uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */ - uint32_t Length_Low; /* Message length in bits */ - uint32_t Length_High; /* Message length in bits */ + uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */ + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ uint16_t Message_Block_Index; /* Index into message block array */ - uint8_t Message_Block[64]; /* 512-bit message blocks */ + uint8_t Message_Block[64]; /* 512-bit message blocks */ } SHA1_CTX; void SHA1_Init(SHA1_CTX *); @@ -94,10 +94,26 @@ void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len); void SHA1_Final(uint8_t *digest, SHA1_CTX *); /************************************************************************** - * MD5 declarations + * MD2 declarations **************************************************************************/ -/* MD5 context. */ +#define MD2_SIZE 16 + +typedef struct +{ + unsigned char cksum[16]; /* checksum of the data block */ + unsigned char state[48]; /* intermediate digest state */ + unsigned char buffer[16]; /* data block being processed */ + int left; /* amount of data in buffer */ +} MD2_CTX; + +EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx); +EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen); +EXP_FUNC void STDCALL MD2_Final(uint8_t *digest, MD2_CTX *ctx); + +/************************************************************************** + * MD5 declarations + **************************************************************************/ #define MD5_SIZE 16 diff --git a/crypto/md2.c b/crypto/md2.c new file mode 100644 index 000000000..7ee3b91fc --- /dev/null +++ b/crypto/md2.c @@ -0,0 +1,142 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright (C) 2006-2007 Christophe Devine + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License, version 2.1 as published by the Free Software Foundation. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +/* + * The MD2 algorithm was designed by Ron Rivest in 1989. + * + * http://www.ietf.org/rfc/rfc1115.txt + * http://www.ietf.org/rfc/rfc1319.txt + */ + +#include +#include + +#include "crypto.h" + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +/* + * MD2 context setup + */ +EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx) +{ + memset(ctx, 0, sizeof *ctx); +} + +static void md2_process(MD2_CTX *ctx) +{ + int i, j; + unsigned char t = 0; + + for (i = 0; i < 16; i++) + { + ctx->state[i + 16] = ctx->buffer[i]; + ctx->state[i + 32] = ctx->buffer[i] ^ ctx->state[i]; + } + + for (i = 0; i < 18; i++) + { + for (j = 0; j < 48; j++) + t = (ctx->state[j] ^= PI_SUBST[t]); + + t = (t + i) & 0xFF; + } + + t = ctx->cksum[15]; + + for (i = 0; i < 16; i++) + t = (ctx->cksum[i] ^= PI_SUBST[ctx->buffer[i] ^ t]); +} + +/* + * MD2 process buffer + */ +EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen) +{ + int fill; + + while (ilen > 0) + { + if (ctx->left + ilen > 16) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy(ctx->buffer + ctx->left, input, fill); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if (ctx->left == 16) + { + ctx->left = 0; + md2_process(ctx); + } + } +} + +/* + * MD2 final digest + */ +EXP_FUNC void STDCALL MD2_Final(uint8_t *output, MD2_CTX *ctx) +{ + int i; + uint8_t x; + + x = (uint8_t)(16 - ctx->left); + + for (i = ctx->left; i < 16; i++) + ctx->buffer[i] = x; + + md2_process(ctx); + + memcpy(ctx->buffer, ctx->cksum, 16); + md2_process(ctx); + + memcpy(output, ctx->state, 16); +} diff --git a/ssl/Makefile b/ssl/Makefile index d0bfc1149..2dcbeceec 100644 --- a/ssl/Makefile +++ b/ssl/Makefile @@ -55,6 +55,7 @@ libs: $(TARGET1) $(TARGET2) CRYPTO_OBJ=\ $(CRYPTO_PATH)aes.o \ $(CRYPTO_PATH)hmac.o \ + $(CRYPTO_PATH)md2.o \ $(CRYPTO_PATH)md5.o \ $(CRYPTO_PATH)rc4.o \ $(CRYPTO_PATH)sha1.o diff --git a/ssl/test/ssltest.c b/ssl/test/ssltest.c index 469be5141..b91c5fe89 100644 --- a/ssl/test/ssltest.c +++ b/ssl/test/ssltest.c @@ -604,11 +604,9 @@ static int cert_tests(void) ssl_ctx_free(ssl_ctx); free(buf); - /* Verisign use MD2 which is not supported */ ssl_ctx = ssl_ctx_new(0, 0); len = get_file("../ssl/test/verisign.x509_ca", &buf); - if ((res = add_cert_auth(ssl_ctx, buf, len)) != - X509_VFY_ERROR_UNSUPPORTED_DIGEST) + if ((res = add_cert_auth(ssl_ctx, buf, len)) <0) { printf("Cert #7\n"); ssl_display_error(res); diff --git a/ssl/x509.c b/ssl/x509.c index 32e19fdbb..85110951b 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -126,6 +126,15 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) SHA1_Final(sha_dgst, &sha_ctx); x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE); } + else if (x509_ctx->sig_type == SIG_TYPE_MD2) + { + MD2_CTX md2_ctx; + uint8_t md2_dgst[MD2_SIZE]; + MD2_Init(&md2_ctx); + MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs); + MD2_Final(md2_dgst, &md2_ctx); + x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE); + } offset = end_tbs; /* skip the v3 data */ if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||