Constify ASN1_PCTX_*
[openssl.git] / crypto / asn1 / asn1_gen.c
index 0e1cc08894f0cb3b19cdead37aa0da6730b407ef..493a693aa3840c4b79b69710a70406d59d5f89a4 100644 (file)
@@ -1,63 +1,13 @@
-/* asn1_gen.c */
 /*
- * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
- * 2002.
- */
-/* ====================================================================
- * Copyright (c) 2002 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
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
+ * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
  */
 
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include <openssl/x509v3.h>
 
@@ -74,6 +24,8 @@
 #define ASN1_GEN_STR(str,val)   {str, sizeof(str) - 1, val}
 
 #define ASN1_FLAG_EXP_MAX       20
+/* Maximum number of nested sequences */
+#define ASN1_GEN_SEQ_MAX_DEPTH  50
 
 /* Input formats */
 
@@ -110,17 +62,20 @@ typedef struct {
     int exp_count;
 } tag_exp_arg;
 
+static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
+                              int *perr);
 static int bitstr_cb(const char *elem, int len, void *bitstr);
 static int asn1_cb(const char *elem, int len, void *bitstr);
 static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
                       int exp_constructed, int exp_pad, int imp_ok);
 static int parse_tagging(const char *vstart, int vlen, int *ptag,
                          int *pclass);
-static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf);
+static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
+                             int depth, int *perr);
 static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
 static int asn1_str2tag(const char *tagstr, int len);
 
-ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
+ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf)
 {
     X509V3_CTX cnf;
 
@@ -131,7 +86,17 @@ ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
     return ASN1_generate_v3(str, &cnf);
 }
 
-ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
+ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
+{
+    int err = 0;
+    ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err);
+    if (err)
+        ASN1err(ASN1_F_ASN1_GENERATE_V3, err);
+    return ret;
+}
+
+static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth,
+                              int *perr)
 {
     ASN1_TYPE *ret;
     tag_exp_arg asn1_tags;
@@ -144,7 +109,7 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
     unsigned char *p;
     const unsigned char *cp;
     int cpy_len;
-    long hdr_len;
+    long hdr_len = 0;
     int hdr_constructed = 0, hdr_tag, hdr_class;
     int r;
 
@@ -152,17 +117,22 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
     asn1_tags.imp_class = -1;
     asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
     asn1_tags.exp_count = 0;
-    if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
+    if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) {
+        *perr = ASN1_R_UNKNOWN_TAG;
         return NULL;
+    }
 
     if ((asn1_tags.utype == V_ASN1_SEQUENCE)
         || (asn1_tags.utype == V_ASN1_SET)) {
         if (!cnf) {
-            ASN1err(ASN1_F_ASN1_GENERATE_V3,
-                    ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
+            *perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG;
             return NULL;
         }
-        ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
+        if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) {
+            *perr = ASN1_R_ILLEGAL_NESTED_TAGGING;
+            return NULL;
+        }
+        ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr);
     } else
         ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
 
@@ -223,7 +193,7 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
     /* Allocate buffer for new encoding */
 
     new_der = OPENSSL_malloc(len);
-    if (!new_der)
+    if (new_der == NULL)
         goto err;
 
     /* Generate tagged encoding */
@@ -260,10 +230,8 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
     ret = d2i_ASN1_TYPE(NULL, &cp, len);
 
  err:
-    if (orig_der)
-        OPENSSL_free(orig_der);
-    if (new_der)
-        OPENSSL_free(new_der);
+    OPENSSL_free(orig_der);
+    OPENSSL_free(new_der);
 
     return ret;
 
@@ -280,7 +248,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
     int tmp_tag, tmp_class;
 
     if (elem == NULL)
