Loading CHANGES +6 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,12 @@ Changes between 0.9.7 and 0.9.8 [xx XXX xxxx] *) IPv6 support for certificate extensions. The various extensions which use the IP:a.b.c.d can now take IPv6 addresses using the formats of RFC1884 2.2 . IPv6 addresses are now also displayed correctly. [Steve Henson] *) Added an ENGINE that implements RSA by performing private key exponentiations with the GMP library. The conversions to and from GMP's mpz_t format aren't optimised nor are any montgomery forms Loading crypto/x509v3/v3_alt.c +41 −23 Original line number Diff line number Diff line /* v3_alt.c */ /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 1999. * project. */ /* ==================================================================== * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -100,7 +100,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) { unsigned char *p; char oline[256]; char oline[256], htmp[5]; int i; switch (gen->type) { case GEN_OTHERNAME: Loading Loading @@ -134,12 +135,25 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, case GEN_IPADD: p = gen->d.ip->data; /* BUG: doesn't support IPV6 */ if(gen->d.ip->length != 4) { if(gen->d.ip->length == 4) sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); else if(gen->d.ip->length == 16) { oline[0] = 0; for (i = 0; i < 8; i++) { sprintf(htmp, "%X", p[0] << 8 | p[1]); p += 2; strcat(oline, htmp); if (i != 7) strcat(oline, ":"); } } else { X509V3_add_value("IP Address","<invalid>", &ret); break; } sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); X509V3_add_value("IP Address",oline, &ret); break; Loading @@ -154,6 +168,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) { unsigned char *p; int i; switch (gen->type) { case GEN_OTHERNAME: Loading Loading @@ -188,12 +203,24 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) case GEN_IPADD: p = gen->d.ip->data; /* BUG: doesn't support IPV6 */ if(gen->d.ip->length != 4) { if(gen->d.ip->length == 4) BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); else if(gen->d.ip->length == 16) { BIO_printf(out, "IP Address"); for (i = 0; i < 8; i++) { BIO_printf(out, ":%X", p[0] << 8 | p[1]); p += 2; } BIO_puts(out, "\n"); } else { BIO_printf(out,"IP Address:<invalid>"); break; } BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); break; case GEN_RID: Loading Loading @@ -418,21 +445,12 @@ if(!name_cmp(name, "email")) { gen->d.rid = obj; type = GEN_RID; } else if(!name_cmp(name, "IP")) { int i1,i2,i3,i4; unsigned char ip[4]; if((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) || (i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) || (i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) { if(!(gen->d.ip = a2i_IPADDRESS(value))) { X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS); ERR_add_error_data(2, "value=", value); goto err; } ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4; if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) || !ASN1_STRING_set(gen->d.ip, ip, 4)) { X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); goto err; } type = GEN_IPADD; } else if(!name_cmp(name, "otherName")) { if (!do_othername(gen, value, ctx)) Loading crypto/x509v3/v3_utl.c +208 −2 Original line number Diff line number Diff line /* v3_utl.c */ /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 1999. * project. */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -70,6 +70,11 @@ static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); static void str_free(void *str); static int append_ia5(STACK **sk, ASN1_IA5STRING *email); static int ipv4_from_asc(unsigned char *v4, const char *in); static int ipv6_from_asc(unsigned char *v6, const char *in); static int ipv6_cb(const char *elem, int len, void *usr); static int ipv6_hex(unsigned char *out, const char *in, int inlen); /* Add a CONF_VALUE name value pair to stack */ int X509V3_add_value(const char *name, const char *value, Loading Loading @@ -534,3 +539,204 @@ void X509_email_free(STACK *sk) { sk_pop_free(sk, str_free); } /* Convert IP addresses both IPv4 and IPv6 into an * OCTET STRING compatible with RFC3280. */ ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) { unsigned char ipout[16]; ASN1_OCTET_STRING *ret; int iplen; /* If string contains a ':' assume IPv6 */ if (strchr(ipasc, ':')) { if (!ipv6_from_asc(ipout, ipasc)) return NULL; iplen = 16; } else { if (!ipv4_from_asc(ipout, ipasc)) return NULL; iplen = 4; } ret = ASN1_OCTET_STRING_new(); if (!ret) return NULL; if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { ASN1_OCTET_STRING_free(ret); return NULL; } return ret; } static int ipv4_from_asc(unsigned char *v4, const char *in) { int a0, a1, a2, a3; if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) return 0; if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) return 0; v4[0] = a0; v4[1] = a1; v4[2] = a2; v4[3] = a3; return 1; } typedef struct { /* Temporary store for IPV6 output */ unsigned char tmp[16]; /* Total number of bytes in tmp */ int total; /* The position of a zero (corresponding to '::') */ int zero_pos; /* Number of zeroes */ int zero_cnt; } IPV6_STAT; static int ipv6_from_asc(unsigned char *v6, const char *in) { IPV6_STAT v6stat; v6stat.total = 0; v6stat.zero_pos = -1; v6stat.zero_cnt = 0; /* Treat the IPv6 representation as a list of values * separated by ':'. The presence of a '::' will parse * as one, two or three zero length elements. */ if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) return 0; /* Now for some sanity checks */ if (v6stat.zero_pos == -1) { /* If no '::' must have exactly 16 bytes */ if (v6stat.total != 16) return 0; } else { /* If '::' must have less than 16 bytes */ if (v6stat.total == 16) return 0; /* More than three zeroes is an error */ if (v6stat.zero_cnt > 3) return 0; /* Can only have three zeroes if nothing else present */ else if (v6stat.zero_cnt == 3) { if (v6stat.total > 0) return 0; } /* Can only have two zeroes if at start or end */ else if (v6stat.zero_cnt == 2) { if ((v6stat.zero_pos != 0) && (v6stat.zero_pos != v6stat.total)) return 0; } else /* Can only have one zero if *not* start or end */ { if ((v6stat.zero_pos == 0) || (v6stat.zero_pos == v6stat.total)) return 0; } } /* Format result */ /* Copy initial part */ if (v6stat.zero_pos > 0) memcpy(v6, v6stat.tmp, v6stat.zero_pos); /* Zero middle */ if (v6stat.total != 16) memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); /* Copy final part */ if (v6stat.total != v6stat.zero_pos) memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, v6stat.tmp + v6stat.zero_pos, v6stat.total - v6stat.zero_pos); return 1; } static int ipv6_cb(const char *elem, int len, void *usr) { IPV6_STAT *s = usr; /* Error if 16 bytes written */ if (s->total == 16) return 0; if (len == 0) { /* Zero length element, corresponds to '::' */ if (s->zero_pos == -1) s->zero_pos = s->total; /* If we've already got a :: its an error */ else if (s->zero_pos != s->total) return 0; s->zero_cnt++; } else { /* If more than 4 characters could be final a.b.c.d form */ if (len > 4) { /* Need at least 4 bytes left */ if (s->total > 12) return 0; /* Must be end of string */ if (elem[len]) return 0; if (!ipv4_from_asc(s->tmp + s->total, elem)) return 0; s->total += 4; } else { if (!ipv6_hex(s->tmp + s->total, elem, len)) return 0; s->total += 2; } } return 1; } /* Convert a string of up to 4 hex digits into the corresponding * IPv6 form. */ static int ipv6_hex(unsigned char *out, const char *in, int inlen) { unsigned char c; unsigned int num = 0; if (inlen > 4) return 0; while(inlen--) { c = *in++; num <<= 4; if ((c >= '0') && (c <= '9')) num |= c - '0'; else if ((c >= 'A') && (c <= 'F')) num |= c - 'A' + 10; else if ((c >= 'a') && (c <= 'f')) num |= c - 'a' + 10; else return 0; } out[0] = num >> 8; out[1] = num & 0xff; return 1; } crypto/x509v3/x509v3.h +1 −0 Original line number Diff line number Diff line Loading @@ -547,6 +547,7 @@ STACK *X509_get1_email(X509 *x); STACK *X509_REQ_get1_email(X509_REQ *x); void X509_email_free(STACK *sk); ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes Loading Loading
CHANGES +6 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,12 @@ Changes between 0.9.7 and 0.9.8 [xx XXX xxxx] *) IPv6 support for certificate extensions. The various extensions which use the IP:a.b.c.d can now take IPv6 addresses using the formats of RFC1884 2.2 . IPv6 addresses are now also displayed correctly. [Steve Henson] *) Added an ENGINE that implements RSA by performing private key exponentiations with the GMP library. The conversions to and from GMP's mpz_t format aren't optimised nor are any montgomery forms Loading
crypto/x509v3/v3_alt.c +41 −23 Original line number Diff line number Diff line /* v3_alt.c */ /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 1999. * project. */ /* ==================================================================== * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -100,7 +100,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) { unsigned char *p; char oline[256]; char oline[256], htmp[5]; int i; switch (gen->type) { case GEN_OTHERNAME: Loading Loading @@ -134,12 +135,25 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, case GEN_IPADD: p = gen->d.ip->data; /* BUG: doesn't support IPV6 */ if(gen->d.ip->length != 4) { if(gen->d.ip->length == 4) sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); else if(gen->d.ip->length == 16) { oline[0] = 0; for (i = 0; i < 8; i++) { sprintf(htmp, "%X", p[0] << 8 | p[1]); p += 2; strcat(oline, htmp); if (i != 7) strcat(oline, ":"); } } else { X509V3_add_value("IP Address","<invalid>", &ret); break; } sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); X509V3_add_value("IP Address",oline, &ret); break; Loading @@ -154,6 +168,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) { unsigned char *p; int i; switch (gen->type) { case GEN_OTHERNAME: Loading Loading @@ -188,12 +203,24 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) case GEN_IPADD: p = gen->d.ip->data; /* BUG: doesn't support IPV6 */ if(gen->d.ip->length != 4) { if(gen->d.ip->length == 4) BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); else if(gen->d.ip->length == 16) { BIO_printf(out, "IP Address"); for (i = 0; i < 8; i++) { BIO_printf(out, ":%X", p[0] << 8 | p[1]); p += 2; } BIO_puts(out, "\n"); } else { BIO_printf(out,"IP Address:<invalid>"); break; } BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); break; case GEN_RID: Loading Loading @@ -418,21 +445,12 @@ if(!name_cmp(name, "email")) { gen->d.rid = obj; type = GEN_RID; } else if(!name_cmp(name, "IP")) { int i1,i2,i3,i4; unsigned char ip[4]; if((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) || (i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) || (i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) { if(!(gen->d.ip = a2i_IPADDRESS(value))) { X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS); ERR_add_error_data(2, "value=", value); goto err; } ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4; if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) || !ASN1_STRING_set(gen->d.ip, ip, 4)) { X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); goto err; } type = GEN_IPADD; } else if(!name_cmp(name, "otherName")) { if (!do_othername(gen, value, ctx)) Loading
crypto/x509v3/v3_utl.c +208 −2 Original line number Diff line number Diff line /* v3_utl.c */ /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 1999. * project. */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Loading Loading @@ -70,6 +70,11 @@ static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); static void str_free(void *str); static int append_ia5(STACK **sk, ASN1_IA5STRING *email); static int ipv4_from_asc(unsigned char *v4, const char *in); static int ipv6_from_asc(unsigned char *v6, const char *in); static int ipv6_cb(const char *elem, int len, void *usr); static int ipv6_hex(unsigned char *out, const char *in, int inlen); /* Add a CONF_VALUE name value pair to stack */ int X509V3_add_value(const char *name, const char *value, Loading Loading @@ -534,3 +539,204 @@ void X509_email_free(STACK *sk) { sk_pop_free(sk, str_free); } /* Convert IP addresses both IPv4 and IPv6 into an * OCTET STRING compatible with RFC3280. */ ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) { unsigned char ipout[16]; ASN1_OCTET_STRING *ret; int iplen; /* If string contains a ':' assume IPv6 */ if (strchr(ipasc, ':')) { if (!ipv6_from_asc(ipout, ipasc)) return NULL; iplen = 16; } else { if (!ipv4_from_asc(ipout, ipasc)) return NULL; iplen = 4; } ret = ASN1_OCTET_STRING_new(); if (!ret) return NULL; if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { ASN1_OCTET_STRING_free(ret); return NULL; } return ret; } static int ipv4_from_asc(unsigned char *v4, const char *in) { int a0, a1, a2, a3; if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) return 0; if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) return 0; v4[0] = a0; v4[1] = a1; v4[2] = a2; v4[3] = a3; return 1; } typedef struct { /* Temporary store for IPV6 output */ unsigned char tmp[16]; /* Total number of bytes in tmp */ int total; /* The position of a zero (corresponding to '::') */ int zero_pos; /* Number of zeroes */ int zero_cnt; } IPV6_STAT; static int ipv6_from_asc(unsigned char *v6, const char *in) { IPV6_STAT v6stat; v6stat.total = 0; v6stat.zero_pos = -1; v6stat.zero_cnt = 0; /* Treat the IPv6 representation as a list of values * separated by ':'. The presence of a '::' will parse * as one, two or three zero length elements. */ if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) return 0; /* Now for some sanity checks */ if (v6stat.zero_pos == -1) { /* If no '::' must have exactly 16 bytes */ if (v6stat.total != 16) return 0; } else { /* If '::' must have less than 16 bytes */ if (v6stat.total == 16) return 0; /* More than three zeroes is an error */ if (v6stat.zero_cnt > 3) return 0; /* Can only have three zeroes if nothing else present */ else if (v6stat.zero_cnt == 3) { if (v6stat.total > 0) return 0; } /* Can only have two zeroes if at start or end */ else if (v6stat.zero_cnt == 2) { if ((v6stat.zero_pos != 0) && (v6stat.zero_pos != v6stat.total)) return 0; } else /* Can only have one zero if *not* start or end */ { if ((v6stat.zero_pos == 0) || (v6stat.zero_pos == v6stat.total)) return 0; } } /* Format result */ /* Copy initial part */ if (v6stat.zero_pos > 0) memcpy(v6, v6stat.tmp, v6stat.zero_pos); /* Zero middle */ if (v6stat.total != 16) memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); /* Copy final part */ if (v6stat.total != v6stat.zero_pos) memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, v6stat.tmp + v6stat.zero_pos, v6stat.total - v6stat.zero_pos); return 1; } static int ipv6_cb(const char *elem, int len, void *usr) { IPV6_STAT *s = usr; /* Error if 16 bytes written */ if (s->total == 16) return 0; if (len == 0) { /* Zero length element, corresponds to '::' */ if (s->zero_pos == -1) s->zero_pos = s->total; /* If we've already got a :: its an error */ else if (s->zero_pos != s->total) return 0; s->zero_cnt++; } else { /* If more than 4 characters could be final a.b.c.d form */ if (len > 4) { /* Need at least 4 bytes left */ if (s->total > 12) return 0; /* Must be end of string */ if (elem[len]) return 0; if (!ipv4_from_asc(s->tmp + s->total, elem)) return 0; s->total += 4; } else { if (!ipv6_hex(s->tmp + s->total, elem, len)) return 0; s->total += 2; } } return 1; } /* Convert a string of up to 4 hex digits into the corresponding * IPv6 form. */ static int ipv6_hex(unsigned char *out, const char *in, int inlen) { unsigned char c; unsigned int num = 0; if (inlen > 4) return 0; while(inlen--) { c = *in++; num <<= 4; if ((c >= '0') && (c <= '9')) num |= c - '0'; else if ((c >= 'A') && (c <= 'F')) num |= c - 'A' + 10; else if ((c >= 'a') && (c <= 'f')) num |= c - 'a' + 10; else return 0; } out[0] = num >> 8; out[1] = num & 0xff; return 1; }
crypto/x509v3/x509v3.h +1 −0 Original line number Diff line number Diff line Loading @@ -547,6 +547,7 @@ STACK *X509_get1_email(X509 *x); STACK *X509_REQ_get1_email(X509_REQ *x); void X509_email_free(STACK *sk); ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes Loading