From 419144adce049b5341bd94d355c52d099eac56e3 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sat, 22 Sep 2018 19:35:12 -0500 Subject: [PATCH] Fix undefined function pointer casts in {d2i,i2d}_Foo_{bio,fp} Lacking C++, this instead adds a mess of macros. With this done, all the function-pointer-munging "_of" macros in asn1.h can also be removed. Update-Note: A number of *really* old and unused ASN.1 macros were removed. Bug: chromium:785442 Change-Id: Iab260d114c7d8cdf0429759e714d91ce3f3c04b2 Reviewed-on: https://boringssl-review.googlesource.com/32106 Reviewed-by: Adam Langley Reviewed-by: Adam Langley --- crypto/asn1/a_d2i_fp.c | 221 ++----------------------- crypto/asn1/a_dup.c | 24 --- crypto/asn1/a_i2d_fp.c | 66 +------- crypto/bio/bio.c | 13 ++ crypto/pkcs7/pkcs7_x509.c | 12 +- crypto/pkcs8/pkcs8_x509.c | 12 +- crypto/x509/x_all.c | 309 +++++++++++------------------------ crypto/x509v3/v3_genn.c | 7 +- include/openssl/asn1.h | 68 -------- include/openssl/bio.h | 6 +- include/openssl/type_check.h | 4 - ssl/ssl_x509.cc | 22 ++- 12 files changed, 151 insertions(+), 613 deletions(-) diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index ee71ee9e..fd423e27 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -58,66 +58,24 @@ #include -#include +#include #include #include -static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); - -#ifndef NO_OLD_ASN1 -# ifndef OPENSSL_NO_FP_API - -void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x) -{ - BIO *b = BIO_new_fp(in, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); - return NULL; - } - void *ret = ASN1_d2i_bio(xnew, d2i, b, x); - BIO_free(b); - return (ret); -} -# endif - -void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x) -{ - BUF_MEM *b = NULL; - const unsigned char *p; - void *ret = NULL; - int len; - - len = asn1_d2i_read_bio(in, &b); - if (len < 0) - goto err; - - p = (unsigned char *)b->data; - ret = d2i(x, &p, len); - err: - if (b != NULL) - BUF_MEM_free(b); - return (ret); -} - -#endif void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) { - BUF_MEM *b = NULL; - const unsigned char *p; - void *ret = NULL; - int len; - - len = asn1_d2i_read_bio(in, &b); - if (len < 0) - goto err; - - p = (const unsigned char *)b->data; - ret = ASN1_item_d2i(x, &p, len, it); - err: - if (b != NULL) - BUF_MEM_free(b); - return (ret); + uint8_t *data; + size_t len; + // Historically, this function did not impose a limit in OpenSSL and is used + // to read CRLs, so we leave this without an external bound. + if (!BIO_read_asn1(in, &data, &len, INT_MAX)) { + return NULL; + } + const uint8_t *ptr = data; + void *ret = ASN1_item_d2i(x, &ptr, len, it); + OPENSSL_free(data); + return ret; } #ifndef OPENSSL_NO_FP_API @@ -133,158 +91,3 @@ void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) return ret; } #endif - -typedef struct asn1_const_ctx_st - { - const unsigned char *p;/* work char pointer */ - int eos; /* end of sequence read for indefinite encoding */ - int error; /* error code to use when returning an error */ - int inf; /* constructed if 0x20, indefinite is 0x21 */ - int tag; /* tag from last 'get object' */ - int xclass; /* class from last 'get object' */ - long slen; /* length of last 'get object' */ - const unsigned char *max; /* largest value of p allowed */ - const unsigned char *q;/* temporary variable */ - const unsigned char **pp;/* variable */ - int line; /* used in error processing */ - } ASN1_const_CTX; - -#define HEADER_SIZE 8 -#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) -static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) -{ - BUF_MEM *b; - unsigned char *p; - int i; - ASN1_const_CTX c; - size_t want = HEADER_SIZE; - int eos = 0; - size_t off = 0; - size_t len = 0; - - b = BUF_MEM_new(); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return -1; - } - - ERR_clear_error(); - for (;;) { - if (want >= (len - off)) { - want -= (len - off); - - if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } - i = BIO_read(in, &(b->data[len]), want); - if ((i < 0) && ((len - off) == 0)) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA); - goto err; - } - if (i > 0) { - if (len + i < len) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); - goto err; - } - len += i; - } - } - /* else data already loaded */ - - p = (unsigned char *)&(b->data[off]); - c.p = p; - c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass), - len - off); - if (c.inf & 0x80) { - uint32_t error = ERR_peek_error(); - if (ERR_GET_LIB(error) != ERR_LIB_ASN1 || - ERR_GET_REASON(error) != ASN1_R_TOO_LONG) { - goto err; - } - ERR_clear_error(); - } - i = c.p - p; /* header length */ - off += i; /* end of data */ - - if (c.inf & 1) { - /* no data body so go round again */ - eos++; - if (eos < 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); - goto err; - } - want = HEADER_SIZE; - } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) { - /* eos value, so go back and read another header */ - eos--; - if (eos <= 0) - break; - else - want = HEADER_SIZE; - } else { - /* suck in c.slen bytes of data */ - want = c.slen; - if (want > (len - off)) { - size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; - want -= (len - off); - if (want > INT_MAX /* BIO_read takes an int length */ || - len + want < len) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); - goto err; - } - while (want > 0) { - /* - * Read content in chunks of increasing size - * so we can return an error for EOF without - * having to allocate the entire content length - * in one go. - */ - size_t chunk = want > chunk_max ? chunk_max : want; - - if (!BUF_MEM_grow_clean(b, len + chunk)) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - goto err; - } - want -= chunk; - while (chunk > 0) { - i = BIO_read(in, &(b->data[len]), chunk); - if (i <= 0) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA); - goto err; - } - /* - * This can't overflow because |len+want| didn't - * overflow. - */ - len += i; - chunk -= i; - } - if (chunk_max < INT_MAX/2) - chunk_max *= 2; - } - } - if (off + c.slen < off) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); - goto err; - } - off += c.slen; - if (eos <= 0) { - break; - } else - want = HEADER_SIZE; - } - } - - if (off > INT_MAX) { - OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); - goto err; - } - - *pb = b; - return off; - err: - if (b != NULL) - BUF_MEM_free(b); - return -1; -} diff --git a/crypto/asn1/a_dup.c b/crypto/asn1/a_dup.c index 57394f58..9ede8511 100644 --- a/crypto/asn1/a_dup.c +++ b/crypto/asn1/a_dup.c @@ -59,30 +59,6 @@ #include #include -void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x) -{ - unsigned char *b, *p; - const unsigned char *p2; - int i; - char *ret; - - if (x == NULL) - return (NULL); - - i = i2d(x, NULL); - b = OPENSSL_malloc(i + 10); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (NULL); - } - p = b; - i = i2d(x, &p); - p2 = b; - ret = d2i(NULL, &p2, i); - OPENSSL_free(b); - return (ret); -} - /* * ASN1_ITEM version of dup: this follows the model above except we don't * need to allocate the buffer. At some point this could be rewritten to diff --git a/crypto/asn1/a_i2d_fp.c b/crypto/asn1/a_i2d_fp.c index 5cc97d2a..db0d8122 100644 --- a/crypto/asn1/a_i2d_fp.c +++ b/crypto/asn1/a_i2d_fp.c @@ -56,54 +56,10 @@ #include +#include #include #include -int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x) -{ - BIO *b = BIO_new_fp(out, BIO_NOCLOSE); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB); - return 0; - } - int ret = ASN1_i2d_bio(i2d, b, x); - BIO_free(b); - return ret; -} - -int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x) -{ - char *b; - unsigned char *p; - int i, j = 0, n, ret = 1; - - n = i2d(x, NULL); - if (n <= 0) - return 0; - - b = (char *)OPENSSL_malloc(n); - if (b == NULL) { - OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (0); - } - - p = (unsigned char *)b; - i2d(x, &p); - - for (;;) { - i = BIO_write(out, &(b[j]), n); - if (i == n) - break; - if (i <= 0) { - ret = 0; - break; - } - j += i; - n -= i; - } - OPENSSL_free(b); - return (ret); -} int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) { @@ -120,25 +76,13 @@ int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) { unsigned char *b = NULL; - int i, j = 0, n, ret = 1; - - n = ASN1_item_i2d(x, &b, it); + int n = ASN1_item_i2d(x, &b, it); if (b == NULL) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); - return (0); + return 0; } - for (;;) { - i = BIO_write(out, &(b[j]), n); - if (i == n) - break; - if (i <= 0) { - ret = 0; - break; - } - j += i; - n -= i; - } + int ret = BIO_write_all(out, b, n); OPENSSL_free(b); - return (ret); + return ret; } diff --git a/crypto/bio/bio.c b/crypto/bio/bio.c index 3e788b87..881c14e1 100644 --- a/crypto/bio/bio.c +++ b/crypto/bio/bio.c @@ -177,6 +177,19 @@ int BIO_write(BIO *bio, const void *in, int inl) { return ret; } +int BIO_write_all(BIO *bio, const void *data, size_t len) { + const uint8_t *data_u8 = data; + while (len > 0) { + int ret = BIO_write(bio, data_u8, len > INT_MAX ? INT_MAX : (int)len); + if (ret <= 0) { + return 0; + } + data_u8 += ret; + len -= ret; + } + return 1; +} + int BIO_puts(BIO *bio, const char *in) { return BIO_write(bio, in, strlen(in)); } diff --git a/crypto/pkcs7/pkcs7_x509.c b/crypto/pkcs7/pkcs7_x509.c index a2a6b46a..d6ca44ea 100644 --- a/crypto/pkcs7/pkcs7_x509.c +++ b/crypto/pkcs7/pkcs7_x509.c @@ -333,17 +333,7 @@ int i2d_PKCS7(const PKCS7 *p7, uint8_t **out) { } int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) { - size_t written = 0; - while (written < p7->ber_len) { - size_t todo = p7->ber_len - written; - int len = todo > INT_MAX ? INT_MAX : (int)todo; - int ret = BIO_write(bio, p7->ber_bytes + written, len); - if (ret <= 0) { - return 0; - } - written += (size_t)ret; - } - return 1; + return BIO_write_all(bio, p7->ber_bytes, p7->ber_len); } void PKCS7_free(PKCS7 *p7) { diff --git a/crypto/pkcs8/pkcs8_x509.c b/crypto/pkcs8/pkcs8_x509.c index dc74d968..2c7841ee 100644 --- a/crypto/pkcs8/pkcs8_x509.c +++ b/crypto/pkcs8/pkcs8_x509.c @@ -861,17 +861,7 @@ int i2d_PKCS12(const PKCS12 *p12, uint8_t **out) { } int i2d_PKCS12_bio(BIO *bio, const PKCS12 *p12) { - size_t written = 0; - while (written < p12->ber_len) { - size_t todo = p12->ber_len - written; - int len = todo > INT_MAX ? INT_MAX : (int)todo; - int ret = BIO_write(bio, p12->ber_bytes + written, len); - if (ret <= 0) { - return 0; - } - written += (size_t)ret; - } - return 1; + return BIO_write_all(bio, p12->ber_bytes, p12->ber_len); } int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12) { diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 064c89c8..a37d7bde 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -54,14 +54,18 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +#include + +#include + #include #include #include #include #include +#include #include #include -#include int X509_verify(X509 *a, EVP_PKEY *r) { @@ -201,154 +205,102 @@ int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) } #ifndef OPENSSL_NO_FP_API -RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa) -{ - return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa); -} -int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa) -{ - return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa); -} +#define IMPLEMENT_D2I_FP(type, name, bio_func) \ + type *name(FILE *fp, type **obj) { \ + BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); \ + if (bio == NULL) { \ + return NULL; \ + } \ + type *ret = bio_func(bio, obj); \ + BIO_free(bio); \ + return ret; \ + } -RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) -{ - return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa); -} +#define IMPLEMENT_I2D_FP(type, name, bio_func) \ + int name(FILE *fp, type *obj) { \ + BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); \ + if (bio == NULL) { \ + return 0; \ + } \ + int ret = bio_func(bio, obj); \ + BIO_free(bio); \ + return ret; \ + } -RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) -{ - return ASN1_d2i_fp((void *(*)(void)) - RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp, - (void **)rsa); -} +IMPLEMENT_D2I_FP(RSA, d2i_RSAPrivateKey_fp, d2i_RSAPrivateKey_bio) +IMPLEMENT_I2D_FP(RSA, i2d_RSAPrivateKey_fp, i2d_RSAPrivateKey_bio) -int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) -{ - return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa); -} +IMPLEMENT_D2I_FP(RSA, d2i_RSAPublicKey_fp, d2i_RSAPublicKey_bio) +IMPLEMENT_I2D_FP(RSA, i2d_RSAPublicKey_fp, i2d_RSAPublicKey_bio) -int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) -{ - return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY, fp, rsa); -} +IMPLEMENT_D2I_FP(RSA, d2i_RSA_PUBKEY_fp, d2i_RSA_PUBKEY_bio) +IMPLEMENT_I2D_FP(RSA, i2d_RSA_PUBKEY_fp, i2d_RSA_PUBKEY_bio) #endif -RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa) -{ - return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa); -} +#define IMPLEMENT_D2I_BIO(type, name, d2i_func) \ + type *name(BIO *bio, type **obj) { \ + uint8_t *data; \ + size_t len; \ + if (!BIO_read_asn1(bio, &data, &len, 100 * 1024)) { \ + return NULL; \ + } \ + const uint8_t *ptr = data; \ + type *ret = d2i_func(obj, &ptr, (long)len); \ + OPENSSL_free(data); \ + return ret; \ + } -int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa) -{ - return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa); -} +#define IMPLEMENT_I2D_BIO(type, name, i2d_func) \ + int name(BIO *bio, type *obj) { \ + uint8_t *data = NULL; \ + int len = i2d_func(obj, &data); \ + if (len < 0) { \ + return 0; \ + } \ + int ret = BIO_write_all(bio, data, len); \ + OPENSSL_free(data); \ + return ret; \ + } -RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) -{ - return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa); -} +IMPLEMENT_D2I_BIO(RSA, d2i_RSAPrivateKey_bio, d2i_RSAPrivateKey) +IMPLEMENT_I2D_BIO(RSA, i2d_RSAPrivateKey_bio, i2d_RSAPrivateKey) -RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) -{ - return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa); -} +IMPLEMENT_D2I_BIO(RSA, d2i_RSAPublicKey_bio, d2i_RSAPublicKey) +IMPLEMENT_I2D_BIO(RSA, i2d_RSAPublicKey_bio, i2d_RSAPublicKey) -int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa) -{ - return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa); -} - -int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) -{ - return ASN1_i2d_bio_of_const(RSA, i2d_RSA_PUBKEY, bp, rsa); -} +IMPLEMENT_D2I_BIO(RSA, d2i_RSA_PUBKEY_bio, d2i_RSA_PUBKEY) +IMPLEMENT_I2D_BIO(RSA, i2d_RSA_PUBKEY_bio, i2d_RSA_PUBKEY) #ifndef OPENSSL_NO_DSA # ifndef OPENSSL_NO_FP_API -DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa) -{ - return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa); -} +IMPLEMENT_D2I_FP(DSA, d2i_DSAPrivateKey_fp, d2i_DSAPrivateKey_bio) +IMPLEMENT_I2D_FP(DSA, i2d_DSAPrivateKey_fp, i2d_DSAPrivateKey_bio) -int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa) -{ - return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa); -} - -DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa) -{ - return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa); -} - -int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa) -{ - return ASN1_i2d_fp_of_const(DSA, i2d_DSA_PUBKEY, fp, dsa); -} +IMPLEMENT_D2I_FP(DSA, d2i_DSA_PUBKEY_fp, d2i_DSA_PUBKEY_bio) +IMPLEMENT_I2D_FP(DSA, i2d_DSA_PUBKEY_fp, i2d_DSA_PUBKEY_bio) # endif -DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa) -{ - return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa); -} - -int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa) -{ - return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa); -} - -DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa) -{ - return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa); -} - -int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa) -{ - return ASN1_i2d_bio_of_const(DSA, i2d_DSA_PUBKEY, bp, dsa); -} +IMPLEMENT_D2I_BIO(DSA, d2i_DSAPrivateKey_bio, d2i_DSAPrivateKey) +IMPLEMENT_I2D_BIO(DSA, i2d_DSAPrivateKey_bio, i2d_DSAPrivateKey) +IMPLEMENT_D2I_BIO(DSA, d2i_DSA_PUBKEY_bio, d2i_DSA_PUBKEY) +IMPLEMENT_I2D_BIO(DSA, i2d_DSA_PUBKEY_bio, i2d_DSA_PUBKEY) #endif #ifndef OPENSSL_NO_FP_API -EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey) -{ - return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey); -} +IMPLEMENT_D2I_FP(EC_KEY, d2i_ECPrivateKey_fp, d2i_ECPrivateKey_bio) +IMPLEMENT_I2D_FP(EC_KEY, i2d_ECPrivateKey_fp, i2d_ECPrivateKey_bio) -int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey) -{ - return ASN1_i2d_fp_of_const(EC_KEY, i2d_EC_PUBKEY, fp, eckey); -} - -EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey) -{ - return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey); -} - -int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey) -{ - return ASN1_i2d_fp_of_const(EC_KEY, i2d_ECPrivateKey, fp, eckey); -} +IMPLEMENT_D2I_FP(EC_KEY, d2i_EC_PUBKEY_fp, d2i_EC_PUBKEY_bio) +IMPLEMENT_I2D_FP(EC_KEY, i2d_EC_PUBKEY_fp, i2d_EC_PUBKEY_bio) #endif -EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey) -{ - return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey); -} -int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa) -{ - return ASN1_i2d_bio_of_const(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa); -} +IMPLEMENT_D2I_BIO(EC_KEY, d2i_ECPrivateKey_bio, d2i_ECPrivateKey) +IMPLEMENT_I2D_BIO(EC_KEY, i2d_ECPrivateKey_bio, i2d_ECPrivateKey) -EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey) -{ - return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey); -} - -int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey) -{ - return ASN1_i2d_bio_of_const(EC_KEY, i2d_ECPrivateKey, bp, eckey); -} +IMPLEMENT_D2I_BIO(EC_KEY, d2i_EC_PUBKEY_bio, d2i_EC_PUBKEY) +IMPLEMENT_I2D_BIO(EC_KEY, i2d_EC_PUBKEY_bio, i2d_EC_PUBKEY) int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md, unsigned int *len) @@ -389,40 +341,18 @@ int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, } #ifndef OPENSSL_NO_FP_API -X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8) -{ - return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8); -} - -int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8) -{ - return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8); -} +IMPLEMENT_D2I_FP(X509_SIG, d2i_PKCS8_fp, d2i_PKCS8_bio) +IMPLEMENT_I2D_FP(X509_SIG, i2d_PKCS8_fp, i2d_PKCS8_bio) #endif -X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8) -{ - return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8); -} - -int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8) -{ - return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8); -} +IMPLEMENT_D2I_BIO(X509_SIG, d2i_PKCS8_bio, d2i_X509_SIG) +IMPLEMENT_I2D_BIO(X509_SIG, i2d_PKCS8_bio, i2d_X509_SIG) #ifndef OPENSSL_NO_FP_API -PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, - PKCS8_PRIV_KEY_INFO **p8inf) -{ - return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, - d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf); -} - -int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf) -{ - return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp, - p8inf); -} +IMPLEMENT_D2I_FP(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_fp, + d2i_PKCS8_PRIV_KEY_INFO_bio) +IMPLEMENT_I2D_FP(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_fp, + i2d_PKCS8_PRIV_KEY_INFO_bio) int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) { @@ -436,38 +366,16 @@ int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) return ret; } -int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey) -{ - return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PrivateKey, fp, pkey); -} +IMPLEMENT_D2I_FP(EVP_PKEY, d2i_PrivateKey_fp, d2i_PrivateKey_bio) +IMPLEMENT_I2D_FP(EVP_PKEY, i2d_PrivateKey_fp, i2d_PrivateKey_bio) -EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a) -{ - return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a); -} +IMPLEMENT_D2I_FP(EVP_PKEY, d2i_PUBKEY_fp, d2i_PUBKEY_bio) +IMPLEMENT_I2D_FP(EVP_PKEY, i2d_PUBKEY_fp, i2d_PUBKEY_bio) -int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey) -{ - return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PUBKEY, fp, pkey); -} - -EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) -{ - return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a); -} - -PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, - PKCS8_PRIV_KEY_INFO **p8inf) -{ - return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new, - d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf); -} - -int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf) -{ - return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp, - p8inf); -} +IMPLEMENT_D2I_BIO(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_bio, + d2i_PKCS8_PRIV_KEY_INFO) +IMPLEMENT_I2D_BIO(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_bio, + i2d_PKCS8_PRIV_KEY_INFO) int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) { @@ -482,32 +390,11 @@ int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) } #endif -int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey) -{ - return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PrivateKey, bp, pkey); -} +IMPLEMENT_D2I_BIO(EVP_PKEY, d2i_PrivateKey_bio, d2i_AutoPrivateKey) +IMPLEMENT_I2D_BIO(EVP_PKEY, i2d_PrivateKey_bio, i2d_PrivateKey) -EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a) -{ - return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a); -} +IMPLEMENT_D2I_BIO(EVP_PKEY, d2i_PUBKEY_bio, d2i_PUBKEY) +IMPLEMENT_I2D_BIO(EVP_PKEY, i2d_PUBKEY_bio, i2d_PUBKEY) -int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey) -{ - return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PUBKEY, bp, pkey); -} - -EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) -{ - return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a); -} - -DH *d2i_DHparams_bio(BIO *bp, DH **dh) -{ - return ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, dh); -} - -int i2d_DHparams_bio(BIO *bp, const DH *dh) -{ - return ASN1_i2d_bio_of_const(DH, i2d_DHparams, bp, dh); -} +IMPLEMENT_D2I_BIO(DH, d2i_DHparams_bio, d2i_DHparams) +IMPLEMENT_I2D_BIO(const DH, i2d_DHparams_bio, i2d_DHparams) diff --git a/crypto/x509v3/v3_genn.c b/crypto/x509v3/v3_genn.c index 8c926879..552a5244 100644 --- a/crypto/x509v3/v3_genn.c +++ b/crypto/x509v3/v3_genn.c @@ -100,12 +100,7 @@ ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES) IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES) -GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a) -{ - return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME, - (d2i_of_void *)d2i_GENERAL_NAME, - (char *)a); -} +IMPLEMENT_ASN1_DUP_FUNCTION(GENERAL_NAME) /* Returns 0 if they are equal, != 0 otherwise. */ int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h index 46e5f537..7be3d63f 100644 --- a/include/openssl/asn1.h +++ b/include/openssl/asn1.h @@ -302,15 +302,6 @@ typedef struct ASN1_VALUE_st ASN1_VALUE; #define I2D_OF(type) int (*)(type *,unsigned char **) #define I2D_OF_const(type) int (*)(const type *,unsigned char **) -#define CHECKED_D2I_OF(type, d2i) \ - ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0))) -#define CHECKED_I2D_OF(type, i2d) \ - ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0))) -#define CHECKED_NEW_OF(type, xnew) \ - ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0))) -#define CHECKED_PPTR_OF(type, p) \ - ((void**) (1 ? p : (type**)0)) - typedef void *d2i_of_void(void **, const unsigned char **, long); typedef int i2d_of_void(const void *, unsigned char **); @@ -762,76 +753,17 @@ OPENSSL_EXPORT void ASN1_put_object(unsigned char **pp, int constructed, int len OPENSSL_EXPORT int ASN1_put_eoc(unsigned char **pp); OPENSSL_EXPORT int ASN1_object_size(int constructed, int length, int tag); -/* Used to implement other functions */ -OPENSSL_EXPORT void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x); - -#define ASN1_dup_of(type,i2d,d2i,x) \ - ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \ - CHECKED_D2I_OF(type, d2i), \ - CHECKED_PTR_OF(type, x))) - -#define ASN1_dup_of_const(type,i2d,d2i,x) \ - ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \ - CHECKED_D2I_OF(type, d2i), \ - CHECKED_PTR_OF(const type, x))) - OPENSSL_EXPORT void *ASN1_item_dup(const ASN1_ITEM *it, void *x); -/* ASN1 alloc/free macros for when a type is only used internally */ - -#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type)) -#define M_ASN1_free_of(x, type) \ - ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type)) - #ifndef OPENSSL_NO_FP_API -OPENSSL_EXPORT void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x); - -#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \ - ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \ - CHECKED_D2I_OF(type, d2i), \ - in, \ - CHECKED_PPTR_OF(type, x))) - OPENSSL_EXPORT void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); -OPENSSL_EXPORT int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x); - -#define ASN1_i2d_fp_of(type,i2d,out,x) \ - (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \ - out, \ - CHECKED_PTR_OF(type, x))) - -#define ASN1_i2d_fp_of_const(type,i2d,out,x) \ - (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \ - out, \ - CHECKED_PTR_OF(const type, x))) - OPENSSL_EXPORT int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); OPENSSL_EXPORT int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags); #endif OPENSSL_EXPORT int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in); -OPENSSL_EXPORT void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x); - -#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \ - ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \ - CHECKED_D2I_OF(type, d2i), \ - in, \ - CHECKED_PPTR_OF(type, x))) - OPENSSL_EXPORT void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); -OPENSSL_EXPORT int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, void *x); - -#define ASN1_i2d_bio_of(type,i2d,out,x) \ - (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \ - out, \ - CHECKED_PTR_OF(type, x))) - -#define ASN1_i2d_bio_of_const(type,i2d,out,x) \ - (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \ - out, \ - CHECKED_PTR_OF(const type, x))) - OPENSSL_EXPORT int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x); OPENSSL_EXPORT int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a); OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a); diff --git a/include/openssl/bio.h b/include/openssl/bio.h index 70c2fbf7..8e2db65f 100644 --- a/include/openssl/bio.h +++ b/include/openssl/bio.h @@ -117,10 +117,14 @@ OPENSSL_EXPORT int BIO_read(BIO *bio, void *data, int len); // return a line for this call, remove the warning above. OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size); -// BIO_write writes |len| bytes from |data| to BIO. It returns the number of +// BIO_write writes |len| bytes from |data| to |bio|. It returns the number of // bytes written or a negative number on error. OPENSSL_EXPORT int BIO_write(BIO *bio, const void *data, int len); +// BIO_write_all writes |len| bytes from |data| to |bio|, looping as necessary. +// It returns one if all bytes were successfully written and zero on error. +OPENSSL_EXPORT int BIO_write_all(BIO *bio, const void *data, size_t len); + // BIO_puts writes a NUL terminated string from |buf| to |bio|. It returns the // number of bytes written or a negative number on error. OPENSSL_EXPORT int BIO_puts(BIO *bio, const char *buf); diff --git a/include/openssl/type_check.h b/include/openssl/type_check.h index da78d70c..e5d70479 100644 --- a/include/openssl/type_check.h +++ b/include/openssl/type_check.h @@ -72,10 +72,6 @@ extern "C" { // CHECKED_CAST casts |p| from type |from| to type |to|. #define CHECKED_CAST(to, from, p) ((to) (1 ? (p) : (from)0)) -// CHECKED_PTR_OF casts a given pointer to void* and statically checks that it -// was a pointer to |type|. -#define CHECKED_PTR_OF(type, p) CHECKED_CAST(void*, type*, (p)) - #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define OPENSSL_COMPILE_ASSERT(cond, msg) _Static_assert(cond, #msg) #else diff --git a/ssl/ssl_x509.cc b/ssl/ssl_x509.cc index 9fa800ff..ec203b22 100644 --- a/ssl/ssl_x509.cc +++ b/ssl/ssl_x509.cc @@ -999,17 +999,25 @@ int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) { return 1; } -static SSL_SESSION *ssl_session_new_with_crypto_x509(void) { - return ssl_session_new(&ssl_crypto_x509_method).release(); -} - SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) { - return ASN1_d2i_bio_of(SSL_SESSION, ssl_session_new_with_crypto_x509, - d2i_SSL_SESSION, bio, out); + uint8_t *data; + size_t len; + if (!BIO_read_asn1(bio, &data, &len, 1024 * 1024)) { + return 0; + } + bssl::UniquePtr free_data(data); + const uint8_t *ptr = data; + return d2i_SSL_SESSION(out, &ptr, static_cast(len)); } int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) { - return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session); + uint8_t *data; + size_t len; + if (!SSL_SESSION_to_bytes(session, &data, &len)) { + return 0; + } + bssl::UniquePtr free_data(data); + return BIO_write_all(bio, data, len); } IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)