diff options
Diffstat (limited to 'libtomcrypt/src/pk')
127 files changed, 5221 insertions, 2003 deletions
diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c index bace8c8..5203fcf 100644 --- a/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c +++ b/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -45,8 +43,8 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen, return CRYPT_INVALID_PACKET; } - /* offset in the data */ - x = 1; + /* offset in the data */ + x = 1; /* get the length of the data */ if (in[x] & 0x80) { @@ -67,7 +65,7 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen, /* short format */ dlen = in[x++] & 0x7F; } - + /* is the data len too long or too short? */ if ((dlen == 0) || (dlen + x > inlen)) { return CRYPT_INVALID_PACKET; @@ -97,6 +95,6 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c new file mode 100644 index 0000000..223899b --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c @@ -0,0 +1,107 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_decode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +#define SETBIT(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n)))) +#define CLRBIT(v, n) (v=((unsigned char)(v) & ~(1U << (unsigned char)(n)))) + +/** + Store a BIT STRING + @param in The DER encoded BIT STRING + @param inlen The size of the DER BIT STRING + @param out [out] The array of bits stored (8 per char) + @param outlen [in/out] The number of bits stored + @return CRYPT_OK if successful +*/ +int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long dlen, blen, x, y; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* packet must be at least 4 bytes */ + if (inlen < 4) { + return CRYPT_INVALID_ARG; + } + + /* check for 0x03 */ + if ((in[0]&0x1F) != 0x03) { + return CRYPT_INVALID_PACKET; + } + + /* offset in the data */ + x = 1; + + /* get the length of the data */ + if (in[x] & 0x80) { + /* long format get number of length bytes */ + y = in[x++] & 0x7F; + + /* invalid if 0 or > 2 */ + if (y == 0 || y > 2) { + return CRYPT_INVALID_PACKET; + } + + /* read the data len */ + dlen = 0; + while (y--) { + dlen = (dlen << 8) | (unsigned long)in[x++]; + } + } else { + /* short format */ + dlen = in[x++] & 0x7F; + } + + /* is the data len too long or too short? */ + if ((dlen == 0) || (dlen + x > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* get padding count */ + blen = ((dlen - 1) << 3) - (in[x++] & 7); + + /* too many bits? */ + if (blen > *outlen) { + *outlen = blen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode/store the bits */ + for (y = 0; y < blen; y++) { + if (in[x] & (1 << (7 - (y & 7)))) { + SETBIT(out[y/8], 7-(y%8)); + } else { + CLRBIT(out[y/8], 7-(y%8)); + } + if ((y & 7) == 7) { + ++x; + } + } + + /* we done */ + *outlen = blen; + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c index e64bd1f..c552184 100644 --- a/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c +++ b/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -84,6 +82,6 @@ int der_encode_bit_string(const unsigned char *in, unsigned long inlen, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c new file mode 100644 index 0000000..298c4e3 --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_encode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k)) + +/** + Store a BIT STRING + @param in The array of bits to store (8 per char) + @param inlen The number of bits to store + @param out [out] The destination for the DER encoded BIT STRING + @param outlen [in/out] The max size and resulting size of the DER BIT STRING + @return CRYPT_OK if successful +*/ +int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y; + unsigned char buf; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* avoid overflows */ + if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header (include bit padding count in length) */ + x = 0; + y = (inlen >> 3) + ((inlen&7) ? 1 : 0) + 1; + + out[x++] = 0x03; + if (y < 128) { + out[x++] = (unsigned char)y; + } else if (y < 256) { + out[x++] = 0x81; + out[x++] = (unsigned char)y; + } else if (y < 65536) { + out[x++] = 0x82; + out[x++] = (unsigned char)((y>>8)&255); + out[x++] = (unsigned char)(y&255); + } + + /* store number of zero padding bits */ + out[x++] = (unsigned char)((8 - inlen) & 7); + + /* store the bits in big endian format */ + for (y = buf = 0; y < inlen; y++) { + buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7)); + if ((y & 7) == 7) { + out[x++] = buf; + buf = 0; + } + } + /* store last byte */ + if (inlen & 7) { + out[x++] = buf; + } + + *outlen = x; + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c b/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c index 3ec5f58..b9c99fb 100644 --- a/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c +++ b/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -17,7 +15,7 @@ #ifdef LTC_DER /** - Gets length of DER encoding of BIT STRING + Gets length of DER encoding of BIT STRING @param nbits The number of bits in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful @@ -29,7 +27,7 @@ int der_length_bit_string(unsigned long nbits, unsigned long *outlen) /* get the number of the bytes */ nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1; - + if (nbytes < 128) { /* 03 LL PP DD DD DD ... */ *outlen = 2 + nbytes; @@ -49,6 +47,6 @@ int der_length_bit_string(unsigned long nbits, unsigned long *outlen) #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c b/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c index e7c5699..da60ca9 100644 --- a/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c +++ b/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -30,18 +28,18 @@ int der_decode_boolean(const unsigned char *in, unsigned long inlen, { LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); - - if (inlen != 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) { + + if (inlen < 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) { return CRYPT_INVALID_ARG; } - + *out = (in[2]==0xFF) ? 1 : 0; - + return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c b/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c index b40fae6..c5cacdd 100644 --- a/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c +++ b/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -25,27 +23,27 @@ @param outlen [in/out] The max size and resulting size of the DER BOOLEAN @return CRYPT_OK if successful */ -int der_encode_boolean(int in, +int der_encode_boolean(int in, unsigned char *out, unsigned long *outlen) { LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(out != NULL); - + if (*outlen < 3) { *outlen = 3; return CRYPT_BUFFER_OVERFLOW; } - + *outlen = 3; out[0] = 0x01; out[1] = 0x01; out[2] = in ? 0xFF : 0x00; - + return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c b/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c index 5437031..a1a3a7b 100644 --- a/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c +++ b/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -17,7 +15,7 @@ #ifdef LTC_DER /** - Gets length of DER encoding of a BOOLEAN + Gets length of DER encoding of a BOOLEAN @param outlen [out] The length of the DER encoding @return CRYPT_OK if successful */ @@ -30,6 +28,6 @@ int der_length_boolean(unsigned long *outlen) #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c b/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c index 1220b37..0bfd3bb 100644 --- a/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c +++ b/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -51,6 +49,16 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, data = list[x].data; switch (list[x].type) { + case LTC_ASN1_BOOLEAN: + if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) { + if (der_length_boolean(&z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + case LTC_ASN1_INTEGER: if (der_decode_integer(in, *inlen, data) == CRYPT_OK) { if (der_length_integer(data, &z) == CRYPT_OK) { @@ -82,6 +90,17 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, } break; + case LTC_ASN1_RAW_BIT_STRING: + if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_bit_string(size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + case LTC_ASN1_OCTET_STRING: if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_octet_string(size, &z) == CRYPT_OK) { @@ -100,7 +119,7 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, return CRYPT_OK; } break; - + case LTC_ASN1_OBJECT_IDENTIFIER: if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_object_identifier(data, size, &z) == CRYPT_OK) { @@ -112,6 +131,17 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, } break; + case LTC_ASN1_TELETEX_STRING: + if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_teletex_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + case LTC_ASN1_IA5_STRING: if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_ia5_string(data, size, &z) == CRYPT_OK) { @@ -123,7 +153,6 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, } break; - case LTC_ASN1_PRINTABLE_STRING: if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_printable_string(data, size, &z) == CRYPT_OK) { @@ -155,6 +184,15 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, } break; + case LTC_ASN1_GENERALIZEDTIME: + z = *inlen; + if (der_decode_generalizedtime(in, &z, data) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + break; + case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: @@ -167,7 +205,10 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, } break; - default: + case LTC_ASN1_CHOICE: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: + case LTC_ASN1_EOL: return CRYPT_INVALID_ARG; } } @@ -177,6 +218,6 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c b/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c new file mode 100644 index 0000000..016a4c2 --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c @@ -0,0 +1,144 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_decode_generalizedtime.c + ASN.1 DER, decode a GeneralizedTime, Steffen Jaeckel + Based on der_decode_utctime.c +*/ + +#ifdef LTC_DER + +static int _char_to_int(unsigned char x) +{ + switch (x) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + default: return 100; + } +} + +#define DECODE_V(y, max) do {\ + y = _char_to_int(buf[x])*10 + _char_to_int(buf[x+1]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 2; \ +} while(0) + +#define DECODE_V4(y, max) do {\ + y = _char_to_int(buf[x])*1000 + _char_to_int(buf[x+1])*100 + _char_to_int(buf[x+2])*10 + _char_to_int(buf[x+3]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 4; \ +} while(0) + +/** + Decodes a Generalized time structure in DER format (reads all 6 valid encoding formats) + @param in Input buffer + @param inlen Length of input buffer in octets + @param out [out] Destination of Generalized time structure + @return CRYPT_OK if successful +*/ +int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, + ltc_generalizedtime *out) +{ + unsigned char buf[32]; + unsigned long x; + int y; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(out != NULL); + + /* check header */ + if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* decode the string */ + for (x = 0; x < in[1]; x++) { + y = der_ia5_value_decode(in[x+2]); + if (y == -1) { + return CRYPT_INVALID_PACKET; + } + if (!((y >= '0' && y <= '9') + || y == 'Z' || y == '.' + || y == '+' || y == '-')) { + return CRYPT_INVALID_PACKET; + } + buf[x] = y; + } + *inlen = 2 + x; + + if (x < 15) { + return CRYPT_INVALID_PACKET; + } + + /* possible encodings are +YYYYMMDDhhmmssZ +YYYYMMDDhhmmss+hh'mm' +YYYYMMDDhhmmss-hh'mm' +YYYYMMDDhhmmss.fsZ +YYYYMMDDhhmmss.fs+hh'mm' +YYYYMMDDhhmmss.fs-hh'mm' + + So let's do a trivial decode upto [including] ss + */ + + x = 0; + DECODE_V4(out->YYYY, 10000); + DECODE_V(out->MM, 13); + DECODE_V(out->DD, 32); + DECODE_V(out->hh, 24); + DECODE_V(out->mm, 60); + DECODE_V(out->ss, 60); + + /* clear fractional seconds info */ + out->fs = 0; + + /* now is it Z or . */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } else if (buf[x] == '.') { + x++; + while (buf[x] >= '0' && buf[x] <= '9') { + unsigned fs = out->fs; + if (x >= sizeof(buf)) return CRYPT_INVALID_PACKET; + out->fs *= 10; + out->fs += _char_to_int(buf[x]); + if (fs > out->fs) return CRYPT_OVERFLOW; + x++; + } + } + + /* now is it Z, +, - */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } else if (buf[x] == '+' || buf[x] == '-') { + out->off_dir = (buf[x++] == '+') ? 0 : 1; + DECODE_V(out->off_hh, 24); + DECODE_V(out->off_mm, 60); + return CRYPT_OK; + } else { + return CRYPT_INVALID_PACKET; + } +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c b/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c new file mode 100644 index 0000000..ddc472a --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c @@ -0,0 +1,108 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_encode_utctime.c + ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel + Based on der_encode_utctime.c +*/ + +#ifdef LTC_DER + +static const char * const baseten = "0123456789"; + +#define STORE_V(y) do {\ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); \ +} while(0) + +#define STORE_V4(y) do {\ + out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); \ +} while(0) + +/** + Encodes a Generalized time structure in DER format + @param gtime The GeneralizedTime structure to encode + @param out The destination of the DER encoding of the GeneralizedTime structure + @param outlen [in/out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_encode_generalizedtime(ltc_generalizedtime *gtime, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, tmplen; + int err; + + LTC_ARGCHK(gtime != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) { + return err; + } + if (tmplen > *outlen) { + *outlen = tmplen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header */ + out[0] = 0x18; + + /* store values */ + x = 2; + STORE_V4(gtime->YYYY); + STORE_V(gtime->MM); + STORE_V(gtime->DD); + STORE_V(gtime->hh); + STORE_V(gtime->mm); + STORE_V(gtime->ss); + + if (gtime->fs) { + unsigned long divisor; + unsigned fs = gtime->fs; + unsigned len = 0; + out[x++] = der_ia5_char_encode('.'); + divisor = 1; + do { + fs /= 10; + divisor *= 10; + len++; + } while(fs != 0); + while (len-- > 1) { + divisor /= 10; + out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]); + } + out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]); + } + + if (gtime->off_mm || gtime->off_hh) { + out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+'); + STORE_V(gtime->off_hh); + STORE_V(gtime->off_mm); + } else { + out[x++] = der_ia5_char_encode('Z'); + } + + /* store length */ + out[1] = (unsigned char)(x - 2); + + /* all good let's return */ + *outlen = x; + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c b/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c new file mode 100644 index 0000000..def6270 --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c @@ -0,0 +1,58 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_length_utctime.c + ASN.1 DER, get length of GeneralizedTime, Steffen Jaeckel + Based on der_length_utctime.c +*/ + +#ifdef LTC_DER + +/** + Gets length of DER encoding of GeneralizedTime + @param gtime The GeneralizedTime structure to get the size of + @param outlen [out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_length_generalizedtime(ltc_generalizedtime *gtime, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(gtime != NULL); + + if (gtime->fs == 0) { + /* we encode as YYYYMMDDhhmmssZ */ + *outlen = 2 + 14 + 1; + } else { + unsigned long len = 2 + 14 + 1; + unsigned fs = gtime->fs; + do { + fs /= 10; + len++; + } while(fs != 0); + if (gtime->off_hh == 0 && gtime->off_mm == 0) { + /* we encode as YYYYMMDDhhmmss.fsZ */ + len += 1; + } + else { + /* we encode as YYYYMMDDhhmmss.fs{+|-}hh'mm' */ + len += 5; + } + *outlen = len; + } + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c b/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c index 1880ada..c347251 100644 --- a/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c +++ b/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -88,9 +86,9 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, return CRYPT_OK; } - + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c b/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c index 6009dbc..18b926e 100644 --- a/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c +++ b/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -37,7 +35,7 @@ int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, /* get the size */ if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) { - return err; + return err; } /* too big? */ @@ -80,6 +78,6 @@ int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c b/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c index f10c1b8..5f1a78d 100644 --- a/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c +++ b/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -21,106 +19,106 @@ static const struct { int code, value; } ia5_table[] = { { '\0', 0 }, -{ '\a', 7 }, -{ '\b', 8 }, -{ '\t', 9 }, -{ '\n', 10 }, -{ '\f', 12 }, -{ '\r', 13 }, -{ ' ', 32 }, -{ '!', 33 }, -{ '"', 34 }, -{ '#', 35 }, -{ '$', 36 }, -{ '%', 37 }, -{ '&', 38 }, -{ '\'', 39 }, -{ '(', 40 }, -{ ')', 41 }, -{ '*', 42 }, -{ '+', 43 }, -{ ',', 44 }, -{ '-', 45 }, -{ '.', 46 }, -{ '/', 47 }, -{ '0', 48 }, -{ '1', 49 }, -{ '2', 50 }, -{ '3', 51 }, -{ '4', 52 }, -{ '5', 53 }, -{ '6', 54 }, -{ '7', 55 }, -{ '8', 56 }, -{ '9', 57 }, -{ ':', 58 }, -{ ';', 59 }, -{ '<', 60 }, -{ '=', 61 }, -{ '>', 62 }, -{ '?', 63 }, -{ '@', 64 }, -{ 'A', 65 }, -{ 'B', 66 }, -{ 'C', 67 }, -{ 'D', 68 }, -{ 'E', 69 }, -{ 'F', 70 }, -{ 'G', 71 }, -{ 'H', 72 }, -{ 'I', 73 }, -{ 'J', 74 }, -{ 'K', 75 }, -{ 'L', 76 }, -{ 'M', 77 }, -{ 'N', 78 }, -{ 'O', 79 }, -{ 'P', 80 }, -{ 'Q', 81 }, -{ 'R', 82 }, -{ 'S', 83 }, -{ 'T', 84 }, -{ 'U', 85 }, -{ 'V', 86 }, -{ 'W', 87 }, -{ 'X', 88 }, -{ 'Y', 89 }, -{ 'Z', 90 }, -{ '[', 91 }, -{ '\\', 92 }, -{ ']', 93 }, -{ '^', 94 }, -{ '_', 95 }, -{ '`', 96 }, -{ 'a', 97 }, -{ 'b', 98 }, -{ 'c', 99 }, -{ 'd', 100 }, -{ 'e', 101 }, -{ 'f', 102 }, -{ 'g', 103 }, -{ 'h', 104 }, -{ 'i', 105 }, -{ 'j', 106 }, -{ 'k', 107 }, -{ 'l', 108 }, -{ 'm', 109 }, -{ 'n', 110 }, -{ 'o', 111 }, -{ 'p', 112 }, -{ 'q', 113 }, -{ 'r', 114 }, -{ 's', 115 }, -{ 't', 116 }, -{ 'u', 117 }, -{ 'v', 118 }, -{ 'w', 119 }, -{ 'x', 120 }, -{ 'y', 121 }, -{ 'z', 122 }, -{ '{', 123 }, -{ '|', 124 }, -{ '}', 125 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '#', 35 }, +{ '$', 36 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '*', 42 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ ';', 59 }, +{ '<', 60 }, +{ '=', 61 }, +{ '>', 62 }, +{ '?', 63 }, +{ '@', 64 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ '[', 91 }, +{ '\\', 92 }, +{ ']', 93 }, +{ '^', 94 }, +{ '_', 95 }, +{ '`', 96 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +{ '{', 123 }, +{ '|', 124 }, +{ '}', 125 }, { '~', 126 } }; @@ -145,10 +143,10 @@ int der_ia5_value_decode(int v) } return -1; } - + /** - Gets length of DER encoding of IA5 STRING - @param octets The values you want to encode + Gets length of DER encoding of IA5 STRING + @param octets The values you want to encode @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful @@ -189,6 +187,6 @@ int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, un #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c b/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c index 0ed8ad7..88cf93f 100644 --- a/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c +++ b/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -54,7 +52,7 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) if (x + z > inlen) { return CRYPT_INVALID_PACKET; } - + /* no so read it */ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) { return err; @@ -62,7 +60,7 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) } else { /* long form */ z &= 0x7F; - + /* will number of length bytes overflow? (or > 4) */ if (((x + z) > inlen) || (z > 4) || (z == 0)) { return CRYPT_INVALID_PACKET; @@ -97,7 +95,7 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) return CRYPT_MEM; } mp_clear(tmp); - } + } return CRYPT_OK; @@ -105,6 +103,6 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c b/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c index e80bb3c..a8bada5 100644 --- a/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c +++ b/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -27,7 +25,7 @@ @return CRYPT_OK if successful */ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) -{ +{ unsigned long tmplen, y; int err, leading_zero; @@ -97,7 +95,7 @@ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) } } else if (mp_iszero(num) != LTC_MP_YES) { void *tmp; - + /* negative */ if (mp_init(&tmp) != CRYPT_OK) { return CRYPT_MEM; @@ -119,12 +117,12 @@ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) } /* we good */ - *outlen = tmplen; + *outlen = tmplen; return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c b/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c index 9d49683..753ef0e 100644 --- a/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c +++ b/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -18,8 +16,8 @@ #ifdef LTC_DER /** - Gets length of DER encoding of num - @param num The int to get the size of + Gets length of DER encoding of num + @param num The int to get the size of @param outlen [out] The length of the DER encoding for the given integer @return CRYPT_OK if successful */ @@ -46,7 +44,6 @@ int der_length_integer(void *num, unsigned long *outlen) } else { /* it's negative */ /* find power of 2 that is a multiple of eight and greater than count bits */ - leading_zero = 0; z = mp_count_bits(num); z = z + (8 - (z & 7)); if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z; @@ -71,12 +68,12 @@ int der_length_integer(void *num, unsigned long *outlen) ++len; /* return length */ - *outlen = len; + *outlen = len; return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c index 406acdc..75bc127 100644 --- a/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c +++ b/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -28,6 +26,7 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle unsigned long *words, unsigned long *outlen) { unsigned long x, y, t, len; + int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(words != NULL); @@ -40,6 +39,7 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle /* must be room for at least two words */ if (*outlen < 2) { + *outlen = 2; return CRYPT_BUFFER_OVERFLOW; } @@ -48,19 +48,19 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle if ((in[x++] & 0x1F) != 0x06) { return CRYPT_INVALID_PACKET; } - + /* get the length */ if (in[x] < 128) { - len = in[x++]; + len = in[x++]; } else { - if (in[x] < 0x81 || in[x] > 0x82) { - return CRYPT_INVALID_PACKET; - } - y = in[x++] & 0x7F; - len = 0; - while (y--) { - len = (len << 8) | (unsigned long)in[x++]; - } + if (in[x] < 0x81 || in[x] > 0x82) { + return CRYPT_INVALID_PACKET; + } + y = in[x++] & 0x7F; + len = 0; + while (y--) { + len = (len << 8) | (unsigned long)in[x++]; + } } if (len < 1 || (len + x) > inlen) { @@ -71,29 +71,36 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle y = 0; t = 0; while (len--) { - t = (t << 7) | (in[x] & 0x7F); - if (!(in[x++] & 0x80)) { - /* store t */ - if (y >= *outlen) { - return CRYPT_BUFFER_OVERFLOW; - } - if (y == 0) { - words[0] = t / 40; - words[1] = t % 40; - y = 2; - } else { - words[y++] = t; + t = (t << 7) | (in[x] & 0x7F); + if (!(in[x++] & 0x80)) { + /* store t */ + if (y >= *outlen) { + y++; + } else { + if (y == 0) { + words[0] = t / 40; + words[1] = t % 40; + y = 2; + } else { + words[y++] = t; + } + } + t = 0; } - t = 0; - } } - + + if (y > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; + } + *outlen = y; - return CRYPT_OK; + return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c index f018ba9..b1ce62c 100644 --- a/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c +++ b/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -55,7 +53,7 @@ int der_encode_object_identifier(unsigned long *words, unsigned long nwords, } /* store header + length */ - x = 0; + x = 0; out[x++] = 0x06; if (z < 128) { out[x++] = (unsigned char)z; @@ -71,33 +69,33 @@ int der_encode_object_identifier(unsigned long *words, unsigned long nwords, } /* store first byte */ - wordbuf = words[0] * 40 + words[1]; - for (i = 1; i < nwords; i++) { - /* store 7 bit words in little endian */ - t = wordbuf & 0xFFFFFFFF; - if (t) { - y = x; - mask = 0; - while (t) { - out[x++] = (unsigned char)((t & 0x7F) | mask); - t >>= 7; - mask |= 0x80; /* upper bit is set on all but the last byte */ - } - /* now swap bytes y...x-1 */ - z = x - 1; - while (y < z) { - t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t; - ++y; - --z; - } - } else { - /* zero word */ - out[x++] = 0x00; - } - - if (i < nwords - 1) { - wordbuf = words[i + 1]; - } + wordbuf = words[0] * 40 + words[1]; + for (i = 1; i < nwords; i++) { + /* store 7 bit words in little endian */ + t = wordbuf & 0xFFFFFFFF; + if (t) { + y = x; + mask = 0; + while (t) { + out[x++] = (unsigned char)((t & 0x7F) | mask); + t >>= 7; + mask |= 0x80; /* upper bit is set on all but the last byte */ + } + /* now swap bytes y...x-1 */ + z = x - 1; + while (y < z) { + t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t; + ++y; + --z; + } + } else { + /* zero word */ + out[x++] = 0x00; + } + + if (i < nwords - 1) { + wordbuf = words[i + 1]; + } } *outlen = x; @@ -106,6 +104,6 @@ int der_encode_object_identifier(unsigned long *words, unsigned long nwords, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c b/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c index ccb1e6d..ac08915 100644 --- a/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c +++ b/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -32,14 +30,14 @@ unsigned long der_object_identifier_bits(unsigned long x) /** Gets length of DER encoding of Object Identifier - @param nwords The number of OID words + @param nwords The number of OID words @param words The actual OID words to get the size of @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen) { - unsigned long y, z, t, wordbuf; + unsigned long y, z, t, wordbuf; LTC_ARGCHK(words != NULL); LTC_ARGCHK(outlen != NULL); @@ -84,6 +82,6 @@ int der_length_object_identifier(unsigned long *words, unsigned long nwords, uns #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c b/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c index 952d739..02859dc 100644 --- a/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c +++ b/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -83,9 +81,9 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen, return CRYPT_OK; } - + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c b/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c index 9a16c3b..9c9d1a6 100644 --- a/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c +++ b/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -38,7 +36,7 @@ int der_encode_octet_string(const unsigned char *in, unsigned long inlen, /* get the size */ if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) { - return err; + return err; } /* too big? */ @@ -81,6 +79,6 @@ int der_encode_octet_string(const unsigned char *in, unsigned long inlen, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c b/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c index 07da058..10c9e89 100644 --- a/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c +++ b/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -17,7 +15,7 @@ #ifdef LTC_DER /** - Gets length of DER encoding of OCTET STRING + Gets length of DER encoding of OCTET STRING @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful @@ -48,6 +46,6 @@ int der_length_octet_string(unsigned long noctets, unsigned long *outlen) #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c b/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c index 56bf376..6947429 100644 --- a/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c +++ b/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -88,9 +86,9 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen, return CRYPT_OK; } - + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c b/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c index 7d7cfd2..ee54e48 100644 --- a/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c +++ b/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -37,7 +35,7 @@ int der_encode_printable_string(const unsigned char *in, unsigned long inlen, /* get the size */ if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) { - return err; + return err; } /* too big? */ @@ -80,6 +78,6 @@ int der_encode_printable_string(const unsigned char *in, unsigned long inlen, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c b/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c index 9f78f20..40f0beb 100644 --- a/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c +++ b/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -20,80 +18,80 @@ static const struct { int code, value; } printable_table[] = { -{ ' ', 32 }, -{ '\'', 39 }, -{ '(', 40 }, -{ ')', 41 }, -{ '+', 43 }, -{ ',', 44 }, -{ '-', 45 }, -{ '.', 46 }, -{ '/', 47 }, -{ '0', 48 }, -{ '1', 49 }, -{ '2', 50 }, -{ '3', 51 }, -{ '4', 52 }, -{ '5', 53 }, -{ '6', 54 }, -{ '7', 55 }, -{ '8', 56 }, -{ '9', 57 }, -{ ':', 58 }, -{ '=', 61 }, -{ '?', 63 }, -{ 'A', 65 }, -{ 'B', 66 }, -{ 'C', 67 }, -{ 'D', 68 }, -{ 'E', 69 }, -{ 'F', 70 }, -{ 'G', 71 }, -{ 'H', 72 }, -{ 'I', 73 }, -{ 'J', 74 }, -{ 'K', 75 }, -{ 'L', 76 }, -{ 'M', 77 }, -{ 'N', 78 }, -{ 'O', 79 }, -{ 'P', 80 }, -{ 'Q', 81 }, -{ 'R', 82 }, -{ 'S', 83 }, -{ 'T', 84 }, -{ 'U', 85 }, -{ 'V', 86 }, -{ 'W', 87 }, -{ 'X', 88 }, -{ 'Y', 89 }, -{ 'Z', 90 }, -{ 'a', 97 }, -{ 'b', 98 }, -{ 'c', 99 }, -{ 'd', 100 }, -{ 'e', 101 }, -{ 'f', 102 }, -{ 'g', 103 }, -{ 'h', 104 }, -{ 'i', 105 }, -{ 'j', 106 }, -{ 'k', 107 }, -{ 'l', 108 }, -{ 'm', 109 }, -{ 'n', 110 }, -{ 'o', 111 }, -{ 'p', 112 }, -{ 'q', 113 }, -{ 'r', 114 }, -{ 's', 115 }, -{ 't', 116 }, -{ 'u', 117 }, -{ 'v', 118 }, -{ 'w', 119 }, -{ 'x', 120 }, -{ 'y', 121 }, -{ 'z', 122 }, +{ ' ', 32 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ '=', 61 }, +{ '?', 63 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, }; int der_printable_char_encode(int c) @@ -117,10 +115,10 @@ int der_printable_value_decode(int v) } return -1; } - + /** - Gets length of DER encoding of Printable STRING - @param octets The values you want to encode + Gets length of DER encoding of Printable STRING + @param octets The values you want to encode @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful @@ -161,6 +159,6 @@ int der_length_printable_string(const unsigned char *octets, unsigned long nocte #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c index 5042b18..b820c68 100644 --- a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c @@ -5,11 +5,8 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include <stdarg.h> /** @@ -31,13 +28,14 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, ltc_asn1_list *list, unsigned long outlen, int ordered) { - int err, type; - unsigned long size, x, y, z, i, blksize; + int err, i; + ltc_asn1_type type; + unsigned long size, x, y, z, blksize; void *data; LTC_ARGCHK(in != NULL); LTC_ARGCHK(list != NULL); - + /* get blk size */ if (inlen < 2) { return CRYPT_INVALID_PACKET; @@ -50,9 +48,12 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, } ++x; + /* check if the msb is set, which signals that the + * 7 lsb bits represent the number of bytes of the length + */ if (in[x] < 128) { blksize = in[x++]; - } else if (in[x] & 0x80) { + } else { if (in[x] < 0x81 || in[x] > 0x83) { return CRYPT_INVALID_PACKET; } @@ -68,28 +69,28 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, while (y--) { blksize = (blksize << 8) | (unsigned long)in[x++]; } - } + } - /* would this blksize overflow? */ - if (x + blksize > inlen) { - return CRYPT_INVALID_PACKET; - } + /* would this blksize overflow? */ + if (x + blksize > inlen) { + return CRYPT_INVALID_PACKET; + } /* mark all as unused */ - for (i = 0; i < outlen; i++) { + for (i = 0; i < (int)outlen; i++) { list[i].used = 0; - } + } - /* ok read data */ + /* ok read data */ inlen = blksize; - for (i = 0; i < outlen; i++) { + for (i = 0; i < (int)outlen; i++) { z = 0; type = list[i].type; size = list[i].size; data = list[i].data; if (!ordered && list[i].used == 1) { continue; } - if (type == LTC_ASN1_EOL) { + if (type == LTC_ASN1_EOL) { break; } @@ -97,13 +98,14 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, case LTC_ASN1_BOOLEAN: z = inlen; if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { + if (!ordered) { continue; } goto LBL_ERR; } if ((err = der_length_boolean(&z)) != CRYPT_OK) { goto LBL_ERR; - } - break; - + } + break; + case LTC_ASN1_INTEGER: z = inlen; if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { @@ -124,7 +126,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { goto LBL_ERR; } - + break; case LTC_ASN1_BIT_STRING: @@ -139,6 +141,18 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, } break; + case LTC_ASN1_RAW_BIT_STRING: + z = inlen; + if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + case LTC_ASN1_OCTET_STRING: z = inlen; if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { @@ -159,7 +173,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, } z = 2; break; - + case LTC_ASN1_OBJECT_IDENTIFIER: z = inlen; if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { @@ -172,6 +186,18 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, } break; + case LTC_ASN1_TELETEX_STRING: + z = inlen; + if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + case LTC_ASN1_IA5_STRING: z = inlen; if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { @@ -217,6 +243,14 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, } break; + case LTC_ASN1_GENERALIZEDTIME: + z = inlen; + if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) { + if (!ordered) { continue; } + goto LBL_ERR; + } + break; + case LTC_ASN1_SET: z = inlen; if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) { @@ -227,7 +261,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, goto LBL_ERR; } break; - + case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: /* detect if we have the right type */ @@ -255,33 +289,40 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, } break; - default: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: + case LTC_ASN1_EOL: err = CRYPT_INVALID_ARG; goto LBL_ERR; } x += z; inlen -= z; list[i].used = 1; - if (!ordered) { + if (!ordered) { /* restart the decoder */ i = -1; - } + } } - - for (i = 0; i < outlen; i++) { + + for (i = 0; i < (int)outlen; i++) { if (list[i].used == 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } - } - err = CRYPT_OK; + } + + if (inlen == 0) { + err = CRYPT_OK; + } else { + err = CRYPT_INPUT_TOO_LONG; + } LBL_ERR: return err; -} - +} + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c index 4fd3aaa..142ef95 100644 --- a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -17,102 +15,129 @@ #ifdef LTC_DER -static unsigned long fetch_length(const unsigned char *in, unsigned long inlen) +static unsigned long _fetch_length(const unsigned char *in, unsigned long inlen, unsigned long *data_offset) { - unsigned long x, y, z; + unsigned long x, z; - y = 0; + *data_offset = 0; /* skip type and read len */ if (inlen < 2) { return 0xFFFFFFFF; } - ++in; ++y; - + ++in; ++(*data_offset); + /* read len */ - x = *in++; ++y; - + x = *in++; ++(*data_offset); + /* <128 means literal */ if (x < 128) { - return x+y; + return x+*data_offset; } x &= 0x7F; /* the lower 7 bits are the length of the length */ inlen -= 2; - + /* len means len of len! */ if (x == 0 || x > 4 || x > inlen) { return 0xFFFFFFFF; } - - y += x; + + *data_offset += x; z = 0; - while (x--) { + while (x--) { z = (z<<8) | ((unsigned long)*in); ++in; } - return z+y; + return z+*data_offset; } -/** +static int _new_element(ltc_asn1_list **l) +{ + /* alloc new link */ + if (*l == NULL) { + *l = XCALLOC(1, sizeof(ltc_asn1_list)); + if (*l == NULL) { + return CRYPT_MEM; + } + } else { + (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list)); + if ((*l)->next == NULL) { + return CRYPT_MEM; + } + (*l)->next->prev = *l; + *l = (*l)->next; + } + return CRYPT_OK; +} + +/** ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. @param in The input buffer - @param inlen [in/out] The length of the input buffer and on output the amount of decoded data + @param inlen [in/out] The length of the input buffer and on output the amount of decoded data @param out [out] A pointer to the linked list @return CRYPT_OK on success. -*/ +*/ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) { ltc_asn1_list *l; - unsigned long err, type, len, totlen, x, y; + unsigned long err, type, len, totlen, data_offset; void *realloc_tmp; - + LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); LTC_ARGCHK(out != NULL); l = NULL; totlen = 0; - + + if (*inlen == 0) { + /* alloc new link */ + if ((err = _new_element(&l)) != CRYPT_OK) { + goto error; + } + } + /* scan the input and and get lengths and what not */ - while (*inlen) { + while (*inlen) { /* read the type byte */ type = *in; /* fetch length */ - len = fetch_length(in, *inlen); + len = _fetch_length(in, *inlen, &data_offset); if (len > *inlen) { err = CRYPT_INVALID_PACKET; goto error; } /* alloc new link */ - if (l == NULL) { - l = XCALLOC(1, sizeof(*l)); - if (l == NULL) { - err = CRYPT_MEM; - goto error; - } - } else { - l->next = XCALLOC(1, sizeof(*l)); - if (l->next == NULL) { - err = CRYPT_MEM; - goto error; - } - l->next->prev = l; - l = l->next; + if ((err = _new_element(&l)) != CRYPT_OK) { + goto error; + } + + if ((type & 0x20) && (type != 0x30) && (type != 0x31)) { + /* constructed, use the 'used' field to store the original identifier */ + l->used = type; + /* treat constructed elements like SETs */ + type = 0x20; + } + else if ((type & 0xC0) == 0x80) { + /* context-specific, use the 'used' field to store the original identifier */ + l->used = type; + /* context-specific elements are treated as opaque data */ + type = 0x80; } - /* now switch on type */ + /* now switch on type */ switch (type) { case 0x01: /* BOOLEAN */ l->type = LTC_ASN1_BOOLEAN; l->size = 1; l->data = XCALLOC(1, sizeof(int)); - + if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { goto error; } - + if ((err = der_length_boolean(&len)) != CRYPT_OK) { goto error; } @@ -125,12 +150,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc if ((err = mp_init(&l->data)) != CRYPT_OK) { goto error; } - + /* decode field */ if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { goto error; } - + /* calc length of object */ if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { goto error; @@ -146,11 +171,11 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc err = CRYPT_MEM; goto error; } - + if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } - + if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { goto error; } @@ -166,34 +191,34 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc err = CRYPT_MEM; goto error; } - + if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } - + if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x05: /* NULL */ - + /* valid NULL is 0x05 0x00 */ if (in[0] != 0x05 || in[1] != 0x00) { err = CRYPT_INVALID_PACKET; goto error; } - + /* simple to store ;-) */ l->type = LTC_ASN1_NULL; l->data = NULL; l->size = 0; len = 2; - + break; - + case 0x06: /* OID */ - + /* init field */ l->type = LTC_ASN1_OBJECT_IDENTIFIER; l->size = len; @@ -202,15 +227,15 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc err = CRYPT_MEM; goto error; } - + if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } - + if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { goto error; } - + /* resize it to save a bunch of mem */ if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { /* out of heap but this is not an error */ @@ -218,9 +243,9 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc } l->data = realloc_tmp; break; - + case 0x0C: /* UTF8 */ - + /* init field */ l->type = LTC_ASN1_UTF8_STRING; l->size = len; @@ -229,18 +254,18 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc err = CRYPT_MEM; goto error; } - + if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } - + if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x13: /* PRINTABLE */ - + /* init field */ l->type = LTC_ASN1_PRINTABLE_STRING; l->size = len; @@ -249,18 +274,38 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc err = CRYPT_MEM; goto error; } - + if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } - + if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; - + + case 0x14: /* TELETEXT */ + + /* init field */ + l->type = LTC_ASN1_TELETEX_STRING; + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + case 0x16: /* IA5 */ - + /* init field */ l->type = LTC_ASN1_IA5_STRING; l->size = len; @@ -269,18 +314,18 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc err = CRYPT_MEM; goto error; } - + if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } - + if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; - + case 0x17: /* UTC TIME */ - + /* init field */ l->type = LTC_ASN1_UTCTIME; l->size = 1; @@ -289,83 +334,125 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc err = CRYPT_MEM; goto error; } - + len = *inlen; if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { goto error; } - + if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { goto error; } break; - + + case 0x18: + l->type = LTC_ASN1_GENERALIZEDTIME; + l->size = len; + + if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) { + goto error; + } + + break; + + case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */ case 0x30: /* SEQUENCE */ case 0x31: /* SET */ - + /* init field */ - l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET; - - /* we have to decode the SEQUENCE header and get it's length */ - - /* move past type */ - ++in; --(*inlen); - - /* read length byte */ - x = *in++; --(*inlen); - - /* smallest SEQUENCE/SET header */ - y = 2; - - /* now if it's > 127 the next bytes are the length of the length */ - if (x > 128) { - x &= 0x7F; - in += x; - *inlen -= x; - - /* update sequence header len */ - y += x; - } - + if (type == 0x20) { + l->type = LTC_ASN1_CONSTRUCTED; + } + else if (type == 0x30) { + l->type = LTC_ASN1_SEQUENCE; + } + else { + l->type = LTC_ASN1_SET; + } + + if ((l->data = XMALLOC(len)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + XMEMCPY(l->data, in, len); + l->size = len; + + + /* jump to the start of the data */ + in += data_offset; + *inlen -= data_offset; + len = len - data_offset; + /* Sequence elements go as child */ - len = len - y; if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) { goto error; } - + /* len update */ - totlen += y; - - /* link them up y0 */ - l->child->parent = l; - + totlen += data_offset; + + /* the flexi decoder can also do nothing, so make sure a child has been allocated */ + if (l->child) { + /* link them up y0 */ + l->child->parent = l; + } + + break; + + case 0x80: /* Context-specific */ + l->type = LTC_ASN1_CONTEXT_SPECIFIC; + + if ((l->data = XCALLOC(1, len - data_offset)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + XMEMCPY(l->data, in + data_offset, len - data_offset); + l->size = len - data_offset; + break; + default: /* invalid byte ... this is a soft error */ /* remove link */ - l = l->prev; - XFREE(l->next); - l->next = NULL; + if (l->prev) { + l = l->prev; + XFREE(l->next); + l->next = NULL; + } goto outside; } - + /* advance pointers */ totlen += len; in += len; *inlen -= len; } - -outside: - - /* rewind l please */ - while (l->prev != NULL || l->parent != NULL) { - if (l->parent != NULL) { - l = l->parent; - } else { - l = l->prev; + +outside: + + /* in case we processed anything */ + if (totlen) { + /* rewind l please */ + while (l->prev != NULL || l->parent != NULL) { + if (l->parent != NULL) { + l = l->parent; + } else { + l = l->prev; + } } } - + /* return */ *out = l; *inlen = totlen; @@ -381,6 +468,6 @@ error: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c index 4202eb3..1361b76 100644 --- a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" #include <stdarg.h> @@ -25,10 +23,11 @@ @param inlen Length of input in octets @remark <...> is of the form <type, size, data> (int, unsigned long, void*) @return CRYPT_OK on success -*/ +*/ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) { - int err, type; + int err; + ltc_asn1_type type; unsigned long size, x; void *data; va_list args; @@ -40,11 +39,13 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) va_start(args, inlen); x = 0; for (;;) { - type = va_arg(args, int); + type = (ltc_asn1_type)va_arg(args, int); size = va_arg(args, unsigned long); data = va_arg(args, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); - if (type == LTC_ASN1_EOL) { + if (type == LTC_ASN1_EOL) { break; } @@ -64,10 +65,15 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: case LTC_ASN1_CHOICE: - ++x; + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_TELETEX_STRING: + case LTC_ASN1_GENERALIZEDTIME: + ++x; break; - - default: + + case LTC_ASN1_EOL: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: va_end(args); return CRYPT_INVALID_ARG; } @@ -88,11 +94,11 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) va_start(args, inlen); x = 0; for (;;) { - type = va_arg(args, int); + type = (ltc_asn1_type)va_arg(args, int); size = va_arg(args, unsigned long); data = va_arg(args, void*); - if (type == LTC_ASN1_EOL) { + if (type == LTC_ASN1_EOL) { break; } @@ -110,23 +116,23 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) case LTC_ASN1_UTCTIME: case LTC_ASN1_SEQUENCE: case LTC_ASN1_SET: - case LTC_ASN1_SETOF: + case LTC_ASN1_SETOF: case LTC_ASN1_CHOICE: - list[x].type = type; - list[x].size = size; - list[x++].data = data; + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_TELETEX_STRING: + case LTC_ASN1_GENERALIZEDTIME: + LTC_SET_ASN1(list, x++, type, data, size); + break; + /* coverity[dead_error_line] */ + case LTC_ASN1_EOL: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: break; - - default: - va_end(args); - err = CRYPT_INVALID_ARG; - goto LBL_ERR; } } va_end(args); err = der_decode_sequence(in, inlen, list, x); -LBL_ERR: XFREE(list); return err; } @@ -134,6 +140,6 @@ LBL_ERR: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c new file mode 100644 index 0000000..6826181 --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c @@ -0,0 +1,112 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" +/** + @file der_decode_subject_public_key_info.c + ASN.1 DER, encode a Subject Public Key structure --nmav +*/ + +#ifdef LTC_DER + +/* AlgorithmIdentifier := SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm + * } + * + * SubjectPublicKeyInfo := SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ +/** + Decode a subject public key info + @param in The input buffer + @param inlen The length of the input buffer + @param algorithm One out of the enum #public_key_algorithms + @param public_key The buffer for the public key + @param public_key_len [in/out] The length of the public key buffer and the written length + @param parameters_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len The number of parameters to include + @return CRYPT_OK on success +*/ +int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, + unsigned int algorithm, void* public_key, unsigned long* public_key_len, + unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len) +{ + int err; + unsigned long len; + oid_st oid; + unsigned char *tmpbuf; + unsigned long tmpoid[16]; + ltc_asn1_list alg_id[2]; + ltc_asn1_list subject_pubkey[2]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != 0); + LTC_ARGCHK(public_key_len != NULL); + + err = pk_get_oid(algorithm, &oid); + if (err != CRYPT_OK) { + return err; + } + + /* see if the OpenSSL DER format RSA public key will work */ + tmpbuf = XCALLOC(1, inlen); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + /* this includes the internal hash ID and optional params (NULL in this case) */ + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0])); + LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)parameters_type, parameters, parameters_len); + + /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey + * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet + */ + LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, 2); + LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U); + + err=der_decode_sequence(in, inlen, subject_pubkey, 2UL); + if (err != CRYPT_OK) { + goto LBL_ERR; + } + + if ((alg_id[0].size != oid.OIDlen) || + XMEMCMP(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) { + /* OID mismatch */ + err = CRYPT_PK_INVALID_TYPE; + goto LBL_ERR; + } + + len = subject_pubkey[1].size/8; + if (*public_key_len > len) { + XMEMCPY(public_key, subject_pubkey[1].data, len); + *public_key_len = len; + } else { + *public_key_len = len; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + err = CRYPT_OK; + +LBL_ERR: + + XFREE(tmpbuf); + + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c index e92f7c3..2b42ff4 100644 --- a/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c @@ -5,11 +5,8 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include <stdarg.h> /** @@ -23,15 +20,16 @@ Encode a SEQUENCE @param list The list of items to encode @param inlen The number of items in the list - @param out [out] The destination + @param out [out] The destination @param outlen [in/out] The size of the output @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF @return CRYPT_OK on success */ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, - unsigned char *out, unsigned long *outlen, int type_of) + unsigned char *out, unsigned long *outlen, int type_of) { - int err, type; + int err; + ltc_asn1_type type; unsigned long size, x, y, z, i; void *data; @@ -40,123 +38,8 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, LTC_ARGCHK(outlen != NULL); /* get size of output that will be required */ - y = 0; - for (i = 0; i < inlen; i++) { - type = list[i].type; - size = list[i].size; - data = list[i].data; - - if (type == LTC_ASN1_EOL) { - break; - } - - switch (type) { - case LTC_ASN1_BOOLEAN: - if ((err = der_length_boolean(&x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_INTEGER: - if ((err = der_length_integer(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_SHORT_INTEGER: - if ((err = der_length_short_integer(*((unsigned long*)data), &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_BIT_STRING: - if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_OCTET_STRING: - if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_NULL: - y += 2; - break; - - case LTC_ASN1_OBJECT_IDENTIFIER: - if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_IA5_STRING: - if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_PRINTABLE_STRING: - if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_UTF8_STRING: - if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_UTCTIME: - if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: - if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { - goto LBL_ERR; - } - y += x; - break; - - default: - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } - } - - /* calc header size */ - z = y; - if (y < 128) { - y += 2; - } else if (y < 256) { - /* 0x30 0x81 LL */ - y += 3; - } else if (y < 65536UL) { - /* 0x30 0x82 LL LL */ - y += 4; - } else if (y < 16777216UL) { - /* 0x30 0x83 LL LL LL */ - y += 5; - } else { - err = CRYPT_INVALID_ARG; - goto LBL_ERR; - } + y = 0; z = 0; + if ((err = der_length_sequence_ex(list, inlen, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG; /* too big ? */ if (*outlen < y) { @@ -168,7 +51,7 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, /* store header */ x = 0; out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31; - + if (z < 128) { out[x++] = (unsigned char)z; } else if (z < 256) { @@ -192,7 +75,7 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, size = list[i].size; data = list[i].data; - if (type == LTC_ASN1_EOL) { + if (type == LTC_ASN1_EOL) { break; } @@ -202,17 +85,13 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; - + case LTC_ASN1_INTEGER: z = *outlen; if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_SHORT_INTEGER: @@ -220,8 +99,6 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_BIT_STRING: @@ -229,8 +106,13 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; + break; + + case LTC_ASN1_RAW_BIT_STRING: + z = *outlen; + if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } break; case LTC_ASN1_OCTET_STRING: @@ -238,14 +120,12 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_NULL: - out[x++] = 0x05; - out[x++] = 0x00; - *outlen -= 2; + out[x] = 0x05; + out[x+1] = 0x00; + z = 2; break; case LTC_ASN1_OBJECT_IDENTIFIER: @@ -253,8 +133,6 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_IA5_STRING: @@ -262,17 +140,13 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; - + case LTC_ASN1_PRINTABLE_STRING: z = *outlen; if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_UTF8_STRING: @@ -280,8 +154,6 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_UTCTIME: @@ -289,8 +161,13 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = *outlen; + if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } break; case LTC_ASN1_SET: @@ -298,8 +175,6 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_SETOF: @@ -307,8 +182,6 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; case LTC_ASN1_SEQUENCE: @@ -316,20 +189,29 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen, if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { goto LBL_ERR; } - x += z; - *outlen -= z; break; - - default: + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: err = CRYPT_INVALID_ARG; goto LBL_ERR; } + + x += z; + *outlen -= z; } *outlen = x; - err = CRYPT_OK; + err = CRYPT_OK; LBL_ERR: return err; } #endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c index 659f029..c1b40c7 100644 --- a/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" #include <stdarg.h> @@ -25,10 +23,11 @@ @param outlen [in/out] Length of buffer and resulting length of output @remark <...> is of the form <type, size, data> (int, unsigned long, void*) @return CRYPT_OK on success -*/ +*/ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) { - int err, type; + int err; + ltc_asn1_type type; unsigned long size, x; void *data; va_list args; @@ -41,11 +40,13 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) va_start(args, outlen); x = 0; for (;;) { - type = va_arg(args, int); + type = (ltc_asn1_type)va_arg(args, int); size = va_arg(args, unsigned long); data = va_arg(args, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); - if (type == LTC_ASN1_EOL) { + if (type == LTC_ASN1_EOL) { break; } @@ -64,10 +65,16 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) case LTC_ASN1_SEQUENCE: case LTC_ASN1_SET: case LTC_ASN1_SETOF: - ++x; + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_GENERALIZEDTIME: + ++x; break; - - default: + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: va_end(args); return CRYPT_INVALID_ARG; } @@ -88,11 +95,11 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) va_start(args, outlen); x = 0; for (;;) { - type = va_arg(args, int); + type = (ltc_asn1_type)va_arg(args, int); size = va_arg(args, unsigned long); data = va_arg(args, void*); - if (type == LTC_ASN1_EOL) { + if (type == LTC_ASN1_EOL) { break; } @@ -111,12 +118,16 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) case LTC_ASN1_SEQUENCE: case LTC_ASN1_SET: case LTC_ASN1_SETOF: - list[x].type = type; - list[x].size = size; - list[x++].data = data; + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_GENERALIZEDTIME: + LTC_SET_ASN1(list, x++, type, data, size); break; - - default: + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: va_end(args); err = CRYPT_INVALID_ARG; goto LBL_ERR; @@ -124,7 +135,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) } va_end(args); - err = der_encode_sequence(list, x, out, outlen); + err = der_encode_sequence(list, x, out, outlen); LBL_ERR: XFREE(list); return err; @@ -133,6 +144,6 @@ LBL_ERR: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c new file mode 100644 index 0000000..dcb869a --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c @@ -0,0 +1,71 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_encode_subject_public_key_info.c + ASN.1 DER, encode a Subject Public Key structure --nmav +*/ + +#ifdef LTC_DER + +/* AlgorithmIdentifier := SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm + * } + * + * SubjectPublicKeyInfo := SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ +/** + Encode a subject public key info + @param out The output buffer + @param outlen [in/out] Length of buffer and resulting length of output + @param algorithm One out of the enum #public_key_algorithms + @param public_key The buffer for the public key + @param public_key_len The length of the public key buffer + @param parameters_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len The number of parameters to include + @return CRYPT_OK on success +*/ +int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, + unsigned int algorithm, void* public_key, unsigned long public_key_len, + unsigned long parameters_type, void* parameters, unsigned long parameters_len) +{ + int err; + ltc_asn1_list alg_id[2]; + oid_st oid; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + err = pk_get_oid(algorithm, &oid); + if (err != CRYPT_OK) { + return err; + } + + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid.OID, oid.OIDlen); + LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)parameters_type, parameters, parameters_len); + + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id, + LTC_ASN1_RAW_BIT_STRING, public_key_len*8U, public_key, + LTC_ASN1_EOL, 0UL, NULL); + +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ + diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c b/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c index 7221f99..aed7cc2 100644 --- a/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -18,17 +16,24 @@ #ifdef LTC_DER /** - Get the length of a DER sequence + Get the length of a DER sequence @param list The sequences of items in the SEQUENCE @param inlen The number of items - @param outlen [out] The length required in octets to store it + @param outlen [out] The length required in octets to store it @return CRYPT_OK on success */ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, - unsigned long *outlen) + unsigned long *outlen) +{ + return der_length_sequence_ex(list, inlen, outlen, NULL); +} + +int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen, unsigned long *payloadlen) { - int err, type; - unsigned long size, x, y, z, i; + int err; + ltc_asn1_type type; + unsigned long size, x, y, i, z; void *data; LTC_ARGCHK(list != NULL); @@ -41,7 +46,7 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, size = list[i].size; data = list[i].data; - if (type == LTC_ASN1_EOL) { + if (type == LTC_ASN1_EOL) { break; } @@ -52,7 +57,7 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, } y += x; break; - + case LTC_ASN1_INTEGER: if ((err = der_length_integer(data, &x)) != CRYPT_OK) { goto LBL_ERR; @@ -68,6 +73,7 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, break; case LTC_ASN1_BIT_STRING: + case LTC_ASN1_RAW_BIT_STRING: if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { goto LBL_ERR; } @@ -99,6 +105,13 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, y += x; break; + case LTC_ASN1_TELETEX_STRING: + if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + case LTC_ASN1_PRINTABLE_STRING: if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; @@ -113,6 +126,13 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, y += x; break; + case LTC_ASN1_GENERALIZEDTIME: + if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + case LTC_ASN1_UTF8_STRING: if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; @@ -129,8 +149,11 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, y += x; break; - - default: + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: + case LTC_ASN1_EOL: err = CRYPT_INVALID_ARG; goto LBL_ERR; } @@ -155,6 +178,7 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, } /* store size */ + if (payloadlen) *payloadlen = z; *outlen = y; err = CRYPT_OK; @@ -164,6 +188,6 @@ LBL_ERR: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c b/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c index c933f58..3c2a663 100644 --- a/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -20,11 +18,13 @@ /** Free memory allocated by der_decode_sequence_flexi() @param in The list to free -*/ +*/ void der_sequence_free(ltc_asn1_list *in) { ltc_asn1_list *l; - + + if (!in) return; + /* walk to the start of the chain */ while (in->prev != NULL || in->parent != NULL) { if (in->parent != NULL) { @@ -33,7 +33,7 @@ void der_sequence_free(ltc_asn1_list *in) in = in->prev; } } - + /* now walk the list and free stuff */ while (in != NULL) { /* is there a child? */ @@ -42,24 +42,22 @@ void der_sequence_free(ltc_asn1_list *in) in->child->parent = NULL; der_sequence_free(in->child); } - - switch (in->type) { - case LTC_ASN1_SET: - case LTC_ASN1_SETOF: - case LTC_ASN1_SEQUENCE: break; + + switch (in->type) { + case LTC_ASN1_SETOF: break; case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); } break; default : if (in->data != NULL) { XFREE(in->data); } } - + /* move to next and free current */ l = in->next; - free(in); + XFREE(in); in = l; - } + } } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c b/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c new file mode 100644 index 0000000..9b9e036 --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c @@ -0,0 +1,50 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_sequence_shrink.c + Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi(), Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Free memory allocated for CONSTRUCTED, + SET or SEQUENCE elements by der_decode_sequence_flexi() + @param in The list to shrink +*/ +void der_sequence_shrink(ltc_asn1_list *in) +{ + if (!in) return; + + /* now walk the list and free stuff */ + while (in != NULL) { + /* is there a child? */ + if (in->child) { + der_sequence_shrink(in->child); + } + + switch (in->type) { + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_SET: + case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break; + default: break; + } + + /* move to next and free current */ + in = in->next; + } +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c b/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c index a2d0128..fef3092 100644 --- a/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c +++ b/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -18,35 +16,42 @@ #ifdef LTC_DER /* LTC define to ASN.1 TAG */ -static int ltc_to_asn1(int v) +static int _ltc_to_asn1(ltc_asn1_type v) { switch (v) { case LTC_ASN1_BOOLEAN: return 0x01; case LTC_ASN1_INTEGER: case LTC_ASN1_SHORT_INTEGER: return 0x02; + case LTC_ASN1_RAW_BIT_STRING: case LTC_ASN1_BIT_STRING: return 0x03; case LTC_ASN1_OCTET_STRING: return 0x04; case LTC_ASN1_NULL: return 0x05; case LTC_ASN1_OBJECT_IDENTIFIER: return 0x06; case LTC_ASN1_UTF8_STRING: return 0x0C; case LTC_ASN1_PRINTABLE_STRING: return 0x13; + case LTC_ASN1_TELETEX_STRING: return 0x14; case LTC_ASN1_IA5_STRING: return 0x16; case LTC_ASN1_UTCTIME: return 0x17; + case LTC_ASN1_GENERALIZEDTIME: return 0x18; case LTC_ASN1_SEQUENCE: return 0x30; case LTC_ASN1_SET: case LTC_ASN1_SETOF: return 0x31; - default: return -1; + case LTC_ASN1_CHOICE: + case LTC_ASN1_CONSTRUCTED: + case LTC_ASN1_CONTEXT_SPECIFIC: + case LTC_ASN1_EOL: return -1; } -} - + return -1; +} + -static int qsort_helper(const void *a, const void *b) +static int _qsort_helper(const void *a, const void *b) { ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b; int r; - - r = ltc_to_asn1(A->type) - ltc_to_asn1(B->type); - + + r = _ltc_to_asn1(A->type) - _ltc_to_asn1(B->type); + /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */ if (r == 0) { /* their order in the original list now determines the position */ @@ -54,13 +59,13 @@ static int qsort_helper(const void *a, const void *b) } else { return r; } -} +} /* Encode a SET type @param list The list of items to encode @param inlen The number of items in the list - @param out [out] The destination + @param out [out] The destination @param outlen [in/out] The size of the output @return CRYPT_OK on success */ @@ -70,34 +75,34 @@ int der_encode_set(ltc_asn1_list *list, unsigned long inlen, ltc_asn1_list *copy; unsigned long x; int err; - + /* make copy of list */ copy = XCALLOC(inlen, sizeof(*copy)); if (copy == NULL) { return CRYPT_MEM; - } - + } + /* fill in used member with index so we can fully sort it */ for (x = 0; x < inlen; x++) { copy[x] = list[x]; copy[x].used = x; - } - + } + /* sort it by the "type" field */ - XQSORT(copy, inlen, sizeof(*copy), &qsort_helper); - + XQSORT(copy, inlen, sizeof(*copy), &_qsort_helper); + /* call der_encode_sequence_ex() */ - err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET); - + err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET); + /* free list */ XFREE(copy); - + return err; -} +} #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c b/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c index 8e87f84..b837cdd 100644 --- a/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c +++ b/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -22,15 +20,15 @@ struct edge { unsigned long size; }; -static int qsort_helper(const void *a, const void *b) +static int _qsort_helper(const void *a, const void *b) { struct edge *A = (struct edge *)a, *B = (struct edge *)b; int r; unsigned long x; - + /* compare min length */ r = XMEMCMP(A->start, B->start, MIN(A->size, B->size)); - + if (r == 0 && A->size != B->size) { if (A->size > B->size) { for (x = B->size; x < A->size; x++) { @@ -44,28 +42,29 @@ static int qsort_helper(const void *a, const void *b) return -1; } } - } + } } - - return r; + + return r; } /** Encode a SETOF stucture @param list The list of items to encode @param inlen The number of items in the list - @param out [out] The destination + @param out [out] The destination @param outlen [in/out] The size of the output @return CRYPT_OK on success -*/ +*/ int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen) { - unsigned long x, y, z, hdrlen; + unsigned long x, y, z; + ptrdiff_t hdrlen; int err; struct edge *edges; unsigned char *ptr, *buf; - + /* check that they're all the same type */ for (x = 1; x < inlen; x++) { if (list[x].type != list[x-1].type) { @@ -77,43 +76,43 @@ int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, buf = XCALLOC(1, *outlen); if (buf == NULL) { return CRYPT_MEM; - } - + } + /* encode list */ if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) { XFREE(buf); return err; } - + /* allocate edges */ edges = XCALLOC(inlen, sizeof(*edges)); if (edges == NULL) { XFREE(buf); return CRYPT_MEM; - } - + } + /* skip header */ - ptr = buf + 1; + ptr = buf + 1; + + /* now skip length data */ + x = *ptr++; + if (x >= 0x80) { + ptr += (x & 0x7F); + } + + /* get the size of the static header */ + hdrlen = ptr - buf; + - /* now skip length data */ - x = *ptr++; - if (x >= 0x80) { - ptr += (x & 0x7F); - } - - /* get the size of the static header */ - hdrlen = ((unsigned long)ptr) - ((unsigned long)buf); - - /* scan for edges */ x = 0; while (ptr < (buf + *outlen)) { /* store start */ edges[x].start = ptr; - + /* skip type */ z = 1; - + /* parse length */ y = ptr[z++]; if (y < 128) { @@ -125,38 +124,38 @@ int der_encode_setof(ltc_asn1_list *list, unsigned long inlen, edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]); } } - + /* skip content */ edges[x].size += z; ptr += edges[x].size; ++x; - } - + } + /* sort based on contents (using edges) */ - XQSORT(edges, inlen, sizeof(*edges), &qsort_helper); - + XQSORT(edges, inlen, sizeof(*edges), &_qsort_helper); + /* copy static header */ XMEMCPY(out, buf, hdrlen); - + /* copy+sort using edges+indecies to output from buffer */ - for (y = hdrlen, x = 0; x < inlen; x++) { + for (y = (unsigned long)hdrlen, x = 0; x < inlen; x++) { XMEMCPY(out+y, edges[x].start, edges[x].size); y += edges[x].size; - } - + } + #ifdef LTC_CLEAN_STACK zeromem(buf, *outlen); -#endif - +#endif + /* free buffers */ XFREE(edges); XFREE(buf); - + return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c b/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c index a174740..71debf3 100644 --- a/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c +++ b/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -63,6 +61,6 @@ int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsig #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c b/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c index 903ceb4..ea413eb 100644 --- a/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c +++ b/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -26,10 +24,10 @@ @return CRYPT_OK if successful */ int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen) -{ +{ unsigned long len, x, y, z; int err; - + LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); @@ -86,12 +84,12 @@ int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned lon /* we good */ *outlen = x; - + return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c b/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c index 0b8fdcf..52d0e1a 100644 --- a/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c +++ b/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -18,8 +16,8 @@ #ifdef LTC_DER /** - Gets length of DER encoding of num - @param num The integer to get the size of + Gets length of DER encoding of num + @param num The integer to get the size of @param outlen [out] The length of the DER encoding for the given integer @return CRYPT_OK if successful */ @@ -39,7 +37,7 @@ int der_length_short_integer(unsigned long num, unsigned long *outlen) ++z; y >>= 8; } - + /* handle zero */ if (z == 0) { z = 1; @@ -58,13 +56,13 @@ int der_length_short_integer(unsigned long num, unsigned long *outlen) len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0; /* return length */ - *outlen = len; - + *outlen = len; + return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c new file mode 100644 index 0000000..0c7c3c8 --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c @@ -0,0 +1,93 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_decode_teletex_string.c + ASN.1 DER, encode a teletex STRING +*/ + +#ifdef LTC_DER + +/** + Store a teletex STRING + @param in The DER encoded teletex STRING + @param inlen The size of the DER teletex STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x14 */ + if ((in[0] & 0x1F) != 0x14) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* decode the length */ + if (in[x] & 0x80) { + /* valid # of bytes in length are 1,2,3 */ + y = in[x] & 0x7F; + if ((y == 0) || (y > 3) || ((x + y) > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* read the length in */ + len = 0; + ++x; + while (y--) { + len = (len << 8) | in[x++]; + } + } else { + len = in[x++] & 0x7F; + } + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_teletex_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c b/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c new file mode 100644 index 0000000..29fe5b0 --- /dev/null +++ b/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c @@ -0,0 +1,208 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file der_length_teletex_string.c + ASN.1 DER, get length of teletex STRING +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} teletex_table[] = { +{ '\0', 0 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\v', 11 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ ';', 59 }, +{ '<', 60 }, +{ '=', 61 }, +{ '>', 62 }, +{ '?', 63 }, +{ '@', 64 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ '[', 91 }, +{ ']', 93 }, +{ '_', 95 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +{ '|', 124 }, +{ ' ', 160 }, +{ 0xa1, 161 }, +{ 0xa2, 162 }, +{ 0xa3, 163 }, +{ '$', 164 }, +{ 0xa5, 165 }, +{ '#', 166 }, +{ 0xa7, 167 }, +{ 0xa4, 168 }, +{ 0xab, 171 }, +{ 0xb0, 176 }, +{ 0xb1, 177 }, +{ 0xb2, 178 }, +{ 0xb3, 179 }, +{ 0xd7, 180 }, +{ 0xb5, 181 }, +{ 0xb6, 182 }, +{ 0xb7, 183 }, +{ 0xf7, 184 }, +{ 0xbb, 187 }, +{ 0xbc, 188 }, +{ 0xbd, 189 }, +{ 0xbe, 190 }, +{ 0xbf, 191 }, +}; + +int der_teletex_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].code == c) { + return teletex_table[x].value; + } + } + return -1; +} + +int der_teletex_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].value == v) { + return teletex_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of teletex STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_teletex_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if (noctets < 128) { + /* 16 LL DD DD DD ... */ + *outlen = 2 + noctets; + } else if (noctets < 256) { + /* 16 81 LL DD DD DD ... */ + *outlen = 3 + noctets; + } else if (noctets < 65536UL) { + /* 16 82 LL LL DD DD DD ... */ + *outlen = 4 + noctets; + } else if (noctets < 16777216UL) { + /* 16 83 LL LL LL DD DD DD ... */ + *outlen = 5 + noctets; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c b/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c index c86bc75..07fcb80 100644 --- a/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c +++ b/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -17,7 +15,7 @@ #ifdef LTC_DER -static int char_to_int(unsigned char x) +static int _char_to_int(unsigned char x) { switch (x) { case '0': return 0; @@ -30,12 +28,12 @@ static int char_to_int(unsigned char x) case '7': return 7; case '8': return 8; case '9': return 9; + default: return 100; } - return 100; } #define DECODE_V(y, max) \ - y = char_to_int(buf[x])*10 + char_to_int(buf[x+1]); \ + y = _char_to_int(buf[x])*10 + _char_to_int(buf[x+1]); \ if (y >= max) return CRYPT_INVALID_PACKET; \ x += 2; @@ -49,7 +47,7 @@ static int char_to_int(unsigned char x) int der_decode_utctime(const unsigned char *in, unsigned long *inlen, ltc_utctime *out) { - unsigned char buf[32]; + unsigned char buf[32] = { 0 }; /* initialize as all zeroes */ unsigned long x; int y; @@ -73,7 +71,7 @@ int der_decode_utctime(const unsigned char *in, unsigned long *inlen, *inlen = 2 + x; - /* possible encodings are + /* possible encodings are YYMMDDhhmmZ YYMMDDhhmm+hh'mm' YYMMDDhhmm-hh'mm' @@ -81,7 +79,7 @@ YYMMDDhhmmssZ YYMMDDhhmmss+hh'mm' YYMMDDhhmmss-hh'mm' - So let's do a trivial decode upto [including] mm + So let's do a trivial decode upto [including] mm */ x = 0; @@ -122,6 +120,6 @@ YYMMDDhhmmss-hh'mm' #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c b/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c index f8d0c56..c6c8464 100644 --- a/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c +++ b/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -17,7 +15,7 @@ #ifdef LTC_DER -static const char *baseten = "0123456789"; +static const char * const baseten = "0123456789"; #define STORE_V(y) \ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ @@ -30,12 +28,12 @@ static const char *baseten = "0123456789"; @param outlen [in/out] The length of the DER encoding @return CRYPT_OK if successful */ -int der_encode_utctime(ltc_utctime *utctime, +int der_encode_utctime(ltc_utctime *utctime, unsigned char *out, unsigned long *outlen) { unsigned long x, tmplen; int err; - + LTC_ARGCHK(utctime != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); @@ -47,7 +45,7 @@ int der_encode_utctime(ltc_utctime *utctime, *outlen = tmplen; return CRYPT_BUFFER_OVERFLOW; } - + /* store header */ out[0] = 0x17; @@ -70,7 +68,7 @@ int der_encode_utctime(ltc_utctime *utctime, /* store length */ out[1] = (unsigned char)(x - 2); - + /* all good let's return */ *outlen = x; return CRYPT_OK; @@ -78,6 +76,6 @@ int der_encode_utctime(ltc_utctime *utctime, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c b/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c index e33c4f3..4202083 100644 --- a/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c +++ b/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -41,6 +39,6 @@ int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen) #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c b/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c index d9cbdaf..195a3f5 100644 --- a/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c +++ b/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -31,6 +29,7 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, { wchar_t tmp; unsigned long x, y, z, len; + int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); @@ -73,10 +72,10 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, for (y = 0; x < inlen; ) { /* get first byte */ tmp = in[x++]; - + /* count number of bytes */ for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF); - + if (z > 4 || (x + (z - 1) > inlen)) { return CRYPT_INVALID_PACKET; } @@ -93,19 +92,23 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F); } - if (y > *outlen) { - *outlen = y; - return CRYPT_BUFFER_OVERFLOW; + if (y < *outlen) { + out[y] = tmp; } - out[y++] = tmp; + y++; + } + if (y > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; } *outlen = y; - return CRYPT_OK; + return err; } - + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c b/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c index 847a726..4c2030f 100644 --- a/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c +++ b/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -37,9 +35,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, /* get the size */ for (x = len = 0; x < inlen; x++) { - if (in[x] < 0 || in[x] > 0x1FFFF) { - return CRYPT_INVALID_ARG; - } + if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; len += der_utf8_charsize(in[x]); } @@ -57,7 +53,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, /* too big? */ if (y > *outlen) { - *outlen = len; + *outlen = y; return CRYPT_BUFFER_OVERFLOW; } @@ -79,6 +75,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, out[x++] = (unsigned char)((len>>8)&255); out[x++] = (unsigned char)(len&255); } else { + /* coverity[dead_error_line] */ return CRYPT_INVALID_ARG; } @@ -88,7 +85,9 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, case 1: out[x++] = (unsigned char)in[y]; break; case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break; case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; +#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; +#endif } } @@ -100,6 +99,6 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c b/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c index 3321f94..88f4355 100644 --- a/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c +++ b/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -27,15 +25,38 @@ unsigned long der_utf8_charsize(const wchar_t c) return 1; } else if (c <= 0x7FF) { return 2; +#if LTC_WCHAR_MAX == 0xFFFF + } else { + return 3; + } +#else } else if (c <= 0xFFFF) { return 3; } else { return 4; } +#endif +} + +/** + Test whether the given code point is valid character + @param c The UTF-8 character to test + @return 1 - valid, 0 - invalid +*/ +int der_utf8_valid_char(const wchar_t c) +{ + LTC_UNUSED_PARAM(c); +#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF + if (c > 0x10FFFF) return 0; +#endif +#if LTC_WCHAR_MAX != 0xFFFF && LTC_WCHAR_MAX != 0xFFFFFFFF + if (c < 0) return 0; +#endif + return 1; } /** - Gets length of DER encoding of UTF8 STRING + Gets length of DER encoding of UTF8 STRING @param in The characters to measure the length of @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @@ -50,9 +71,7 @@ int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned lo len = 0; for (x = 0; x < noctets; x++) { - if (in[x] < 0 || in[x] > 0x10FFFF) { - return CRYPT_INVALID_ARG; - } + if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; len += der_utf8_charsize(in[x]); } @@ -78,6 +97,6 @@ int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned lo #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh.c b/libtomcrypt/src/pk/dh/dh.c new file mode 100644 index 0000000..763b007 --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh.c @@ -0,0 +1,237 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ +const ltc_dh_set_type ltc_dh_sets[] = { +#ifdef LTC_DH768 +{ /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */ + 96, + "DH-768", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH1024 +{ /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */ + 128, + "DH-1024", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" + "FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH1536 +{ /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */ + 192, + "DH-1536", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH2048 +{ /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */ + 256, + "DH-2048", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH3072 +{ /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */ + 384, + "DH-3072", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH4096 +{ /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */ + 512, + "DH-4096", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + "FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH6144 +{ /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */ + 768, + "DH-6144", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH8192 +{ /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */ + 1024, + "DH-8192", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" +}, +#endif +{ + 0, + NULL, + NULL, + NULL +} +}; + +/** + Returns the DH group size (octets) for given key + @param key The DH key to get the size of + @return The group size in octets (0 on error) + */ +int dh_get_groupsize(dh_key *key) +{ + if (key == NULL) return 0; + return mp_unsigned_bin_size(key->prime); +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_check_pubkey.c b/libtomcrypt/src/pk/dh/dh_check_pubkey.c new file mode 100644 index 0000000..fb4f37b --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_check_pubkey.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Check DH public key (INTERNAL ONLY, not part of public API) + @param key The key you wish to test + @return CRYPT_OK if successful +*/ +int dh_check_pubkey(dh_key *key) +{ + void *p_minus1; + ltc_mp_digit digit; + int i, digit_count, bits_set = 0, err; + + LTC_ARGCHK(key != NULL); + + if ((err = mp_init(&p_minus1)) != CRYPT_OK) { + return err; + } + + /* avoid: y <= 1 OR y >= p-1 */ + if ((err = mp_sub_d(key->prime, 1, p_minus1)) != CRYPT_OK) { + goto error; + } + if (mp_cmp(key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(key->y, 1) != LTC_MP_GT) { + err = CRYPT_INVALID_ARG; + goto error; + } + + /* public key must have more than one bit set */ + digit_count = mp_get_digit_count(key->y); + for (i = 0; i < digit_count && bits_set < 2; i++) { + digit = mp_get_digit(key->y, i); + while (digit > 0) { + if (digit & 1) bits_set++; + digit >>= 1; + } + } + if (bits_set > 1) { + err = CRYPT_OK; + } + else { + err = CRYPT_INVALID_ARG; + } + +error: + mp_clear(p_minus1); + return err; +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_export.c b/libtomcrypt/src/pk/dh/dh_export.c new file mode 100644 index 0000000..6a02a89 --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_export.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Export a DH key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the DH key + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) +{ + unsigned char flags[1]; + int err; + unsigned long version = 0; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (type == PK_PRIVATE) { + /* export x - private key */ + flags[0] = 1; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } + else { + /* export y - public key */ + flags[0] = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL); + } + + return err; +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_export_key.c b/libtomcrypt/src/pk/dh/dh_export_key.c new file mode 100644 index 0000000..d48c011 --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_export_key.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Binary export a DH key to a buffer + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the DH key + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int dh_export_key(void *out, unsigned long *outlen, int type, dh_key *key) +{ + unsigned long len; + void *k; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + k = (type == PK_PRIVATE) ? key->x : key->y; + len = mp_unsigned_bin_size(k); + + if (*outlen < len) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = len; + + return mp_to_unsigned_bin(k, out); +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_free.c b/libtomcrypt/src/pk/dh/dh_free.c new file mode 100644 index 0000000..b4f58ca --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_free.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Free the allocated ram for a DH key + @param key The key which you wish to free +*/ +void dh_free(dh_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, NULL); +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_generate_key.c b/libtomcrypt/src/pk/dh/dh_generate_key.c new file mode 100644 index 0000000..69fb6f9 --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_generate_key.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +static int _dh_groupsize_to_keysize(int groupsize) +{ + /* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8 + * We use "Estimate 2" to get an appropriate private key (exponent) size. + */ + if (groupsize <= 0) { + return 0; + } + else if (groupsize <= 192) { + return 30; /* 1536-bit => key size 240-bit */ + } + else if (groupsize <= 256) { + return 40; /* 2048-bit => key size 320-bit */ + } + else if (groupsize <= 384) { + return 52; /* 3072-bit => key size 416-bit */ + } + else if (groupsize <= 512) { + return 60; /* 4096-bit => key size 480-bit */ + } + else if (groupsize <= 768) { + return 67; /* 6144-bit => key size 536-bit */ + } + else if (groupsize <= 1024) { + return 77; /* 8192-bit => key size 616-bit */ + } + else { + return 0; + } +} + +int dh_generate_key(prng_state *prng, int wprng, dh_key *key) +{ + unsigned char *buf; + unsigned long keysize; + int err, max_iterations = LTC_PK_MAX_RETRIES; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* good prng? */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + keysize = _dh_groupsize_to_keysize(mp_unsigned_bin_size(key->prime)); + if (keysize == 0) { + err = CRYPT_INVALID_KEYSIZE; + goto freemp; + } + + /* allocate buffer */ + buf = XMALLOC(keysize); + if (buf == NULL) { + err = CRYPT_MEM; + goto freemp; + } + + key->type = PK_PRIVATE; + do { + /* make up random buf */ + if (prng_descriptor[wprng].read(buf, keysize, prng) != keysize) { + err = CRYPT_ERROR_READPRNG; + goto freebuf; + } + /* load the x value - private key */ + if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { + goto freebuf; + } + /* compute the y value - public key */ + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { + goto freebuf; + } + err = dh_check_pubkey(key); + } while (err != CRYPT_OK && max_iterations-- > 0); + +freebuf: + zeromem(buf, keysize); + XFREE(buf); +freemp: + if (err != CRYPT_OK) dh_free(key); + return err; +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_import.c b/libtomcrypt/src/pk/dh/dh_import.c new file mode 100644 index 0000000..601e5e7 --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_import.c @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Import a DH key from a binary packet + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) +{ + unsigned char flags[1]; + int err; + unsigned long version; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + /* init */ + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + return err; + } + + /* find out what type of key it is */ + err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, &flags, + LTC_ASN1_EOL, 0UL, NULL); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + goto error; + } + + if (version == 0) { + if (flags[0] == 1) { + key->type = PK_PRIVATE; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + /* compute public key: y = (base ^ x) mod prime */ + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { + goto error; + } + } + else if (flags[0] == 0) { + key->type = PK_PUBLIC; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* check public key */ + if ((err = dh_check_pubkey(key)) != CRYPT_OK) { + goto error; + } + + return CRYPT_OK; + +error: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_set.c b/libtomcrypt/src/pk/dh/dh_set.c new file mode 100644 index 0000000..8d0af7d --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_set.c @@ -0,0 +1,124 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Import DH key parts p and g from raw numbers + + @param p DH's p (prime) + @param plen DH's p's length + @param g DH's g (group) + @param glen DH's g's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int dh_set_pg(const unsigned char *p, unsigned long plen, + const unsigned char *g, unsigned long glen, + dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(g != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + return err; + } + + if ((err = mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK) { goto LBL_ERR; } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +/** + Import DH key parts p and g from built-in DH groups + + @param groupsize The size of the DH group to use + @param key [out] Where the newly created DH key will be stored + @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. +*/ +int dh_set_pg_groupsize(int groupsize, dh_key *key) +{ + int err, i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(groupsize > 0); + + for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++); + if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE; + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +/** + Import DH public or private key part from raw numbers + + NB: The p & g parts must be set beforehand + + @param in The key-part to import, either public or private. + @param inlen The key-part's length + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (type == PK_PRIVATE) { + key->type = PK_PRIVATE; + if ((err = mp_read_unsigned_bin(key->x, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto LBL_ERR; } + } + else { + key->type = PK_PUBLIC; + if ((err = mp_read_unsigned_bin(key->y, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + } + + /* check public key */ + if ((err = dh_check_pubkey(key)) != CRYPT_OK) { + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c b/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c new file mode 100644 index 0000000..7003011 --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Import DH key parts p and g from dhparam + + dhparam data: openssl dhparam -outform DER -out dhparam.der 2048 + + @param dhparam The DH param DER encoded data + @param dhparamlen The length of dhparam data + @param key [out] Where the newly created DH key will be stored + @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. +*/ +int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(dhparam != NULL); + LTC_ARGCHK(dhparamlen > 0); + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + return err; + } + if ((err = der_decode_sequence_multi(dhparam, dhparamlen, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dh/dh_shared_secret.c b/libtomcrypt/src/pk/dh/dh_shared_secret.c new file mode 100644 index 0000000..1eb69fb --- /dev/null +++ b/libtomcrypt/src/pk/dh/dh_shared_secret.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_MDH + +/** + Create a DH shared secret. + @param private_key The private DH key in the pair + @param public_key The public DH key in the pair + @param out [out] The destination of the shared data + @param outlen [in/out] The max size and resulting size of the shared data. + @return CRYPT_OK if successful +*/ +int dh_shared_secret(dh_key *private_key, dh_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + void *tmp; + unsigned long x; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* types valid? */ + if (private_key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* same DH group? */ + if (mp_cmp(private_key->prime, public_key->prime) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } + if (mp_cmp(private_key->base, public_key->base) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } + + /* init big numbers */ + if ((err = mp_init(&tmp)) != CRYPT_OK) { + return err; + } + + /* check public key */ + if ((err = dh_check_pubkey(public_key)) != CRYPT_OK) { + goto error; + } + + /* compute tmp = y^x mod p */ + if ((err = mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) { + goto error; + } + + /* enough space for output? */ + x = (unsigned long)mp_unsigned_bin_size(tmp); + if (*outlen < x) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { + goto error; + } + *outlen = x; + err = CRYPT_OK; + +error: + mp_clear(tmp); + return err; +} + +#endif /* LTC_MDH */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c b/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c index c622c78..ef4e1dd 100644 --- a/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c +++ b/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c @@ -5,15 +5,13 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file dsa_decrypt_key.c DSA Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MDSA @@ -27,12 +25,13 @@ @return CRYPT_OK if successful */ int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, + unsigned char *out, unsigned long *outlen, dsa_key *key) { unsigned char *skey, *expt; void *g_pub; - unsigned long x, y, hashOID[32]; + unsigned long x, y; + unsigned long hashOID[32] = { 0 }; int hash, err; ltc_asn1_list decode[3]; @@ -45,21 +44,21 @@ int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } - + /* decode to find out hash */ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); - - if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { + err = der_decode_sequence(in, inlen, decode, 1); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { return err; } - hash = find_hash_oid(hashOID, decode[0].size); + hash = find_hash_oid(hashOID, decode[0].size); if (hash_is_valid(hash) != CRYPT_OK) { return CRYPT_INVALID_PACKET; } /* we now have the hash! */ - + if ((err = mp_init(&g_pub)) != CRYPT_OK) { return err; } @@ -77,7 +76,7 @@ int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, mp_clear(g_pub); return CRYPT_MEM; } - + LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER, g_pub, 1UL); LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); @@ -92,7 +91,8 @@ int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, goto LBL_ERR; } - y = MIN(mp_unsigned_bin_size(key->p) + 1, MAXBLOCKSIZE); + y = mp_unsigned_bin_size(key->p) + 1; + y = MIN(y, MAXBLOCKSIZE); if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) { goto LBL_ERR; } @@ -125,7 +125,7 @@ LBL_ERR: XFREE(expt); XFREE(skey); - + mp_clear(g_pub); return err; @@ -133,7 +133,7 @@ LBL_ERR: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c b/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c index a082969..c854367 100644 --- a/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c +++ b/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c @@ -5,15 +5,13 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file dsa_encrypt_key.c DSA Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MDSA @@ -24,14 +22,14 @@ @param out [out] The destination for the ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param hash The index of the hash you want to use + @param wprng The index of the PRNG you wish to use + @param hash The index of the hash you want to use @param key The DSA key you want to encrypt to @return CRYPT_OK if successful */ int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, int hash, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, dsa_key *key) { unsigned char *expt, *skey; @@ -61,7 +59,7 @@ int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, if ((err = mp_init_multi(&g_pub, &g_priv, NULL)) != CRYPT_OK) { return err; } - + expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1); skey = XMALLOC(MAXBLOCKSIZE); if (expt == NULL || skey == NULL) { @@ -74,24 +72,19 @@ int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, mp_clear_multi(g_pub, g_priv, NULL); return CRYPT_MEM; } - - /* make a random x, g^x pair */ - x = mp_unsigned_bin_size(key->q); - if (prng_descriptor[wprng].read(expt, x, prng) != x) { - err = CRYPT_ERROR_READPRNG; - goto LBL_ERR; - } - - /* load x */ - if ((err = mp_read_unsigned_bin(g_priv, expt, x)) != CRYPT_OK) { - goto LBL_ERR; + + /* make a random g_priv, g_pub = g^x pair + private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) + */ + if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != CRYPT_OK) { + goto LBL_ERR; } - + /* compute y */ if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) { goto LBL_ERR; } - + /* make random key */ x = mp_unsigned_bin_size(key->p) + 1; if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) { @@ -102,7 +95,7 @@ int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) { goto LBL_ERR; } - + /* Encrypt key */ for (x = 0; x < inlen; x++) { skey[x] ^= in[x]; @@ -123,13 +116,13 @@ LBL_ERR: XFREE(skey); XFREE(expt); - + mp_clear_multi(g_pub, g_priv, NULL); return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_export.c b/libtomcrypt/src/pk/dsa/dsa_export.c index e4c4508..1f6bb5a 100644 --- a/libtomcrypt/src/pk/dsa/dsa_export.c +++ b/libtomcrypt/src/pk/dsa/dsa_export.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -27,12 +25,16 @@ */ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key) { - unsigned char flags[1]; + unsigned long zero=0; + int err, std; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); + std = type & PK_STD; + type &= ~PK_STD; + /* can we store the static header? */ if (type == PK_PRIVATE && key->type != PK_PRIVATE) { return CRYPT_PK_TYPE_MISMATCH; @@ -42,31 +44,73 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key return CRYPT_INVALID_ARG; } - flags[0] = (type != PK_PUBLIC) ? 1 : 0; - if (type == PK_PRIVATE) { - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL); + if (std) { + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } + else { + unsigned char flags[1]; + flags[0] = 1; + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } } else { - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_EOL, 0UL, NULL); + if (std) { + unsigned long tmplen = (mp_count_bits(key->y) / 8) + 8; + unsigned char* tmp = XMALLOC(tmplen); + ltc_asn1_list int_list[3]; + + if (tmp == NULL) { + return CRYPT_MEM; + } + + err = der_encode_integer(key->y, tmp, &tmplen); + if (err != CRYPT_OK) { + goto error; + } + + LTC_SET_ASN1(int_list, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL); + + err = der_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp, + tmplen, LTC_ASN1_SEQUENCE, int_list, + sizeof(int_list) / sizeof(int_list[0])); + +error: + XFREE(tmp); + return err; + } + else { + unsigned char flags[1]; + flags[0] = 0; + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL); + } } } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_free.c b/libtomcrypt/src/pk/dsa/dsa_free.c index 5f5ce72..5cac656 100644 --- a/libtomcrypt/src/pk/dsa/dsa_free.c +++ b/libtomcrypt/src/pk/dsa/dsa_free.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -24,11 +22,12 @@ void dsa_free(dsa_key *key) { LTC_ARGCHKVD(key != NULL); - mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); + mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, NULL); + key->type = key->qord = 0; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_generate_key.c b/libtomcrypt/src/pk/dsa/dsa_generate_key.c new file mode 100644 index 0000000..18b2df6 --- /dev/null +++ b/libtomcrypt/src/pk/dsa/dsa_generate_key.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file dsa_make_key.c + DSA implementation, generate a DSA key +*/ + +#ifdef LTC_MDSA + +/** + Create a DSA key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key [in/out] Where to store the created key + @return CRYPT_OK if successful. +*/ +int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* so now we have our DH structure, generator g, order q, modulus p + Now we need a random exponent [mod q] and it's power g^x mod p + */ + /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ + if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; } + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; } + key->type = PK_PRIVATE; + + return CRYPT_OK; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c b/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c new file mode 100644 index 0000000..91c7ef7 --- /dev/null +++ b/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c @@ -0,0 +1,244 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file dsa_generate_pqg.c + DSA implementation - generate DSA parameters p, q & g +*/ + +#ifdef LTC_MDSA + +/** + Create DSA parameters (INTERNAL ONLY, not part of public API) + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param group_size Size of the multiplicative group (octets) + @param modulus_size Size of the modulus (octets) + @param p [out] bignum where generated 'p' is stored (must be initialized by caller) + @param q [out] bignum where generated 'q' is stored (must be initialized by caller) + @param g [out] bignum where generated 'g' is stored (must be initialized by caller) + @return CRYPT_OK if successful, upon error this function will free all allocated memory +*/ +static int _dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) +{ + unsigned long L, N, n, outbytes, seedbytes, counter, j, i; + int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; + unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; + void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; + + /* check size */ + if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) { + return CRYPT_INVALID_ARG; + } + + /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function + * + * L = The desired length of the prime p (in bits e.g. L = 1024) + * N = The desired length of the prime q (in bits e.g. N = 160) + * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N + * outlen = The bit length of Hash function + * + * 1. Check that the (L, N) + * 2. If (seedlen <N), then return INVALID. + * 3. n = ceil(L / outlen) - 1 + * 4. b = L- 1 - (n * outlen) + * 5. domain_parameter_seed = an arbitrary sequence of seedlen bits + * 6. U = Hash (domain_parameter_seed) mod 2^(N-1) + * 7. q = 2^(N-1) + U + 1 - (U mod 2) + * 8. Test whether or not q is prime as specified in Appendix C.3 + * 9. If qis not a prime, then go to step 5. + * 10. offset = 1 + * 11. For counter = 0 to (4L- 1) do { + * For j=0 to n do { + * Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen + * } + * W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen)) + * X = W + 2^(L-1) Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L + * c = X mod 2*q + * p = X - (c - 1) Comment: p ~ 1 (mod 2*q) + * If (p >= 2^(L-1)) { + * Test whether or not p is prime as specified in Appendix C.3. + * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter + * } + * offset = offset + n + 1 Comment: Increment offset + * } + */ + + seedbytes = group_size; + L = modulus_size * 8; + N = group_size * 8; + + /* XXX-TODO no Lucas test */ +#ifdef LTC_MPI_HAS_LUCAS_TEST + /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ + mr_tests_p = (L <= 2048) ? 3 : 2; + if (N <= 160) { mr_tests_q = 19; } + else if (N <= 224) { mr_tests_q = 24; } + else { mr_tests_q = 27; } +#else + /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ + if (L <= 1024) { mr_tests_p = 40; } + else if (L <= 2048) { mr_tests_p = 56; } + else { mr_tests_p = 64; } + + if (N <= 160) { mr_tests_q = 40; } + else if (N <= 224) { mr_tests_q = 56; } + else { mr_tests_q = 64; } +#endif + + if (N <= 256) { + hash = register_hash(&sha256_desc); + } + else if (N <= 384) { + hash = register_hash(&sha384_desc); + } + else if (N <= 512) { + hash = register_hash(&sha512_desc); + } + else { + return CRYPT_INVALID_ARG; /* group_size too big */ + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } + outbytes = hash_descriptor[hash].hashsize; + + n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; + + if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } + if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } + + err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL); + if (err != CRYPT_OK) { goto cleanup1; } + + if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } + /* t2L1 = 2^(L-1) */ + if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } + /* t2N1 = 2^(N-1) */ + if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } + /* t2seedlen = 2^seedlen */ + + for(found_p=0; !found_p;) { + /* q */ + for(found_q=0; !found_q;) { + if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } + i = outbytes; + if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } + if (!mp_isodd(q)) mp_add_d(q, 1, q); + if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } + if (res == LTC_MP_YES) found_q = 1; + } + + /* p */ + if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } + for(counter=0; counter < 4*L && !found_p; counter++) { + for(j=0; j<=n; j++) { + if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } + /* seedinc = (seedinc+1) % 2^seed_bitlen */ + if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } + zeromem(sbuf, seedbytes); + if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } + i = outbytes; + err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); + if (err != CRYPT_OK) { goto cleanup; } + } + if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } + if (mp_cmp(p, t2L1) != LTC_MP_LT) { + /* p >= 2^(L-1) */ + if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } + if (res == LTC_MP_YES) { + found_p = 1; + } + } + } + } + + /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g + * 1. e = (p - 1)/q + * 2. h = any integer satisfying: 1 < h < (p - 1) + * h could be obtained from a random number generator or from a counter that changes after each use + * 3. g = h^e mod p + * 4. if (g == 1), then go to step 2. + * + */ + + if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } + /* e = (p - 1)/q */ + i = mp_count_bits(p); + do { + do { + if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } + } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); + if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } + /* h is randon and 1 < h < (p-1) */ + if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } + } while (mp_cmp_d(g, 1) == LTC_MP_EQ); + + err = CRYPT_OK; +cleanup: + mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL); +cleanup1: + XFREE(sbuf); +cleanup2: + XFREE(wbuf); +cleanup3: + return err; +} + +/** + Generate DSA parameters p, q & g + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param group_size Size of the multiplicative group (octets) + @param modulus_size Size of the modulus (octets) + @param key [out] Where to store the created key + @return CRYPT_OK if successful. +*/ +int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init mp_ints */ + if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL)) != CRYPT_OK) { + return err; + } + /* generate params */ + err = _dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g); + if (err != CRYPT_OK) { + goto cleanup; + } + + key->qord = group_size; + + return CRYPT_OK; + +cleanup: + dsa_free(key); + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_import.c b/libtomcrypt/src/pk/dsa/dsa_import.c index 47a68ca..e6a7560 100644 --- a/libtomcrypt/src/pk/dsa/dsa_import.c +++ b/libtomcrypt/src/pk/dsa/dsa_import.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -18,7 +16,7 @@ #ifdef LTC_MDSA /** - Import a DSA key + Import a DSA key @param in The binary packet to import from @param inlen The length of the binary packet @param key [out] Where to store the imported key @@ -26,8 +24,10 @@ */ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) { + int err, stat; + unsigned long zero = 0; + unsigned char* tmpbuf = NULL; unsigned char flags[1]; - int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); @@ -38,53 +38,115 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) return CRYPT_MEM; } + /* try to match the old libtomcrypt format */ + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_EOL, 0UL, NULL); + + if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) { + /* private key */ + if (flags[0] == 1) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PRIVATE; + goto LBL_OK; + } + /* public key */ + else if (flags[0] == 0) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PUBLIC; + goto LBL_OK; + } + else { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } /* get key type */ if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; - } + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + + key->type = PK_PRIVATE; + } else { /* public */ + ltc_asn1_list params[3]; + unsigned long tmpbuf_len = inlen; + + LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); + + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } - if (flags[0] == 1) { - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; + err = der_decode_subject_public_key_info(in, inlen, PKA_DSA, + tmpbuf, &tmpbuf_len, + LTC_ASN1_SEQUENCE, params, 3); + if (err != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; } - key->type = PK_PRIVATE; - } else { - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, flags, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; + + if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; } + + XFREE(tmpbuf); key->type = PK_PUBLIC; - } - key->qord = mp_unsigned_bin_size(key->q); + } + +LBL_OK: + key->qord = mp_unsigned_bin_size(key->q); - if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || - (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA) { + /* quick p, q, g validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + /* validate x, y */ + if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { err = CRYPT_INVALID_PACKET; - goto error; + goto LBL_ERR; } return CRYPT_OK; -error: - mp_clear_multi(key->p, key->g, key->q, key->x, key->y, NULL); +LBL_ERR: + dsa_free(key); return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_make_key.c b/libtomcrypt/src/pk/dsa/dsa_make_key.c index 1c16d03..8ac08f8 100644 --- a/libtomcrypt/src/pk/dsa/dsa_make_key.c +++ b/libtomcrypt/src/pk/dsa/dsa_make_key.c @@ -5,133 +5,37 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file dsa_make_key.c - DSA implementation, generate a DSA key, Tom St Denis + DSA implementation, generate a DSA key */ #ifdef LTC_MDSA /** - Create a DSA key + Old-style creation of a DSA key @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param key [out] Where to store the created key - @return CRYPT_OK if successful, upon error this function will free all allocated memory + @return CRYPT_OK if successful. */ int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) { - void *tmp, *tmp2; - int err, res; - unsigned char *buf; - - LTC_ARGCHK(key != NULL); - LTC_ARGCHK(ltc_mp.name != NULL); - - /* check prng */ - if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; - } - - /* check size */ - if (group_size >= LTC_MDSA_MAX_GROUP || group_size <= 15 || - group_size >= modulus_size || (modulus_size - group_size) >= LTC_MDSA_DELTA) { - return CRYPT_INVALID_ARG; - } - - /* allocate ram */ - buf = XMALLOC(LTC_MDSA_DELTA); - if (buf == NULL) { - return CRYPT_MEM; - } - - /* init mp_ints */ - if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { - XFREE(buf); - return err; - } - - /* make our prime q */ - if ((err = rand_prime(key->q, group_size, prng, wprng)) != CRYPT_OK) { goto error; } - - /* double q */ - if ((err = mp_add(key->q, key->q, tmp)) != CRYPT_OK) { goto error; } - - /* now make a random string and multply it against q */ - if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) { - err = CRYPT_ERROR_READPRNG; - goto error; - } - - /* force magnitude */ - buf[0] |= 0xC0; + int err; - /* force even */ - buf[modulus_size - group_size - 1] &= ~1; - - if ((err = mp_read_unsigned_bin(tmp2, buf, modulus_size - group_size)) != CRYPT_OK) { goto error; } - if ((err = mp_mul(key->q, tmp2, key->p)) != CRYPT_OK) { goto error; } - if ((err = mp_add_d(key->p, 1, key->p)) != CRYPT_OK) { goto error; } - - /* now loop until p is prime */ - for (;;) { - if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { goto error; } - if (res == LTC_MP_YES) break; - - /* add 2q to p and 2 to tmp2 */ - if ((err = mp_add(tmp, key->p, key->p)) != CRYPT_OK) { goto error; } - if ((err = mp_add_d(tmp2, 2, tmp2)) != CRYPT_OK) { goto error; } - } - - /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */ - mp_set(key->g, 1); - - do { - if ((err = mp_add_d(key->g, 1, key->g)) != CRYPT_OK) { goto error; } - if ((err = mp_exptmod(key->g, tmp2, key->p, tmp)) != CRYPT_OK) { goto error; } - } while (mp_cmp_d(tmp, 1) == LTC_MP_EQ); - - /* at this point tmp generates a group of order q mod p */ - mp_exch(tmp, key->g); - - /* so now we have our DH structure, generator g, order q, modulus p - Now we need a random exponent [mod q] and it's power g^x mod p - */ - do { - if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) { - err = CRYPT_ERROR_READPRNG; - goto error; - } - if ((err = mp_read_unsigned_bin(key->x, buf, group_size)) != CRYPT_OK) { goto error; } - } while (mp_cmp_d(key->x, 1) != LTC_MP_GT); - if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto error; } - - key->type = PK_PRIVATE; - key->qord = group_size; - -#ifdef LTC_CLEAN_STACK - zeromem(buf, LTC_MDSA_DELTA); -#endif + if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; } + if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } - err = CRYPT_OK; - goto done; -error: - mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL); -done: - mp_clear_multi(tmp, tmp2, NULL); - XFREE(buf); - return err; + return CRYPT_OK; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_set.c b/libtomcrypt/src/pk/dsa/dsa_set.c new file mode 100644 index 0000000..a4d4042 --- /dev/null +++ b/libtomcrypt/src/pk/dsa/dsa_set.c @@ -0,0 +1,112 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + + +#ifdef LTC_MDSA + +/** + Import DSA's p, q & g from raw numbers + @param p DSA's p in binary representation + @param plen The length of p + @param q DSA's q in binary representation + @param qlen The length of q + @param g DSA's g in binary representation + @param glen The length of g + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_pqg(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + const unsigned char *g, unsigned long glen, + dsa_key *key) +{ + int err, stat; + + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(q != NULL); + LTC_ARGCHK(g != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); + if (err != CRYPT_OK) return err; + + if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } + + key->qord = mp_unsigned_bin_size(key->q); + + /* do only a quick validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +/** + Import DSA public or private key-part from raw numbers + + NB: The p, q & g parts must be set beforehand + + @param in The key-part to import, either public or private. + @param inlen The key-part's length + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key) +{ + int err, stat = 0; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->x != NULL); + LTC_ARGCHK(key->y != NULL); + LTC_ARGCHK(key->p != NULL); + LTC_ARGCHK(key->g != NULL); + LTC_ARGCHK(key->q != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (type == PK_PRIVATE) { + key->type = PK_PRIVATE; + if ((err = mp_read_unsigned_bin(key->x, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto LBL_ERR; } + } + else { + key->type = PK_PUBLIC; + if ((err = mp_read_unsigned_bin(key->y, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + } + + if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c b/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c new file mode 100644 index 0000000..edbed1c --- /dev/null +++ b/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c @@ -0,0 +1,67 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + + +#ifdef LTC_MDSA + +/** + Import DSA's p, q & g from dsaparam + + dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048 + + @param dsaparam The DSA param DER encoded data + @param dsaparamlen The length of dhparam data + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, + dsa_key *key) +{ + int err, stat; + + LTC_ARGCHK(dsaparam != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); + if (err != CRYPT_OK) return err; + + if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + key->qord = mp_unsigned_bin_size(key->q); + + /* quick p, q, g validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_shared_secret.c b/libtomcrypt/src/pk/dsa/dsa_shared_secret.c index 5adaa5f..4c18261 100644 --- a/libtomcrypt/src/pk/dsa/dsa_shared_secret.c +++ b/libtomcrypt/src/pk/dsa/dsa_shared_secret.c @@ -5,22 +5,20 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file dsa_shared_secret.c DSA Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MDSA /** Create a DSA shared secret between two keys @param private_key The private DSA key (the exponent) - @param base The base of the exponentiation (allows this to be used for both encrypt and decrypt) + @param base The base of the exponentiation (allows this to be used for both encrypt and decrypt) @param public_key The public key @param out [out] Destination of the shared secret @param outlen [in/out] The max size and resulting size of the shared secret @@ -48,7 +46,7 @@ int dsa_shared_secret(void *private_key, void *base, mp_clear(res); return err; } - + x = (unsigned long)mp_unsigned_bin_size(res); if (*outlen < x) { *outlen = x; @@ -66,7 +64,7 @@ done: } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_sign_hash.c b/libtomcrypt/src/pk/dsa/dsa_sign_hash.c index 3fc7e99..fda2ca1 100644 --- a/libtomcrypt/src/pk/dsa/dsa_sign_hash.c +++ b/libtomcrypt/src/pk/dsa/dsa_sign_hash.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -34,7 +32,7 @@ int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, { void *k, *kinv, *tmp; unsigned char *buf; - int err; + int err, qbits; LTC_ARGCHK(in != NULL); LTC_ARGCHK(r != NULL); @@ -61,20 +59,15 @@ int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, /* Init our temps */ if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) { goto ERRBUF; } + qbits = mp_count_bits(key->q); retry: do { /* gen random k */ - if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) { - err = CRYPT_ERROR_READPRNG; - goto error; - } - - /* read k */ - if ((err = mp_read_unsigned_bin(k, buf, key->qord)) != CRYPT_OK) { goto error; } + if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; } - /* k > 1 ? */ - if (mp_cmp_d(k, 1) != LTC_MP_GT) { goto retry; } + /* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */ + if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT) { goto retry; } /* test gcd */ if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; } @@ -89,6 +82,9 @@ retry: if (mp_iszero(r) == LTC_MP_YES) { goto retry; } + /* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/ + inlen = MIN(inlen, (unsigned long)(key->qord)); + /* now find s = (in + xr)/k mod q */ if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; } if ((err = mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; } @@ -98,7 +94,7 @@ retry: if (mp_iszero(s) == LTC_MP_YES) { goto retry; } err = CRYPT_OK; -error: +error: mp_clear_multi(k, kinv, tmp, NULL); ERRBUF: #ifdef LTC_CLEAN_STACK @@ -139,9 +135,9 @@ int dsa_sign_hash(const unsigned char *in, unsigned long inlen, goto error; } - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, LTC_ASN1_EOL, 0UL, NULL); error: @@ -151,6 +147,6 @@ error: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_verify_hash.c b/libtomcrypt/src/pk/dsa/dsa_verify_hash.c index 59beec2..3d3fab5 100644 --- a/libtomcrypt/src/pk/dsa/dsa_verify_hash.c +++ b/libtomcrypt/src/pk/dsa/dsa_verify_hash.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -25,11 +23,11 @@ @param hash The hash that was signed @param hashlen The length of the hash that was signed @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @param key The corresponding public DH key + @param key The corresponding public DSA key @return CRYPT_OK if successful (even if the signature is invalid) */ int dsa_verify_hash_raw( void *r, void *s, - const unsigned char *hash, unsigned long hashlen, + const unsigned char *hash, unsigned long hashlen, int *stat, dsa_key *key) { void *w, *v, *u1, *u2; @@ -49,11 +47,14 @@ int dsa_verify_hash_raw( void *r, void *s, } /* neither r or s can be null or >q*/ - if (mp_iszero(r) == LTC_MP_YES || mp_iszero(s) == LTC_MP_YES || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) { + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) { err = CRYPT_INVALID_PACKET; goto error; } - + + /* FIPS 186-4 4.7: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash' */ + hashlen = MIN(hashlen, (unsigned long)(key->qord)); + /* w = 1/s mod q */ if ((err = mp_invmod(s, key->q, w)) != CRYPT_OK) { goto error; } @@ -62,7 +63,7 @@ int dsa_verify_hash_raw( void *r, void *s, if ((err = mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK) { goto error; } /* u2 = r*w mod q */ - if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; } /* v = g^u1 * y^u2 mod p mod q */ if ((err = mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK) { goto error; } @@ -88,25 +89,35 @@ error: @param hash The hash that was signed @param hashlen The length of the hash that was signed @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @param key The corresponding public DH key + @param key The corresponding public DSA key @return CRYPT_OK if successful (even if the signature is invalid) */ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, + const unsigned char *hash, unsigned long hashlen, int *stat, dsa_key *key) { int err; void *r, *s; + ltc_asn1_list sig_seq[2]; + unsigned long reallen = 0; + + LTC_ARGCHK(stat != NULL); + *stat = 0; /* must be set before the first return */ if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) { - return CRYPT_MEM; + return err; + } + + LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL); + LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL); + + err = der_decode_sequence(sig, siglen, sig_seq, 2); + if (err != CRYPT_OK) { + goto LBL_ERR; } - /* decode the sequence */ - if ((err = der_decode_sequence_multi(sig, siglen, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + err = der_length_sequence(sig_seq, 2, &reallen); + if (err != CRYPT_OK || reallen != siglen) { goto LBL_ERR; } @@ -121,6 +132,6 @@ LBL_ERR: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/dsa/dsa_verify_key.c b/libtomcrypt/src/pk/dsa/dsa_verify_key.c index fa839ef..258e6cb 100644 --- a/libtomcrypt/src/pk/dsa/dsa_verify_key.c +++ b/libtomcrypt/src/pk/dsa/dsa_verify_key.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" @@ -18,83 +16,184 @@ #ifdef LTC_MDSA /** - Verify a DSA key for validity - @param key The key to verify + Validate a DSA key + + Yeah, this function should've been called dsa_validate_key() + in the first place and for compat-reasons we keep it + as it was (for now). + + @param key The key to validate @param stat [out] Result of test, 1==valid, 0==invalid @return CRYPT_OK if successful */ int dsa_verify_key(dsa_key *key, int *stat) { - void *tmp, *tmp2; - int res, err; + int err; + + err = dsa_int_validate_primes(key, stat); + if (err != CRYPT_OK || *stat == 0) return err; + + err = dsa_int_validate_pqg(key, stat); + if (err != CRYPT_OK || *stat == 0) return err; + + return dsa_int_validate_xy(key, stat); +} + +/** + Non-complex part (no primality testing) of the validation + of DSA params (p, q, g) + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_pqg(dsa_key *key, int *stat) +{ + void *tmp1, *tmp2; + int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(stat != NULL); - - /* default to an invalid key */ *stat = 0; - /* first make sure key->q and key->p are prime */ - if ((err = mp_prime_is_prime(key->q, 8, &res)) != CRYPT_OK) { - return err; - } - if (res == 0) { + /* check q-order */ + if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || + (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || + (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) { return CRYPT_OK; } - if ((err = mp_prime_is_prime(key->p, 8, &res)) != CRYPT_OK) { - return err; - } - if (res == 0) { + /* FIPS 186-4 chapter 4.1: 1 < g < p */ + if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) { return CRYPT_OK; } - /* now make sure that g is not -1, 0 or 1 and <p */ - if (mp_cmp_d(key->g, 0) == LTC_MP_EQ || mp_cmp_d(key->g, 1) == LTC_MP_EQ) { - return CRYPT_OK; - } - if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != CRYPT_OK) { return err; } - if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { goto error; } - if (mp_cmp(tmp, key->g) == LTC_MP_EQ || mp_cmp(key->g, key->p) != LTC_MP_LT) { + if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) { return err; } + + /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */ + if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; } + if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; } + if (mp_iszero(tmp2) != LTC_MP_YES) { err = CRYPT_OK; goto error; } - /* 1 < y < p-1 */ - if (!(mp_cmp_d(key->y, 1) == LTC_MP_GT && mp_cmp(key->y, tmp) == LTC_MP_LT)) { + /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in + * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1 + */ + if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; } + if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) { err = CRYPT_OK; goto error; } - /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */ - if ((err = mp_div(tmp, key->q, tmp, tmp2)) != CRYPT_OK) { goto error; } - if (mp_iszero(tmp2) != LTC_MP_YES) { - err = CRYPT_OK; - goto error; + err = CRYPT_OK; + *stat = 1; +error: + mp_clear_multi(tmp2, tmp1, NULL); + return err; +} + +/** + Primality testing of DSA params p and q + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_primes(dsa_key *key, int *stat) +{ + int err, res; + + *stat = 0; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* key->q prime? */ + if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { + return err; + } + if (res == LTC_MP_NO) { + return CRYPT_OK; } - if ((err = mp_exptmod(key->g, key->q, key->p, tmp)) != CRYPT_OK) { goto error; } - if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { - err = CRYPT_OK; - goto error; + /* key->p prime? */ + if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { + return err; } + if (res == LTC_MP_NO) { + return CRYPT_OK; + } + + *stat = 1; + return CRYPT_OK; +} + +/** + Validation of a DSA key (x and y values) - /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */ - if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) { goto error; } - if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_xy(dsa_key *key, int *stat) +{ + void *tmp; + int err; + + *stat = 0; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* 1 < y < p-1 */ + if ((err = mp_init(&tmp)) != CRYPT_OK) { + return err; + } + if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) { err = CRYPT_OK; goto error; } - /* at this point we are out of tests ;-( */ + if (key->type == PK_PRIVATE) { + /* FIPS 186-4 chapter 4.1: 0 < x < q */ + if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) { + err = CRYPT_OK; + goto error; + } + /* FIPS 186-4 chapter 4.1: y = g^x mod p */ + if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp(tmp, key->y) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + } + else { + /* with just a public key we cannot test y = g^x mod p therefore we + * only test that y^q mod p = 1, which makes sure y is in g^x mod p + */ + if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + } + err = CRYPT_OK; *stat = 1; -error: - mp_clear_multi(tmp, tmp2, NULL); +error: + mp_clear(tmp); return err; } + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc.c b/libtomcrypt/src/pk/ecc/ecc.c index 56ed526..18da0b3 100644 --- a/libtomcrypt/src/pk/ecc/ecc.c +++ b/libtomcrypt/src/pk/ecc/ecc.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,13 +17,13 @@ /** @file ecc.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC /* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ const ltc_ecc_set_type ltc_ecc_sets[] = { -#ifdef ECC112 +#ifdef LTC_ECC112 { 14, "SECP112R1", @@ -36,7 +34,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { "A89CE5AF8724C0A23E0E0FF77500" }, #endif -#ifdef ECC128 +#ifdef LTC_ECC128 { 16, "SECP128R1", @@ -47,7 +45,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { "CF5AC8395BAFEB13C02DA292DDED7A83", }, #endif -#ifdef ECC160 +#ifdef LTC_ECC160 { 20, "SECP160R1", @@ -58,7 +56,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { "23A628553168947D59DCC912042351377AC5FB32", }, #endif -#ifdef ECC192 +#ifdef LTC_ECC192 { 24, "ECC-192", @@ -69,7 +67,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", }, #endif -#ifdef ECC224 +#ifdef LTC_ECC224 { 28, "ECC-224", @@ -80,7 +78,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", }, #endif -#ifdef ECC256 +#ifdef LTC_ECC256 { 32, "ECC-256", @@ -91,7 +89,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", }, #endif -#ifdef ECC384 +#ifdef LTC_ECC384 { 48, "ECC-384", @@ -102,7 +100,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", }, #endif -#ifdef ECC521 +#ifdef LTC_ECC521 { 66, "ECC-521", @@ -121,7 +119,7 @@ const ltc_ecc_set_type ltc_ecc_sets[] = { #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c index 09dae07..773b683 100644 --- a/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c +++ b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ecc_ansi_x963_export.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC @@ -32,33 +30,40 @@ int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen) { unsigned char buf[ECC_BUF_SIZE]; - unsigned long numlen; + unsigned long numlen, xlen, ylen; LTC_ARGCHK(key != NULL); - LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if (ltc_ecc_is_valid_idx(key->idx) == 0) { return CRYPT_INVALID_ARG; } numlen = key->dp->size; + xlen = mp_unsigned_bin_size(key->pubkey.x); + ylen = mp_unsigned_bin_size(key->pubkey.y); + + if (xlen > numlen || ylen > numlen || sizeof(buf) < numlen) { + return CRYPT_BUFFER_OVERFLOW; + } if (*outlen < (1 + 2*numlen)) { *outlen = 1 + 2*numlen; return CRYPT_BUFFER_OVERFLOW; } + LTC_ARGCHK(out != NULL); + /* store byte 0x04 */ out[0] = 0x04; /* pad and store x */ zeromem(buf, sizeof(buf)); - mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - mp_unsigned_bin_size(key->pubkey.x))); + mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - xlen)); XMEMCPY(out+1, buf, numlen); /* pad and store y */ zeromem(buf, sizeof(buf)); - mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - mp_unsigned_bin_size(key->pubkey.y))); + mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - ylen)); XMEMCPY(out+1+numlen, buf, numlen); *outlen = 1 + 2*numlen; @@ -67,6 +72,6 @@ int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c index ec34245..ee5a4c9 100644 --- a/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c +++ b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,11 +17,11 @@ /** @file ecc_ansi_x963_import.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC -/** Import an ANSI X9.63 format public key +/** Import an ANSI X9.63 format public key @param in The input data to read @param inlen The length of the input data @param key [out] destination to store imported key \ @@ -36,10 +34,10 @@ int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key * int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp) { int x, err; - + LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); - + /* must be odd */ if ((inlen & 1) == 0) { return CRYPT_INVALID_ARG; @@ -99,6 +97,6 @@ error: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c b/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c index 49df8e8..8f8ad2f 100644 --- a/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c +++ b/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ecc_decrypt_key.c ECC Crypto, Tom St Denis -*/ +*/ #if defined(LTC_MECC) && defined(LTC_DER) @@ -33,11 +31,12 @@ @return CRYPT_OK if successful */ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, + unsigned char *out, unsigned long *outlen, ecc_key *key) { unsigned char *ecc_shared, *skey, *pub_expt; - unsigned long x, y, hashOID[32]; + unsigned long x, y; + unsigned long hashOID[32] = { 0 }; int hash, err; ecc_key pubkey; ltc_asn1_list decode[3]; @@ -51,15 +50,15 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } - + /* decode to find out hash */ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); - - if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) { + err = der_decode_sequence(in, inlen, decode, 1); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { return err; } - hash = find_hash_oid(hashOID, decode[0].size); + hash = find_hash_oid(hashOID, decode[0].size); if (hash_is_valid(hash) != CRYPT_OK) { return CRYPT_INVALID_PACKET; } @@ -144,7 +143,7 @@ LBL_ERR: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c b/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c index e97e737..6d26efb 100644 --- a/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c +++ b/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,25 +17,25 @@ /** @file ecc_encrypt_key.c ECC Crypto, Tom St Denis -*/ +*/ #if defined(LTC_MECC) && defined(LTC_DER) /** - Encrypt a symmetric key with ECC + Encrypt a symmetric key with ECC @param in The symmetric key you want to encrypt @param inlen The length of the key to encrypt (octets) @param out [out] The destination for the ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param hash The index of the hash you want to use + @param wprng The index of the PRNG you wish to use + @param hash The index of the hash you want to use @param key The ECC key you want to encrypt to @return CRYPT_OK if successful */ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, int hash, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, ecc_key *key) { unsigned char *pub_expt, *ecc_shared, *skey; @@ -90,7 +88,7 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, ecc_free(&pubkey); goto LBL_ERR; } - + /* make random key */ x = ECC_BUF_SIZE; if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { @@ -102,7 +100,7 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) { goto LBL_ERR; } - + /* Encrypt key */ for (x = 0; x < inlen; x++) { skey[x] ^= in[x]; @@ -130,7 +128,7 @@ LBL_ERR: } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_export.c b/libtomcrypt/src/pk/ecc/ecc_export.c index 6a712fd..be137e1 100644 --- a/libtomcrypt/src/pk/ecc/ecc_export.c +++ b/libtomcrypt/src/pk/ecc/ecc_export.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ecc_export.c ECC Crypto, Tom St Denis -*/ +*/ #if defined(LTC_MECC) && defined(LTC_DER) @@ -40,7 +38,7 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); - + /* type valid? */ if (key->type != PK_PRIVATE && type == PK_PRIVATE) { return CRYPT_PK_TYPE_MISMATCH; @@ -76,7 +74,7 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_free.c b/libtomcrypt/src/pk/ecc/ecc_free.c index c9e5d6c..4a8ca45 100644 --- a/libtomcrypt/src/pk/ecc/ecc_free.c +++ b/libtomcrypt/src/pk/ecc/ecc_free.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ecc_free.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC @@ -34,7 +32,7 @@ void ecc_free(ecc_key *key) } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_get_size.c b/libtomcrypt/src/pk/ecc/ecc_get_size.c index a824aa4..4dc5d22 100644 --- a/libtomcrypt/src/pk/ecc/ecc_get_size.c +++ b/libtomcrypt/src/pk/ecc/ecc_get_size.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,13 +17,13 @@ /** @file ecc_get_size.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC /** Get the size of an ECC key - @param key The key to get the size of + @param key The key to get the size of @return The size (octets) of the key or INT_MAX on error */ int ecc_get_size(ecc_key *key) @@ -38,7 +36,7 @@ int ecc_get_size(ecc_key *key) } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_import.c b/libtomcrypt/src/pk/ecc/ecc_import.c index 9506076..9b61055 100644 --- a/libtomcrypt/src/pk/ecc/ecc_import.c +++ b/libtomcrypt/src/pk/ecc/ecc_import.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,34 +17,34 @@ /** @file ecc_import.c ECC Crypto, Tom St Denis -*/ +*/ #if defined(LTC_MECC) && defined(LTC_DER) -static int is_point(ecc_key *key) +static int _is_point(ecc_key *key) { void *prime, *b, *t1, *t2; int err; - + if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) { return err; } - + /* load prime and b */ if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } - + /* compute y^2 */ if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } - + /* compute x^3 */ if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 + 3x */ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } @@ -58,14 +56,14 @@ static int is_point(ecc_key *key) while (mp_cmp(t1, prime) != LTC_MP_LT) { if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } } - + /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } - + error: mp_clear_multi(prime, b, t1, t2, NULL); return err; @@ -107,9 +105,9 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co } /* find out what type of key it is */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_BIT_STRING, 1UL, &flags, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_EOL, 0UL, NULL); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { goto done; } @@ -126,7 +124,7 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto done; } - } else { + } else if (flags[0] == 0) { /* public key */ key->type = PK_PUBLIC; if ((err = der_decode_sequence_multi(in, inlen, @@ -138,6 +136,10 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co goto done; } } + else { + err = CRYPT_INVALID_PACKET; + goto done; + } if (dp == NULL) { /* find the idx */ @@ -153,9 +155,9 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co } /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; } - + /* is it a point on the curve? */ - if ((err = is_point(key)) != CRYPT_OK) { + if ((err = _is_point(key)) != CRYPT_OK) { goto done; } @@ -166,7 +168,7 @@ done: return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_make_key.c b/libtomcrypt/src/pk/ecc/ecc_make_key.c index 9bbeb44..113a994 100644 --- a/libtomcrypt/src/pk/ecc/ecc_make_key.c +++ b/libtomcrypt/src/pk/ecc/ecc_make_key.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,12 +17,12 @@ /** @file ecc_make_key.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC /** - Make a new ECC key + Make a new ECC key @param prng An active PRNG state @param wprng The index of the PRNG you wish to use @param keysize The keysize for the new key (in octets from 20 to 65 bytes) @@ -124,7 +122,7 @@ ERR_BUF: } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_shared_secret.c b/libtomcrypt/src/pk/ecc/ecc_shared_secret.c index 5aece5e..d18a205 100644 --- a/libtomcrypt/src/pk/ecc/ecc_shared_secret.c +++ b/libtomcrypt/src/pk/ecc/ecc_shared_secret.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ecc_shared_secret.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC @@ -89,7 +87,7 @@ done: } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_sign_hash.c b/libtomcrypt/src/pk/ecc/ecc_sign_hash.c index 0ef7e2b..bae0c00 100644 --- a/libtomcrypt/src/pk/ecc/ecc_sign_hash.c +++ b/libtomcrypt/src/pk/ecc/ecc_sign_hash.c @@ -5,42 +5,26 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ -/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b - * - * All curves taken from NIST recommendation paper of July 1999 - * Available at http://csrc.nist.gov/cryptval/dss.htm - */ #include "tomcrypt.h" +#ifdef LTC_MECC + /** @file ecc_sign_hash.c ECC Crypto, Tom St Denis */ -#if defined(LTC_MECC) && defined(LTC_DER) - -/** - Sign a message digest - @param in The message digest to sign - @param inlen The length of the digest - @param out [out] The destination for the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param key A private ECC key - @return CRYPT_OK if successful -*/ -int ecc_sign_hash(const unsigned char *in, unsigned long inlen, +static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, ecc_key *key) + prng_state *prng, int wprng, ecc_key *key, int sigformat) { ecc_key pubkey; void *r, *s, *e, *p; - int err; + int err, max_iterations = LTC_PK_MAX_RETRIES; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); @@ -61,16 +45,33 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, return err; } - /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) { return err; } if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; } - if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto errnokey; } + + /* get the hash and load it as a bignum into 'e' */ + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > inlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i<pbytes; i++) { + buf[i] = ch; + ch = (in[i] << (8-shift_right)); + buf[i] = buf[i] ^ (in[i] >> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; } + } /* make up a key and export the public copy */ - for (;;) { + do { if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) { goto errnokey; } @@ -92,13 +93,30 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen, break; } } + } while (--max_iterations > 0); + + if (max_iterations == 0) { + goto errnokey; } - /* store as SEQUENCE { r, s -- integer } */ + if (sigformat == 1) { + /* RFC7518 format */ + if (*outlen < 2*pbytes) { err = CRYPT_MEM; goto errnokey; } + zeromem(out, 2*pbytes); + i = mp_unsigned_bin_size(r); + if ((err = mp_to_unsigned_bin(r, out + (pbytes - i))) != CRYPT_OK) { goto errnokey; } + i = mp_unsigned_bin_size(s); + if ((err = mp_to_unsigned_bin(s, out + (2*pbytes - i))) != CRYPT_OK) { goto errnokey; } + *outlen = 2*pbytes; + err = CRYPT_OK; + } + else { + /* store as ASN.1 SEQUENCE { r, s -- integer } */ err = der_encode_sequence_multi(out, outlen, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, LTC_ASN1_EOL, 0UL, NULL); + } goto errnokey; error: ecc_free(&pubkey); @@ -107,8 +125,44 @@ errnokey: return err; } +/** + Sign a message digest + @param in The message digest to sign + @param inlen The length of the digest + @param out [out] The destination for the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param key A private ECC key + @return CRYPT_OK if successful +*/ +int ecc_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_key *key) +{ + return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 0); +} + +/** + Sign a message digest in RFC7518 format + @param in The message digest to sign + @param inlen The length of the digest + @param out [out] The destination for the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param key A private ECC key + @return CRYPT_OK if successful +*/ +int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_key *key) +{ + return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 1); +} + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_sizes.c b/libtomcrypt/src/pk/ecc/ecc_sizes.c index b02a9f9..7c311fe 100644 --- a/libtomcrypt/src/pk/ecc/ecc_sizes.c +++ b/libtomcrypt/src/pk/ecc/ecc_sizes.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ecc_sizes.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC @@ -42,7 +40,7 @@ void ecc_sizes(int *low, int *high) } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_test.c b/libtomcrypt/src/pk/ecc/ecc_test.c index 873e70b..b6d54d1 100644 --- a/libtomcrypt/src/pk/ecc/ecc_test.c +++ b/libtomcrypt/src/pk/ecc/ecc_test.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ecc_test.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC @@ -89,7 +87,7 @@ done: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ecc_verify_hash.c b/libtomcrypt/src/pk/ecc/ecc_verify_hash.c index c10076b..e352789 100644 --- a/libtomcrypt/src/pk/ecc/ecc_verify_hash.c +++ b/libtomcrypt/src/pk/ecc/ecc_verify_hash.c @@ -5,52 +5,27 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ -/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b - * - * All curves taken from NIST recommendation paper of July 1999 - * Available at http://csrc.nist.gov/cryptval/dss.htm - */ #include "tomcrypt.h" +#ifdef LTC_MECC + /** @file ecc_verify_hash.c ECC Crypto, Tom St Denis */ -#if defined(LTC_MECC) && defined(LTC_DER) - -/* verify - * - * w = s^-1 mod n - * u1 = xw - * u2 = rw - * X = u1*G + u2*Q - * v = X_x1 mod n - * accept if v == r - */ - -/** - Verify an ECC signature - @param sig The signature to verify - @param siglen The length of the signature (octets) - @param hash The hash (message digest) that was signed - @param hashlen The length of the hash (octets) - @param stat Result of signature, 1==valid, 0==invalid - @param key The corresponding public ECC key - @return CRYPT_OK if successful (even if the signature is not valid) -*/ -int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, +static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, - int *stat, ecc_key *key) + int *stat, ecc_key *key, int sigformat) { ecc_point *mG, *mQ; void *r, *s, *v, *w, *u1, *u2, *e, *p, *m; void *mp; int err; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; LTC_ARGCHK(sig != NULL); LTC_ARGCHK(hash != NULL); @@ -79,12 +54,22 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, goto error; } - /* parse header */ + if (sigformat == 1) { + /* RFC7518 format */ + if ((siglen % 2) == 1) { + err = CRYPT_INVALID_PACKET; + goto error; + } + i = siglen / 2; + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } + } + else { + /* ASN.1 format */ if ((err = der_decode_sequence_multi(sig, siglen, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto error; + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; } } /* get the order */ @@ -99,8 +84,24 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, goto error; } - /* read hash */ - if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != CRYPT_OK) { goto error; } + /* read hash - truncate if needed */ + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > hashlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i<pbytes; i++) { + buf[i] = ch; + ch = (hash[i] << (8-shift_right)); + buf[i] = buf[i] ^ (hash[i] >> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } + } /* w = s^-1 mod n */ if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } @@ -158,8 +159,42 @@ error: return err; } +/** + Verify an ECC signature + @param sig The signature to verify + @param siglen The length of the signature (octets) + @param hash The hash (message digest) that was signed + @param hashlen The length of the hash (octets) + @param stat Result of signature, 1==valid, 0==invalid + @param key The corresponding public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, ecc_key *key) +{ + return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 0); +} + +/** + Verify an ECC signature in RFC7518 format + @param sig The signature to verify + @param siglen The length of the signature (octets) + @param hash The hash (message digest) that was signed + @param hashlen The length of the hash (octets) + @param stat Result of signature, 1==valid, 0==invalid + @param key The corresponding public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, ecc_key *key) +{ + return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 1); +} + #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c b/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c index 4a02068..057a899 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,14 +17,14 @@ /** @file ltc_ecc_is_valid_idx.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC /** Returns whether an ECC idx is valid or not @param n The idx number to check @return 1 if valid, 0 if not -*/ +*/ int ltc_ecc_is_valid_idx(int n) { int x; @@ -40,7 +38,7 @@ int ltc_ecc_is_valid_idx(int n) } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_map.c b/libtomcrypt/src/pk/ecc/ltc_ecc_map.c index 4f3ec09..c745f29 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_map.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_map.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ltc_ecc_map.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC @@ -40,7 +38,7 @@ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp) LTC_ARGCHK(mp != NULL); if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) { - return CRYPT_MEM; + return err; } /* first map z back to normal */ @@ -48,7 +46,7 @@ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp) /* get 1/z */ if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; } - + /* get 1/z^2 and 1/z^3 */ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; } @@ -70,7 +68,7 @@ done: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c b/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c index a6d1aab..cef1844 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ltc_ecc_mul2add.c ECC Crypto, Shamir's Trick, Tom St Denis -*/ +*/ #ifdef LTC_MECC @@ -31,9 +29,9 @@ @param B Second point to multiply @param kB What to multiple B by @param C [out] Destination point (can overlap with A or B - @param modulus Modulus for curve + @param modulus Modulus for curve @return CRYPT_OK on success -*/ +*/ int ltc_ecc_mul2add(ecc_point *A, void *kA, ecc_point *B, void *kB, ecc_point *C, @@ -44,7 +42,7 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA, unsigned char *tA, *tB; int err, first; void *mp, *mu; - + /* argchks */ LTC_ARGCHK(A != NULL); LTC_ARGCHK(B != NULL); @@ -93,16 +91,16 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA, } } - /* init montgomery reduction */ - if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto ERR_P; - } - if ((err = mp_init(&mu)) != CRYPT_OK) { + } + if ((err = mp_init(&mu)) != CRYPT_OK) { goto ERR_MP; - } - if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto ERR_MU; - } + } /* copy ones ... */ if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; } @@ -126,7 +124,7 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA, for (y = 1; y < 4; y++) { if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } } - } + } nibble = 3; first = 1; @@ -134,20 +132,21 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA, bitbufB = tB[0]; /* for every byte of the multiplicands */ - for (x = -1;; ) { + for (x = 0;; ) { /* grab a nibble */ if (++nibble == 4) { - ++x; if (x == len) break; + if (x == len) break; bitbufA = tA[x]; bitbufB = tB[x]; nibble = 0; + ++x; } /* extract two bits from both, shift/update */ nA = (bitbufA >> 6) & 0x03; nB = (bitbufB >> 6) & 0x03; - bitbufA = (bitbufA << 2) & 0xFF; - bitbufB = (bitbufB << 2) & 0xFF; + bitbufA = (bitbufA << 2) & 0xFF; + bitbufB = (bitbufB << 2) & 0xFF; /* if both zero, if first, continue */ if ((nA == 0) && (nB == 0) && (first == 1)) { @@ -202,6 +201,6 @@ ERR_T: #endif #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c index 4b11392..5834865 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,7 +17,7 @@ /** @file ltc_ecc_mulmod.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC #ifndef LTC_ECC_TIMING_RESISTANT @@ -28,7 +26,7 @@ #define WINSIZE 4 /** - Perform a point multiplication + Perform a point multiplication @param k The scalar to multiply by @param G The base point @param R [out] Destination for kG @@ -41,7 +39,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) ecc_point *tG, *M[8]; int i, j, err; void *mu, *mp; - unsigned long buf; + ltc_mp_digit buf; int first, bitbuf, bitcpy, bitcnt, mode, digidx; LTC_ARGCHK(k != NULL); @@ -62,7 +60,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) mp_clear(mu); return err; } - + /* alloc ram for window temps */ for (i = 0; i < 8; i++) { M[i] = ltc_ecc_new_point(); @@ -85,14 +83,14 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK) { goto done; } if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK) { goto done; } if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK) { goto done; } - } else { + } else { if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } } mp_clear(mu); mu = NULL; - + /* calc the M tab, which holds kG for k==8..15 */ /* M[0] == 8G */ if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; } @@ -217,6 +215,6 @@ done: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c index 25dcf0a..ca5c9d9 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -39,7 +37,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) ecc_point *tG, *M[3]; int i, j, err; void *mu, *mp; - unsigned long buf; + ltc_mp_digit buf; int bitcnt, mode, digidx; LTC_ARGCHK(k != NULL); @@ -159,7 +157,7 @@ done: #endif #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_points.c b/libtomcrypt/src/pk/ecc/ltc_ecc_points.c index 9be9eff..a63bdb5 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_points.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_points.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,13 +17,13 @@ /** @file ltc_ecc_points.c ECC Crypto, Tom St Denis -*/ +*/ #ifdef LTC_MECC /** Allocate a new ECC point - @return A newly allocated point or NULL on error + @return A newly allocated point or NULL on error */ ecc_point *ltc_ecc_new_point(void) { @@ -54,7 +52,7 @@ void ltc_ecc_del_point(ecc_point *p) } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c index c45a47b..9e22e10 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,9 +17,9 @@ /** @file ltc_ecc_projective_add_point.c ECC Crypto, Tom St Denis -*/ +*/ -#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC)) +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) /** Add two ECC points @@ -46,11 +44,11 @@ int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) { return err; } - + /* should we dbl instead? */ if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; } - if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) && + if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) && (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) { mp_clear_multi(t1, t2, x, y, z, NULL); @@ -144,7 +142,7 @@ int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void /* T1 = T1 * X */ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } - + /* X = Y*Y */ if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } @@ -158,7 +156,7 @@ int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } if (mp_cmp_d(t2, 0) == LTC_MP_LT) { if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } - } + } /* T2 = T2 - X */ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } if (mp_cmp_d(t2, 0) == LTC_MP_LT) { @@ -190,7 +188,7 @@ done: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c index ce31ccc..0c6b996 100644 --- a/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c +++ b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c @@ -5,8 +5,6 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b @@ -19,9 +17,9 @@ /** @file ltc_ecc_projective_dbl_point.c ECC Crypto, Tom St Denis -*/ +*/ -#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC)) +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) /** Double an ECC point @@ -62,7 +60,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void if (mp_cmp(R->z, modulus) != LTC_MP_LT) { if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; } } - + /* T2 = X - T1 */ if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } if (mp_cmp_d(t2, 0) == LTC_MP_LT) { @@ -121,7 +119,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } } - /* Y = Y - X */ + /* Y = Y - X */ if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } @@ -134,14 +132,14 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } } - + err = CRYPT_OK; done: mp_clear_multi(t1, t2, NULL); return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/katja/katja_decrypt_key.c b/libtomcrypt/src/pk/katja/katja_decrypt_key.c index e8819d9..72009b0 100644 --- a/libtomcrypt/src/pk/katja/katja_decrypt_key.c +++ b/libtomcrypt/src/pk/katja/katja_decrypt_key.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file katja_decrypt_key.c - Katja LTC_PKCS #1 OAEP Decryption, Tom St Denis -*/ + Katja PKCS #1 OAEP Decryption, Tom St Denis +*/ -#ifdef MKAT +#ifdef LTC_MKAT /** - (LTC_PKCS #1 v2.0) decrypt then OAEP depad + (PKCS #1 v2.0) decrypt then OAEP depad @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @@ -31,7 +29,7 @@ @return CRYPT_OK if succcessul (even if invalid) */ int katja_decrypt_key(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, + unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, int hash_idx, int *stat, katja_key *key) @@ -39,7 +37,7 @@ int katja_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmp; - + LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); @@ -52,7 +50,7 @@ int katja_decrypt_key(const unsigned char *in, unsigned long inlen, if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } - + /* get modulus len in bits */ modulus_bitlen = mp_count_bits( (key->N)); @@ -100,6 +98,6 @@ int katja_decrypt_key(const unsigned char *in, unsigned long inlen, -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/katja/katja_encrypt_key.c b/libtomcrypt/src/pk/katja/katja_encrypt_key.c index ef59e92..9ed72fb 100644 --- a/libtomcrypt/src/pk/katja/katja_encrypt_key.c +++ b/libtomcrypt/src/pk/katja/katja_encrypt_key.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file katja_encrypt_key.c - Katja LTC_PKCS-style OAEP encryption, Tom St Denis -*/ + Katja PKCS-style OAEP encryption, Tom St Denis +*/ -#ifdef MKAT +#ifdef LTC_MKAT /** - (LTC_PKCS #1 v2.0) OAEP pad then encrypt + (PKCS #1 v2.0) OAEP pad then encrypt @param in The plaintext @param inlen The length of the plaintext (octets) @param out [out] The ciphertext @@ -30,7 +28,7 @@ @param hash_idx The index of the desired hash @param key The Katja key to encrypt to @return CRYPT_OK if successful -*/ +*/ int katja_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, @@ -38,12 +36,12 @@ int katja_encrypt_key(const unsigned char *in, unsigned long inlen, { unsigned long modulus_bitlen, modulus_bytelen, x; int err; - + LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); - + /* valid prng and hash ? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; @@ -51,7 +49,7 @@ int katja_encrypt_key(const unsigned char *in, unsigned long inlen, if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } - + /* get modulus len in bits */ modulus_bitlen = mp_count_bits((key->N)); @@ -70,11 +68,11 @@ int katja_encrypt_key(const unsigned char *in, unsigned long inlen, /* OAEP pad the key */ x = *outlen; - if ((err = pkcs_1_oaep_encode(in, inlen, lparam, - lparamlen, modulus_bitlen, prng, prng_idx, hash_idx, + if ((err = pkcs_1_oaep_encode(in, inlen, lparam, + lparamlen, modulus_bitlen, prng, prng_idx, hash_idx, out, &x)) != CRYPT_OK) { return err; - } + } /* Katja exptmod the OAEP pad */ return katja_exptmod(out, x, out, outlen, PK_PUBLIC, key); @@ -82,6 +80,6 @@ int katja_encrypt_key(const unsigned char *in, unsigned long inlen, #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/katja/katja_export.c b/libtomcrypt/src/pk/katja/katja_export.c index 5f4d327..0412e65 100644 --- a/libtomcrypt/src/pk/katja/katja_export.c +++ b/libtomcrypt/src/pk/katja/katja_export.c @@ -5,17 +5,15 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file katja_export.c - Export Katja LTC_PKCS-style keys, Tom St Denis -*/ + Export Katja PKCS-style keys, Tom St Denis +*/ -#ifdef MKAT +#ifdef LTC_MKAT /** This will export either an KatjaPublicKey or KatjaPrivateKey @@ -24,7 +22,7 @@ @param type The type of exported key (PK_PRIVATE or PK_PUBLIC) @param key The Katja key to export @return CRYPT_OK if successful -*/ +*/ int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key *key) { int err; @@ -41,35 +39,35 @@ int katja_export(unsigned char *out, unsigned long *outlen, int type, katja_key if (type == PK_PRIVATE) { /* private key */ - /* output is + /* output is Version, n, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p, pq */ - if ((err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &zero, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, + if ((err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, - LTC_ASN1_INTEGER, 1UL, key->pq, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_INTEGER, 1UL, key->pq, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { return err; } - + /* clear zero and return */ return CRYPT_OK; } else { /* public key */ - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_INTEGER, 1UL, key->N, + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_EOL, 0UL, NULL); } } #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/katja/katja_exptmod.c b/libtomcrypt/src/pk/katja/katja_exptmod.c index 5df8908..afc847f 100644 --- a/libtomcrypt/src/pk/katja/katja_exptmod.c +++ b/libtomcrypt/src/pk/katja/katja_exptmod.c @@ -5,28 +5,26 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file katja_exptmod.c - Katja LTC_PKCS-style exptmod, Tom St Denis -*/ + Katja PKCS-style exptmod, Tom St Denis +*/ -#ifdef MKAT +#ifdef LTC_MKAT -/** - Compute an RSA modular exponentiation +/** + Compute an RSA modular exponentiation @param in The input data to send into RSA @param inlen The length of the input (octets) - @param out [out] The destination + @param out [out] The destination @param outlen [in/out] The max size and resulting size of the output @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC - @param key The RSA key to use + @param key The RSA key to use @return CRYPT_OK if successful -*/ +*/ int katja_exptmod(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int which, katja_key *key) @@ -39,7 +37,7 @@ int katja_exptmod(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); - + /* is the key of the right type for the operation? */ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) { return CRYPT_PK_NOT_PRIVATE; @@ -110,6 +108,6 @@ done: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/katja/katja_free.c b/libtomcrypt/src/pk/katja/katja_free.c index c5a46af..117bbf4 100644 --- a/libtomcrypt/src/pk/katja/katja_free.c +++ b/libtomcrypt/src/pk/katja/katja_free.c @@ -5,17 +5,15 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file katja_free.c Free an Katja key, Tom St Denis -*/ +*/ -#ifdef MKAT +#ifdef LTC_MKAT /** Free an Katja key from memory @@ -30,6 +28,6 @@ void katja_free(katja_key *key) #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/katja/katja_import.c b/libtomcrypt/src/pk/katja/katja_import.c index 425f498..98357c0 100644 --- a/libtomcrypt/src/pk/katja/katja_import.c +++ b/libtomcrypt/src/pk/katja/katja_import.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file katja_import.c - Import a LTC_PKCS-style Katja key, Tom St Denis -*/ + Import a PKCS-style Katja key, Tom St Denis +*/ -#ifdef MKAT +#ifdef LTC_MKAT /** - Import an KatjaPublicKey or KatjaPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1] + Import an KatjaPublicKey or KatjaPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1] @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @@ -34,29 +32,29 @@ int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key) LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ - if ((err = mp_init_multi(&zero, &key->d, &key->N, &key->dQ, + if ((err = mp_init_multi(&zero, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, &key->pq, NULL)) != CRYPT_OK) { return err; } - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, key->N, + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) { /* it's a private key */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, zero, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, zero, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, - LTC_ASN1_INTEGER, 1UL, key->pq, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_INTEGER, 1UL, key->pq, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } @@ -76,6 +74,6 @@ LBL_ERR: #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/katja/katja_make_key.c b/libtomcrypt/src/pk/katja/katja_make_key.c index eec8e98..6f83bcc 100644 --- a/libtomcrypt/src/pk/katja/katja_make_key.c +++ b/libtomcrypt/src/pk/katja/katja_make_key.c @@ -5,19 +5,17 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file katja_make_key.c Katja key generation, Tom St Denis -*/ +*/ -#ifdef MKAT +#ifdef LTC_MKAT -/** +/** Create a Katja key @param prng An active PRNG state @param wprng The index of the PRNG desired @@ -29,7 +27,7 @@ int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key) { void *p, *q, *tmp1, *tmp2; int err; - + LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); @@ -68,7 +66,7 @@ int katja_make_key(prng_state *prng, int wprng, int size, katja_key *key) if ((err = mp_copy( p, key->p)) != CRYPT_OK) { goto error2; } if ((err = mp_copy( q, key->q)) != CRYPT_OK) { goto error2; } if ((err = mp_mul(key->p, key->q, key->pq)) != CRYPT_OK) { goto error2; } /* tmp1 = pq */ - if ((err = mp_mul(key->pq, key->p, key->N)) != CRYPT_OK) { goto error2; } /* N = p^2q */ + if ((err = mp_mul(key->pq, key->p, key->N)) != CRYPT_OK) { goto error2; } /* N = p^2q */ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto error2; } /* tmp1 = q-1 */ if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto error2; } /* tmp2 = p-1 */ if ((err = mp_lcm(tmp1, tmp2, key->d)) != CRYPT_OK) { goto error2; } /* tmp1 = lcd(p-1,q-1) */ @@ -96,6 +94,6 @@ done: #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c index 2d9df75..5324c1e 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c @@ -5,14 +5,12 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -/** +/** @file pkcs_1_i2osp.c - Integer to Octet I2OSP, Tom St Denis + Integer to Octet I2OSP, Tom St Denis */ #ifdef LTC_PKCS_1 @@ -22,7 +20,7 @@ */ /** - LTC_PKCS #1 Integer to binary + PKCS #1 Integer to binary @param n The integer to store @param modulus_len The length of the RSA modulus @param out [out] The destination for the integer @@ -46,6 +44,6 @@ int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out) #endif /* LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c index af8f7e2..c6283ca 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c @@ -5,23 +5,21 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -/** +/** @file pkcs_1_mgf1.c - The Mask Generation Function (MGF1) for LTC_PKCS #1, Tom St Denis + The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis */ #ifdef LTC_PKCS_1 /** - Perform LTC_PKCS #1 MGF1 (internal) + Perform PKCS #1 MGF1 (internal) + @param hash_idx The index of the hash desired @param seed The seed for MGF1 @param seedlen The length of the seed - @param hash_idx The index of the hash desired @param mask [out] The destination @param masklen The length of the mask desired @return CRYPT_OK if successful @@ -35,12 +33,12 @@ int pkcs_1_mgf1(int hash_idx, int err; hash_state *md; unsigned char *buf; - + LTC_ARGCHK(seed != NULL); LTC_ARGCHK(mask != NULL); /* ensure valid hash */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } @@ -103,6 +101,6 @@ LBL_ERR: #endif /* LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c index 9ac9976..27c9245 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -/** +/** @file pkcs_1_oaep_decode.c - OAEP Padding for LTC_PKCS #1, Tom St Denis + OAEP Padding for PKCS #1, Tom St Denis */ #ifdef LTC_PKCS_1 /** - LTC_PKCS #1 v2.00 OAEP decode + PKCS #1 v2.00 OAEP decode @param msg The encoded data to decode @param msglen The length of the encoded data (octets) @param lparam The session or system data (can be NULL) @@ -28,7 +26,7 @@ @param out [out] Destination of decoding @param outlen [in/out] The max size and resulting size of the decoding @param res [out] Result of decoding, 1==valid, 0==invalid - @return CRYPT_OK if successful (even if invalid) + @return CRYPT_OK if successful */ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, @@ -38,7 +36,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, { unsigned char *DB, *seed, *mask; unsigned long hLen, x, y, modulus_len; - int err; + int err, ret; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(out != NULL); @@ -47,9 +45,9 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, /* default to invalid packet */ *res = 0; - + /* test valid hash */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[hash_idx].hashsize; @@ -78,17 +76,18 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, } /* ok so it's now in the form - - 0x00 || maskedseed || maskedDB - + + 0x00 || maskedseed || maskedDB + 1 || hLen || modulus_len - hLen - 1 - + */ + ret = CRYPT_OK; + /* must have leading 0x00 byte */ if (msg[0] != 0x00) { - err = CRYPT_OK; - goto LBL_ERR; + ret = CRYPT_INVALID_PACKET; } /* now read the masked seed */ @@ -100,7 +99,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, XMEMCPY(DB, msg + x, modulus_len - hLen - 1); x += modulus_len - hLen - 1; - /* compute MGF1 of maskedDB (hLen) */ + /* compute MGF1 of maskedDB (hLen) */ if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } @@ -117,7 +116,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { - DB[y] ^= mask[y]; + DB[y] ^= mask[y]; } /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ @@ -136,9 +135,8 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, } /* compare the lhash'es */ - if (XMEMCMP(seed, DB, hLen) != 0) { - err = CRYPT_OK; - goto LBL_ERR; + if (XMEM_NEQ(seed, DB, hLen) != 0) { + ret = CRYPT_INVALID_PACKET; } /* now zeroes before a 0x01 */ @@ -146,28 +144,26 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, /* step... */ } - /* error out if wasn't 0x01 */ + /* error if wasn't 0x01 */ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { - err = CRYPT_INVALID_PACKET; - goto LBL_ERR; + ret = CRYPT_INVALID_PACKET; } /* rest is the message (and skip 0x01) */ if ((modulus_len - hLen - 1 - ++x) > *outlen) { - *outlen = modulus_len - hLen - 1 - x; - err = CRYPT_BUFFER_OVERFLOW; - goto LBL_ERR; + ret = CRYPT_INVALID_PACKET; } - /* copy message */ - *outlen = modulus_len - hLen - 1 - x; - XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); - x += modulus_len - hLen - 1; + if (ret == CRYPT_OK) { + /* copy message */ + *outlen = modulus_len - hLen - 1 - x; + XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); - /* valid packet */ - *res = 1; + /* valid packet */ + *res = 1; + } + err = ret; - err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); @@ -184,6 +180,6 @@ LBL_ERR: #endif /* LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c index 4403477..5042946 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file pkcs_1_oaep_encode.c - OAEP Padding for LTC_PKCS #1, Tom St Denis + OAEP Padding for PKCS #1, Tom St Denis */ #ifdef LTC_PKCS_1 /** - LTC_PKCS #1 v2.00 OAEP encode + PKCS #1 v2.00 OAEP encode @param msg The data to encode @param msglen The length of the data to encode (octets) @param lparam A session or system parameter (can be NULL) @@ -46,7 +44,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, LTC_ARGCHK(outlen != NULL); /* test valid hash */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } @@ -120,10 +118,10 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { - DB[y] ^= mask[y]; + DB[y] ^= mask[y]; } - /* compute MGF1 of maskedDB (hLen) */ + /* compute MGF1 of maskedDB (hLen) */ if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } @@ -149,7 +147,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, x += modulus_len - hLen - 1; *outlen = x; - + err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK @@ -168,6 +166,6 @@ LBL_ERR: #endif /* LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c index 2df7574..743c70b 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c @@ -5,14 +5,12 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -/** +/** @file pkcs_1_os2ip.c - Octet to Integer OS2IP, Tom St Denis + Octet to Integer OS2IP, Tom St Denis */ #ifdef LTC_PKCS_1 @@ -31,6 +29,6 @@ int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen) #endif /* LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c index 222048c..8e112a1 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -/** +/** @file pkcs_1_pss_decode.c - LTC_PKCS #1 PSS Signature Padding, Tom St Denis + PKCS #1 PSS Signature Padding, Tom St Denis */ #ifdef LTC_PKCS_1 /** - LTC_PKCS #1 v2.00 PSS decode + PKCS #1 v2.00 PSS decode @param msghash The hash to verify @param msghashlen The length of the hash (octets) @param sig The signature data (encoded data) @@ -51,11 +49,12 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, } hLen = hash_descriptor[hash_idx].hashsize; + modulus_bitlen--; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ - if ((saltlen > modulus_len) || - (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) { + if ((saltlen > modulus_len) || + (modulus_len < hLen + saltlen + 2)) { return CRYPT_PK_INVALID_SIZE; } @@ -93,10 +92,10 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, /* copy out the hash */ XMEMCPY(hash, sig + x, hLen); - x += hLen; + /* x += hLen; */ /* check the MSB */ - if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) { + if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen)))) != 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } @@ -110,9 +109,9 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } - + /* now clear the first byte [make sure smaller than modulus] */ - DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); + DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen)); /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ @@ -149,17 +148,17 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, } /* mask == hash means valid signature */ - if (XMEMCMP(mask, hash, hLen) == 0) { + if (XMEM_NEQ(mask, hash, hLen) == 0) { *res = 1; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK - zeromem(DB, modulus_len); - zeromem(mask, modulus_len); - zeromem(salt, modulus_len); - zeromem(hash, modulus_len); + zeromem(DB, modulus_len); + zeromem(mask, modulus_len); + zeromem(salt, modulus_len); + zeromem(hash, modulus_len); #endif XFREE(hash); @@ -172,6 +171,6 @@ LBL_ERR: #endif /* LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c index b22a99f..c795114 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -/** +/** @file pkcs_1_pss_encode.c - LTC_PKCS #1 PSS Signature Padding, Tom St Denis + PKCS #1 PSS Signature Padding, Tom St Denis */ #ifdef LTC_PKCS_1 /** - LTC_PKCS #1 v2.00 Signature Encoding + PKCS #1 v2.00 Signature Encoding @param msghash The hash to encode @param msghashlen The length of the hash (octets) @param saltlen The length of the salt desired (octets) @@ -31,7 +29,7 @@ @return CRYPT_OK if successful */ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, prng_state *prng, + unsigned long saltlen, prng_state *prng, int prng_idx, int hash_idx, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen) @@ -54,6 +52,7 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, } hLen = hash_descriptor[hash_idx].hashsize; + modulus_bitlen--; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ @@ -115,7 +114,7 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, x += modulus_len - saltlen - hLen - 2; DB[x++] = 0x01; XMEMCPY(DB + x, salt, saltlen); - x += saltlen; + /* x += saltlen; */ /* generate mask of length modulus_len - hLen - 1 from hash */ if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { @@ -147,17 +146,17 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, out[y] = 0xBC; /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ - out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)); + out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen); /* store output size */ *outlen = modulus_len; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK - zeromem(DB, modulus_len); - zeromem(mask, modulus_len); - zeromem(salt, modulus_len); - zeromem(hash, modulus_len); + zeromem(DB, modulus_len); + zeromem(mask, modulus_len); + zeromem(salt, modulus_len); + zeromem(hash, modulus_len); #endif XFREE(hash); @@ -170,6 +169,6 @@ LBL_ERR: #endif /* LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c index 8345601..94e1b2a 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c @@ -5,19 +5,17 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file pkcs_1_v1_5_decode.c * - * LTC_PKCS #1 v1.5 Padding. (Andreas Lange) + * PKCS #1 v1.5 Padding. (Andreas Lange) */ #ifdef LTC_PKCS_1 -/** @brief LTC_PKCS #1 v1.5 decode. +/** @brief PKCS #1 v1.5 decode. * * @param msg The encoded data to decode * @param msglen The length of the encoded data (octets) @@ -27,13 +25,13 @@ * @param outlen [in/out] The max size and resulting size of the decoding * @param is_valid [out] Boolean whether the padding was valid * - * @return CRYPT_OK if successful (even if invalid) + * @return CRYPT_OK if successful */ -int pkcs_1_v1_5_decode(const unsigned char *msg, +int pkcs_1_v1_5_decode(const unsigned char *msg, unsigned long msglen, int block_type, unsigned long modulus_bitlen, - unsigned char *out, + unsigned char *out, unsigned long *outlen, int *is_valid) { @@ -51,26 +49,25 @@ int pkcs_1_v1_5_decode(const unsigned char *msg, return CRYPT_PK_INVALID_SIZE; } + result = CRYPT_OK; + /* separate encoded message */ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) { result = CRYPT_INVALID_PACKET; - goto bail; } - if (block_type == LTC_LTC_PKCS_1_EME) { + if (block_type == LTC_PKCS_1_EME) { for (i = 2; i < modulus_len; i++) { /* separator */ if (msg[i] == 0x00) { break; } } ps_len = i++ - 2; - if ((i >= modulus_len) || (ps_len < 8)) { - /* There was no octet with hexadecimal value 0x00 to separate ps from m, - * or the length of ps is less than 8 octets. + if (i >= modulus_len) { + /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ result = CRYPT_INVALID_PACKET; - goto bail; } } else { for (i = 2; i < modulus_len - 1; i++) { @@ -81,30 +78,35 @@ int pkcs_1_v1_5_decode(const unsigned char *msg, if (msg[i] != 0) { /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ result = CRYPT_INVALID_PACKET; - goto bail; } ps_len = i - 2; } + if (ps_len < 8) + { + /* The length of ps is less than 8 octets. + */ + result = CRYPT_INVALID_PACKET; + } + if (*outlen < (msglen - (2 + ps_len + 1))) { - *outlen = msglen - (2 + ps_len + 1); - result = CRYPT_BUFFER_OVERFLOW; - goto bail; + result = CRYPT_INVALID_PACKET; } - *outlen = (msglen - (2 + ps_len + 1)); - XMEMCPY(out, &msg[2 + ps_len + 1], *outlen); + if (result == CRYPT_OK) { + *outlen = (msglen - (2 + ps_len + 1)); + XMEMCPY(out, &msg[2 + ps_len + 1], *outlen); + + /* valid packet */ + *is_valid = 1; + } - /* valid packet */ - *is_valid = 1; - result = CRYPT_OK; -bail: return result; } /* pkcs_1_v1_5_decode */ #endif /* #ifdef LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c b/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c index 1c35069..dd92c64 100644 --- a/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c +++ b/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c @@ -5,38 +5,36 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /*! \file pkcs_1_v1_5_encode.c * - * LTC_PKCS #1 v1.5 Padding (Andreas Lange) + * PKCS #1 v1.5 Padding (Andreas Lange) */ #ifdef LTC_PKCS_1 -/*! \brief LTC_PKCS #1 v1.5 encode. +/*! \brief PKCS #1 v1.5 encode. * * \param msg The data to encode * \param msglen The length of the data to encode (octets) * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) * \param modulus_bitlen The bit length of the RSA modulus - * \param prng An active PRNG state (only for LTC_LTC_PKCS_1_EME) - * \param prng_idx The index of the PRNG desired (only for LTC_LTC_PKCS_1_EME) + * \param prng An active PRNG state (only for LTC_PKCS_1_EME) + * \param prng_idx The index of the PRNG desired (only for LTC_PKCS_1_EME) * \param out [out] The destination for the encoded data * \param outlen [in/out] The max size and resulting size of the encoded data * * \return CRYPT_OK if successful */ -int pkcs_1_v1_5_encode(const unsigned char *msg, +int pkcs_1_v1_5_encode(const unsigned char *msg, unsigned long msglen, int block_type, unsigned long modulus_bitlen, - prng_state *prng, + prng_state *prng, int prng_idx, - unsigned char *out, + unsigned char *out, unsigned long *outlen) { unsigned long modulus_len, ps_len, i; @@ -44,12 +42,12 @@ int pkcs_1_v1_5_encode(const unsigned char *msg, int result; /* valid block_type? */ - if ((block_type != LTC_LTC_PKCS_1_EMSA) && - (block_type != LTC_LTC_PKCS_1_EME)) { + if ((block_type != LTC_PKCS_1_EMSA) && + (block_type != LTC_PKCS_1_EME)) { return CRYPT_PK_INVALID_PADDING; } - if (block_type == LTC_LTC_PKCS_1_EME) { /* encryption padding, we need a valid PRNG */ + if (block_type == LTC_PKCS_1_EME) { /* encryption padding, we need a valid PRNG */ if ((result = prng_is_valid(prng_idx)) != CRYPT_OK) { return result; } @@ -72,7 +70,7 @@ int pkcs_1_v1_5_encode(const unsigned char *msg, ps = &out[2]; ps_len = modulus_len - msglen - 3; - if (block_type == LTC_LTC_PKCS_1_EME) { + if (block_type == LTC_PKCS_1_EME) { /* now choose a random ps */ if (prng_descriptor[prng_idx].read(ps, ps_len, prng) != ps_len) { result = CRYPT_ERROR_READPRNG; @@ -106,6 +104,6 @@ bail: #endif /* #ifdef LTC_PKCS_1 */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c b/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c index 31d841f..9e1bced 100644 --- a/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c +++ b/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_decrypt_key.c - RSA LTC_PKCS #1 Decryption, Tom St Denis and Andreas Lange + RSA PKCS #1 Decryption, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** - LTC_PKCS #1 decrypt then v1.5 or OAEP depad + PKCS #1 decrypt then v1.5 or OAEP depad @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @@ -26,7 +24,7 @@ @param lparam The system "lparam" value @param lparamlen The length of the lparam value (octets) @param hash_idx The index of the hash desired - @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5) + @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) @param stat [out] Result of the decryption, 1==valid, 0==invalid @param key The corresponding private RSA key @return CRYPT_OK if succcessul (even if invalid) @@ -51,12 +49,12 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, /* valid padding? */ - if ((padding != LTC_LTC_PKCS_1_V1_5) && - (padding != LTC_LTC_PKCS_1_OAEP)) { + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_OAEP)) { return CRYPT_PK_INVALID_PADDING; } - if (padding == LTC_LTC_PKCS_1_OAEP) { + if (padding == LTC_PKCS_1_OAEP) { /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; @@ -85,13 +83,13 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, return err; } - if (padding == LTC_LTC_PKCS_1_OAEP) { + if (padding == LTC_PKCS_1_OAEP) { /* now OAEP decode the packet */ err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx, out, outlen, stat); } else { - /* now LTC_PKCS #1 v1.5 depad the packet */ - err = pkcs_1_v1_5_decode(tmp, x, LTC_LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); + /* now PKCS #1 v1.5 depad the packet */ + err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); } XFREE(tmp); @@ -100,6 +98,6 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c b/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c index edb7e65..ef066d2 100644 --- a/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c +++ b/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_encrypt_key.c - RSA LTC_PKCS #1 encryption, Tom St Denis and Andreas Lange + RSA PKCS #1 encryption, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** - (LTC_PKCS #1 v2.0) OAEP pad then encrypt + (PKCS #1 v2.0) OAEP pad then encrypt @param in The plaintext @param inlen The length of the plaintext (octets) @param out [out] The ciphertext @@ -28,7 +26,7 @@ @param prng An active PRNG @param prng_idx The index of the desired prng @param hash_idx The index of the desired hash - @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5) + @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) @param key The RSA key to encrypt to @return CRYPT_OK if successful */ @@ -46,8 +44,8 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(key != NULL); /* valid padding? */ - if ((padding != LTC_LTC_PKCS_1_V1_5) && - (padding != LTC_LTC_PKCS_1_OAEP)) { + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_OAEP)) { return CRYPT_PK_INVALID_PADDING; } @@ -56,7 +54,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, return err; } - if (padding == LTC_LTC_PKCS_1_OAEP) { + if (padding == LTC_PKCS_1_OAEP) { /* valid hash? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; @@ -73,7 +71,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, return CRYPT_BUFFER_OVERFLOW; } - if (padding == LTC_LTC_PKCS_1_OAEP) { + if (padding == LTC_PKCS_1_OAEP) { /* OAEP pad the key */ x = *outlen; if ((err = pkcs_1_oaep_encode(in, inlen, lparam, @@ -82,21 +80,21 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, return err; } } else { - /* LTC_PKCS #1 v1.5 pad the key */ + /* PKCS #1 v1.5 pad the key */ x = *outlen; - if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_LTC_PKCS_1_EME, + if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME, modulus_bitlen, prng, prng_idx, out, &x)) != CRYPT_OK) { return err; } } - /* rsa exptmod the OAEP or LTC_PKCS #1 v1.5 pad */ + /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */ return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key); } #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_export.c b/libtomcrypt/src/pk/rsa/rsa_export.c index 40cb066..a9885de 100644 --- a/libtomcrypt/src/pk/rsa/rsa_export.c +++ b/libtomcrypt/src/pk/rsa/rsa_export.c @@ -5,29 +5,28 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_export.c - Export RSA LTC_PKCS keys, Tom St Denis -*/ + Export RSA PKCS keys, Tom St Denis +*/ #ifdef LTC_MRSA /** - This will export either an RSAPublicKey or RSAPrivateKey [defined in LTC_PKCS #1 v2.1] + This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1] @param out [out] Destination of the packet @param outlen [in/out] The max size and resulting size of the packet @param type The type of exported key (PK_PRIVATE or PK_PUBLIC) @param key The RSA key to export @return CRYPT_OK if successful -*/ +*/ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key) { unsigned long zero=0; + int err; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); @@ -39,31 +38,60 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key if (type == PK_PRIVATE) { /* private key */ - /* output is + /* output is Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p */ - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &zero, - LTC_ASN1_INTEGER, 1UL, key->N, + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, LTC_ASN1_EOL, 0UL, NULL); } else { /* public key */ - return der_encode_sequence_multi(out, outlen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, + unsigned long tmplen, *ptmplen; + unsigned char* tmp = NULL; + + if (type & PK_STD) { + tmplen = (mp_count_bits(key->N)/8)*2+8; + tmp = XMALLOC(tmplen); + ptmplen = &tmplen; + if (tmp == NULL) { + return CRYPT_MEM; + } + } + else { + tmp = out; + ptmplen = outlen; + } + + err = der_encode_sequence_multi(tmp, ptmplen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL); + + if ((err != CRYPT_OK) || !(type & PK_STD)) { + goto finish; + } + + err = der_encode_subject_public_key_info(out, outlen, + PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0); + +finish: + if (tmp != out) + XFREE(tmp); + return err; + } } #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_exptmod.c b/libtomcrypt/src/pk/rsa/rsa_exptmod.c index 101a766..37f62d1 100644 --- a/libtomcrypt/src/pk/rsa/rsa_exptmod.c +++ b/libtomcrypt/src/pk/rsa/rsa_exptmod.c @@ -5,41 +5,43 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_exptmod.c - RSA LTC_PKCS exptmod, Tom St Denis -*/ + RSA PKCS exptmod, Tom St Denis + Added RSA blinding --nmav +*/ #ifdef LTC_MRSA -/** - Compute an RSA modular exponentiation +/** + Compute an RSA modular exponentiation @param in The input data to send into RSA @param inlen The length of the input (octets) - @param out [out] The destination + @param out [out] The destination @param outlen [in/out] The max size and resulting size of the output @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC - @param key The RSA key to use + @param key The RSA key to use @return CRYPT_OK if successful -*/ +*/ int rsa_exptmod(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int which, rsa_key *key) { - void *tmp, *tmpa, *tmpb; + void *tmp, *tmpa, *tmpb; + #ifdef LTC_RSA_BLINDING + void *rnd, *rndi /* inverse of rnd */; + #endif unsigned long x; - int err; + int err, has_crt_parameters; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); - + /* is the key of the right type for the operation? */ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) { return CRYPT_PK_NOT_PRIVATE; @@ -51,8 +53,15 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, } /* init and copy into tmp */ - if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK) { return err; } - if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; } + if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, +#ifdef LTC_RSA_BLINDING + &rnd, &rndi, +#endif /* LTC_RSA_BLINDING */ + NULL)) != CRYPT_OK) + { return err; } + if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) + { goto error; } + /* sanity check on the input */ if (mp_cmp(key->N, tmp) == LTC_MP_LT) { @@ -62,19 +71,75 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, /* are we using the private exponent and is the key optimized? */ if (which == PK_PRIVATE) { - /* tmpa = tmp^dP mod p */ - if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; } - - /* tmpb = tmp^dQ mod q */ - if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; } - - /* tmp = (tmpa - tmpb) * qInv (mod p) */ - if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; } - if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; } - - /* tmp = tmpb + q * tmp */ - if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; } - if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; } + #ifdef LTC_RSA_BLINDING + /* do blinding */ + err = mp_rand(rnd, mp_get_digit_count(key->N)); + if (err != CRYPT_OK) { + goto error; + } + + /* rndi = 1/rnd mod N */ + err = mp_invmod(rnd, key->N, rndi); + if (err != CRYPT_OK) { + goto error; + } + + /* rnd = rnd^e */ + err = mp_exptmod( rnd, key->e, key->N, rnd); + if (err != CRYPT_OK) { + goto error; + } + + /* tmp = tmp*rnd mod N */ + err = mp_mulmod( tmp, rnd, key->N, tmp); + if (err != CRYPT_OK) { + goto error; + } + #endif /* LTC_RSA_BLINDING */ + + has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) && + (key->q != NULL) && (mp_get_digit_count(key->q) != 0) && + (key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) && + (key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) && + (key->qP != NULL) && (mp_get_digit_count(key->qP) != 0); + + if (!has_crt_parameters) { + /* + * In case CRT optimization parameters are not provided, + * the private key is directly used to exptmod it + */ + if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; } + } else { + /* tmpa = tmp^dP mod p */ + if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; } + + /* tmpb = tmp^dQ mod q */ + if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; } + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; } + + /* tmp = tmpb + q * tmp */ + if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; } + if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; } + } + + #ifdef LTC_RSA_BLINDING + /* unblind */ + err = mp_mulmod( tmp, rndi, key->N, tmp); + if (err != CRYPT_OK) { + goto error; + } + #endif + + #ifdef LTC_RSA_CRT_HARDENING + if (has_crt_parameters) { + if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; } + if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; } + } + #endif } else { /* exptmod it */ if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; } @@ -102,12 +167,16 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, /* clean up and return */ err = CRYPT_OK; error: - mp_clear_multi(tmp, tmpa, tmpb, NULL); + mp_clear_multi( +#ifdef LTC_RSA_BLINDING + rndi, rnd, +#endif /* LTC_RSA_BLINDING */ + tmpb, tmpa, tmp, NULL); return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_free.c b/libtomcrypt/src/pk/rsa/rsa_free.c index bb6daef..1e62f09 100644 --- a/libtomcrypt/src/pk/rsa/rsa_free.c +++ b/libtomcrypt/src/pk/rsa/rsa_free.c @@ -5,15 +5,13 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_free.c Free an RSA key, Tom St Denis -*/ +*/ #ifdef LTC_MRSA @@ -24,11 +22,11 @@ void rsa_free(rsa_key *key) { LTC_ARGCHKVD(key != NULL); - mp_clear_multi(key->e, key->d, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); + mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, NULL); } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_get_size.c b/libtomcrypt/src/pk/rsa/rsa_get_size.c new file mode 100644 index 0000000..8c90194 --- /dev/null +++ b/libtomcrypt/src/pk/rsa/rsa_get_size.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file rsa_get_size.c + Retrieve the size of an RSA key, Steffen Jaeckel. +*/ + +#ifdef LTC_MRSA + +/** + Retrieve the size in bytes of an RSA key. + @param key The RSA key + @return The size in bytes of the RSA key or INT_MAX on error. +*/ +int rsa_get_size(rsa_key *key) +{ + int ret = INT_MAX; + LTC_ARGCHK(key != NULL); + + if (key) + { + ret = mp_unsigned_bin_size(key->N); + } /* if */ + + return ret; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_import.c b/libtomcrypt/src/pk/rsa/rsa_import.c index 85c676b..84cd6f6 100644 --- a/libtomcrypt/src/pk/rsa/rsa_import.c +++ b/libtomcrypt/src/pk/rsa/rsa_import.c @@ -5,20 +5,18 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_import.c - Import a LTC_PKCS RSA key, Tom St Denis -*/ + Import a PKCS RSA key, Tom St Denis +*/ #ifdef LTC_MRSA /** - Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1] + Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1] @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @@ -28,87 +26,68 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; void *zero; - unsigned char *tmpbuf; - unsigned long t, x, y, z, tmpoid[16]; - ltc_asn1_list ssl_pubkey_hashoid[2]; - ltc_asn1_list ssl_pubkey[2]; + unsigned char *tmpbuf=NULL; + unsigned long tmpbuf_len; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ - if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, + if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) { return err; } /* see if the OpenSSL DER format RSA public key will work */ - tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8); + tmpbuf_len = inlen; + tmpbuf = XCALLOC(1, tmpbuf_len); if (tmpbuf == NULL) { err = CRYPT_MEM; goto LBL_ERR; } - /* this includes the internal hash ID and optional params (NULL in this case) */ - LTC_SET_ASN1(ssl_pubkey_hashoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0])); - LTC_SET_ASN1(ssl_pubkey_hashoid, 1, LTC_ASN1_NULL, NULL, 0); - - /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it - then proceed to convert bit to octet - */ - LTC_SET_ASN1(ssl_pubkey, 0, LTC_ASN1_SEQUENCE, &ssl_pubkey_hashoid, 2); - LTC_SET_ASN1(ssl_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8); - - if (der_decode_sequence(in, inlen, - ssl_pubkey, 2UL) == CRYPT_OK) { - - /* ok now we have to reassemble the BIT STRING to an OCTET STRING. Thanks OpenSSL... */ - for (t = y = z = x = 0; x < ssl_pubkey[1].size; x++) { - y = (y << 1) | tmpbuf[x]; - if (++z == 8) { - tmpbuf[t++] = (unsigned char)y; - y = 0; - z = 0; - } - } + err = der_decode_subject_public_key_info(in, inlen, + PKA_RSA, tmpbuf, &tmpbuf_len, + LTC_ASN1_NULL, NULL, 0); + + if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */ /* now it should be SEQUENCE { INTEGER, INTEGER } */ - if ((err = der_decode_sequence_multi(tmpbuf, t, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, + if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - XFREE(tmpbuf); goto LBL_ERR; } - XFREE(tmpbuf); key->type = PK_PUBLIC; - return CRYPT_OK; + err = CRYPT_OK; + goto LBL_FREE; } - XFREE(tmpbuf); - /* not SSL public key, try to match against LTC_PKCS #1 standards */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + /* not SSL public key, try to match against PKCS #1 standards */ + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_EOL, 0UL, NULL); + + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { goto LBL_ERR; } if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) { - if ((err = mp_init(&zero)) != CRYPT_OK) { + if ((err = mp_init(&zero)) != CRYPT_OK) { goto LBL_ERR; } /* it's a private key */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, zero, - LTC_ASN1_INTEGER, 1UL, key->N, + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, zero, + LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { mp_clear(zero); goto LBL_ERR; @@ -121,23 +100,30 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) goto LBL_ERR; } else { /* it's a public key and we lack e */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } key->type = PK_PUBLIC; } - return CRYPT_OK; + err = CRYPT_OK; + goto LBL_FREE; + LBL_ERR: mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); + +LBL_FREE: + if (tmpbuf != NULL) + XFREE(tmpbuf); + return err; } #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c b/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c new file mode 100644 index 0000000..8e15e06 --- /dev/null +++ b/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c @@ -0,0 +1,153 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file rsa_import_pkcs8.c + Import a PKCS RSA key +*/ + +#ifdef LTC_MRSA + +/* Public-Key Cryptography Standards (PKCS) #8: + * Private-Key Information Syntax Specification Version 1.2 + * https://tools.ietf.org/html/rfc5208 + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * where: + * - Version ::= INTEGER + * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * - PrivateKey ::= OCTET STRING + * - Attributes ::= SET OF Attribute + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData } + * where: + * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * - EncryptedData ::= OCTET STRING + */ + +/** + Import an RSAPublicKey or RSAPrivateKey in PKCS#8 format + @param in The packet to import from + @param inlen It's length (octets) + @param passwd The password for decrypting privkey (NOT SUPPORTED YET) + @param passwdlen Password's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *passwd, unsigned long passwdlen, + rsa_key *key) +{ + int err; + void *zero, *iter; + unsigned char *buf1 = NULL, *buf2 = NULL; + unsigned long buf1len, buf2len; + unsigned long oid[16]; + oid_st rsaoid; + ltc_asn1_list alg_seq[2], top_seq[3]; + ltc_asn1_list alg_seq_e[2], key_seq_e[2], top_seq_e[2]; + unsigned char *decrypted = NULL; + unsigned long decryptedlen; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* get RSA alg oid */ + err = pk_get_oid(PKA_RSA, &rsaoid); + if (err != CRYPT_OK) { goto LBL_NOFREE; } + + /* alloc buffers */ + buf1len = inlen; /* approx. */ + buf1 = XMALLOC(buf1len); + if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; } + buf2len = inlen; /* approx. */ + buf2 = XMALLOC(buf2len); + if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; } + + /* init key */ + err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, &zero, &iter, NULL); + if (err != CRYPT_OK) { goto LBL_FREE2; } + + /* try to decode encrypted priv key */ + LTC_SET_ASN1(key_seq_e, 0, LTC_ASN1_OCTET_STRING, buf1, buf1len); + LTC_SET_ASN1(key_seq_e, 1, LTC_ASN1_INTEGER, iter, 1UL); + LTC_SET_ASN1(alg_seq_e, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL); + LTC_SET_ASN1(alg_seq_e, 1, LTC_ASN1_SEQUENCE, key_seq_e, 2UL); + LTC_SET_ASN1(top_seq_e, 0, LTC_ASN1_SEQUENCE, alg_seq_e, 2UL); + LTC_SET_ASN1(top_seq_e, 1, LTC_ASN1_OCTET_STRING, buf2, buf2len); + err=der_decode_sequence(in, inlen, top_seq_e, 2UL); + if (err == CRYPT_OK) { + LTC_UNUSED_PARAM(passwd); + LTC_UNUSED_PARAM(passwdlen); + /* XXX: TODO encrypted pkcs8 not implemented yet */ + /* fprintf(stderr, "decrypt: iter=%ld salt.len=%ld encdata.len=%ld\n", mp_get_int(iter), key_seq_e[0].size, top_seq_e[1].size); */ + err = CRYPT_PK_INVALID_TYPE; + goto LBL_ERR; + } + else { + decrypted = (unsigned char *)in; + decryptedlen = inlen; + } + + /* try to decode unencrypted priv key */ + LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL); + LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL); + LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL); + LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL); + LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len); + err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL); + if (err != CRYPT_OK) { goto LBL_ERR; } + + /* check alg oid */ + if ((alg_seq[0].size != rsaoid.OIDlen) || + XMEMCMP(rsaoid.OID, alg_seq[0].data, rsaoid.OIDlen * sizeof(rsaoid.OID[0]))) { + err = CRYPT_PK_INVALID_TYPE; + goto LBL_ERR; + } + + err = der_decode_sequence_multi(buf1, top_seq[2].size, + LTC_ASN1_INTEGER, 1UL, zero, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->dP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_EOL, 0UL, NULL); + if (err != CRYPT_OK) { goto LBL_ERR; } + key->type = PK_PRIVATE; + err = CRYPT_OK; + goto LBL_FREE2; + +LBL_ERR: + rsa_free(key); +LBL_FREE2: + mp_clear_multi(iter, zero, NULL); + XFREE(buf2); +LBL_FREE1: + XFREE(buf1); +LBL_NOFREE: + return err; +} + +#endif /* LTC_MRSA */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_import_x509.c b/libtomcrypt/src/pk/rsa/rsa_import_x509.c new file mode 100644 index 0000000..0f2d5f1 --- /dev/null +++ b/libtomcrypt/src/pk/rsa/rsa_import_x509.c @@ -0,0 +1,118 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file rsa_import.c + Import an RSA key from a X.509 certificate, Steffen Jaeckel +*/ + +#ifdef LTC_MRSA + +/** + Import an RSA key from a X.509 certificate + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + unsigned char *tmpbuf; + unsigned long tmpbuf_len, tmp_inlen; + ltc_asn1_list *decoded_list = NULL, *l; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, + &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) { + return err; + } + + tmpbuf_len = inlen; + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + tmp_inlen = inlen; + if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) { + l = decoded_list; + /* Move 2 levels up in the tree + SEQUENCE + SEQUENCE + ... + */ + if (l->type == LTC_ASN1_SEQUENCE && l->child) { + l = l->child; + if (l->type == LTC_ASN1_SEQUENCE && l->child) { + l = l->child; + + err = CRYPT_ERROR; + + /* Move forward in the tree until we find this combination + ... + SEQUENCE + SEQUENCE + OBJECT IDENTIFIER 1.2.840.113549.1.1.1 + NULL + BIT STRING + */ + do { + /* The additional check for l->data is there to make sure + * we won't try to decode a list that has been 'shrunk' + */ + if (l->type == LTC_ASN1_SEQUENCE && l->data && l->child && + l->child->type == LTC_ASN1_SEQUENCE && l->child->child && + l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER && l->child->next && + l->child->next->type == LTC_ASN1_BIT_STRING) { + err = der_decode_subject_public_key_info(l->data, l->size, + PKA_RSA, tmpbuf, &tmpbuf_len, + LTC_ASN1_NULL, NULL, 0); + if (err == CRYPT_OK) { + /* now it should be SEQUENCE { INTEGER, INTEGER } */ + if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PUBLIC; + err = CRYPT_OK; + goto LBL_FREE; + } + } + l = l->next; + } while(l); + } + } + } + + +LBL_ERR: + rsa_free(key); + +LBL_FREE: + if (decoded_list) der_free_sequence_flexi(decoded_list); + if (tmpbuf != NULL) XFREE(tmpbuf); + + return err; +} + +#endif /* LTC_MRSA */ + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_make_key.c b/libtomcrypt/src/pk/rsa/rsa_make_key.c index d62e37e..c5c4c28 100644 --- a/libtomcrypt/src/pk/rsa/rsa_make_key.c +++ b/libtomcrypt/src/pk/rsa/rsa_make_key.c @@ -5,19 +5,17 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_make_key.c RSA key generation, Tom St Denis -*/ +*/ #ifdef LTC_MRSA -/** +/** Create an RSA key @param prng An active PRNG state @param wprng The index of the PRNG desired @@ -33,10 +31,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) LTC_ARGCHK(ltc_mp.name != NULL); LTC_ARGCHK(key != NULL); - - if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) { - return CRYPT_INVALID_KEYSIZE; - } + LTC_ARGCHK(size > 0); if ((e < 3) || ((e & 1) == 0)) { return CRYPT_INVALID_ARG; @@ -51,26 +46,26 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) } /* make primes p and q (optimization provided by Wayne Scott) */ - if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) { goto errkey; } /* tmp3 = e */ + if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) { goto cleanup; } /* tmp3 = e */ /* make prime "p" */ do { - if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; } - if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */ - if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(p-1, e) */ + if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */ + if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(p-1, e) */ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */ /* make prime "q" */ do { - if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto errkey; } - if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */ - if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = gcd(q-1, e) */ + if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */ + if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(q-1, e) */ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */ /* tmp1 = lcm(p-1, q-1) */ - if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */ + if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = p-1 */ /* tmp1 = q-1 (previous do/while loop) */ - if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = lcm(p-1, q-1) */ + if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */ /* make key */ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) { @@ -99,14 +94,14 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) err = CRYPT_OK; goto cleanup; errkey: - mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL); + rsa_free(key); cleanup: - mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL); + mp_clear_multi(tmp3, tmp2, tmp1, q, p, NULL); return err; } #endif -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_set.c b/libtomcrypt/src/pk/rsa/rsa_set.c new file mode 100644 index 0000000..0d540c4 --- /dev/null +++ b/libtomcrypt/src/pk/rsa/rsa_set.c @@ -0,0 +1,134 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + + +#ifdef LTC_MRSA + +/** + Import RSA key from raw numbers + + @param N RSA's N + @param Nlen RSA's N's length + @param e RSA's e + @param elen RSA's e's length + @param d RSA's d (only private key, NULL for public key) + @param dlen RSA's d's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_key(const unsigned char *N, unsigned long Nlen, + const unsigned char *e, unsigned long elen, + const unsigned char *d, unsigned long dlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(N != NULL); + LTC_ARGCHK(e != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL); + if (err != CRYPT_OK) return err; + + if ((err = mp_read_unsigned_bin(key->N , (unsigned char *)N , Nlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->e , (unsigned char *)e , elen)) != CRYPT_OK) { goto LBL_ERR; } + if (d && dlen) { + if ((err = mp_read_unsigned_bin(key->d , (unsigned char *)d , dlen)) != CRYPT_OK) { goto LBL_ERR; } + key->type = PK_PRIVATE; + } + else { + key->type = PK_PUBLIC; + } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +/** + Import factors of an RSA key from raw numbers + + Only for private keys. + + @param p RSA's p + @param plen RSA's p's length + @param q RSA's q + @param qlen RSA's q's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_factors(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(q != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + + if ((err = mp_read_unsigned_bin(key->p , (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->q , (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +/** + Import CRT parameters of an RSA key from raw numbers + + Only for private keys. + + @param dP RSA's dP + @param dPlen RSA's dP's length + @param dQ RSA's dQ + @param dQlen RSA's dQ's length + @param qP RSA's qP + @param qPlen RSA's qP's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, + const unsigned char *dQ, unsigned long dQlen, + const unsigned char *qP, unsigned long qPlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(dP != NULL); + LTC_ARGCHK(dQ != NULL); + LTC_ARGCHK(qP != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + + if ((err = mp_read_unsigned_bin(key->dP, (unsigned char *)dP, dPlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->dQ, (unsigned char *)dQ, dQlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->qP, (unsigned char *)qP, qPlen)) != CRYPT_OK) { goto LBL_ERR; } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +#endif /* LTC_MRSA */ + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_sign_hash.c b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c index 3b64095..05c7155 100644 --- a/libtomcrypt/src/pk/rsa/rsa_sign_hash.c +++ b/libtomcrypt/src/pk/rsa/rsa_sign_hash.c @@ -5,25 +5,23 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_sign_hash.c - RSA LTC_PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange + RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** - LTC_PKCS #1 pad then sign + PKCS #1 pad then sign @param in The hash to sign @param inlen The length of the hash to sign (octets) @param out [out] The signature @param outlen [in/out] The max size and resulting size of the signature - @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5) + @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) @param prng An active PRNG state @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @@ -47,15 +45,21 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(key != NULL); /* valid padding? */ - if ((padding != LTC_LTC_PKCS_1_V1_5) && (padding != LTC_LTC_PKCS_1_PSS)) { + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_PSS) && + (padding != LTC_PKCS_1_V1_5_NA1)) { return CRYPT_PK_INVALID_PADDING; } - if (padding == LTC_LTC_PKCS_1_PSS) { - /* valid prng and hash ? */ + if (padding == LTC_PKCS_1_PSS) { + /* valid prng ? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } + } + + if (padding != LTC_PKCS_1_V1_5_NA1) { + /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } @@ -71,7 +75,7 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, return CRYPT_BUFFER_OVERFLOW; } - if (padding == LTC_LTC_PKCS_1_PSS) { + if (padding == LTC_PKCS_1_PSS) { /* PSS pad the key */ x = *outlen; if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, @@ -79,48 +83,56 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, return err; } } else { - /* LTC_PKCS #1 v1.5 pad the hash */ + /* PKCS #1 v1.5 pad the hash */ unsigned char *tmpin; - ltc_asn1_list digestinfo[2], siginfo[2]; - /* not all hashes have OIDs... so sad */ - if (hash_descriptor[hash_idx].OIDlen == 0) { - return CRYPT_INVALID_ARG; - } + if (padding == LTC_PKCS_1_V1_5) { + ltc_asn1_list digestinfo[2], siginfo[2]; + /* not all hashes have OIDs... so sad */ + if (hash_descriptor[hash_idx].OIDlen == 0) { + return CRYPT_INVALID_ARG; + } - /* construct the SEQUENCE - SEQUENCE { - SEQUENCE {hashoid OID - blah NULL - } - hash OCTET STRING + /* construct the SEQUENCE + SEQUENCE { + SEQUENCE {hashoid OID + blah NULL + } + hash OCTET STRING + } + */ + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); + LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); + LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); + + /* allocate memory for the encoding */ + y = mp_unsigned_bin_size(key->N); + tmpin = XMALLOC(y); + if (tmpin == NULL) { + return CRYPT_MEM; } - */ - LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); - LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); - LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); - LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); - - /* allocate memory for the encoding */ - y = mp_unsigned_bin_size(key->N); - tmpin = XMALLOC(y); - if (tmpin == NULL) { - return CRYPT_MEM; - } - if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { - XFREE(tmpin); - return err; + if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { + XFREE(tmpin); + return err; + } + } else { + /* set the pointer and data-length to the input values */ + tmpin = (unsigned char *)in; + y = inlen; } x = *outlen; - if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_LTC_PKCS_1_EMSA, - modulus_bitlen, NULL, 0, - out, &x)) != CRYPT_OK) { + err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); + + if (padding == LTC_PKCS_1_V1_5) { XFREE(tmpin); + } + + if (err != CRYPT_OK) { return err; } - XFREE(tmpin); } /* RSA encode it */ @@ -129,6 +141,6 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c b/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c new file mode 100644 index 0000000..b217f94 --- /dev/null +++ b/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file rsa_sign_saltlen_get.c + Retrieve the maximum size of the salt, Steffen Jaeckel. +*/ + +#ifdef LTC_MRSA + +/** + Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature. + @param padding Type of padding (LTC_PKCS_1_PSS only) + @param hash_idx The index of the desired hash + @param key The RSA key + @return The maximum salt length in bytes or INT_MAX on error. +*/ +int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, rsa_key *key) +{ + int ret = INT_MAX; + LTC_ARGCHK(key != NULL); + + if ((hash_is_valid(hash_idx) == CRYPT_OK) && + (padding == LTC_PKCS_1_PSS)) + { + ret = rsa_get_size(key); + if (ret < INT_MAX) + { + ret -= (hash_descriptor[hash_idx].hashsize + 2); + } /* if */ + } /* if */ + + return ret; +} + +#endif + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/libtomcrypt/src/pk/rsa/rsa_verify_hash.c index fe83690..b584696 100644 --- a/libtomcrypt/src/pk/rsa/rsa_verify_hash.c +++ b/libtomcrypt/src/pk/rsa/rsa_verify_hash.c @@ -5,25 +5,23 @@ * * The library is free for all purposes without any express * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" /** @file rsa_verify_hash.c - RSA LTC_PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange + RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** - LTC_PKCS #1 de-sign then v1.5 or PSS depad + PKCS #1 de-sign then v1.5 or PSS depad @param sig The signature data @param siglen The length of the signature data (octets) @param hash The hash of the message that was signed @param hashlen The length of the hash of the message that was signed (octets) - @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5) + @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) @param hash_idx The index of the desired hash @param saltlen The length of the salt used during signature @param stat [out] The result of the signature comparison, 1==valid, 0==invalid @@ -50,12 +48,13 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, /* valid padding? */ - if ((padding != LTC_LTC_PKCS_1_V1_5) && - (padding != LTC_LTC_PKCS_1_PSS)) { + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_PSS) && + (padding != LTC_PKCS_1_V1_5_NA1)) { return CRYPT_PK_INVALID_PADDING; } - if (padding == LTC_LTC_PKCS_1_PSS) { + if (padding != LTC_PKCS_1_V1_5_NA1) { /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; @@ -90,21 +89,21 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, return CRYPT_INVALID_PACKET; } - if (padding == LTC_LTC_PKCS_1_PSS) { + if (padding == LTC_PKCS_1_PSS) { /* PSS decode and verify it */ - err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); + + if(modulus_bitlen%8 == 1){ + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat); + } + else{ + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); + } + } else { - /* LTC_PKCS #1 v1.5 decode it */ + /* PKCS #1 v1.5 decode it */ unsigned char *out; - unsigned long outlen, loid[16]; + unsigned long outlen; int decoded; - ltc_asn1_list digestinfo[2], siginfo[2]; - - /* not all hashes have OIDs... so sad */ - if (hash_descriptor[hash_idx].OIDlen == 0) { - err = CRYPT_INVALID_ARG; - goto bail_2; - } /* allocate temp buffer for decoded hash */ outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3; @@ -114,36 +113,63 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, goto bail_2; } - if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { - XFREE(out); + if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { + XFREE(out); goto bail_2; } - /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ - /* construct the SEQUENCE - SEQUENCE { - SEQUENCE {hashoid OID - blah NULL + if (padding == LTC_PKCS_1_V1_5) { + unsigned long loid[16], reallen; + ltc_asn1_list digestinfo[2], siginfo[2]; + + /* not all hashes have OIDs... so sad */ + if (hash_descriptor[hash_idx].OIDlen == 0) { + err = CRYPT_INVALID_ARG; + goto bail_2; + } + + /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ + /* construct the SEQUENCE + SEQUENCE { + SEQUENCE {hashoid OID + blah NULL + } + hash OCTET STRING + } + */ + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0])); + LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); + LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); + + if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) { + /* fallback to Legacy:missing NULL */ + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1); + if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) { + XFREE(out); + goto bail_2; } - hash OCTET STRING } - */ - LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0])); - LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); - LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); - LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); - - if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) { - XFREE(out); - goto bail_2; - } - /* test OID */ - if ((digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) && + if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + + /* test OID */ + if ((reallen == outlen) && + (digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) && (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) && - (siginfo[1].size == hashlen) && + (siginfo[1].size == hashlen) && (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) { - *stat = 1; + *stat = 1; + } + } else { + /* only check if the hash is equal */ + if ((hashlen == outlen) && + (XMEMCMP(out, hash, hashlen) == 0)) { + *stat = 1; + } } #ifdef LTC_CLEAN_STACK @@ -162,6 +188,6 @@ bail_2: #endif /* LTC_MRSA */ -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ |