From de12116417081f7b834bca4a583f97169040ce52 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Thu, 16 Nov 2006 00:19:39 +0000 Subject: [PATCH] Initial, incomplete support for typesafe macros without using function casts. --- CHANGES | 7 +++++ crypto/asn1/asn1.h | 6 ++++ crypto/asn1/asn1_gen.c | 16 +++------- crypto/asn1/d2i_pr.c | 3 +- crypto/asn1/p5_pbe.c | 2 +- crypto/asn1/p5_pbev2.c | 4 +-- crypto/asn1/tasn_dec.c | 8 +++-- crypto/asn1/tasn_enc.c | 2 +- crypto/asn1/tasn_fre.c | 2 +- crypto/asn1/tasn_prn.c | 2 +- crypto/asn1/tasn_typ.c | 11 +++++++ crypto/conf/conf.h | 5 +-- crypto/dsa/dsa_ameth.c | 4 +-- crypto/stack/safestack.h | 67 +++++++++++++++++++++++++++++++++++++++- crypto/ui/ui.h | 2 +- 15 files changed, 111 insertions(+), 30 deletions(-) diff --git a/CHANGES b/CHANGES index 41efec4a88..e672750b2d 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,13 @@ Changes between 0.9.8e and 0.9.9 [xx XXX xxxx] + *) Initial incomplete changes to avoid need for function casts in OpenSSL + when OPENSSL_NO_FCAST is set: some compilers (gcc 4.2 and later) reject + their use. Safestack is reimplemented using inline functions: tests show + that these calls are typically optimized away by compilers so they have + no additional overhead. Update ASN1 to avoid use of legacy functions. + [Steve Henson] + *) Win32/64 targets are linked with Winsock2. [Andy Polyakov] diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index d2b8329098..bb8992c063 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -518,12 +518,18 @@ typedef struct asn1_type_st * contain the set or sequence bytes */ ASN1_STRING * set; ASN1_STRING * sequence; + ASN1_VALUE * asn1_value; } value; } ASN1_TYPE; DECLARE_STACK_OF(ASN1_TYPE) DECLARE_ASN1_SET_OF(ASN1_TYPE) +typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY; + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY) + typedef struct NETSCAPE_X509_st { ASN1_OCTET_STRING *header; diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c index e21c05e1d0..a6cd1ad20e 100644 --- a/crypto/asn1/asn1_gen.c +++ b/crypto/asn1/asn1_gen.c @@ -442,9 +442,9 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf) ASN1_TYPE *ret = NULL; STACK_OF(ASN1_TYPE) *sk = NULL; STACK_OF(CONF_VALUE) *sect = NULL; - unsigned char *der = NULL, *p; + unsigned char *der = NULL; int derlen; - int i, is_set; + int i; sk = sk_ASN1_TYPE_new_null(); if (section) { @@ -465,17 +465,9 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf) /* Now we has a STACK of the components, convert to the correct form */ if (utype == V_ASN1_SET) - is_set = 1; + derlen = i2d_ASN1_SET_ANY(sk, &der); else - is_set = 0; - - - derlen = i2d_ASN1_SET_OF_ASN1_TYPE(sk, NULL, i2d_ASN1_TYPE, utype, - V_ASN1_UNIVERSAL, is_set); - der = OPENSSL_malloc(derlen); - p = der; - i2d_ASN1_SET_OF_ASN1_TYPE(sk, &p, i2d_ASN1_TYPE, utype, - V_ASN1_UNIVERSAL, is_set); + derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der); if (!(ret = ASN1_TYPE_new())) goto bad; diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index 42e5a4e651..e90cfa9db8 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -124,8 +124,7 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, * by analyzing it we can determine the passed structure: this * assumes the input is surrounded by an ASN1 SEQUENCE. */ - inkey = d2i_ASN1_SET_OF_ASN1_TYPE(NULL, &p, length, d2i_ASN1_TYPE, - ASN1_TYPE_free, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); + inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length); /* Since we only need to discern "traditional format" RSA and DSA * keys we can just count the elements. */ diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c index da91170094..f3355e7a12 100644 --- a/crypto/asn1/p5_pbe.c +++ b/crypto/asn1/p5_pbe.c @@ -106,7 +106,7 @@ X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt, } astype->type = V_ASN1_SEQUENCE; - if(!ASN1_pack_string_of(PBEPARAM, pbe, i2d_PBEPARAM, + if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &astype->value.sequence)) { ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE); goto err; diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c index 3c1db8afcc..6724a3ec5d 100644 --- a/crypto/asn1/p5_pbev2.c +++ b/crypto/asn1/p5_pbev2.c @@ -188,7 +188,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, if(!(pbe2->keyfunc->parameter = ASN1_TYPE_new())) goto merr; - if(!ASN1_pack_string_of(PBKDF2PARAM, kdf, i2d_PBKDF2PARAM, + if(!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM), &pbe2->keyfunc->parameter->value.sequence)) goto merr; pbe2->keyfunc->parameter->type = V_ASN1_SEQUENCE; @@ -204,7 +204,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, /* Encode PBE2PARAM into parameter */ - if(!ASN1_pack_string_of(PBE2PARAM, pbe2, i2d_PBE2PARAM, + if(!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM), &ret->parameter->value.sequence)) goto merr; ret->parameter->type = V_ASN1_SEQUENCE; diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index c32510ffda..61632a9dd2 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -114,6 +114,8 @@ unsigned long ASN1_tag2bit(int tag) /* Macro to initialize and invalidate the cache */ #define asn1_tlc_clear(c) if (c) (c)->valid = 0 +/* Version to avoid compiler warning about 'c' always non-NULL */ +#define asn1_tlc_clear_nc(c) (c)->valid = 0 /* Decode an ASN1 item, this currently behaves just * like a standard 'd2i' function. 'in' points to @@ -130,7 +132,7 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, ASN1_VALUE *ptmpval = NULL; if (!pval) pval = &ptmpval; - asn1_tlc_clear(&c); + asn1_tlc_clear_nc(&c); if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) return *pval; return NULL; @@ -140,7 +142,7 @@ int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt) { ASN1_TLC c; - asn1_tlc_clear(&c); + asn1_tlc_clear_nc(&c); return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); } @@ -944,7 +946,7 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, if (utype != typ->type) ASN1_TYPE_set(typ, utype, NULL); opval = pval; - pval = (ASN1_VALUE **)&typ->value.ptr; + pval = &typ->value.asn1_value; } switch(utype) { diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index 685401e163..28f6e42521 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -597,7 +597,7 @@ int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, typ = (ASN1_TYPE *)*pval; utype = typ->type; *putype = utype; - pval = (ASN1_VALUE **)&typ->value.ptr; + pval = &typ->value.asn1_value; } else utype = *putype; diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c index 81b6ac898a..43c00dee81 100644 --- a/crypto/asn1/tasn_fre.c +++ b/crypto/asn1/tasn_fre.c @@ -221,7 +221,7 @@ void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) { ASN1_TYPE *typ = (ASN1_TYPE *)*pval; utype = typ->type; - pval = (ASN1_VALUE **)&typ->value.ptr; + pval = &typ->value.asn1_value; if (!*pval) return; } diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c index cf4c4ab374..d9f32bd890 100644 --- a/crypto/asn1/tasn_prn.c +++ b/crypto/asn1/tasn_prn.c @@ -533,7 +533,7 @@ static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, { ASN1_TYPE *atype = (ASN1_TYPE *)*fld; utype = atype->type; - fld = (ASN1_VALUE **)&atype->value.ptr; + fld = &atype->value.asn1_value; str = (ASN1_STRING *)*fld; if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) pname = NULL; diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c index 6f17f1bec7..ec96d48877 100644 --- a/crypto/asn1/tasn_typ.c +++ b/crypto/asn1/tasn_typ.c @@ -135,3 +135,14 @@ IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0) /* Special, OCTET STRING with indefinite length constructed support */ IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF) + +ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY) +ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY) + +ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY) +ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY) diff --git a/crypto/conf/conf.h b/crypto/conf/conf.h index 4c073dd831..39f21b69f2 100644 --- a/crypto/conf/conf.h +++ b/crypto/conf/conf.h @@ -79,8 +79,6 @@ typedef struct } CONF_VALUE; DECLARE_STACK_OF(CONF_VALUE) -DECLARE_STACK_OF(CONF_MODULE) -DECLARE_STACK_OF(CONF_IMODULE) struct conf_st; struct conf_method_st; @@ -105,6 +103,9 @@ struct conf_method_st typedef struct conf_imodule_st CONF_IMODULE; typedef struct conf_module_st CONF_MODULE; +DECLARE_STACK_OF(CONF_MODULE) +DECLARE_STACK_OF(CONF_IMODULE) + /* DSO module function typedefs */ typedef int conf_init_func(CONF_IMODULE *md, const CONF *cnf); typedef void conf_finish_func(CONF_IMODULE *md); diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index b38099175c..d39833ca0d 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -205,9 +205,7 @@ static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) if (*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { ASN1_TYPE *t1, *t2; - if(!(ndsa = ASN1_seq_unpack_ASN1_TYPE(p, pklen, - d2i_ASN1_TYPE, - ASN1_TYPE_free))) + if(!(ndsa = d2i_ASN1_SEQUENCE_ANY(NULL, &p, pklen))); goto decerr; if (sk_ASN1_TYPE_num(ndsa) != 2) goto decerr; diff --git a/crypto/stack/safestack.h b/crypto/stack/safestack.h index 5e55d15866..2d3a2e940e 100644 --- a/crypto/stack/safestack.h +++ b/crypto/stack/safestack.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2006 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 @@ -57,6 +57,69 @@ #include +#ifdef OPENSSL_NO_FCAST + +#ifndef OPENSSL_INLINE +#define OPENSSL_INLINE static inline +#endif + +#define STACK_OF(type) struct stack_st_##type + +#define IMPLEMENT_STACK_OF(type) /* nada (obsolete in new safestack approach)*/ + +#define DECLARE_STACK_OF(type) \ +STACK_OF(type) \ + { \ + STACK stack; \ + }; \ +OPENSSL_INLINE STACK_OF(type) *sk_##type##_new( \ + int (*cmp)(const type * const *, const type *const *)) \ + { return (STACK_OF(type) *)sk_new((int (*)())cmp); } \ +OPENSSL_INLINE STACK_OF(type) *sk_##type##_new_null() \ + { return (STACK_OF(type) *)sk_new_null(); } \ +OPENSSL_INLINE void sk_##type##_free(STACK_OF(type) *sk) \ + { sk_free((STACK *)sk); } \ +OPENSSL_INLINE int sk_##type##_num(const STACK_OF(type) *sk) \ + { return M_sk_num((const STACK *)sk); } \ +OPENSSL_INLINE type *sk_##type##_value(const STACK_OF(type) *sk,int n) \ + { return (type *)sk_value((STACK *)sk,n); } \ +OPENSSL_INLINE type *sk_##type##_set(STACK_OF(type) *sk,int n,type *v) \ + { return (type *)(sk_set((STACK *)sk,n,(char *)v)); } \ +OPENSSL_INLINE void sk_##type##_zero(STACK_OF(type) *sk) \ + { sk_zero((STACK *)sk); } \ +OPENSSL_INLINE int sk_##type##_push(STACK_OF(type) *sk,type *v) \ + { return sk_push((STACK *)sk,(char *)v); } \ +OPENSSL_INLINE int sk_##type##_unshift(STACK_OF(type) *sk,type *v) \ + { return sk_unshift((STACK *)sk,(char *)v); } \ +OPENSSL_INLINE int sk_##type##_find(STACK_OF(type) *sk,type *v) \ + { return sk_find((STACK *)sk,(char *)v); } \ +OPENSSL_INLINE type *sk_##type##_delete(STACK_OF(type) *sk,int n) \ + { return (type *)sk_delete((STACK *)sk,n); } \ +OPENSSL_INLINE void sk_##type##_delete_ptr(STACK_OF(type) *sk,type *v) \ + { sk_delete_ptr((STACK *)sk,(char *)v); } \ +OPENSSL_INLINE int sk_##type##_insert(STACK_OF(type) *sk,type *v,int n) \ + { return sk_insert((STACK *)sk,(char *)v,n); } \ +OPENSSL_INLINE int (*sk_##type##_set_cmp_func(STACK_OF(type) *sk, \ + int (*cmp)(const type * const *,const type * const *))) \ + (const type *const *,const type *const *) \ + { return (int (*)(const type * const *,const type *const *)) \ + sk_set_cmp_func((STACK *)sk,(int(*)(const char * const *, const char * const *))cmp); } \ +OPENSSL_INLINE STACK_OF(type) *sk_##type##_dup(STACK_OF(type) *sk) \ + { return (STACK_OF(type) *)sk_dup((STACK *)sk); } \ +OPENSSL_INLINE void sk_##type##_pop_free(STACK_OF(type) *sk,void (*func)(type *)) \ + { sk_pop_free((STACK *)sk,(void (*)(void *))func); } \ +OPENSSL_INLINE type *sk_##type##_shift(STACK_OF(type) *sk) \ + { return (type *)sk_shift((STACK *)sk); } \ +OPENSSL_INLINE type *sk_##type##_pop(STACK_OF(type) *sk) \ + { return (type *)sk_pop((STACK *)sk); } \ +OPENSSL_INLINE void sk_##type##_sort(STACK_OF(type) *sk) \ + { sk_sort((STACK *)sk); } \ +OPENSSL_INLINE int sk_##type##_is_sorted(const STACK_OF(type) *sk) \ + { return sk_is_sorted((const STACK *)sk); } + + +#else + typedef void (*openssl_fptr)(void); #define openssl_fcast(f) ((openssl_fptr)f) @@ -1918,4 +1981,6 @@ STACK_OF(type) \ SKM_PKCS12_decrypt_d2i(PKCS7, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq)) /* End of util/mkstack.pl block, you may now edit :-) */ +#endif + #endif /* !defined HEADER_SAFESTACK_H */ diff --git a/crypto/ui/ui.h b/crypto/ui/ui.h index 018296412b..c343595a39 100644 --- a/crypto/ui/ui.h +++ b/crypto/ui/ui.h @@ -287,8 +287,8 @@ UI_METHOD *UI_OpenSSL(void); /* The UI_STRING type is the data structure that contains all the needed info about a string or a prompt, including test data for a verification prompt. */ -DECLARE_STACK_OF(UI_STRING) typedef struct ui_string_st UI_STRING; +DECLARE_STACK_OF(UI_STRING) /* The different types of strings that are currently supported. This is only needed by method authors. */ -- 2.34.1