-        return 0;
+        return -1;
 
     for (i = 0, p = elem; i < len; p++, i++) {
         /* Look for the ':' in name value pairs */
@@ -353,17 +321,17 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
         break;
 
     case ASN1_GEN_FLAG_FORMAT:
-        if(!vstart) {
+        if (!vstart) {
             ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
             return -1;
         }
-        if (!strncmp(vstart, "ASCII", 5))
+        if (strncmp(vstart, "ASCII", 5) == 0)
             arg->format = ASN1_GEN_FORMAT_ASCII;
-        else if (!strncmp(vstart, "UTF8", 4))
+        else if (strncmp(vstart, "UTF8", 4) == 0)
             arg->format = ASN1_GEN_FORMAT_UTF8;
-        else if (!strncmp(vstart, "HEX", 3))
+        else if (strncmp(vstart, "HEX", 3) == 0)
             arg->format = ASN1_GEN_FORMAT_HEX;
-        else if (!strncmp(vstart, "BITLIST", 7))
+        else if (strncmp(vstart, "BITLIST", 7) == 0)
             arg->format = ASN1_GEN_FORMAT_BITLIST;
         else {
             ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
@@ -434,7 +402,8 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
 
 /* Handle multiple types: SET and SEQUENCE */
 
-static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
+static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf,
+                             int depth, int *perr)
 {
     ASN1_TYPE *ret = NULL;
     STACK_OF(ASN1_TYPE) *sk = NULL;
@@ -453,7 +422,8 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
             goto bad;
         for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
             ASN1_TYPE *typ =
-                ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf);
+                generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf,
+                            depth + 1, perr);
             if (!typ)
                 goto bad;
             if (!sk_ASN1_TYPE_push(sk, typ))
@@ -472,15 +442,12 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
 
     if (derlen < 0)
         goto bad;
-
-    if (!(ret = ASN1_TYPE_new()))
+    if ((ret = ASN1_TYPE_new()) == NULL)
         goto bad;
-
-    if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
+    if ((ret->value.asn1_string = ASN1_STRING_type_new(utype)) == NULL)
         goto bad;
 
     ret->type = utype;
-
     ret->value.asn1_string->data = der;
     ret->value.asn1_string->length = derlen;
 
@@ -488,13 +455,10 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
 
  bad:
 
-    if (der)
-        OPENSSL_free(der);
+    OPENSSL_free(der);
 
-    if (sk)
-        sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
-    if (sect)
-        X509V3_section_free(cnf, sect);
+    sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+    X509V3_section_free(cnf, sect);
 
     return ret;
 }
@@ -603,8 +567,8 @@ static int asn1_str2tag(const char *tagstr, int len)
         len = strlen(tagstr);
 
     tntmp = tnst;
-    for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++) {
-        if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
+    for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) {
+        if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0))
             return tntmp->tag;
     }
 
@@ -614,15 +578,12 @@ static int asn1_str2tag(const char *tagstr, int len)
 static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
 {
     ASN1_TYPE *atmp = NULL;
-
     CONF_VALUE vtmp;
-
     unsigned char *rdata;
     long rdlen;
-
     int no_unused = 1;
 
-    if (!(atmp = ASN1_TYPE_new())) {
+    if ((atmp = ASN1_TYPE_new()) == NULL) {
         ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
@@ -659,7 +620,8 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
             ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
             goto bad_form;
         }
-        if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) {
+        if ((atmp->value.integer
+                    = s2i_ASN1_INTEGER(NULL, str)) == NULL) {
             ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER);
             goto bad_str;
         }
@@ -670,7 +632,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
             ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
             goto bad_form;
         }
-        if (!(atmp->value.object = OBJ_txt2obj(str, 0))) {
+        if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) {
             ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT);
             goto bad_str;
         }
@@ -682,7 +644,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
             ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT);
             goto bad_form;
         }
-        if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+        if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
             ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
             goto bad_str;
         }
@@ -707,7 +669,6 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
     case V_ASN1_UNIVERSALSTRING:
     case V_ASN1_GENERALSTRING:
     case V_ASN1_NUMERICSTRING:
-
         if (format == ASN1_GEN_FORMAT_ASCII)
             format = MBSTRING_ASC;
         else if (format == ASN1_GEN_FORMAT_UTF8)
@@ -726,25 +687,20 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
         break;
 
     case V_ASN1_BIT_STRING:
-
     case V_ASN1_OCTET_STRING:
-
-        if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+        if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
             ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
             goto bad_form;
         }
 
         if (format == ASN1_GEN_FORMAT_HEX) {
-
-            if (!(rdata = string_to_hex((char *)str, &rdlen))) {
+            if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) {
                 ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX);
                 goto bad_str;
             }
-
             atmp->value.asn1_string->data = rdata;
             atmp->value.asn1_string->length = rdlen;
             atmp->value.asn1_string->type = utype;
-
         } else if (format == ASN1_GEN_FORMAT_ASCII)
             ASN1_STRING_set(atmp->value.asn1_string, str, -1);
         else if ((format == ASN1_GEN_FORMAT_BITLIST)
@@ -812,7 +768,7 @@ static int mask_cb(const char *elem, int len, void *arg)
     int tag;
     if (elem == NULL)
         return 0;
-    if (len == 3 && !strncmp(elem, "DIR", 3)) {
+    if ((len == 3) && (strncmp(elem, "DIR", 3) == 0)) {
         *pmask |= B_ASN1_DIRECTORYSTRING;
         return 1;
     }