]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Backport some useful ASN1 utility functions from HEAD.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 2 Apr 2008 11:11:51 +0000 (11:11 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 2 Apr 2008 11:11:51 +0000 (11:11 +0000)
CHANGES
crypto/asn1/a_type.c
crypto/asn1/asn1.h
crypto/asn1/asn1_lib.c
crypto/asn1/asn1t.h
crypto/asn1/x_algor.c
crypto/x509/x509.h
crypto/x509/x509_att.c

diff --git a/CHANGES b/CHANGES
index 4211498e8159b7a328239a9c58505f381248168a..595008e96e7dd58655fbf6df5936c984f2ea6a22 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,15 @@
 
  Changes between 0.9.8g and 0.9.8h  [xx XXX xxxx]
 
+  *) Add utility functions to handle ASN1 structures. ASN1_STRING_set0():
+     sets string data without copying. X509_ALGOR_set0() and
+     X509_ALGOR_get0(): set and retrieve X509_ALGOR (AlgorithmIdentifier)
+     data. Attribute function X509at_get0_data_by_OBJ(): retrieves data
+     from an X509_ATTRIBUTE structure optionally checking it occurs only
+     once. ASN1_TYPE_set1(): set and ASN1_TYPE structure copying supplied
+     data.
+     [Steve Henson]
+
   *) Fix BN flag handling in RSA_eay_mod_exp() and BN_MONT_CTX_set()
      to get the expected BN_FLG_CONSTTIME behavior.
      [Bodo Moeller (Google)]
index a6acef16f3b3f27a5a51182ef289ced8796b562e..36beceacdb07e83ace8c91531822d8975edce57f 100644 (file)
@@ -59,6 +59,7 @@
 #include <stdio.h>
 #include "cryptlib.h"
 #include <openssl/asn1t.h>
+#include <openssl/objects.h>
 
 int ASN1_TYPE_get(ASN1_TYPE *a)
        {
@@ -79,6 +80,31 @@ void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
        a->value.ptr=value;
        }
 
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
+       {
+       if (!value || (type == V_ASN1_BOOLEAN))
+               {
+               void *p = (void *)value;
+               ASN1_TYPE_set(a, type, p);
+               }
+       else if (type == V_ASN1_OBJECT)
+               {
+               ASN1_OBJECT *odup;
+               odup = OBJ_dup(value);
+               if (!odup)
+                       return 0;
+               ASN1_TYPE_set(a, type, odup);
+               }
+       else
+               {
+               ASN1_STRING *sdup;
+               sdup = ASN1_STRING_dup((ASN1_STRING *)value);
+               if (!sdup)
+                       return 0;
+               ASN1_TYPE_set(a, type, sdup);
+               }
+       return 1;
+       }
 
 IMPLEMENT_STACK_OF(ASN1_TYPE)
 IMPLEMENT_ASN1_SET_OF(ASN1_TYPE)
index 9780d33594859be135d12c0c50a42be97471a14b..fdcc33a5dd4bcda3f182b5199f96d33022a7f6de 100644 (file)
@@ -159,6 +159,7 @@ extern "C" {
 #define MBSTRING_UNIV          (MBSTRING_FLAG|4)
 
 struct X509_algor_st;
+DECLARE_STACK_OF(X509_ALGOR)
 
 #define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
 #define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
@@ -311,8 +312,8 @@ typedef struct ASN1_VALUE_st ASN1_VALUE;
        int i2d_##name##_NDEF(name *a, unsigned char **out);
 
 #define DECLARE_ASN1_FUNCTIONS_const(name) \
-       name *name##_new(void); \
-       void name##_free(name *a);
+       DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
+       DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
 
 #define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
        type *name##_new(void); \
@@ -753,6 +754,7 @@ DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
 
 int ASN1_TYPE_get(ASN1_TYPE *a);
 void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
 
 ASN1_OBJECT *  ASN1_OBJECT_new(void );
 void           ASN1_OBJECT_free(ASN1_OBJECT *a);
@@ -775,6 +777,7 @@ int                 ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b);
   /* Since this is used to store all sorts of things, via macros, for now, make
      its data void * */
 int            ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+void           ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
 int ASN1_STRING_length(ASN1_STRING *x);
 void ASN1_STRING_length_set(ASN1_STRING *x, int n);
 int ASN1_STRING_type(ASN1_STRING *x);
@@ -927,6 +930,12 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
 
 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
 void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
 
index d5ae5b2258a4d156d4d7a9d93b6aea0a10523978..5af559ef8da70c5b24da7e620c28f17e6d9a05b9 100644 (file)
@@ -393,6 +393,14 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
        return(1);
        }
 
