Home | History | Annotate | Download | only in x509
      1 /* Copyright (c) 2014, Google Inc.
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     14 
     15 #include <openssl/x509.h>
     16 
     17 #include <assert.h>
     18 #include <limits.h>
     19 
     20 #include <openssl/bytestring.h>
     21 #include <openssl/err.h>
     22 #include <openssl/mem.h>
     23 #include <openssl/obj.h>
     24 #include <openssl/pem.h>
     25 #include <openssl/stack.h>
     26 
     27 #include "../bytestring/internal.h"
     28 
     29 
     30 /* 1.2.840.113549.1.7.1 */
     31 static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
     32                                      0x0d, 0x01, 0x07, 0x01};
     33 
     34 /* 1.2.840.113549.1.7.2 */
     35 static const uint8_t kPKCS7SignedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
     36                                            0x0d, 0x01, 0x07, 0x02};
     37 
     38 /* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7
     39  * SignedData blob from |cbs| and sets |*out| to point to the rest of the
     40  * input. If the input is in BER format, then |*der_bytes| will be set to a
     41  * pointer that needs to be freed by the caller once they have finished
     42  * processing |*out| (which will be pointing into |*der_bytes|).
     43  *
     44  * It returns one on success or zero on error. On error, |*der_bytes| is
     45  * NULL. */
     46 static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) {
     47   size_t der_len;
     48   CBS in, content_info, content_type, wrapped_signed_data, signed_data;
     49   uint64_t version;
     50 
     51   /* The input may be in BER format. */
     52   *der_bytes = NULL;
     53   if (!CBS_asn1_ber_to_der(cbs, der_bytes, &der_len)) {
     54     return 0;
     55   }
     56   if (*der_bytes != NULL) {
     57     CBS_init(&in, *der_bytes, der_len);
     58   } else {
     59     CBS_init(&in, CBS_data(cbs), CBS_len(cbs));
     60   }
     61 
     62   /* See https://tools.ietf.org/html/rfc2315#section-7 */
     63   if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) ||
     64       !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {
     65     goto err;
     66   }
     67 
     68   if (!CBS_mem_equal(&content_type, kPKCS7SignedData,
     69                      sizeof(kPKCS7SignedData))) {
     70     OPENSSL_PUT_ERROR(X509, X509_R_NOT_PKCS7_SIGNED_DATA);
     71     goto err;
     72   }
     73 
     74   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
     75   if (!CBS_get_asn1(&content_info, &wrapped_signed_data,
     76                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
     77       !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) ||
     78       !CBS_get_asn1_uint64(&signed_data, &version) ||
     79       !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
     80       !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) {
     81     goto err;
     82   }
     83 
     84   if (version < 1) {
     85     OPENSSL_PUT_ERROR(X509, X509_R_BAD_PKCS7_VERSION);
     86     goto err;
     87   }
     88 
     89   CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data));
     90   return 1;
     91 
     92 err:
     93   OPENSSL_free(*der_bytes);
     94   *der_bytes = NULL;
     95   return 0;
     96 }
     97 
     98 int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
     99   CBS signed_data, certificates;
    100   uint8_t *der_bytes = NULL;
    101   int ret = 0;
    102   const size_t initial_certs_len = sk_X509_num(out_certs);
    103 
    104   if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) {
    105     return 0;
    106   }
    107 
    108   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
    109   if (!CBS_get_asn1(&signed_data, &certificates,
    110                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
    111     OPENSSL_PUT_ERROR(X509, X509_R_NO_CERTIFICATES_INCLUDED);
    112     goto err;
    113   }
    114 
    115   while (CBS_len(&certificates) > 0) {
    116     CBS cert;
    117     X509 *x509;
    118     const uint8_t *inp;
    119 
    120     if (!CBS_get_asn1_element(&certificates, &cert, CBS_ASN1_SEQUENCE)) {
    121       goto err;
    122     }
    123 
    124     if (CBS_len(&cert) > LONG_MAX) {
    125       goto err;
    126     }
    127     inp = CBS_data(&cert);
    128     x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert));
    129     if (!x509) {
    130       goto err;
    131     }
    132 
    133     assert(inp == CBS_data(&cert) + CBS_len(&cert));
    134 
    135     if (sk_X509_push(out_certs, x509) == 0) {
    136       X509_free(x509);
    137       goto err;
    138     }
    139   }
    140 
    141   ret = 1;
    142 
    143 err:
    144   OPENSSL_free(der_bytes);
    145 
    146   if (!ret) {
    147     while (sk_X509_num(out_certs) != initial_certs_len) {
    148       X509 *x509 = sk_X509_pop(out_certs);
    149       X509_free(x509);
    150     }
    151   }
    152 
    153   return ret;
    154 }
    155 
    156 int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) {
    157   CBS signed_data, crls;
    158   uint8_t *der_bytes = NULL;
    159   int ret = 0;
    160   const size_t initial_crls_len = sk_X509_CRL_num(out_crls);
    161 
    162   if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) {
    163     return 0;
    164   }
    165 
    166   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
    167 
    168   /* Even if only CRLs are included, there may be an empty certificates block.
    169    * OpenSSL does this, for example. */
    170   if (CBS_peek_asn1_tag(&signed_data,
    171                         CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) &&
    172       !CBS_get_asn1(&signed_data, NULL /* certificates */,
    173                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
    174     goto err;
    175   }
    176 
    177   if (!CBS_get_asn1(&signed_data, &crls,
    178                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
    179     OPENSSL_PUT_ERROR(X509, X509_R_NO_CRLS_INCLUDED);
    180     goto err;
    181   }
    182 
    183   while (CBS_len(&crls) > 0) {
    184     CBS crl_data;
    185     X509_CRL *crl;
    186     const uint8_t *inp;
    187 
    188     if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) {
    189       goto err;
    190     }
    191 
    192     if (CBS_len(&crl_data) > LONG_MAX) {
    193       goto err;
    194     }
    195     inp = CBS_data(&crl_data);
    196     crl = d2i_X509_CRL(NULL, &inp, (long)CBS_len(&crl_data));
    197     if (!crl) {
    198       goto err;
    199     }
    200 
    201     assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data));
    202 
    203     if (sk_X509_CRL_push(out_crls, crl) == 0) {
    204       X509_CRL_free(crl);
    205       goto err;
    206     }
    207   }
    208 
    209   ret = 1;
    210 
    211 err:
    212   OPENSSL_free(der_bytes);
    213 
    214   if (!ret) {
    215     while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
    216       X509_CRL_free(sk_X509_CRL_pop(out_crls));
    217     }
    218   }
    219 
    220   return ret;
    221 }
    222 
    223 int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) {
    224   uint8_t *data;
    225   long len;
    226   int ret;
    227 
    228   /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
    229    * internally will actually allow several other values too, including
    230    * "CERTIFICATE". */
    231   if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
    232                           PEM_STRING_PKCS7, pem_bio,
    233                           NULL /* password callback */,
    234                           NULL /* password callback argument */)) {
    235     return 0;
    236   }
    237 
    238   CBS cbs;
    239   CBS_init(&cbs, data, len);
    240   ret = PKCS7_get_certificates(out_certs, &cbs);
    241   OPENSSL_free(data);
    242   return ret;
    243 }
    244 
    245 int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) {
    246   uint8_t *data;
    247   long len;
    248   int ret;
    249 
    250   /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
    251    * internally will actually allow several other values too, including
    252    * "CERTIFICATE". */
    253   if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
    254                           PEM_STRING_PKCS7, pem_bio,
    255                           NULL /* password callback */,
    256                           NULL /* password callback argument */)) {
    257     return 0;
    258   }
    259 
    260   CBS cbs;
    261   CBS_init(&cbs, data, len);
    262   ret = PKCS7_get_CRLs(out_crls, &cbs);
    263   OPENSSL_free(data);
    264   return ret;
    265 }
    266 
    267 /* pkcs7_bundle writes a PKCS#7, SignedData structure to |out| and then calls
    268  * |cb| with a CBB to which certificate or CRL data can be written, and the
    269  * opaque context pointer, |arg|. The callback can return zero to indicate an
    270  * error.
    271  *
    272  * pkcs7_bundle returns one on success or zero on error. */
    273 static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg),
    274                         const void *arg) {
    275   CBB outer_seq, oid, wrapped_seq, seq, version_bytes, digest_algos_set,
    276       content_info;
    277 
    278   /* See https://tools.ietf.org/html/rfc2315#section-7 */
    279   if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
    280       !CBB_add_asn1(&outer_seq, &oid, CBS_ASN1_OBJECT) ||
    281       !CBB_add_bytes(&oid, kPKCS7SignedData, sizeof(kPKCS7SignedData)) ||
    282       !CBB_add_asn1(&outer_seq, &wrapped_seq,
    283                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
    284       /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
    285       !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
    286       !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) ||
    287       !CBB_add_u8(&version_bytes, 1) ||
    288       !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
    289       !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
    290       !CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) ||
    291       !CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
    292       !cb(&seq, arg)) {
    293     return 0;
    294   }
    295 
    296   return CBB_flush(out);
    297 }
    298 
    299 static int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) {
    300   const STACK_OF(X509) *certs = arg;
    301   size_t i;
    302   CBB certificates;
    303 
    304   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
    305   if (!CBB_add_asn1(out, &certificates,
    306                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
    307     return 0;
    308   }
    309 
    310   for (i = 0; i < sk_X509_num(certs); i++) {
    311     X509 *x509 = sk_X509_value(certs, i);
    312     uint8_t *buf;
    313     int len = i2d_X509(x509, NULL);
    314 
    315     if (len < 0 ||
    316         !CBB_add_space(&certificates, &buf, len) ||
    317         i2d_X509(x509, &buf) < 0) {
    318       return 0;
    319     }
    320   }
    321 
    322   return CBB_flush(out);
    323 }
    324 
    325 int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
    326   return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs);
    327 }
    328 
    329 static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) {
    330   const STACK_OF(X509_CRL) *crls = arg;
    331   size_t i;
    332   CBB crl_data;
    333 
    334   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
    335   if (!CBB_add_asn1(out, &crl_data,
    336                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
    337     return 0;
    338   }
    339 
    340   for (i = 0; i < sk_X509_CRL_num(crls); i++) {
    341     X509_CRL *crl = sk_X509_CRL_value(crls, i);
    342     uint8_t *buf;
    343     int len = i2d_X509_CRL(crl, NULL);
    344 
    345     if (len < 0 ||
    346         !CBB_add_space(&crl_data, &buf, len) ||
    347         i2d_X509_CRL(crl, &buf) < 0) {
    348       return 0;
    349     }
    350   }
    351 
    352   return CBB_flush(out);
    353 }
    354 
    355 int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
    356   return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
    357 }
    358