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/pkcs7.h> 16 17 #include <openssl/bytestring.h> 18 #include <openssl/err.h> 19 #include <openssl/mem.h> 20 #include <openssl/pool.h> 21 #include <openssl/stack.h> 22 23 #include "internal.h" 24 #include "../bytestring/internal.h" 25 26 27 /* 1.2.840.113549.1.7.1 */ 28 static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 29 0x0d, 0x01, 0x07, 0x01}; 30 31 /* 1.2.840.113549.1.7.2 */ 32 static const uint8_t kPKCS7SignedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 33 0x0d, 0x01, 0x07, 0x02}; 34 35 /* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7 36 * SignedData blob from |cbs| and sets |*out| to point to the rest of the 37 * input. If the input is in BER format, then |*der_bytes| will be set to a 38 * pointer that needs to be freed by the caller once they have finished 39 * processing |*out| (which will be pointing into |*der_bytes|). 40 * 41 * It returns one on success or zero on error. On error, |*der_bytes| is 42 * NULL. */ 43 int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) { 44 size_t der_len; 45 CBS in, content_info, content_type, wrapped_signed_data, signed_data; 46 uint64_t version; 47 48 /* The input may be in BER format. */ 49 *der_bytes = NULL; 50 if (!CBS_asn1_ber_to_der(cbs, der_bytes, &der_len)) { 51 return 0; 52 } 53 if (*der_bytes != NULL) { 54 CBS_init(&in, *der_bytes, der_len); 55 } else { 56 CBS_init(&in, CBS_data(cbs), CBS_len(cbs)); 57 } 58 59 /* See https://tools.ietf.org/html/rfc2315#section-7 */ 60 if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) || 61 !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) { 62 goto err; 63 } 64 65 if (!CBS_mem_equal(&content_type, kPKCS7SignedData, 66 sizeof(kPKCS7SignedData))) { 67 OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NOT_PKCS7_SIGNED_DATA); 68 goto err; 69 } 70 71 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 72 if (!CBS_get_asn1(&content_info, &wrapped_signed_data, 73 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || 74 !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) || 75 !CBS_get_asn1_uint64(&signed_data, &version) || 76 !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) || 77 !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) { 78 goto err; 79 } 80 81 if (version < 1) { 82 OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_BAD_PKCS7_VERSION); 83 goto err; 84 } 85 86 CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data)); 87 return 1; 88 89 err: 90 OPENSSL_free(*der_bytes); 91 *der_bytes = NULL; 92 return 0; 93 } 94 95 int PKCS7_get_raw_certificates(STACK_OF(CRYPTO_BUFFER) *out_certs, CBS *cbs, 96 CRYPTO_BUFFER_POOL *pool) { 97 CBS signed_data, certificates; 98 uint8_t *der_bytes = NULL; 99 int ret = 0; 100 const size_t initial_certs_len = sk_CRYPTO_BUFFER_num(out_certs); 101 102 if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { 103 return 0; 104 } 105 106 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 107 if (!CBS_get_asn1(&signed_data, &certificates, 108 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 109 OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_CERTIFICATES_INCLUDED); 110 goto err; 111 } 112 113 while (CBS_len(&certificates) > 0) { 114 CBS cert; 115 if (!CBS_get_asn1_element(&certificates, &cert, CBS_ASN1_SEQUENCE)) { 116 goto err; 117 } 118 119 CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&cert, pool); 120 if (buf == NULL || 121 !sk_CRYPTO_BUFFER_push(out_certs, buf)) { 122 CRYPTO_BUFFER_free(buf); 123 goto err; 124 } 125 } 126 127 ret = 1; 128 129 err: 130 OPENSSL_free(der_bytes); 131 132 if (!ret) { 133 while (sk_CRYPTO_BUFFER_num(out_certs) != initial_certs_len) { 134 CRYPTO_BUFFER *buf = sk_CRYPTO_BUFFER_pop(out_certs); 135 CRYPTO_BUFFER_free(buf); 136 } 137 } 138 139 return ret; 140 } 141 142 int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg), 143 const void *arg) { 144 CBB outer_seq, oid, wrapped_seq, seq, version_bytes, digest_algos_set, 145 content_info; 146 147 /* See https://tools.ietf.org/html/rfc2315#section-7 */ 148 if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) || 149 !CBB_add_asn1(&outer_seq, &oid, CBS_ASN1_OBJECT) || 150 !CBB_add_bytes(&oid, kPKCS7SignedData, sizeof(kPKCS7SignedData)) || 151 !CBB_add_asn1(&outer_seq, &wrapped_seq, 152 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || 153 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 154 !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) || 155 !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) || 156 !CBB_add_u8(&version_bytes, 1) || 157 !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) || 158 !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) || 159 !CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) || 160 !CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) || 161 !cb(&seq, arg)) { 162 return 0; 163 } 164 165 return CBB_flush(out); 166 } 167