+void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
+       {
+       if (str->data)
+               OPENSSL_free(str->data);
+       str->data = data;
+       str->length = len;
+       }
+
 ASN1_STRING *ASN1_STRING_new(void)
        {
        return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
index adbc2a63dd0f3c0da0b7242b4bb73754a04009d8..bf315e65ed38b890223837fee7d4557d9f46c41a 100644 (file)
@@ -169,6 +169,9 @@ extern "C" {
 #define ASN1_NDEF_SEQUENCE(tname) \
        ASN1_SEQUENCE(tname)
 
+#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+       ASN1_SEQUENCE_cb(tname, cb)
+
 #define ASN1_SEQUENCE_cb(tname, cb) \
        static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
        ASN1_SEQUENCE(tname)
@@ -368,6 +371,10 @@ extern "C" {
 #define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
 
+/* EXPLICIT using indefinite length constructed form */
+#define ASN1_NDEF_EXP(stname, field, type, tag) \
+                       ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
+
 /* EXPLICIT OPTIONAL using indefinite length constructed form */
 #define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
index 00b9ea54a15fa4f8f02f0bf9195d63b3f57ae7f1..33533aba862bb8ae4e569c6af432bc78813d8a31 100644 (file)
@@ -66,8 +66,65 @@ ASN1_SEQUENCE(X509_ALGOR) = {
        ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
 } ASN1_SEQUENCE_END(X509_ALGOR)
 
+ASN1_ITEM_TEMPLATE(X509_ALGORS) = 
+       ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
+ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
+
 IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
 
 IMPLEMENT_STACK_OF(X509_ALGOR)
 IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
+
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
+       {
+       if (!alg)
+               return 0;
+       if (ptype != V_ASN1_UNDEF)
+               {
+               if (alg->parameter == NULL)
+                       alg->parameter = ASN1_TYPE_new();
+               if (alg->parameter == NULL)
+                       return 0;
+               }
+       if (alg)
+               {
+               if (alg->algorithm)
+                       ASN1_OBJECT_free(alg->algorithm);
+               alg->algorithm = aobj;
+               }
+       if (ptype == 0)
+               return 1;       
+       if (ptype == V_ASN1_UNDEF)
+               {
+               if (alg->parameter)
+                       {
+                       ASN1_TYPE_free(alg->parameter);
+                       alg->parameter = NULL;
+                       }
+               }
+       else
+               ASN1_TYPE_set(alg->parameter, ptype, pval);
+       return 1;
+       }
+
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+                                               X509_ALGOR *algor)
+       {
+       if (paobj)
+               *paobj = algor->algorithm;
+       if (pptype)
+               {
+               if (algor->parameter == NULL)
+                       {
+                       *pptype = V_ASN1_UNDEF;
+                       return;
+                       }
+               else
+                       *pptype = algor->parameter->type;
+               if (ppval)
+                       *ppval = algor->parameter->value.ptr;
+               }
+       }
+
index c431237ec7e94aaa3e6389b86667cefefbf0d62d..e71b5257e576135c544e353ad86cc08a2d09ae54 100644 (file)
@@ -146,9 +146,10 @@ struct X509_algor_st
        ASN1_TYPE *parameter;
        } /* X509_ALGOR */;
 
-DECLARE_STACK_OF(X509_ALGOR)
 DECLARE_ASN1_SET_OF(X509_ALGOR)
 
+typedef STACK_OF(X509_ALGOR) X509_ALGORS;
+
 typedef struct X509_val_st
        {
        ASN1_TIME *notBefore;
@@ -864,6 +865,10 @@ X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
 X509_CRL *X509_CRL_dup(X509_CRL *crl);
 X509_REQ *X509_REQ_dup(X509_REQ *req);
 X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval);
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+                                               X509_ALGOR *algor);
+
 X509_NAME *X509_NAME_dup(X509_NAME *xn);
 X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
 
@@ -885,6 +890,7 @@ X509_REQ *  X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
 X509 *         X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey);
 
 DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
 DECLARE_ASN1_FUNCTIONS(X509_VAL)
 
 DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
@@ -1194,6 +1200,8 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
 STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
                        const char *attrname, int type,
                        const unsigned char *bytes, int len);
+void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
+                               ASN1_OBJECT *obj, int lastpos, int type);
 X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
             int atrtype, const void *data, int len);
 X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
index 65968c4944aab7f2986eec2ee41fc5efbcb4041e..511b49d589840dd3494a1174e9331e974d08fb5a 100644 (file)
@@ -67,8 +67,7 @@
 
 int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
 {
-       if (!x) return 0;
-       return(sk_X509_ATTRIBUTE_num(x));
+       return sk_X509_ATTRIBUTE_num(x);
 }
 
 int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
@@ -193,6 +192,22 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
        return ret;
 }
 
+void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
+                               ASN1_OBJECT *obj, int lastpos, int type)
+{
+       int i;
+       X509_ATTRIBUTE *at;
+       i = X509at_get_attr_by_OBJ(x, obj, lastpos);
+       if (i == -1)
+               return NULL;
+       if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
+               return NULL;
+       at = X509at_get_attr(x, i);
+       if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
+               return NULL;
+       return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
+}
+
 X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
             int atrtype, const void *data, int len)
 {
@@ -270,8 +285,8 @@ int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
 int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len)
 {
        ASN1_TYPE *ttmp;
-       ASN1_STRING *stmp;
-       int atype;
+       ASN1_STRING *stmp = NULL;
+       int atype = 0;
        if (!attr) return 0;
        if(attrtype & MBSTRING_FLAG) {
                stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
@@ -281,16 +296,22 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *dat
                        return 0;
                }
                atype = stmp->type;
-       } else {
+       } else if (len != -1){
                if(!(stmp = ASN1_STRING_type_new(attrtype))) goto err;
                if(!ASN1_STRING_set(stmp, data, len)) goto err;
                atype = attrtype;
        }
        if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
        if(!(ttmp = ASN1_TYPE_new())) goto err;
+       if (len == -1)
+               {
+               if (!ASN1_TYPE_set1(ttmp, attrtype, data))
+                       goto err;
+               }
+       else
+               ASN1_TYPE_set(ttmp, atype, stmp);
        if(!sk_ASN1_TYPE_push(attr->value.set, ttmp)) goto err;
        attr->single = 0;
-       ASN1_TYPE_set(ttmp, atype, stmp);
        return 1;
        err:
        X509err(X509_F_X509_ATTRIBUTE_SET1_DATA, ERR_R_MALLOC_FAILURE);