pkcs7.c revision e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5
1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc. 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies. 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/x509.h> 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley#include <assert.h> 1846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bytestring.h> 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 21e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/mem.h> 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/obj.h> 2313a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley#include <openssl/pem.h> 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/stack.h> 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "../bytestring/internal.h" 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley/* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7 3046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * SignedData blob from |cbs| and sets |*out| to point to the rest of the 3146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * input. If the input is in BER format, then |*der_bytes| will be set to a 3246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * pointer that needs to be freed by the caller once they have finished 3346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * processing |*out| (which will be pointing into |*der_bytes|). 3446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * 3546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * It returns one on success or zero on error. On error, |*der_bytes| is 3646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * NULL. */ 3746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleystatic int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) { 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t der_len; 3946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS in, content_info, content_type, wrapped_signed_data, signed_data; 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint64_t version; 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* The input may be in BER format. */ 4346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley *der_bytes = NULL; 4446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!CBS_asn1_ber_to_der(cbs, der_bytes, &der_len)) { 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 4746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (*der_bytes != NULL) { 4846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS_init(&in, *der_bytes, der_len); 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_init(&in, CBS_data(cbs), CBS_len(cbs)); 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-7 */ 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) || 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) { 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) { 6046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley OPENSSL_PUT_ERROR(X509, pkcs7_parse_header, 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_R_NOT_PKCS7_SIGNED_DATA); 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&content_info, &wrapped_signed_data, 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) || 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1_uint64(&signed_data, &version) || 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) || 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) { 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (version < 1) { 7646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley OPENSSL_PUT_ERROR(X509, pkcs7_parse_header, 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_R_BAD_PKCS7_VERSION); 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 8146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data)); 8246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return 1; 8346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 8446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleyerr: 8546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (*der_bytes) { 8646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley OPENSSL_free(*der_bytes); 8746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley *der_bytes = NULL; 8846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 8946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 9046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return 0; 9146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley} 9246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 9346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleyint PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) { 9446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS signed_data, certificates; 9546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley uint8_t *der_bytes = NULL; 9646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley int ret = 0; 9746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley const size_t initial_certs_len = sk_X509_num(out_certs); 9846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 9946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { 10046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return 0; 10146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 10246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 10346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1(&signed_data, &certificates, 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates, 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_R_NO_CERTIFICATES_INCLUDED); 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (CBS_len(&certificates) > 0) { 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS cert; 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509 *x509; 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *inp; 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBS_get_asn1_element(&certificates, &cert, CBS_ASN1_SEQUENCE)) { 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley inp = CBS_data(&cert); 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley x509 = d2i_X509(NULL, &inp, CBS_len(&cert)); 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!x509) { 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 12646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley assert(inp == CBS_data(&cert) + CBS_len(&cert)); 12746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 12846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (sk_X509_push(out_certs, x509) == 0) { 12946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley X509_free(x509); 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (der_bytes) { 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(der_bytes); 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ret) { 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (sk_X509_num(out_certs) != initial_certs_len) { 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509 *x509 = sk_X509_pop(out_certs); 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509_free(x509); 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 15146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleyint PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) { 15246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS signed_data, crls; 15346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley uint8_t *der_bytes = NULL; 15446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley int ret = 0; 15546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley const size_t initial_crls_len = sk_X509_CRL_num(out_crls); 15646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 15746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { 15846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return 0; 15946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 16046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 16146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 16246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 16346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley /* Even if only CRLs are included, there may be an empty certificates block. 16446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * OpenSSL does this, for example. */ 16546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (CBS_peek_asn1_tag(&signed_data, 16646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) && 16746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley !CBS_get_asn1(&signed_data, NULL /* certificates */, 16846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 16946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley goto err; 17046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 17146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 17246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!CBS_get_asn1(&signed_data, &crls, 17346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { 17446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley OPENSSL_PUT_ERROR(X509, PKCS7_get_CRLs, 17546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley X509_R_NO_CRLS_INCLUDED); 17646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley goto err; 17746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 17846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 17946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley while (CBS_len(&crls) > 0) { 18046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS crl_data; 18146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley X509_CRL *crl; 18246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley const uint8_t *inp; 18346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 18446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) { 18546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley goto err; 18646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 18746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 18846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley inp = CBS_data(&crl_data); 18946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley crl = d2i_X509_CRL(NULL, &inp, CBS_len(&crl_data)); 19046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!crl) { 19146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley goto err; 19246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 19346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 19446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data)); 19546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 19646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (sk_X509_CRL_push(out_crls, crl) == 0) { 19746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley X509_CRL_free(crl); 19846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley goto err; 19946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 20046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 20146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 20246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley ret = 1; 20346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 20446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleyerr: 20546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (der_bytes) { 20646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley OPENSSL_free(der_bytes); 20746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 20846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 20946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!ret) { 21046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley while (sk_X509_CRL_num(out_crls) != initial_crls_len) { 21146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley X509_CRL_free(sk_X509_CRL_pop(out_crls)); 21246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 21346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 21446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 21546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return ret; 21646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley} 21746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 21813a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langleyint PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) { 21913a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley uint8_t *data; 22013a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley long len; 22113a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley int ret; 22213a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley 22313a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM 22413a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley * internally will actually allow several other values too, including 22513a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley * "CERTIFICATE". */ 22613a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */, 22713a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley PEM_STRING_PKCS7, pem_bio, 22813a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley NULL /* password callback */, 22913a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley NULL /* password callback argument */)) { 23013a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley return 0; 23113a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley } 23213a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley 23313a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley CBS cbs; 23413a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley CBS_init(&cbs, data, len); 23513a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley ret = PKCS7_get_certificates(out_certs, &cbs); 23613a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley OPENSSL_free(data); 23713a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley return ret; 23813a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley} 23913a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley 24013a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langleyint PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) { 24113a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley uint8_t *data; 24213a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley long len; 24313a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley int ret; 24413a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley 24513a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM 24613a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley * internally will actually allow several other values too, including 24713a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley * "CERTIFICATE". */ 24813a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */, 24913a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley PEM_STRING_PKCS7, pem_bio, 25013a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley NULL /* password callback */, 25113a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley NULL /* password callback argument */)) { 25213a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley return 0; 25313a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley } 25413a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley 25513a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley CBS cbs; 25613a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley CBS_init(&cbs, data, len); 25713a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley ret = PKCS7_get_CRLs(out_crls, &cbs); 25813a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley OPENSSL_free(data); 25913a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley return ret; 26013a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley} 26113a2c994a655cbabc53ccaae76c83d6ece01e183Adam Langley 26246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley/* pkcs7_bundle writes a PKCS#7, SignedData structure to |out| and then calls 26346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * |cb| with a CBB to which certificate or CRL data can be written, and the 26446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * opaque context pointer, |arg|. The callback can return zero to indicate an 26546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * error. 26646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * 26746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley * pkcs7_bundle returns one on success or zero on error. */ 26846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleystatic int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg), 26946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley const void *arg) { 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set, 27146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley content_info; 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-7 */ 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) || 275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) || 276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBB_add_asn1(&outer_seq, &wrapped_seq, 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || 278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) || 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) || 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBB_add_u8(&version_bytes, 1) || 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) || 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) || 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !OBJ_nid2cbb(&content_info, NID_pkcs7_data) || 28546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley !cb(&seq, arg)) { 28646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return 0; 28746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 28846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 28946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return CBB_flush(out); 29046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley} 29146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 29246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleystatic int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) { 29346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley const STACK_OF(X509) *certs = arg; 29446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley size_t i; 29546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBB certificates; 29646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 29746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 29846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!CBB_add_asn1(out, &certificates, 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (i = 0; i < sk_X509_num(certs); i++) { 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley X509 *x509 = sk_X509_value(certs, i); 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *buf; 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int len = i2d_X509(x509, NULL); 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len < 0 || 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !CBB_add_space(&certificates, &buf, len) || 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i2d_X509(x509, &buf) < 0) { 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return CBB_flush(out); 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 31746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 31846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleyint PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) { 31946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs); 32046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley} 32146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 32246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleystatic int pkcs7_bundle_crls_cb(CBB *out, const void *arg) { 32346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley const STACK_OF(X509_CRL) *crls = arg; 32446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley size_t i; 32546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBB crl_data; 32646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 32746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ 32846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (!CBB_add_asn1(out, &crl_data, 32946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { 33046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return 0; 33146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 33246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 33346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley for (i = 0; i < sk_X509_CRL_num(crls); i++) { 33446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley X509_CRL *crl = sk_X509_CRL_value(crls, i); 33546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley uint8_t *buf; 33646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley int len = i2d_X509_CRL(crl, NULL); 33746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 33846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley if (len < 0 || 33946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley !CBB_add_space(&crl_data, &buf, len) || 34046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley i2d_X509_CRL(crl, &buf) < 0) { 34146ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return 0; 34246ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 34346ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley } 34446ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 34546ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return CBB_flush(out); 34646ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley} 34746ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley 34846ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langleyint PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) { 34946ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls); 35046ba7161f20f8b1e6729384a98e1b9973ed3c908Adam Langley} 351