diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Makefile | 2 | ||||
-rw-r--r-- | Source/charon.kdevelop | 3 | ||||
-rw-r--r-- | Source/doc/Todo-list.txt | 16 | ||||
-rw-r--r-- | Source/lib/asn1-pluto/asn1-pluto.c | 165 | ||||
-rw-r--r-- | Source/lib/asn1-pluto/asn1-pluto.h | 10 | ||||
-rw-r--r-- | Source/lib/asn1-pluto/ttodata.c | 349 | ||||
-rw-r--r-- | Source/lib/crypto/rsa/rsa_private_key.c | 211 | ||||
-rw-r--r-- | Source/lib/crypto/rsa/rsa_public_key.c | 1 |
8 files changed, 305 insertions, 452 deletions
diff --git a/Source/Makefile b/Source/Makefile index ceb987611..27a0ea3d4 100644 --- a/Source/Makefile +++ b/Source/Makefile @@ -29,7 +29,7 @@ MAIN_DIR= ./ LDFLAGS= -ldl -lgmp -lpthread -rdynamic -CFLAGS= -Icharon -Ilib -Istroke -Wall -g -fPIC -DLEAK_DETECTIVE +CFLAGS= -Icharon -Ilib -Istroke -Wall -g -fPIC #-DLEAK_DETECTIVE # objects is extended by each included Makefile CHARON_OBJS= diff --git a/Source/charon.kdevelop b/Source/charon.kdevelop index 4ab9354b8..b3156ad79 100644 --- a/Source/charon.kdevelop +++ b/Source/charon.kdevelop @@ -13,6 +13,9 @@ <mainprogram>Source</mainprogram> <directoryradio>executable</directoryradio> </run> + <general> + <activedir></activedir> + </general> </kdevcustomproject> <kdevdebugger> <general> diff --git a/Source/doc/Todo-list.txt b/Source/doc/Todo-list.txt index 0942defc8..97bc16b9f 100644 --- a/Source/doc/Todo-list.txt +++ b/Source/doc/Todo-list.txt @@ -1,7 +1,7 @@ - TODO-List for charon + Todo-List for charon ====================== -+ = done, - = todo, ordered by priority ++ = done, / = partial, - = todo, ordered by priority + private key loading: der, without passphrase + load all private keys from ipsec.d/private/ in stroke.c @@ -24,10 +24,13 @@ + utils (plus host) + logger_manager instance in lib + leak detective usable for charon and pluto and anything else - - doxygen fixes (multiple doxyfiles?) - - integrate asn1 parser/oid (asn1/oid) - - integrate PEM loading (pem) - - ... (more to come) + - doxygen split (charon/lib) + + integrate asn1 parser/oid (asn1/oid) + + integrate basic PEM loading + - + - implement 3DES to load encrypted pem files + - port x509 stuff + - - ipsec.secrets parsing @@ -38,7 +41,6 @@ - certificate exchange - trapping - - delete notify, when to send? - notifys on connection setup failure - create child sa message diff --git a/Source/lib/asn1-pluto/asn1-pluto.c b/Source/lib/asn1-pluto/asn1-pluto.c index 46764e10e..01deb5c14 100644 --- a/Source/lib/asn1-pluto/asn1-pluto.c +++ b/Source/lib/asn1-pluto/asn1-pluto.c @@ -572,3 +572,168 @@ bool is_asn1(chunk_t blob) } return TRUE; } + +/* + * codes ASN.1 lengths up to a size of 16'777'215 bytes + */ +void code_asn1_length(size_t length, chunk_t *code) +{ + if (length < 128) + { + code->ptr[0] = length; + code->len = 1; + } + else if (length < 256) + { + code->ptr[0] = 0x81; + code->ptr[1] = (u_char) length; + code->len = 2; + } + else if (length < 65536) + { + code->ptr[0] = 0x82; + code->ptr[1] = length >> 8; + code->ptr[2] = length & 0x00ff; + code->len = 3; + } + else + { + code->ptr[0] = 0x83; + code->ptr[1] = length >> 16; + code->ptr[2] = (length >> 8) & 0x00ff; + code->ptr[3] = length & 0x0000ff; + code->len = 4; + } +} + +/* + * build an empty asn.1 object with tag and length fields already filled in + */ +u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen) +{ + u_char length_buf[4]; + chunk_t length = { length_buf, 0 }; + u_char *pos; + + /* code the asn.1 length field */ + code_asn1_length(datalen, &length); + + /* allocate memory for the asn.1 TLV object */ + object->len = 1 + length.len + datalen; + object->ptr = malloc(object->len); + + /* set position pointer at the start of the object */ + pos = object->ptr; + + /* copy the asn.1 tag field and advance the pointer */ + *pos++ = type; + + /* copy the asn.1 length field and advance the pointer */ + memcpy(pos, length.ptr, length.len); + pos += length.len; + + return pos; +} + +/* + * build a simple ASN.1 object + */ +chunk_t asn1_simple_object(asn1_t tag, chunk_t content) +{ + chunk_t object; + + u_char *pos = build_asn1_object(&object, tag, content.len); + memcpy(pos, content.ptr, content.len); + pos += content.len; + + return object; +} + +/* Build an ASN.1 object from a variable number of individual chunks. + * Depending on the mode, chunks either are moved ('m') or copied ('c'). + */ +chunk_t asn1_wrap(asn1_t type, const char *mode, ...) +{ + chunk_t construct; + va_list chunks; + u_char *pos; + int i; + int count = strlen(mode); + + /* sum up lengths of individual chunks */ + va_start(chunks, mode); + construct.len = 0; + for (i = 0; i < count; i++) + { + chunk_t ch = va_arg(chunks, chunk_t); + construct.len += ch.len; + } + va_end(chunks); + + /* allocate needed memory for construct */ + pos = build_asn1_object(&construct, type, construct.len); + + /* copy or move the chunks */ + va_start(chunks, mode); + for (i = 0; i < count; i++) + { + chunk_t ch = va_arg(chunks, chunk_t); + + switch (*mode++) + { + case 'm': + memcpy(pos, ch.ptr, ch.len); + pos += ch.len; + free(ch.ptr); + break; + case 'c': + default: + memcpy(pos, ch.ptr, ch.len); + pos += ch.len; + } + } + va_end(chunks); + + return construct; +} + +/* + * convert a MP integer into a DER coded ASN.1 object + */ +chunk_t asn1_integer_from_mpz(const mpz_t value) +{ + size_t bits = mpz_sizeinbase(value, 2); /* size in bits */ + chunk_t n; + n.len = 1 + bits / 8; /* size in bytes */ + n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, value); + + return asn1_wrap(ASN1_INTEGER, "m", n); +} + +/* + * convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format + */ +chunk_t timetoasn1(const time_t *time, asn1_t type) +{ + int offset; + const char *format; + char buf[TIMETOA_BUF]; + chunk_t formatted_time; + struct tm *t = gmtime(time); + + if (type == ASN1_GENERALIZEDTIME) + { + format = "%04d%02d%02d%02d%02d%02dZ"; + offset = 1900; + } + else /* ASN1_UTCTIME */ + { + format = "%02d%02d%02d%02d%02d%02dZ"; + offset = (t->tm_year < 100)? 0 : -100; + } + sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday + , t->tm_hour, t->tm_min, t->tm_sec); + formatted_time.ptr = buf; + formatted_time.len = strlen(buf); + return asn1_simple_object(type, formatted_time); +} diff --git a/Source/lib/asn1-pluto/asn1-pluto.h b/Source/lib/asn1-pluto/asn1-pluto.h index c7cc29eb8..3edaa3254 100644 --- a/Source/lib/asn1-pluto/asn1-pluto.h +++ b/Source/lib/asn1-pluto/asn1-pluto.h @@ -103,7 +103,6 @@ typedef struct { } asn1_ctx_t; /* some common prefabricated ASN.1 constants */ - extern const chunk_t ASN1_INTEGER_0; extern const chunk_t ASN1_INTEGER_1; extern const chunk_t ASN1_INTEGER_2; @@ -115,6 +114,8 @@ extern const chunk_t ASN1_rsaEncryption_id; extern const chunk_t ASN1_md5WithRSA_id; extern const chunk_t ASN1_sha1WithRSA_id; +#define TIMETOA_BUF 30 + extern chunk_t asn1_algorithmIdentifier(int oid); extern int known_oid(chunk_t object); extern u_int asn1_length(chunk_t *blob); @@ -126,4 +127,11 @@ extern bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, extern int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters); extern bool is_asn1(chunk_t blob); +extern void code_asn1_length(size_t length, chunk_t *code); +extern u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen); +extern chunk_t asn1_integer_from_mpz(const mpz_t value); +extern chunk_t asn1_simple_object(asn1_t tag, chunk_t content); +extern chunk_t asn1_wrap(asn1_t type, const char *mode, ...); +extern chunk_t timetoasn1(const time_t *time, asn1_t type); + #endif /* _ASN1_H */ diff --git a/Source/lib/asn1-pluto/ttodata.c b/Source/lib/asn1-pluto/ttodata.c index 3ef5acd10..5e8149955 100644 --- a/Source/lib/asn1-pluto/ttodata.c +++ b/Source/lib/asn1-pluto/ttodata.c @@ -372,352 +372,3 @@ size_t errlen; strcat(errp, suf); return (const char *)errp; } - - - -#ifdef TTODATA_MAIN - -#include <stdio.h> - -struct artab; -static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status); -static void regress(char *pgm); -static void hexout(const char *s, size_t len, FILE *f); - -/* - - main - convert first argument to hex, or run regression - */ -int -main(int argc, char *argv[]) -{ - char buf[1024]; - char buf2[1024]; - char err[512]; - size_t n; - size_t i; - char *p = buf; - char *p2 = buf2; - char *pgm = argv[0]; - const char *oops; - - if (argc < 2) { - fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm); - exit(2); - } - - if (strcmp(argv[1], "-r") == 0) { - regress(pgm); /* should not return */ - fprintf(stderr, "%s: regress() returned?!?\n", pgm); - exit(1); - } - - oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n, - err, sizeof(err), TTODATAV_IGNORESPACE); - if (oops != NULL) { - fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm, - oops, argv[1]); - exit(1); - } - - if (n > sizeof(buf)) { - p = (char *)malloc((size_t)n); - if (p == NULL) { - fprintf(stderr, - "%s: unable to malloc %d bytes for result\n", - pgm, n); - exit(1); - } - oops = ttodata(argv[1], 0, 0, p, n, &n); - if (oops != NULL) { - fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n", - pgm, oops); - exit(1); - } - } - - hexout(p, n, stdout); - printf("\n"); - - i = datatot(buf, n, 'h', buf2, sizeof(buf2)); - if (i == 0) { - fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm, - argv[1]); - exit(1); - } - - if (i > sizeof(buf2)) { - p2 = (char *)malloc((size_t)i); - if (p == NULL) { - fprintf(stderr, - "%s: unable to malloc %d bytes for result\n", - pgm, i); - exit(1); - } - i = datatot(buf, n, 'h', p2, i); - if (i == 0) { - fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm); - exit(1); - } - } - - printf("%s\n", p2); - - exit(0); -} - -/* - - hexout - output an arbitrary-length string in hex - */ -static void -hexout(s, len, f) -const char *s; -size_t len; -FILE *f; -{ - size_t i; - - fprintf(f, "0x"); - for (i = 0; i < len; i++) - fprintf(f, "%02x", (unsigned char)s[i]); -} - -struct artab { - int base; -# define IGNORESPACE_BIAS 1000 - char *ascii; /* NULL for end */ - char *data; /* NULL for error expected */ -} atodatatab[] = { - { 0, "", NULL, }, - { 0, "0", NULL, }, - { 0, "0x", NULL, }, - { 0, "0xa", NULL, }, - { 0, "0xab", "\xab", }, - { 0, "0xabc", NULL, }, - { 0, "0xabcd", "\xab\xcd", }, - { 0, "0x0123456789", "\x01\x23\x45\x67\x89", }, - { 0, "0x01x", NULL, }, - { 0, "0xabcdef", "\xab\xcd\xef", }, - { 0, "0xABCDEF", "\xab\xcd\xef", }, - { 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", }, - { 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", }, - { 0, "0XaBc0_", NULL, }, - { 0, "0X_aBc0", NULL, }, - { 0, "0Xa_Bc0", NULL, }, - { 16, "aBc0eEd8", "\xab\xc0\xee\xd8", }, - { 0, "0s", NULL, }, - { 0, "0sA", NULL, }, - { 0, "0sBA", NULL, }, - { 0, "0sCBA", NULL, }, - { 0, "0sDCBA", "\x0c\x20\x40", }, - { 0, "0SDCBA", "\x0c\x20\x40", }, - { 0, "0sDA==", "\x0c", }, - { 0, "0sDC==", NULL, }, - { 0, "0sDCA=", "\x0c\x20", }, - { 0, "0sDCB=", NULL, }, - { 0, "0sDCAZ", "\x0c\x20\x19", }, - { 0, "0sDCAa", "\x0c\x20\x1a", }, - { 0, "0sDCAz", "\x0c\x20\x33", }, - { 0, "0sDCA0", "\x0c\x20\x34", }, - { 0, "0sDCA9", "\x0c\x20\x3d", }, - { 0, "0sDCA+", "\x0c\x20\x3e", }, - { 0, "0sDCA/", "\x0c\x20\x3f", }, - { 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", }, - { 0, "0t", NULL, }, - { 0, "0tabc_xyz", "abc_xyz", }, - { 256, "abc_xyz", "abc_xyz", }, - { 0, NULL, NULL, }, -}; - -struct drtab { - char *data; /* input; NULL for end */ - char format; - int buflen; /* -1 means big buffer */ - int outlen; /* -1 means strlen(ascii)+1 */ - char *ascii; /* NULL for error expected */ -} datatoatab[] = { - { "", 'x', -1, -1, NULL, }, - { "", 'X', -1, -1, NULL, }, - { "", 'n', -1, -1, NULL, }, - { "0", 'x', -1, -1, "0x30", }, - { "0", 'x', 0, 5, "---", }, - { "0", 'x', 1, 5, "", }, - { "0", 'x', 2, 5, "0", }, - { "0", 'x', 3, 5, "0x", }, - { "0", 'x', 4, 5, "0x3", }, - { "0", 'x', 5, 5, "0x30", }, - { "0", 'x', 6, 5, "0x30", }, - { "\xab\xcd", 'x', -1, -1, "0xabcd", }, - { "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", }, - { "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", }, - { "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", }, - { "\x01\x02", 'h', -1, -1, "0x0102", }, - { "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", }, - { "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", }, - { "\x0c\x20\x40", 's', -1, -1, "0sDCBA", }, - { "\x0c\x20\x40", 's', 0, 7, "---", }, - { "\x0c\x20\x40", 's', 1, 7, "", }, - { "\x0c\x20\x40", 's', 2, 7, "0", }, - { "\x0c\x20\x40", 's', 3, 7, "0s", }, - { "\x0c\x20\x40", 's', 4, 7, "0sD", }, - { "\x0c\x20\x40", 's', 5, 7, "0sDC", }, - { "\x0c\x20\x40", 's', 6, 7, "0sDCB", }, - { "\x0c\x20\x40", 's', 7, 7, "0sDCBA", }, - { "\x0c\x20\x40", 's', 8, 7, "0sDCBA", }, - { "\x0c", 's', -1, -1, "0sDA==", }, - { "\x0c\x20", 's', -1, -1, "0sDCA=", }, - { "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", }, - { "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", }, - { "\x0c\x20\x33", 's', -1, -1, "0sDCAz", }, - { "\x0c\x20\x34", 's', -1, -1, "0sDCA0", }, - { "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", }, - { "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", }, - { "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", }, - { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", }, - { "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", }, - { NULL, 'x', -1, -1, NULL, }, -}; - -/* - - regress - regression-test ttodata() and datatot() - */ -static void -check(r, buf, n, oops, status) -struct artab *r; -char *buf; -size_t n; -err_t oops; -int *status; -{ - if (oops != NULL && r->data == NULL) - {} /* error expected */ - else if (oops != NULL) { - printf("`%s' gave error `%s', expecting %d `", r->ascii, - oops, strlen(r->data)); - hexout(r->data, strlen(r->data), stdout); - printf("'\n"); - *status = 1; - } else if (r->data == NULL) { - printf("`%s' gave %d `", r->ascii, n); - hexout(buf, n, stdout); - printf("', expecting error\n"); - *status = 1; - } else if (n != strlen(r->data)) { - printf("length wrong in `%s': got %d `", r->ascii, n); - hexout(buf, n, stdout); - printf("', expecting %d `", strlen(r->data)); - hexout(r->data, strlen(r->data), stdout); - printf("'\n"); - *status = 1; - } else if (memcmp(buf, r->data, n) != 0) { - printf("`%s' gave %d `", r->ascii, n); - hexout(buf, n, stdout); - printf("', expecting %d `", strlen(r->data)); - hexout(r->data, strlen(r->data), stdout); - printf("'\n"); - *status = 1; - } - fflush(stdout); -} - -static void /* should not return at all, in fact */ -regress(pgm) -char *pgm; -{ - struct artab *r; - struct drtab *dr; - char buf[100]; - size_t n; - int status = 0; - - for (r = atodatatab; r->ascii != NULL; r++) { - int base = r->base; - int xbase = 0; - - if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') { - switch (r->ascii[1]) { - case 'x': - case 'X': - xbase = 16; - break; - case 's': - case 'S': - xbase = 64; - break; - case 't': - case 'T': - xbase = 256; - break; - } - } - - if (base >= IGNORESPACE_BIAS) { - base = base - IGNORESPACE_BIAS; - check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); - if (xbase != 0) - check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); - } else { - check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status); - if (base == 64 || xbase == 64) - check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); - if (xbase != 0) { - check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status); - if (base == 64 || xbase == 64) - check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status); - } - } - } - for (dr = datatoatab; dr->data != NULL; dr++) { - size_t should; - - strcpy(buf, "---"); - n = datatot(dr->data, strlen(dr->data), dr->format, buf, - (dr->buflen == -1) ? sizeof(buf) : dr->buflen); - should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1; - if (dr->outlen != -1) - should = dr->outlen; - if (n == 0 && dr->ascii == NULL) - {} /* error expected */ - else if (n == 0) { - printf("`"); - hexout(dr->data, strlen(dr->data), stdout); - printf("' %c gave error, expecting %d `%s'\n", - dr->format, should, dr->ascii); - status = 1; - } else if (dr->ascii == NULL) { - printf("`"); - hexout(dr->data, strlen(dr->data), stdout); - printf("' %c gave %d `%.*s', expecting error\n", - dr->format, n, (int)n, buf); - status = 1; - } else if (n != should) { - printf("length wrong in `"); - hexout(dr->data, strlen(dr->data), stdout); - printf("': got %d `%s'", n, buf); - printf(", expecting %d `%s'\n", should, dr->ascii); - status = 1; - } else if (strcmp(buf, dr->ascii) != 0) { - printf("`"); - hexout(dr->data, strlen(dr->data), stdout); - printf("' gave %d `%s'", n, buf); - printf(", expecting %d `%s'\n", should, dr->ascii); - status = 1; - } - fflush(stdout); - } - exit(status); -} - -#endif /* TTODATA_MAIN */ diff --git a/Source/lib/crypto/rsa/rsa_private_key.c b/Source/lib/crypto/rsa/rsa_private_key.c index af09a2af5..c53dac37b 100644 --- a/Source/lib/crypto/rsa/rsa_private_key.c +++ b/Source/lib/crypto/rsa/rsa_private_key.c @@ -28,7 +28,12 @@ #include "rsa_private_key.h" #include <daemon.h> -#include <asn1-pluto/asn1-pluto.h> +#ifdef NEW_ASN1 +# include <asn1/asn1.h> +# include <asn1/der_decoder.h> +#else +# include <asn1-pluto/asn1-pluto.h> +#endif /* @@ -138,8 +143,7 @@ struct private_rsa_private_key_t { }; -#if 0 -Not used yet, since we use plutos ASN1 stuff +#ifdef NEW_ASN1 /** * Rules for de-/encoding of a private key from/in ASN1 */ @@ -156,8 +160,7 @@ static asn1_rule_t rsa_private_key_rules[] = { { ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, coeff), 0}, {ASN1_END, 0, 0, 0}, }; -#endif - +#else struct { const char *name; size_t offset; @@ -199,7 +202,7 @@ static const asn1Object_t privkeyObjects[] = { #define PKCS1_PRIV_KEY_PUB_EXP 3 #define PKCS1_PRIV_KEY_COEFF 9 #define PKCS1_PRIV_KEY_ROOF 16 - +#endif static private_rsa_private_key_t *rsa_private_key_create_empty(); @@ -447,6 +450,100 @@ static bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public } /** + * Check the loaded key if it is valid and usable + * TODO: Log errors + */ +static status_t check(private_rsa_private_key_t *this) +{ + mpz_t t, u, q1; + status_t status = SUCCESS; + + /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. + * We actually require more (for security). + */ + if (this->k < 512/8) + { + return FAILED; + } + + /* we picked a max modulus size to simplify buffer allocation */ + if (this->k > 8192/8) + { + return FAILED; + } + + mpz_init(t); + mpz_init(u); + mpz_init(q1); + + /* check that n == p * q */ + mpz_mul(u, this->p, this->q); + if (mpz_cmp(u, this->n) != 0) + { + status = FAILED; + } + + /* check that e divides neither p-1 nor q-1 */ + mpz_sub_ui(t, this->p, 1); + mpz_mod(t, t, this->e); + if (mpz_cmp_ui(t, 0) == 0) + { + status = FAILED; + } + + mpz_sub_ui(t, this->q, 1); + mpz_mod(t, t, this->e); + if (mpz_cmp_ui(t, 0) == 0) + { + status = FAILED; + } + + /* check that d is e^-1 (mod lcm(p-1, q-1)) */ + /* see PKCS#1v2, aka RFC 2437, for the "lcm" */ + mpz_sub_ui(q1, this->q, 1); + mpz_sub_ui(u, this->p, 1); + mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */ + mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */ + mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */ + + mpz_mul(t, this->d, this->e); + mpz_mod(t, t, u); + if (mpz_cmp_ui(t, 1) != 0) + { + status = FAILED; + } + + /* check that exp1 is d mod (p-1) */ + mpz_sub_ui(u, this->p, 1); + mpz_mod(t, this->d, u); + if (mpz_cmp(t, this->exp1) != 0) + { + status = FAILED; + } + + /* check that exp2 is d mod (q-1) */ + mpz_sub_ui(u, this->q, 1); + mpz_mod(t, this->d, u); + if (mpz_cmp(t, this->exp2) != 0) + { + status = FAILED; + } + + /* check that coeff is (q^-1) mod p */ + mpz_mul(t, this->coeff, this->q); + mpz_mod(t, t, this->p); + if (mpz_cmp_ui(t, 1) != 0) + { + status = FAILED; + } + + mpz_clear(t); + mpz_clear(u); + mpz_clear(q1); + return status; +} + +/** * Implementation of rsa_private_key.clone. */ static rsa_private_key_t* _clone(private_rsa_private_key_t *this) @@ -595,9 +692,7 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size) return &this->public; } - -#if 0 -NOT used yet, since we use plutos ASN1 parser for now +#ifdef NEW_ASN1 /* * see header */ @@ -627,98 +722,20 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk) return NULL; } this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8; - return &this->public; -} -#endif - -static status_t check(private_rsa_private_key_t *this) -{ - mpz_t t, u, q1; - status_t status = SUCCESS; - - /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. - * We actually require more (for security). - */ - if (this->k < 512/8) - return FAILED; - - /* we picked a max modulus size to simplify buffer allocation */ - if (this->k > 8192/8) - return FAILED; - - mpz_init(t); - mpz_init(u); - mpz_init(q1); - - /* check that n == p * q */ - mpz_mul(u, this->p, this->q); - if (mpz_cmp(u, this->n) != 0) - { - status = FAILED; - } - - /* check that e divides neither p-1 nor q-1 */ - mpz_sub_ui(t, this->p, 1); - mpz_mod(t, t, this->e); - if (mpz_cmp_ui(t, 0) == 0) - { - status = FAILED; - } - - mpz_sub_ui(t, this->q, 1); - mpz_mod(t, t, this->e); - if (mpz_cmp_ui(t, 0) == 0) - { - status = FAILED; - } - - /* check that d is e^-1 (mod lcm(p-1, q-1)) */ - /* see PKCS#1v2, aka RFC 2437, for the "lcm" */ - mpz_sub_ui(q1, this->q, 1); - mpz_sub_ui(u, this->p, 1); - mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */ - mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */ - mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */ - - mpz_mul(t, this->d, this->e); - mpz_mod(t, t, u); - if (mpz_cmp_ui(t, 1) != 0) - { - status = FAILED; - } - /* check that exp1 is d mod (p-1) */ - mpz_sub_ui(u, this->p, 1); - mpz_mod(t, this->d, u); - if (mpz_cmp(t, this->exp1) != 0) - { - status = FAILED; - } - - /* check that exp2 is d mod (q-1) */ - mpz_sub_ui(u, this->q, 1); - mpz_mod(t, this->d, u); - if (mpz_cmp(t, this->exp2) != 0) + if (check(this) != SUCCESS) { - status = FAILED; + destroy(this); + return NULL; } - - /* check that coeff is (q^-1) mod p */ - mpz_mul(t, this->coeff, this->q); - mpz_mod(t, t, this->p); - if (mpz_cmp_ui(t, 1) != 0) + else { - status = FAILED; + return &this->public; } - - mpz_clear(t); - mpz_clear(u); - mpz_clear(q1); - return status; } - +#else /* - * Parses a PKCS#1 private key + * see header */ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob) { @@ -745,6 +762,7 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob) { if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx)) { + destroy(this); return FALSE; } if (objectID == PKCS1_PRIV_KEY_VERSION) @@ -765,6 +783,9 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob) } objectID++; } + + this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8; + if (check(this) != SUCCESS) { destroy(this); @@ -775,9 +796,11 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob) return &this->public; } } +#endif /* * see header + * TODO: PEM files */ rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase) { diff --git a/Source/lib/crypto/rsa/rsa_public_key.c b/Source/lib/crypto/rsa/rsa_public_key.c index 5b85f5256..61739dd38 100644 --- a/Source/lib/crypto/rsa/rsa_public_key.c +++ b/Source/lib/crypto/rsa/rsa_public_key.c @@ -37,6 +37,7 @@ * hash algorithm OIDs. These also contain * the length of the following hash. * These values are also used in rsa_private_key.c. + * TODO: We may move them in asn1 sometime... */ u_int8_t md2_oid[] = { |