From f2ebe2380fa2dc8014f4409ce509c4de13661d8d Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 1 Jan 2006 16:21:11 +0000 Subject: [PATCH] Added SILC_ASN1_SHORT_INT. --- CHANGES | 2 +- TODO | 5 ++++ lib/silcasn1/silcasn1.c | 4 ++- lib/silcasn1/silcasn1.h | 23 ++++++++++++++++ lib/silcasn1/silcasn1_decode.c | 32 ++++++++++++++++++++++ lib/silcasn1/silcasn1_encode.c | 44 +++++++++++++++++++++++++++--- lib/silcasn1/silcasn1_i.h | 3 +- lib/silcasn1/tests/test_silcasn1.c | 35 +++++++++++++++++++++++- lib/silccrypt/rsa.c | 5 ---- lib/silccrypt/silcpk.c | 6 +--- lib/silccrypt/silcpkcs1.c | 12 ++++---- 11 files changed, 147 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index 432bd167..d92c5e24 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -Sat Dec 30 22:54:21 EET 2005 Pekka Riikonen +Fri Dec 30 22:54:21 EET 2005 Pekka Riikonen * New SILC PKCS API enabling support for other public keys and certificates, lib/silccrypt/silcpkcs.[ch], silcpk.[ch]. diff --git a/TODO b/TODO index 3f5aa5cf..b455481c 100644 --- a/TODO +++ b/TODO @@ -175,6 +175,11 @@ lib/silcutil/silctime.[ch] ****DONE**** lib/silcmath ============ + o Import TFM. Talk to Tom to add the missing functions. Use TFM in + client and client library, but TMA in server, due to the significantly + increased memory consumption with TFM, and the rare need for public + key operations in server. + o The SILC MP API function must start returning indication of success and failure of the operation. diff --git a/lib/silcasn1/silcasn1.c b/lib/silcasn1/silcasn1.c index 007f1990..33be523f 100644 --- a/lib/silcasn1/silcasn1.c +++ b/lib/silcasn1/silcasn1.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2003 - 2005 Pekka Riikonen + Copyright (C) 2003 - 2006 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -94,6 +94,8 @@ const char *silc_asn1_tag_name(SilcAsn1Tag tag) return "set"; case SILC_ASN1_TAG_INTEGER: return "integer"; + case SILC_ASN1_TAG_SHORT_INTEGER: + return "short integer"; case SILC_ASN1_TAG_OID: return "oid"; case SILC_ASN1_TAG_BOOLEAN: diff --git a/lib/silcasn1/silcasn1.h b/lib/silcasn1/silcasn1.h index 26c03f38..51a7015c 100644 --- a/lib/silcasn1/silcasn1.h +++ b/lib/silcasn1/silcasn1.h @@ -698,6 +698,29 @@ SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...); #define SILC_ASN1_INT(x) SILC_ASN1_U1(INTEGER, x) #define SILC_ASN1_INT_T(o, t, x) SILC_ASN1_T1(INTEGER, o, t, x) +/****f* silcasn1/SilcASN1API/SILC_ASN1_SHORT_INT + * + * SYNOPSIS + * + * Encoding: + * SILC_ASN1_SHORT_INT(integer) + * SILC_ASN1_SHORT_INT_T(opts, tag, &integer) + * + * Decoding: + * SILC_ASN1_SHORT_INT(&integer) + * SILC_ASN1_SHORT_INT_T(opts, tag, &integer); + * + * DESCRIPTION + * + * Macro used to encode or decode short integer (32 bits). The + * integer type is SilcUInt32. + * + * The `opts' is SilcAsn1Options. The `tag' is a tag number. + * + ***/ +#define SILC_ASN1_SHORT_INT(x) SILC_ASN1_U1(SHORT_INTEGER, x) +#define SILC_ASN1_SHORT_INT_T(o, t, x) SILC_ASN1_T1(SHORT_INTEGER, o, t, x) + /****f* silcasn1/SilcASN1API/SILC_ASN1_ENUM * * SYNOPSIS diff --git a/lib/silcasn1/silcasn1_decode.c b/lib/silcasn1/silcasn1_decode.c index 8fdfef24..5fcfb4c7 100644 --- a/lib/silcasn1/silcasn1_decode.c +++ b/lib/silcasn1/silcasn1_decode.c @@ -310,6 +310,10 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, } } + /* Short integer is actually big integer, so handle it correctly */ + if (type == SILC_ASN1_TAG_SHORT_INTEGER && type == tag) + tag = SILC_ASN1_TAG_INTEGER; + /* Now decode a BER encoded block from the source buffer. It must be exactly the same user is expecting. */ ret = silc_ber_decode(src, &rclass, &renc, (SilcUInt32 *)&rtag, &rdata, @@ -483,6 +487,28 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, break; } + case SILC_ASN1_TAG_SHORT_INTEGER: + { + /* Short Integer */ + SilcMPInt z; + SILC_ASN1_VAD(asn1, opts, SilcUInt32, intval); + + if (rdata_len < 1) { + SILC_LOG_DEBUG(("Malformed integer value")); + SILC_ASN1_VA_FREE(opts, intval); + ret = FALSE; + goto fail; + } + + silc_stack_push(asn1->stack1, NULL); + silc_mp_sinit(asn1->stack1, &z); + silc_mp_bin2mp((unsigned char *)rdata, rdata_len, &z); + *(*intval) = silc_mp_get_ui(&z); + silc_mp_uninit(&z); + silc_stack_pop(asn1->stack1); + break; + } + case SILC_ASN1_TAG_OID: { /* Object identifier */ @@ -493,6 +519,7 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, if (rdata_len < 1) { SILC_LOG_DEBUG(("Malformed object identifier value")); + SILC_ASN1_VA_FREE(opts, oidstr); ret = FALSE; goto fail; } @@ -553,6 +580,7 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, if (rdata_len < 2) { SILC_LOG_DEBUG(("Malformed bit string value")); + SILC_ASN1_VA_FREE(opts, d); ret = FALSE; goto fail; } @@ -579,6 +607,7 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, if (rdata_len < 1) { SILC_LOG_DEBUG(("Malformed UTC time value")); + SILC_ASN1_VA_FREE(opts, t); ret = FALSE; goto fail; } @@ -600,6 +629,7 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, if (rdata_len < 1) { SILC_LOG_DEBUG(("Malformed generalized time value")); + SILC_ASN1_VA_FREE(opts, t); ret = FALSE; goto fail; } @@ -607,6 +637,7 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, /* Parse the time string */ if (!silc_time_generalized(rdata, *t)) { SILC_LOG_DEBUG(("Malformed generalized time value")); + SILC_ASN1_VA_FREE(opts, t); ret = FALSE; goto fail; } @@ -621,6 +652,7 @@ silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type, if (!silc_utf8_valid(rdata, rdata_len)) { SILC_LOG_DEBUG(("Malformed UTF-8 string value")); + SILC_ASN1_VA_FREE(opts, s); ret = FALSE; goto fail; } diff --git a/lib/silcasn1/silcasn1_encode.c b/lib/silcasn1/silcasn1_encode.c index fb24c064..d4b7077a 100644 --- a/lib/silcasn1/silcasn1_encode.c +++ b/lib/silcasn1/silcasn1_encode.c @@ -184,10 +184,7 @@ silc_asn1_encoder(SilcAsn1 asn1, SilcStack stack1, SilcStack stack2, SILC_LOG_DEBUG(("Error decoding underlaying node for ANY")); goto fail; } - if (enc != SILC_BER_ENC_CONSTRUCTED) { - SILC_LOG_DEBUG(("ANY was not constructed type")); - goto fail; - } + assert(enc == SILC_BER_ENC_CONSTRUCTED); /* Now encode with implicit tagging */ len = silc_ber_encoded_len(tag, d_len, FALSE); @@ -295,6 +292,45 @@ silc_asn1_encoder(SilcAsn1 asn1, SilcStack stack1, SilcStack stack2, break; } + case SILC_ASN1_TAG_SHORT_INTEGER: + { + /* Short Integer */ + SilcUInt32 sint = va_arg(asn1->ap, SilcUInt32); + SilcMPInt z; + + if (tag == SILC_ASN1_TAG_SHORT_INTEGER) + tag = SILC_ASN1_TAG_INTEGER; + + memset(&buf, 0, sizeof(buf)); + + silc_stack_push(stack2, &frame); + silc_mp_sinit(stack2, &z); + silc_mp_set_ui(&z, sint); + + len = silc_mp_sizeinbase(&z, 2); + if (!(len & 7)) + len = ((len + 7) / 8) + 1; + else + len = (len + 7) / 8; + silc_buffer_srealloc_size(stack2, &buf, + silc_buffer_truelen(&buf) + len); + buf.data[0] = 0x00; + silc_mp_mp2bin_noalloc(&z, buf.data, silc_buffer_len(&buf)); + silc_mp_uninit(&z); + + /* Encode the integer */ + len = silc_ber_encoded_len(tag, len, indef); + dest = silc_buffer_srealloc_size(stack1, dest, + silc_buffer_truelen(dest) + len); + ret = silc_ber_encode(dest, ber_class, SILC_BER_ENC_PRIMITIVE, + tag, buf.data, silc_buffer_len(&buf), FALSE); + silc_stack_pop(stack2); + if (!ret) + goto fail; + break; + } + break; + case SILC_ASN1_TAG_OID: { /* Object identifier */ diff --git a/lib/silcasn1/silcasn1_i.h b/lib/silcasn1/silcasn1_i.h index b6020105..12203675 100644 --- a/lib/silcasn1/silcasn1_i.h +++ b/lib/silcasn1/silcasn1_i.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2003 - 2005 Pekka Riikonen + Copyright (C) 2003 - 2006 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -42,6 +42,7 @@ struct SilcAsn1Object { #define SILC_ASN1_TAG_CHOICE 0x7003 /* SILC_ASN1_CHOICE given */ #define SILC_ASN1_TAG_SEQUENCE_OF 0x7004 /* SILC_ASN1_SEQUENCE_OF given */ #define SILC_ASN1_TAG_ANY_PRIMITIVE 0x7005 /* Pre-encoded primitive data */ +#define SILC_ASN1_TAG_SHORT_INTEGER 0x7006 /* Short integer */ /* Helper macros for adding the arguments to encoder and decoder. */ diff --git a/lib/silcasn1/tests/test_silcasn1.c b/lib/silcasn1/tests/test_silcasn1.c index 1400a269..2f2ec76c 100644 --- a/lib/silcasn1/tests/test_silcasn1.c +++ b/lib/silcasn1/tests/test_silcasn1.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) SilcBool val = TRUE; int i; unsigned char *str; - SilcUInt32 str_len; + SilcUInt32 str_len, tmpint; char tmp[32]; SilcRng rng; SilcMPInt mpint, mpint2; @@ -710,6 +710,39 @@ int main(int argc, char **argv) printf("\n"); + memset(&node, 0, sizeof(node)); + SILC_LOG_DEBUG(("Encoding ASN.1 tree 12 (SHORT INTEGER)")); + str_len = 198761; + tmpint = 0; + SILC_LOG_DEBUG(("Short integer: %d", str_len)); + SILC_LOG_DEBUG(("Short integer: %d", tmpint)); + success = + silc_asn1_encode(asn1, &node, + SILC_ASN1_SHORT_INT(str_len), + SILC_ASN1_SHORT_INT_T(SILC_ASN1_IMPLICIT, 100, tmpint), + SILC_ASN1_END); + if (!success) { + SILC_LOG_DEBUG(("Encoding failed")); + goto out; + } + SILC_LOG_DEBUG(("Encoding success")); + SILC_LOG_HEXDUMP(("ASN.1 tree"), node.data, silc_buffer_len(&node)); + SILC_LOG_DEBUG(("Decoding ASN.1 tree 12 (SHORT INTEGER)")); + success = + silc_asn1_decode(asn1, &node, + SILC_ASN1_SHORT_INT(&str_len), + SILC_ASN1_SHORT_INT_T(SILC_ASN1_IMPLICIT, 100, &tmpint), + SILC_ASN1_END); + if (!success) { + SILC_LOG_DEBUG(("Decoding failed")); + goto out; + } + SILC_LOG_DEBUG(("Short integer: %d", str_len)); + SILC_LOG_DEBUG(("Short integer: %d", tmpint)); + SILC_LOG_DEBUG(("Decoding success")); + printf("\n"); + + #endif silc_asn1_free(asn1); diff --git a/lib/silccrypt/rsa.c b/lib/silccrypt/rsa.c index b09693a5..e58bca15 100644 --- a/lib/silccrypt/rsa.c +++ b/lib/silccrypt/rsa.c @@ -72,11 +72,6 @@ Fixed double free in public key setting. Use a bit larger e as starting point in key generation. - - o Fri Dec 30 13:39:51 EET 2005 Pekka - - Support PKCS #1 format public and private keys. Support for new - PKCS API. */ #include "silc.h" diff --git a/lib/silccrypt/silcpk.c b/lib/silccrypt/silcpk.c index 0de35d6a..d9b81cba 100644 --- a/lib/silccrypt/silcpk.c +++ b/lib/silccrypt/silcpk.c @@ -971,7 +971,6 @@ SilcBool silc_pkcs_silc_import_private_key(unsigned char *key, /* Parse the RSA SILC private key */ SilcBufferStruct k; SilcMPInt n, e, d, dp, dq, qp, p, q; - SilcMPInt version; unsigned char *tmp; SilcUInt32 len, ver; @@ -1147,12 +1146,10 @@ SilcBool silc_pkcs_silc_import_private_key(unsigned char *key, } /* Encode to PKCS #1 format */ - silc_mp_init(&version); - silc_mp_set_ui(&version, 0); memset(&alg_key, 0, sizeof(alg_key)); if (!silc_asn1_encode(asn1, &alg_key, SILC_ASN1_SEQUENCE, - SILC_ASN1_INT(&version), + SILC_ASN1_SHORT_INT(0), SILC_ASN1_INT(&n), SILC_ASN1_INT(&e), SILC_ASN1_INT(&d), @@ -1164,7 +1161,6 @@ SilcBool silc_pkcs_silc_import_private_key(unsigned char *key, SILC_ASN1_END, SILC_ASN1_END)) goto err; - silc_mp_uninit(&version); silc_mp_uninit(&n); silc_mp_uninit(&e); silc_mp_uninit(&e); diff --git a/lib/silccrypt/silcpkcs1.c b/lib/silccrypt/silcpkcs1.c index 5820861d..88355e76 100644 --- a/lib/silccrypt/silcpkcs1.c +++ b/lib/silccrypt/silcpkcs1.c @@ -354,6 +354,7 @@ SilcBool silc_pkcs1_import_private_key(unsigned char *key, SilcAsn1 asn1; SilcBufferStruct alg_key; RsaPrivateKey *privkey; + SilcUInt32 ver; if (!ret_private_key) return FALSE; @@ -372,7 +373,7 @@ SilcBool silc_pkcs1_import_private_key(unsigned char *key, if (!silc_asn1_decode(asn1, &alg_key, SILC_ASN1_OPTS(SILC_ASN1_ALLOC), SILC_ASN1_SEQUENCE, - SILC_ASN1_INT(NULL), + SILC_ASN1_SHORT_INT(&ver), SILC_ASN1_INT(&privkey->n), SILC_ASN1_INT(&privkey->e), SILC_ASN1_INT(&privkey->d), @@ -384,6 +385,9 @@ SilcBool silc_pkcs1_import_private_key(unsigned char *key, SILC_ASN1_END, SILC_ASN1_END)) goto err; + if (ver != 0) + goto err; + /* Set key length */ privkey->bits = silc_mp_sizeinbase(&privkey->n, 2); @@ -404,7 +408,6 @@ unsigned char *silc_pkcs1_export_private_key(void *private_key, RsaPrivateKey *key = private_key; SilcAsn1 asn1; SilcBufferStruct alg_key; - SilcMPInt version; unsigned char *ret; asn1 = silc_asn1_alloc(); @@ -412,13 +415,11 @@ unsigned char *silc_pkcs1_export_private_key(void *private_key, return FALSE; /* Encode to PKCS #1 private key */ - silc_mp_init(&version); - silc_mp_set_ui(&version, 0); memset(&alg_key, 0, sizeof(alg_key)); if (!silc_asn1_encode(asn1, &alg_key, SILC_ASN1_OPTS(SILC_ASN1_ALLOC), SILC_ASN1_SEQUENCE, - SILC_ASN1_INT(&version), + SILC_ASN1_SHORT_INT(0), SILC_ASN1_INT(&key->n), SILC_ASN1_INT(&key->e), SILC_ASN1_INT(&key->d), @@ -429,7 +430,6 @@ unsigned char *silc_pkcs1_export_private_key(void *private_key, SILC_ASN1_INT(&key->qP), SILC_ASN1_END, SILC_ASN1_END)) goto err; - silc_mp_uninit(&version); ret = silc_buffer_steal(&alg_key, ret_len); silc_asn1_free(asn1); -- 2.24.0