LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/x509 - pkcs7.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 798 1188 67.2 %
Date: 2020-10-30 04:50:48 Functions: 32 39 82.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003-2015 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2015 Red Hat, Inc.
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : /* Functions that relate on PKCS7 certificate lists parsing.
      25             :  */
      26             : 
      27             : #include "gnutls_int.h"
      28             : #include <libtasn1.h>
      29             : 
      30             : #include <datum.h>
      31             : #include <global.h>
      32             : #include "errors.h"
      33             : #include <common.h>
      34             : #include <x509_b64.h>
      35             : #include <pkcs7_int.h>
      36             : #include <gnutls/abstract.h>
      37             : #include <gnutls/pkcs7.h>
      38             : 
      39             : #define ATTR_MESSAGE_DIGEST "1.2.840.113549.1.9.4"
      40             : #define ATTR_SIGNING_TIME "1.2.840.113549.1.9.5"
      41             : #define ATTR_CONTENT_TYPE "1.2.840.113549.1.9.3"
      42             : 
      43             : static const uint8_t one = 1;
      44             : 
      45             : /* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE,
      46             :  * which holds them. If raw is non null then the raw decoded
      47             :  * data are copied (they are locally allocated) there.
      48             :  */
      49         203 : static int _decode_pkcs7_signed_data(gnutls_pkcs7_t pkcs7)
      50             : {
      51         203 :         ASN1_TYPE c2;
      52         203 :         int len, result;
      53         203 :         gnutls_datum_t tmp = {NULL, 0};
      54             : 
      55         203 :         len = MAX_OID_SIZE - 1;
      56         203 :         result = asn1_read_value(pkcs7->pkcs7, "contentType", pkcs7->encap_data_oid, &len);
      57         203 :         if (result != ASN1_SUCCESS) {
      58           1 :                 gnutls_assert();
      59           1 :                 return _gnutls_asn2err(result);
      60             :         }
      61             : 
      62         202 :         if (strcmp(pkcs7->encap_data_oid, SIGNED_DATA_OID) != 0) {
      63          11 :                 gnutls_assert();
      64          11 :                 _gnutls_debug_log("Unknown PKCS7 Content OID '%s'\n", pkcs7->encap_data_oid);
      65          11 :                 return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
      66             :         }
      67             : 
      68         191 :         if ((result = asn1_create_element
      69             :              (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData",
      70             :               &c2)) != ASN1_SUCCESS) {
      71           0 :                 gnutls_assert();
      72           0 :                 return _gnutls_asn2err(result);
      73             :         }
      74             : 
      75             :         /* the Signed-data has been created, so
      76             :          * decode them.
      77             :          */
      78         191 :         result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
      79         191 :         if (result < 0) {
      80           0 :                 gnutls_assert();
      81           0 :                 goto cleanup;
      82             :         }
      83             : 
      84             :         /* Step 1. In case of a signed structure extract certificate set.
      85             :          */
      86             : 
      87         191 :         result = asn1_der_decoding(&c2, tmp.data, tmp.size, NULL);
      88         191 :         if (result != ASN1_SUCCESS) {
      89           1 :                 gnutls_assert();
      90           1 :                 result = _gnutls_asn2err(result);
      91           1 :                 goto cleanup;
      92             :         }
      93             : 
      94             :         /* read the encapsulated content */
      95         190 :         len = MAX_OID_SIZE - 1;
      96         190 :         result =
      97         190 :             asn1_read_value(c2, "encapContentInfo.eContentType", pkcs7->encap_data_oid, &len);
      98         190 :         if (result != ASN1_SUCCESS) {
      99           1 :                 gnutls_assert();
     100           1 :                 result = _gnutls_asn2err(result);
     101           1 :                 goto cleanup;
     102             :         }
     103             : 
     104         189 :         if (strcmp(pkcs7->encap_data_oid, DATA_OID) != 0
     105         129 :             && strcmp(pkcs7->encap_data_oid, DIGESTED_DATA_OID) != 0) {
     106         128 :                 _gnutls_debug_log
     107             :                     ("Unknown PKCS#7 Encapsulated Content OID '%s'; treating as raw data\n",
     108             :                      pkcs7->encap_data_oid);
     109             : 
     110             :         }
     111             : 
     112             :         /* Try reading as octet string according to rfc5652. If that fails, attempt
     113             :          * a raw read according to rfc2315 */
     114         189 :         result = _gnutls_x509_read_string(c2, "encapContentInfo.eContent", &pkcs7->der_signed_data, ASN1_ETYPE_OCTET_STRING, 1);
     115         189 :         if (result < 0) {
     116         141 :                 result = _gnutls_x509_read_value(c2, "encapContentInfo.eContent", &pkcs7->der_signed_data);
     117         141 :                 if (result < 0) {
     118          78 :                         pkcs7->der_signed_data.data = NULL;
     119          78 :                         pkcs7->der_signed_data.size = 0;
     120             :                 } else {
     121          63 :                         int tag_len, len_len;
     122          63 :                         unsigned char cls;
     123          63 :                         unsigned long tag;
     124             : 
     125             :                         /* we skip the embedded element's tag and length - uncharted territorry - used by MICROSOFT_CERT_TRUST_LIST */
     126          63 :                         result = asn1_get_tag_der(pkcs7->der_signed_data.data, pkcs7->der_signed_data.size, &cls, &tag_len, &tag);
     127          63 :                         if (result != ASN1_SUCCESS) {
     128           0 :                                 gnutls_assert();
     129           0 :                                 result = _gnutls_asn2err(result);
     130           0 :                                 goto cleanup;
     131             :                         }
     132             : 
     133          63 :                         result = asn1_get_length_ber(pkcs7->der_signed_data.data+tag_len, pkcs7->der_signed_data.size-tag_len, &len_len);
     134          63 :                         if (result < 0) {
     135           0 :                                 gnutls_assert();
     136           0 :                                 result = GNUTLS_E_ASN1_DER_ERROR;
     137           0 :                                 goto cleanup;
     138             :                         }
     139             : 
     140          63 :                         tag_len += len_len;
     141          63 :                         memmove(pkcs7->der_signed_data.data, &pkcs7->der_signed_data.data[tag_len], pkcs7->der_signed_data.size-tag_len);
     142          63 :                         pkcs7->der_signed_data.size-=tag_len;
     143             :                 }
     144             :         }
     145             : 
     146         189 :         pkcs7->signed_data = c2;
     147         189 :         gnutls_free(tmp.data);
     148             : 
     149         189 :         return 0;
     150             : 
     151           2 :  cleanup:
     152           2 :         gnutls_free(tmp.data);
     153           2 :         if (c2)
     154           1 :                 asn1_delete_structure(&c2);
     155             :         return result;
     156             : }
     157             : 
     158         218 : static int pkcs7_reinit(gnutls_pkcs7_t pkcs7)
     159             : {
     160         218 :         int result;
     161             : 
     162         218 :         asn1_delete_structure(&pkcs7->pkcs7);
     163             : 
     164         218 :         result = asn1_create_element(_gnutls_get_pkix(),
     165             :                                      "PKIX1.pkcs-7-ContentInfo", &pkcs7->pkcs7);
     166         218 :         if (result != ASN1_SUCCESS) {
     167           0 :                 result = _gnutls_asn2err(result);
     168           0 :                 gnutls_assert();
     169           0 :                 return result;
     170             :         }
     171             : 
     172             :         return 0;
     173             : }
     174             : 
     175             : /**
     176             :  * gnutls_pkcs7_init:
     177             :  * @pkcs7: A pointer to the type to be initialized
     178             :  *
     179             :  * This function will initialize a PKCS7 structure. PKCS7 structures
     180             :  * usually contain lists of X.509 Certificates and X.509 Certificate
     181             :  * revocation lists.
     182             :  *
     183             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     184             :  *   negative error value.
     185             :  **/
     186         218 : int gnutls_pkcs7_init(gnutls_pkcs7_t * pkcs7)
     187             : {
     188         218 :         *pkcs7 = gnutls_calloc(1, sizeof(gnutls_pkcs7_int));
     189             : 
     190         218 :         if (*pkcs7) {
     191         218 :                 int result = pkcs7_reinit(*pkcs7);
     192         218 :                 if (result < 0) {
     193           0 :                         gnutls_assert();
     194           0 :                         gnutls_free(*pkcs7);
     195           0 :                         return result;
     196             :                 }
     197             :                 return 0;       /* success */
     198             :         }
     199             :         return GNUTLS_E_MEMORY_ERROR;
     200             : }
     201             : 
     202             : /**
     203             :  * gnutls_pkcs7_deinit:
     204             :  * @pkcs7: the type to be deinitialized
     205             :  *
     206             :  * This function will deinitialize a PKCS7 type.
     207             :  **/
     208         218 : void gnutls_pkcs7_deinit(gnutls_pkcs7_t pkcs7)
     209             : {
     210         218 :         if (!pkcs7)
     211             :                 return;
     212             : 
     213         218 :         if (pkcs7->pkcs7)
     214         217 :                 asn1_delete_structure(&pkcs7->pkcs7);
     215             : 
     216         218 :         if (pkcs7->signed_data)
     217         203 :                 asn1_delete_structure(&pkcs7->signed_data);
     218             : 
     219         218 :         _gnutls_free_datum(&pkcs7->der_signed_data);
     220             : 
     221         218 :         gnutls_free(pkcs7);
     222             : }
     223             : 
     224             : /**
     225             :  * gnutls_pkcs7_import:
     226             :  * @pkcs7: The data to store the parsed PKCS7.
     227             :  * @data: The DER or PEM encoded PKCS7.
     228             :  * @format: One of DER or PEM
     229             :  *
     230             :  * This function will convert the given DER or PEM encoded PKCS7 to
     231             :  * the native #gnutls_pkcs7_t format.  The output will be stored in
     232             :  * @pkcs7.
     233             :  *
     234             :  * If the PKCS7 is PEM encoded it should have a header of "PKCS7".
     235             :  *
     236             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     237             :  *   negative error value.
     238             :  **/
     239             : int
     240         204 : gnutls_pkcs7_import(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * data,
     241             :                     gnutls_x509_crt_fmt_t format)
     242             : {
     243         204 :         int result = 0, need_free = 0;
     244         204 :         gnutls_datum_t _data;
     245             : 
     246         204 :         if (pkcs7 == NULL)
     247             :                 return GNUTLS_E_INVALID_REQUEST;
     248             : 
     249         204 :         _data.data = data->data;
     250         204 :         _data.size = data->size;
     251             : 
     252             :         /* If the PKCS7 is in PEM format then decode it
     253             :          */
     254         204 :         if (format == GNUTLS_X509_FMT_PEM) {
     255          32 :                 result =
     256          64 :                     _gnutls_fbase64_decode(PEM_PKCS7, data->data,
     257          32 :                                            data->size, &_data);
     258             : 
     259          32 :                 if (result < 0) {
     260           0 :                         gnutls_assert();
     261           0 :                         return result;
     262             :                 }
     263             : 
     264             :                 need_free = 1;
     265             :         }
     266             : 
     267         204 :         if (pkcs7->expanded) {
     268           0 :                 result = pkcs7_reinit(pkcs7);
     269           0 :                 if (result < 0) {
     270           0 :                         gnutls_assert();
     271           0 :                         goto cleanup;
     272             :                 }
     273             :         }
     274         204 :         pkcs7->expanded = 1;
     275             : 
     276         204 :         result = asn1_der_decoding(&pkcs7->pkcs7, _data.data, _data.size, NULL);
     277         204 :         if (result != ASN1_SUCCESS) {
     278           1 :                 result = _gnutls_asn2err(result);
     279           1 :                 gnutls_assert();
     280           1 :                 goto cleanup;
     281             :         }
     282             : 
     283             :         /* Decode the signed data.
     284             :          */
     285         203 :         result = _decode_pkcs7_signed_data(pkcs7);
     286         203 :         if (result < 0) {
     287          14 :                 gnutls_assert();
     288          14 :                 goto cleanup;
     289             :         }
     290             : 
     291             :         result = 0;
     292             : 
     293         204 :  cleanup:
     294         204 :         if (need_free)
     295          32 :                 _gnutls_free_datum(&_data);
     296             :         return result;
     297             : }
     298             : 
     299             : /**
     300             :  * gnutls_pkcs7_get_crt_raw2:
     301             :  * @pkcs7: should contain a gnutls_pkcs7_t type
     302             :  * @indx: contains the index of the certificate to extract
     303             :  * @cert: will hold the contents of the certificate; must be deallocated with gnutls_free()
     304             :  *
     305             :  * This function will return a certificate of the PKCS7 or RFC2630
     306             :  * certificate set.
     307             :  *
     308             :  * After the last certificate has been read
     309             :  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
     310             :  *
     311             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     312             :  *   negative error value.  If the provided buffer is not long enough,
     313             :  *   then @certificate_size is updated and
     314             :  *   %GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
     315             :  *
     316             :  * Since: 3.4.2
     317             :  **/
     318             : int
     319       11358 : gnutls_pkcs7_get_crt_raw2(gnutls_pkcs7_t pkcs7,
     320             :                           unsigned indx, gnutls_datum_t * cert)
     321             : {
     322       11358 :         int result, len;
     323       11358 :         char root2[MAX_NAME_SIZE];
     324       11358 :         char oid[MAX_OID_SIZE];
     325       11358 :         gnutls_datum_t tmp = { NULL, 0 };
     326             : 
     327       11358 :         if (pkcs7 == NULL)
     328             :                 return GNUTLS_E_INVALID_REQUEST;
     329             : 
     330             :         /* Step 2. Parse the CertificateSet
     331             :          */
     332       11358 :         snprintf(root2, sizeof(root2), "certificates.?%u", indx + 1);
     333             : 
     334       11358 :         len = sizeof(oid) - 1;
     335             : 
     336       11358 :         result = asn1_read_value(pkcs7->signed_data, root2, oid, &len);
     337             : 
     338       11358 :         if (result == ASN1_VALUE_NOT_FOUND) {
     339           0 :                 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     340           0 :                 goto cleanup;
     341             :         }
     342             : 
     343       11358 :         if (result != ASN1_SUCCESS) {
     344           0 :                 gnutls_assert();
     345           0 :                 result = _gnutls_asn2err(result);
     346           0 :                 goto cleanup;
     347             :         }
     348             : 
     349             :         /* if 'Certificate' is the choice found:
     350             :          */
     351       11358 :         if (strcmp(oid, "certificate") == 0) {
     352       11358 :                 int start, end;
     353             : 
     354       11358 :                 result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
     355       11358 :                 if (result < 0) {
     356           0 :                         gnutls_assert();
     357           0 :                         goto cleanup;
     358             :                 }
     359             : 
     360       11358 :                 result =
     361       22716 :                     asn1_der_decoding_startEnd(pkcs7->signed_data, tmp.data,
     362       11358 :                                                tmp.size, root2, &start, &end);
     363             : 
     364       11358 :                 if (result != ASN1_SUCCESS) {
     365           0 :                         gnutls_assert();
     366           0 :                         result = _gnutls_asn2err(result);
     367           0 :                         goto cleanup;
     368             :                 }
     369             : 
     370       11358 :                 end = end - start + 1;
     371             : 
     372       11358 :                 result = _gnutls_set_datum(cert, &tmp.data[start], end);
     373             :         } else {
     374             :                 result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
     375             :         }
     376             : 
     377       11358 :  cleanup:
     378       11358 :         _gnutls_free_datum(&tmp);
     379       11358 :         return result;
     380             : }
     381             : 
     382             : /**
     383             :  * gnutls_pkcs7_get_crt_raw:
     384             :  * @pkcs7: should contain a gnutls_pkcs7_t type
     385             :  * @indx: contains the index of the certificate to extract
     386             :  * @certificate: the contents of the certificate will be copied
     387             :  *   there (may be null)
     388             :  * @certificate_size: should hold the size of the certificate
     389             :  *
     390             :  * This function will return a certificate of the PKCS7 or RFC2630
     391             :  * certificate set.
     392             :  *
     393             :  * After the last certificate has been read
     394             :  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
     395             :  *
     396             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     397             :  *   negative error value.  If the provided buffer is not long enough,
     398             :  *   then @certificate_size is updated and
     399             :  *   %GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
     400             :  **/
     401             : int
     402           0 : gnutls_pkcs7_get_crt_raw(gnutls_pkcs7_t pkcs7,
     403             :                          unsigned indx, void *certificate,
     404             :                          size_t * certificate_size)
     405             : {
     406           0 :         int ret;
     407           0 :         gnutls_datum_t tmp = { NULL, 0 };
     408             : 
     409           0 :         ret = gnutls_pkcs7_get_crt_raw2(pkcs7, indx, &tmp);
     410           0 :         if (ret < 0)
     411           0 :                 return gnutls_assert_val(ret);
     412             : 
     413           0 :         if ((unsigned)tmp.size > *certificate_size) {
     414           0 :                 *certificate_size = tmp.size;
     415           0 :                 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
     416           0 :                 goto cleanup;
     417             :         }
     418             : 
     419           0 :         *certificate_size = tmp.size;
     420           0 :         if (certificate)
     421           0 :                 memcpy(certificate, tmp.data, tmp.size);
     422             : 
     423           0 :  cleanup:
     424           0 :         _gnutls_free_datum(&tmp);
     425           0 :         return ret;
     426             : }
     427             : 
     428             : /**
     429             :  * gnutls_pkcs7_get_crt_count:
     430             :  * @pkcs7: should contain a #gnutls_pkcs7_t type
     431             :  *
     432             :  * This function will return the number of certificates in the PKCS7
     433             :  * or RFC2630 certificate set.
     434             :  *
     435             :  * Returns: On success, a positive number is returned, otherwise a
     436             :  *   negative error value.
     437             :  **/
     438         170 : int gnutls_pkcs7_get_crt_count(gnutls_pkcs7_t pkcs7)
     439             : {
     440         170 :         int result, count;
     441             : 
     442         170 :         if (pkcs7 == NULL)
     443             :                 return GNUTLS_E_INVALID_REQUEST;
     444             : 
     445             :         /* Step 2. Count the CertificateSet */
     446             : 
     447         170 :         result =
     448         170 :             asn1_number_of_elements(pkcs7->signed_data, "certificates", &count);
     449         170 :         if (result != ASN1_SUCCESS) {
     450          91 :                 gnutls_assert();
     451          91 :                 return 0;       /* no certificates */
     452             :         }
     453             : 
     454          79 :         return count;
     455             : }
     456             : 
     457             : /**
     458             :  * gnutls_pkcs7_signature_info_deinit:
     459             :  * @info: should point to a #gnutls_pkcs7_signature_info_st structure
     460             :  *
     461             :  * This function will deinitialize any allocated value in the
     462             :  * provided #gnutls_pkcs7_signature_info_st.
     463             :  *
     464             :  * Since: 3.4.2
     465             :  **/
     466        1587 : void gnutls_pkcs7_signature_info_deinit(gnutls_pkcs7_signature_info_st * info)
     467             : {
     468        1587 :         gnutls_free(info->sig.data);
     469        1587 :         gnutls_free(info->issuer_dn.data);
     470        1587 :         gnutls_free(info->signer_serial.data);
     471        1587 :         gnutls_free(info->issuer_keyid.data);
     472        1587 :         gnutls_pkcs7_attrs_deinit(info->signed_attrs);
     473        1587 :         gnutls_pkcs7_attrs_deinit(info->unsigned_attrs);
     474        1587 :         memset(info, 0, sizeof(*info));
     475        1587 : }
     476             : 
     477          46 : static time_t parse_time(gnutls_pkcs7_t pkcs7, const char *root)
     478             : {
     479          46 :         char tval[128];
     480          46 :         ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
     481          46 :         time_t ret;
     482          46 :         int result, len;
     483             : 
     484          46 :         result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Time", &c2);
     485          46 :         if (result != ASN1_SUCCESS) {
     486           0 :                 ret = -1;
     487           0 :                 gnutls_assert();
     488           0 :                 goto cleanup;
     489             :         }
     490             : 
     491          46 :         len = sizeof(tval);
     492          46 :         result = asn1_read_value(pkcs7->signed_data, root, tval, &len);
     493          46 :         if (result != ASN1_SUCCESS) {
     494           0 :                 ret = -1;
     495           0 :                 gnutls_assert();
     496           0 :                 goto cleanup;
     497             :         }
     498             : 
     499          46 :         result = _asn1_strict_der_decode(&c2, tval, len, NULL);
     500          46 :         if (result != ASN1_SUCCESS) {
     501           0 :                 ret = -1;
     502           0 :                 gnutls_assert();
     503           0 :                 goto cleanup;
     504             :         }
     505             : 
     506          46 :         ret = _gnutls_x509_get_time(c2, "", 0);
     507             : 
     508          46 :  cleanup:
     509          46 :         asn1_delete_structure(&c2);
     510          46 :         return ret;
     511             : }
     512             : 
     513             : /**
     514             :  * gnutls_pkcs7_get_signature_count:
     515             :  * @pkcs7: should contain a #gnutls_pkcs7_t type
     516             :  *
     517             :  * This function will return the number of signatures in the PKCS7
     518             :  * structure.
     519             :  *
     520             :  * Returns: On success, a positive number is returned, otherwise a
     521             :  *   negative error value.
     522             :  *
     523             :  * Since: 3.4.3
     524             :  **/
     525           0 : int gnutls_pkcs7_get_signature_count(gnutls_pkcs7_t pkcs7)
     526             : {
     527           0 :         int ret, count;
     528             : 
     529           0 :         if (pkcs7 == NULL)
     530             :                 return GNUTLS_E_INVALID_REQUEST;
     531             : 
     532           0 :         ret =
     533           0 :             asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
     534           0 :         if (ret != ASN1_SUCCESS) {
     535           0 :                 gnutls_assert();
     536           0 :                 return 0;
     537             :         }
     538             : 
     539           0 :         return count;
     540             : }
     541             : 
     542             : /**
     543             :  * gnutls_pkcs7_get_signature_info:
     544             :  * @pkcs7: should contain a #gnutls_pkcs7_t type
     545             :  * @idx: the index of the signature info to check
     546             :  * @info: will contain the output signature
     547             :  *
     548             :  * This function will return information about the signature identified
     549             :  * by idx in the provided PKCS #7 structure. The information should be
     550             :  * deinitialized using gnutls_pkcs7_signature_info_deinit().
     551             :  *
     552             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     553             :  *   negative error value.
     554             :  *
     555             :  * Since: 3.4.2
     556             :  **/
     557        1744 : int gnutls_pkcs7_get_signature_info(gnutls_pkcs7_t pkcs7, unsigned idx,
     558             :                                     gnutls_pkcs7_signature_info_st * info)
     559             : {
     560        1744 :         int ret, count, len;
     561        1744 :         char root[256];
     562        1744 :         char oid[MAX_OID_SIZE];
     563        1744 :         gnutls_pk_algorithm_t pk;
     564        1744 :         gnutls_sign_algorithm_t sig;
     565        1744 :         gnutls_datum_t tmp = { NULL, 0 };
     566        1744 :         unsigned i;
     567             : 
     568        1744 :         if (pkcs7 == NULL)
     569             :                 return GNUTLS_E_INVALID_REQUEST;
     570             : 
     571        1744 :         memset(info, 0, sizeof(*info));
     572        1744 :         info->signing_time = -1;
     573             : 
     574        1744 :         ret =
     575        1744 :             asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
     576        1744 :         if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
     577         146 :                 gnutls_assert();
     578         146 :                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     579             :         }
     580        1598 :         snprintf(root, sizeof(root),
     581             :                  "signerInfos.?%u.signatureAlgorithm.algorithm", idx + 1);
     582             : 
     583        1598 :         len = sizeof(oid) - 1;
     584        1598 :         ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
     585        1598 :         if (ret != ASN1_SUCCESS) {
     586           3 :                 gnutls_assert();
     587           3 :                 goto unsupp_algo;
     588             :         }
     589             : 
     590        1595 :         sig = gnutls_oid_to_sign(oid);
     591        1595 :         if (sig == GNUTLS_SIGN_UNKNOWN) {
     592             :                 /* great PKCS #7 allows to only specify a public key algo */
     593         857 :                 pk = gnutls_oid_to_pk(oid);
     594         857 :                 if (pk == GNUTLS_PK_UNKNOWN) {
     595           2 :                         gnutls_assert();
     596           2 :                         goto unsupp_algo;
     597             :                 }
     598             : 
     599             :                 /* use the digests algorithm */
     600         855 :                 snprintf(root, sizeof(root),
     601             :                          "signerInfos.?%u.digestAlgorithm.algorithm", idx + 1);
     602             : 
     603         855 :                 len = sizeof(oid) - 1;
     604         855 :                 ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
     605         855 :                 if (ret != ASN1_SUCCESS) {
     606           4 :                         gnutls_assert();
     607           4 :                         goto unsupp_algo;
     608             :                 }
     609             : 
     610         851 :                 ret = gnutls_oid_to_digest(oid);
     611         851 :                 if (ret == GNUTLS_DIG_UNKNOWN) {
     612           2 :                         gnutls_assert();
     613           2 :                         goto unsupp_algo;
     614             :                 }
     615             : 
     616         849 :                 sig = gnutls_pk_to_sign(pk, ret);
     617         849 :                 if (sig == GNUTLS_SIGN_UNKNOWN) {
     618           0 :                         gnutls_assert();
     619           0 :                         goto unsupp_algo;
     620             :                 }
     621             :         }
     622             : 
     623        1587 :         info->algo = sig;
     624             : 
     625        1587 :         snprintf(root, sizeof(root), "signerInfos.?%u.signature", idx + 1);
     626             :         /* read the signature */
     627        1587 :         ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &info->sig);
     628        1587 :         if (ret < 0) {
     629          19 :                 gnutls_assert();
     630          19 :                 goto fail;
     631             :         }
     632             : 
     633             :         /* read the issuer info */
     634        1568 :         snprintf(root, sizeof(root),
     635             :                  "signerInfos.?%u.sid.issuerAndSerialNumber.issuer.rdnSequence",
     636             :                  idx + 1);
     637             :         /* read the signature */
     638        1568 :         ret =
     639        1568 :             _gnutls_x509_get_raw_field(pkcs7->signed_data, root,
     640             :                                        &info->issuer_dn);
     641        1568 :         if (ret >= 0) {
     642         102 :                 snprintf(root, sizeof(root),
     643             :                          "signerInfos.?%u.sid.issuerAndSerialNumber.serialNumber",
     644             :                          idx + 1);
     645             :                 /* read the signature */
     646         102 :                 ret =
     647         102 :                     _gnutls_x509_read_value(pkcs7->signed_data, root,
     648             :                                             &info->signer_serial);
     649         102 :                 if (ret < 0) {
     650           1 :                         gnutls_assert();
     651           1 :                         goto fail;
     652             :                 }
     653             :         } else {                /* keyid */
     654        1466 :                 snprintf(root, sizeof(root),
     655             :                          "signerInfos.?%u.sid.subjectKeyIdentifier", idx + 1);
     656             :                 /* read the signature */
     657        1466 :                 ret =
     658        1466 :                     _gnutls_x509_read_value(pkcs7->signed_data, root,
     659             :                                             &info->issuer_keyid);
     660        1466 :                 if (ret < 0) {
     661           7 :                         gnutls_assert();
     662             :                 }
     663             :         }
     664             : 
     665        1567 :         if (info->issuer_keyid.data == NULL && info->issuer_dn.data == NULL) {
     666           7 :                 ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     667           7 :                 goto fail;
     668             :         }
     669             : 
     670             :         /* read the signing time */
     671             :         for (i = 0;; i++) {
     672        1776 :                 snprintf(root, sizeof(root),
     673             :                          "signerInfos.?%u.signedAttrs.?%u.type", idx + 1,
     674             :                          i + 1);
     675        1776 :                 len = sizeof(oid) - 1;
     676        1776 :                 ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
     677        1776 :                 if (ret != ASN1_SUCCESS) {
     678             :                         break;
     679             :                 }
     680             : 
     681         216 :                 snprintf(root, sizeof(root),
     682             :                          "signerInfos.?%u.signedAttrs.?%u.values.?1", idx + 1,
     683             :                          i + 1);
     684         216 :                 ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &tmp);
     685         216 :                 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
     686           0 :                         tmp.data = NULL;
     687           0 :                         tmp.size = 0;
     688         216 :                 } else if (ret < 0) {
     689           0 :                         gnutls_assert();
     690           0 :                         goto fail;
     691             :                 }
     692             : 
     693         216 :                 ret = gnutls_pkcs7_add_attr(&info->signed_attrs, oid, &tmp, 0);
     694         216 :                 gnutls_free(tmp.data);
     695             : 
     696         216 :                 if (ret < 0) {
     697           0 :                         gnutls_assert();
     698           0 :                         goto fail;
     699             :                 }
     700             : 
     701         216 :                 if (strcmp(oid, ATTR_SIGNING_TIME) == 0) {
     702          46 :                         info->signing_time = parse_time(pkcs7, root);
     703             :                 }
     704             :         }
     705             : 
     706             :         /* read the unsigned attrs */
     707             :         for (i = 0;; i++) {
     708        1569 :                 snprintf(root, sizeof(root),
     709             :                          "signerInfos.?%u.unsignedAttrs.?%u.type", idx + 1,
     710             :                          i + 1);
     711        1569 :                 len = sizeof(oid) - 1;
     712        1569 :                 ret = asn1_read_value(pkcs7->signed_data, root, oid, &len);
     713        1569 :                 if (ret != ASN1_SUCCESS) {
     714             :                         break;
     715             :                 }
     716             : 
     717           9 :                 snprintf(root, sizeof(root),
     718             :                          "signerInfos.?%u.unsignedAttrs.?%u.values.?1", idx + 1,
     719             :                          i + 1);
     720           9 :                 ret = _gnutls_x509_read_value(pkcs7->signed_data, root, &tmp);
     721           9 :                 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) {
     722           0 :                         tmp.data = NULL;
     723           0 :                         tmp.size = 0;
     724           9 :                 } else if (ret < 0) {
     725           0 :                         gnutls_assert();
     726           0 :                         goto fail;
     727             :                 }
     728             : 
     729           9 :                 ret =
     730           9 :                     gnutls_pkcs7_add_attr(&info->unsigned_attrs, oid, &tmp, 0);
     731           9 :                 gnutls_free(tmp.data);
     732             : 
     733           9 :                 if (ret < 0) {
     734           0 :                         gnutls_assert();
     735           0 :                         goto fail;
     736             :                 }
     737             :         }
     738             : 
     739             :         return 0;
     740          27 :  fail:
     741          27 :         gnutls_free(tmp.data);
     742          27 :         gnutls_pkcs7_signature_info_deinit(info);
     743          27 :         return ret;
     744             :  unsupp_algo:
     745             :         return GNUTLS_E_UNKNOWN_ALGORITHM;
     746             : }
     747             : 
     748             : /* Verifies that the hash attribute ATTR_MESSAGE_DIGEST is present
     749             :  * and matches our calculated hash */
     750          26 : static int verify_hash_attr(gnutls_pkcs7_t pkcs7, const char *root,
     751             :                             gnutls_sign_algorithm_t algo,
     752             :                             const gnutls_datum_t *data)
     753             : {
     754          26 :         unsigned hash;
     755          26 :         gnutls_datum_t tmp = { NULL, 0 };
     756          26 :         gnutls_datum_t tmp2 = { NULL, 0 };
     757          26 :         uint8_t hash_output[MAX_HASH_SIZE];
     758          26 :         unsigned hash_size, i;
     759          26 :         char oid[MAX_OID_SIZE];
     760          26 :         char name[256];
     761          26 :         unsigned msg_digest_ok = 0;
     762          26 :         unsigned num_cont_types = 0;
     763          26 :         int ret;
     764             : 
     765          26 :         hash = gnutls_sign_get_hash_algorithm(algo);
     766             : 
     767             :         /* hash the data */
     768          26 :         if (hash == GNUTLS_DIG_UNKNOWN)
     769           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     770             : 
     771          26 :         hash_size = gnutls_hash_get_len(hash);
     772             : 
     773          26 :         if (data == NULL || data->data == NULL) {
     774          19 :                 data = &pkcs7->der_signed_data;
     775             :         }
     776             : 
     777          26 :         if (data->size == 0) {
     778           1 :                 return gnutls_assert_val(GNUTLS_E_NO_EMBEDDED_DATA);
     779             :         }
     780             : 
     781          25 :         ret = gnutls_hash_fast(hash, data->data, data->size, hash_output);
     782          25 :         if (ret < 0)
     783           0 :                 return gnutls_assert_val(ret);
     784             : 
     785             :         /* now verify that hash matches */
     786          96 :         for (i = 0;; i++) {
     787         121 :                 snprintf(name, sizeof(name), "%s.signedAttrs.?%u", root, i + 1);
     788             : 
     789         121 :                 ret = _gnutls_x509_decode_and_read_attribute(pkcs7->signed_data,
     790             :                                                              name, oid,
     791             :                                                              sizeof(oid), &tmp,
     792             :                                                              1, 0);
     793         121 :                 if (ret < 0) {
     794          25 :                         if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
     795             :                                 break;
     796           0 :                         return gnutls_assert_val(ret);
     797             :                 }
     798             : 
     799          96 :                 if (strcmp(oid, ATTR_MESSAGE_DIGEST) == 0) {
     800          25 :                         ret =
     801          50 :                             _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
     802          25 :                                                        tmp.data, tmp.size,
     803             :                                                        &tmp2, 0);
     804          25 :                         if (ret < 0) {
     805           0 :                                 gnutls_assert();
     806           0 :                                 goto cleanup;
     807             :                         }
     808             : 
     809          25 :                         if (tmp2.size == hash_size
     810          25 :                             && memcmp(hash_output, tmp2.data, tmp2.size) == 0) {
     811             :                                 msg_digest_ok = 1;
     812             :                         } else {
     813           0 :                                 gnutls_assert();
     814             :                         }
     815          71 :                 } else if (strcmp(oid, ATTR_CONTENT_TYPE) == 0) {
     816          25 :                         if (num_cont_types > 0) {
     817           0 :                                 gnutls_assert();
     818           0 :                                 ret = GNUTLS_E_PARSING_ERROR;
     819           0 :                                 goto cleanup;
     820             :                         }
     821             : 
     822          25 :                         num_cont_types++;
     823             : 
     824             :                         /* check if it matches */
     825          25 :                         ret =
     826          25 :                             _gnutls_x509_get_raw_field(pkcs7->signed_data,
     827             :                                                        "encapContentInfo.eContentType",
     828             :                                                        &tmp2);
     829          25 :                         if (ret < 0) {
     830           0 :                                 gnutls_assert();
     831           0 :                                 goto cleanup;
     832             :                         }
     833             : 
     834          25 :                         if (tmp2.size != tmp.size
     835          25 :                             || memcmp(tmp.data, tmp2.data, tmp2.size) != 0) {
     836           0 :                                 gnutls_assert();
     837           0 :                                 ret = GNUTLS_E_PARSING_ERROR;
     838           0 :                                 goto cleanup;
     839             :                         }
     840             :                 }
     841             : 
     842          96 :                 gnutls_free(tmp.data);
     843          96 :                 gnutls_free(tmp2.data);
     844             :         }
     845             : 
     846          25 :         if (msg_digest_ok)
     847             :                 ret = 0;
     848             :         else
     849           0 :                 ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
     850             : 
     851          25 :  cleanup:
     852          25 :         gnutls_free(tmp.data);
     853          25 :         gnutls_free(tmp2.data);
     854          25 :         return ret;
     855             : }
     856             : 
     857             : /* Returns the data to be used for signature verification. PKCS #7
     858             :  * decided that this should not be an easy task.
     859             :  */
     860          61 : static int figure_pkcs7_sigdata(gnutls_pkcs7_t pkcs7, const char *root,
     861             :                                 const gnutls_datum_t * data,
     862             :                                 gnutls_sign_algorithm_t algo,
     863             :                                 gnutls_datum_t * sigdata)
     864             : {
     865          61 :         int ret;
     866          61 :         char name[256];
     867             : 
     868          61 :         snprintf(name, sizeof(name), "%s.signedAttrs", root);
     869             :         /* read the signature */
     870          61 :         ret = _gnutls_x509_get_raw_field(pkcs7->signed_data, name, sigdata);
     871          61 :         if (ret == 0) {
     872             :                 /* verify that hash matches */
     873          26 :                 ret = verify_hash_attr(pkcs7, root, algo, data);
     874          26 :                 if (ret < 0)
     875           1 :                         return gnutls_assert_val(ret);
     876             : 
     877          25 :                 if (sigdata->size > 0)
     878          25 :                         sigdata->data[0] = 0x31;
     879             : 
     880          25 :                 return 0;
     881             :         }
     882             : 
     883             :         /* We have no signedAttrs. Use the provided data, or the encapsulated */
     884          35 :         if (data == NULL || data->data == NULL) {
     885          24 :                 return _gnutls_set_datum(sigdata, pkcs7->der_signed_data.data, pkcs7->der_signed_data.size);
     886             :         }
     887             : 
     888          11 :         return _gnutls_set_datum(sigdata, data->data, data->size);
     889             : }
     890             : 
     891             : /**
     892             :  * gnutls_pkcs7_get_embedded_data:
     893             :  * @pkcs7: should contain a gnutls_pkcs7_t type
     894             :  * @flags: must be zero or %GNUTLS_PKCS7_EDATA_GET_RAW
     895             :  * @data: will hold the embedded data in the provided structure
     896             :  *
     897             :  * This function will return the data embedded in the signature of
     898             :  * the PKCS7 structure. If no data are available then
     899             :  * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
     900             :  *
     901             :  * The returned data must be de-allocated using gnutls_free().
     902             :  *
     903             :  * Note, that this function returns the exact same data that are
     904             :  * authenticated. If the %GNUTLS_PKCS7_EDATA_GET_RAW flag is provided,
     905             :  * the returned data will be including the wrapping tag/value as
     906             :  * they are encoded in the structure.
     907             :  *
     908             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     909             :  *   negative error value.
     910             :  *
     911             :  * Since: 3.4.8
     912             :  **/
     913             : int
     914           6 : gnutls_pkcs7_get_embedded_data(gnutls_pkcs7_t pkcs7, unsigned flags,
     915             :                                gnutls_datum_t *data)
     916             : {
     917           6 :         if (pkcs7 == NULL)
     918             :                 return GNUTLS_E_INVALID_REQUEST;
     919             : 
     920           6 :         if (pkcs7->der_signed_data.size == 0)
     921           0 :                 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     922             : 
     923           6 :         if (flags & GNUTLS_PKCS7_EDATA_GET_RAW) {
     924           1 :                 if (pkcs7->signed_data == NULL)
     925           0 :                         return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
     926             : 
     927           1 :                 return _gnutls_x509_read_value(pkcs7->signed_data, "encapContentInfo.eContent", data);
     928             :         } else {
     929           5 :                 return _gnutls_set_datum(data, pkcs7->der_signed_data.data, pkcs7->der_signed_data.size);
     930             :         }
     931             : }
     932             : 
     933             : /**
     934             :  * gnutls_pkcs7_get_embedded_data_oid:
     935             :  * @pkcs7: should contain a gnutls_pkcs7_t type
     936             :  *
     937             :  * This function will return the OID of the data embedded in the signature of
     938             :  * the PKCS7 structure. If no data are available then %NULL will be
     939             :  * returned. The returned value will be valid during the lifetime
     940             :  * of the @pkcs7 structure.
     941             :  *
     942             :  * Returns: On success, a pointer to an OID string, %NULL on error.
     943             :  *
     944             :  * Since: 3.5.5
     945             :  **/
     946             : const char *
     947         182 : gnutls_pkcs7_get_embedded_data_oid(gnutls_pkcs7_t pkcs7)
     948             : {
     949         182 :         if (pkcs7 == NULL || pkcs7->encap_data_oid[0] == 0)
     950             :                 return NULL;
     951             : 
     952         182 :         return pkcs7->encap_data_oid;
     953             : }
     954             : 
     955             : /**
     956             :  * gnutls_pkcs7_verify_direct:
     957             :  * @pkcs7: should contain a #gnutls_pkcs7_t type
     958             :  * @signer: the certificate believed to have signed the structure
     959             :  * @idx: the index of the signature info to check
     960             :  * @data: The data to be verified or %NULL
     961             :  * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
     962             :  *
     963             :  * This function will verify the provided data against the signature
     964             :  * present in the SignedData of the PKCS #7 structure. If the data
     965             :  * provided are NULL then the data in the encapsulatedContent field
     966             :  * will be used instead.
     967             :  *
     968             :  * Note that, unlike gnutls_pkcs7_verify() this function does not
     969             :  * verify the key purpose of the signer. It is expected for the caller
     970             :  * to verify the intended purpose of the %signer -e.g., via gnutls_x509_crt_get_key_purpose_oid(),
     971             :  * or gnutls_x509_crt_check_key_purpose().
     972             :  *
     973             :  * Note also, that since GnuTLS 3.5.6 this function introduces checks in the
     974             :  * end certificate (@signer), including time checks and key usage checks.
     975             :  *
     976             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
     977             :  *   negative error value. A verification error results to a
     978             :  *   %GNUTLS_E_PK_SIG_VERIFY_FAILED and the lack of encapsulated data
     979             :  *   to verify to a %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
     980             :  *
     981             :  * Since: 3.4.2
     982             :  **/
     983          23 : int gnutls_pkcs7_verify_direct(gnutls_pkcs7_t pkcs7,
     984             :                                gnutls_x509_crt_t signer,
     985             :                                unsigned idx,
     986             :                                const gnutls_datum_t *data, unsigned flags)
     987             : {
     988          23 :         int count, ret;
     989          23 :         gnutls_datum_t tmpdata = { NULL, 0 };
     990          23 :         gnutls_pkcs7_signature_info_st info;
     991          23 :         gnutls_datum_t sigdata = { NULL, 0 };
     992          23 :         char root[128];
     993             : 
     994          23 :         memset(&info, 0, sizeof(info));
     995             : 
     996          23 :         if (pkcs7 == NULL)
     997             :                 return GNUTLS_E_INVALID_REQUEST;
     998             : 
     999          23 :         ret =
    1000          23 :             asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
    1001          23 :         if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
    1002           0 :                 gnutls_assert();
    1003           0 :                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    1004             :         }
    1005             : 
    1006          23 :         ret = gnutls_pkcs7_get_signature_info(pkcs7, idx, &info);
    1007          23 :         if (ret < 0) {
    1008           0 :                 gnutls_assert();
    1009           0 :                 goto cleanup;
    1010             :         }
    1011             : 
    1012          23 :         snprintf(root, sizeof(root), "signerInfos.?%u", idx + 1);
    1013          23 :         ret = figure_pkcs7_sigdata(pkcs7, root, data, info.algo, &sigdata);
    1014          23 :         if (ret < 0) {
    1015           0 :                 gnutls_assert();
    1016           0 :                 goto cleanup;
    1017             :         }
    1018             : 
    1019          23 :         ret =
    1020          23 :             gnutls_x509_crt_verify_data2(signer, info.algo, flags, &sigdata,
    1021             :                                          &info.sig);
    1022          23 :         if (ret < 0) {
    1023           6 :                 gnutls_assert();
    1024             :         }
    1025             : 
    1026          23 :  cleanup:
    1027          23 :         gnutls_free(tmpdata.data);
    1028          23 :         gnutls_free(sigdata.data);
    1029          23 :         gnutls_pkcs7_signature_info_deinit(&info);
    1030             : 
    1031          23 :         return ret;
    1032             : }
    1033             : 
    1034             : /* Finds the issuer of the given certificate (@cert) in the
    1035             :  * included in PKCS#7 list of certificates */
    1036           9 : static gnutls_x509_crt_t find_verified_issuer_of(gnutls_pkcs7_t pkcs7,
    1037             :                                         gnutls_x509_crt_t cert,
    1038             :                                         const char *purpose,
    1039             :                                         unsigned vflags)
    1040             : {
    1041           9 :         gnutls_x509_crt_t issuer = NULL;
    1042           9 :         int ret, count;
    1043           9 :         gnutls_datum_t tmp = { NULL, 0 };
    1044           9 :         unsigned i, vtmp;
    1045             : 
    1046           9 :         count = gnutls_pkcs7_get_crt_count(pkcs7);
    1047           9 :         if (count < 0) {
    1048           0 :                 gnutls_assert();
    1049           0 :                 return NULL;
    1050             :         }
    1051             : 
    1052          23 :         for (i = 0; i < (unsigned)count; i++) {
    1053             :                 /* Try to find the signer in the appended list. */
    1054          19 :                 ret = gnutls_pkcs7_get_crt_raw2(pkcs7, i, &tmp);
    1055          19 :                 if (ret < 0) {
    1056           0 :                         gnutls_assert();
    1057           0 :                         goto fail;
    1058             :                 }
    1059             : 
    1060          19 :                 ret = gnutls_x509_crt_init(&issuer);
    1061          19 :                 if (ret < 0) {
    1062           0 :                         gnutls_assert();
    1063           0 :                         goto fail;
    1064             :                 }
    1065             : 
    1066          19 :                 ret = gnutls_x509_crt_import(issuer, &tmp, GNUTLS_X509_FMT_DER);
    1067          19 :                 if (ret < 0) {
    1068           0 :                         gnutls_assert();
    1069           0 :                         goto fail;
    1070             :                 }
    1071             : 
    1072          19 :                 if (!gnutls_x509_crt_check_issuer(cert, issuer)) {
    1073          14 :                         gnutls_assert();
    1074          14 :                         goto skip;
    1075             :                 }
    1076             : 
    1077           5 :                 ret = gnutls_x509_crt_verify(cert, &issuer, 1, vflags|GNUTLS_VERIFY_DO_NOT_ALLOW_SAME, &vtmp);
    1078           5 :                 if (ret < 0 || vtmp != 0 ||
    1079           0 :                     (purpose != NULL && !_gnutls_check_key_purpose(issuer, purpose, 0))) {
    1080           0 :                         gnutls_assert();        /* maybe next one is trusted */
    1081           0 :                         _gnutls_cert_log("failed verification with", issuer);
    1082           0 :  skip:
    1083          14 :                         gnutls_x509_crt_deinit(issuer);
    1084          14 :                         issuer = NULL;
    1085          14 :                         gnutls_free(tmp.data);
    1086          14 :                         continue;
    1087             :                 }
    1088             : 
    1089           5 :                 _gnutls_cert_log("issued by", issuer);
    1090             : 
    1091             :                 /* we found a signer we trust. let's return it */
    1092             :                 break;
    1093             :         }
    1094             : 
    1095           9 :         if (issuer == NULL) {
    1096           4 :                 gnutls_assert();
    1097           4 :                 return NULL;
    1098             :         }
    1099           5 :         goto cleanup;
    1100             : 
    1101           0 :  fail:
    1102           0 :         if (issuer) {
    1103           0 :                 gnutls_x509_crt_deinit(issuer);
    1104           0 :                 issuer = NULL;
    1105             :         }
    1106             : 
    1107           0 :  cleanup:
    1108           5 :         gnutls_free(tmp.data);
    1109             : 
    1110           5 :         return issuer;
    1111             : }
    1112             : 
    1113             : /* Finds a certificate that is issued by @issuer -if given-, and matches
    1114             :  * either the serial number or the key ID (both in @info) .
    1115             :  */
    1116          24 : static gnutls_x509_crt_t find_child_of_with_serial(gnutls_pkcs7_t pkcs7,
    1117             :                                                    gnutls_x509_crt_t issuer,
    1118             :                                                    const char *purpose,
    1119             :                                                    gnutls_pkcs7_signature_info_st *info)
    1120             : {
    1121          24 :         gnutls_x509_crt_t crt = NULL;
    1122          24 :         int ret, count;
    1123          24 :         uint8_t tmp[128];
    1124          24 :         size_t tmp_size;
    1125          24 :         gnutls_datum_t tmpdata = { NULL, 0 };
    1126          24 :         unsigned i;
    1127             : 
    1128          24 :         count = gnutls_pkcs7_get_crt_count(pkcs7);
    1129          24 :         if (count < 0) {
    1130           0 :                 gnutls_assert();
    1131           0 :                 return NULL;
    1132             :         }
    1133             : 
    1134          37 :         for (i = 0; i < (unsigned)count; i++) {
    1135             :                 /* Try to find the crt in the appended list. */
    1136          35 :                 ret = gnutls_pkcs7_get_crt_raw2(pkcs7, i, &tmpdata);
    1137          35 :                 if (ret < 0) {
    1138           0 :                         gnutls_assert();
    1139           0 :                         goto fail;
    1140             :                 }
    1141             : 
    1142          35 :                 ret = gnutls_x509_crt_init(&crt);
    1143          35 :                 if (ret < 0) {
    1144           0 :                         gnutls_assert();
    1145           0 :                         goto fail;
    1146             :                 }
    1147             : 
    1148          35 :                 ret = gnutls_x509_crt_import(crt, &tmpdata, GNUTLS_X509_FMT_DER);
    1149          35 :                 if (ret < 0) {
    1150           0 :                         gnutls_assert();
    1151           0 :                         goto fail;
    1152             :                 }
    1153             : 
    1154          35 :                 if (issuer != NULL) {
    1155          19 :                         if (!gnutls_x509_crt_check_issuer(crt, issuer)) {
    1156           0 :                                 gnutls_assert();
    1157           0 :                                 goto skip;
    1158             :                         }
    1159             :                 }
    1160             : 
    1161          35 :                 if (purpose) {
    1162          14 :                         ret =
    1163           7 :                             _gnutls_check_key_purpose(crt, purpose, 0);
    1164           7 :                         if (ret == 0) {
    1165           3 :                                 _gnutls_cert_log("key purpose unacceptable", crt);
    1166           3 :                                 goto skip;
    1167             :                         }
    1168             :                 }
    1169             : 
    1170          32 :                 if (info->signer_serial.size > 0) {
    1171          24 :                         tmp_size = sizeof(tmp);
    1172          24 :                         ret = gnutls_x509_crt_get_serial(crt, tmp, &tmp_size);
    1173          24 :                         if (ret < 0) {
    1174           0 :                                 gnutls_assert();
    1175           0 :                                 goto skip;
    1176             :                         }
    1177             : 
    1178          24 :                         if (tmp_size != info->signer_serial.size
    1179          24 :                             || memcmp(info->signer_serial.data, tmp,
    1180             :                                       tmp_size) != 0) {
    1181           6 :                                 _gnutls_cert_log("doesn't match serial", crt);
    1182           6 :                                 gnutls_assert();
    1183           6 :                                 goto skip;
    1184             :                         }
    1185           8 :                 } else if (info->issuer_keyid.size > 0) {
    1186           8 :                         tmp_size = sizeof(tmp);
    1187           8 :                         ret = gnutls_x509_crt_get_subject_key_id(crt, tmp, &tmp_size, NULL);
    1188           8 :                         if (ret < 0) {
    1189           0 :                                 gnutls_assert();
    1190           0 :                                 goto skip;
    1191             :                         }
    1192             : 
    1193           8 :                         if (tmp_size != info->issuer_keyid.size
    1194           8 :                             || memcmp(info->issuer_keyid.data, tmp,
    1195             :                                       tmp_size) != 0) {
    1196           4 :                                 _gnutls_cert_log("doesn't match key ID", crt);
    1197           4 :                                 gnutls_assert();
    1198           4 :  skip:
    1199          13 :                                 gnutls_x509_crt_deinit(crt);
    1200          13 :                                 crt = NULL;
    1201          13 :                                 gnutls_free(tmpdata.data);
    1202          13 :                                 continue;
    1203             :                         }
    1204             :                 } else {
    1205           0 :                         gnutls_assert();
    1206           0 :                         crt = NULL;
    1207           0 :                         goto fail;
    1208             :                 }
    1209             : 
    1210          22 :                 _gnutls_cert_log("signer is", crt);
    1211             : 
    1212             :                 /* we found the child with the given serial or key ID */
    1213             :                 break;
    1214             :         }
    1215             : 
    1216          24 :         if (crt == NULL) {
    1217           2 :                 gnutls_assert();
    1218           2 :                 return NULL;
    1219             :         }
    1220             : 
    1221          22 :         goto cleanup;
    1222           0 :  fail:
    1223           0 :         if (crt) {
    1224           0 :                 gnutls_x509_crt_deinit(crt);
    1225           0 :                 crt = NULL;
    1226             :         }
    1227             : 
    1228           0 :  cleanup:
    1229          22 :         gnutls_free(tmpdata.data);
    1230             : 
    1231          22 :         return crt;
    1232             : }
    1233             : 
    1234             : static
    1235          24 : gnutls_x509_crt_t find_signer(gnutls_pkcs7_t pkcs7, gnutls_x509_trust_list_t tl,
    1236             :                               gnutls_typed_vdata_st * vdata,
    1237             :                               unsigned vdata_size,
    1238             :                               unsigned vflags,
    1239             :                               gnutls_pkcs7_signature_info_st * info)
    1240             : {
    1241          24 :         gnutls_x509_crt_t issuer = NULL;
    1242          24 :         gnutls_x509_crt_t signer = NULL;
    1243          24 :         int ret;
    1244          24 :         gnutls_datum_t tmp = { NULL, 0 };
    1245          24 :         unsigned i, vtmp;
    1246          24 :         const char *purpose = NULL;
    1247             : 
    1248          24 :         if (info->issuer_keyid.data) {
    1249           4 :                 ret =
    1250           8 :                     gnutls_x509_trust_list_get_issuer_by_subject_key_id(tl,
    1251             :                                                                         NULL,
    1252           4 :                                                                         &info->
    1253             :                                                                         issuer_keyid,
    1254             :                                                                         &signer,
    1255             :                                                                         0);
    1256           4 :                 if (ret < 0) {
    1257           4 :                         gnutls_assert();
    1258           4 :                         signer = NULL;
    1259             :                 }
    1260             :         }
    1261             : 
    1262             :         /* get key purpose */
    1263          24 :         for (i = 0; i < vdata_size; i++) {
    1264           6 :                 if (vdata[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
    1265           6 :                         purpose = (char *)vdata[i].data;
    1266           6 :                         break;
    1267             :                 }
    1268             :         }
    1269             : 
    1270             :         /* this will give us the issuer of the signer (wtf) */
    1271          24 :         if (info->issuer_dn.data && signer == NULL) {
    1272          20 :                 ret =
    1273          40 :                     gnutls_x509_trust_list_get_issuer_by_dn(tl,
    1274          20 :                                                             &info->issuer_dn,
    1275             :                                                             &issuer, 0);
    1276          20 :                 if (ret < 0) {
    1277           3 :                         gnutls_assert();
    1278           3 :                         signer = NULL;
    1279             :                 }
    1280             : 
    1281          20 :                 if (issuer) {
    1282             :                         /* try to find the actual signer in the list of
    1283             :                          * certificates */
    1284          17 :                         signer = find_child_of_with_serial(pkcs7, issuer, purpose, info);
    1285          17 :                         if (signer == NULL) {
    1286           2 :                                 gnutls_assert();
    1287           2 :                                 goto fail;
    1288             :                         }
    1289             : 
    1290          15 :                         gnutls_x509_crt_deinit(issuer);
    1291          15 :                         issuer = NULL;
    1292             :                 }
    1293             :         }
    1294             : 
    1295          22 :         if (signer == NULL) {
    1296             :                 /* get the signer from the pkcs7 list; the one that matches serial
    1297             :                  * or key ID */
    1298           7 :                 signer = find_child_of_with_serial(pkcs7, NULL, purpose, info);
    1299           7 :                 if (signer == NULL) {
    1300           0 :                         gnutls_assert();
    1301           0 :                         goto fail;
    1302             :                 }
    1303             : 
    1304             :                 /* if the signer cannot be verified from our trust list, make a chain of certificates
    1305             :                  * starting from the identified signer, to a root we know. */
    1306           7 :                 ret = gnutls_x509_trust_list_verify_crt2(tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
    1307           7 :                 if (ret < 0 || vtmp != 0) {
    1308           6 :                         gnutls_x509_crt_t prev = NULL;
    1309             : 
    1310           6 :                         issuer = signer;
    1311             :                         /* construct a chain */
    1312           9 :                         do {
    1313           9 :                                 if (prev && prev != signer) {
    1314           0 :                                         gnutls_x509_crt_deinit(prev);
    1315             :                                 }
    1316           9 :                                 prev = issuer;
    1317             : 
    1318           9 :                                 issuer = find_verified_issuer_of(pkcs7, issuer, purpose, vflags);
    1319             : 
    1320           9 :                                 if (issuer != NULL && gnutls_x509_crt_check_issuer(issuer, issuer)) {
    1321           2 :                                         if (prev) gnutls_x509_crt_deinit(prev);
    1322           2 :                                         prev = issuer;
    1323           2 :                                         break;
    1324             :                                 }
    1325           7 :                         } while(issuer != NULL);
    1326             : 
    1327           6 :                         issuer = prev; /* the last we have seen */
    1328             : 
    1329           6 :                         if (issuer == NULL) {
    1330           0 :                                 gnutls_assert();
    1331           0 :                                 goto fail;
    1332             :                         }
    1333             : 
    1334           6 :                         ret = gnutls_x509_trust_list_verify_crt2(tl, &issuer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
    1335           6 :                         if (ret < 0 || vtmp != 0) {
    1336             :                                 /* could not construct a valid chain */
    1337           3 :                                 _gnutls_reason_log("signer's chain failed trust list verification", vtmp);
    1338           3 :                                 gnutls_assert();
    1339           3 :                                 goto fail;
    1340             :                         }
    1341             :                 }
    1342             :         } else {
    1343             :                 /* verify that the signer we got is trusted */
    1344          15 :                 ret = gnutls_x509_trust_list_verify_crt2(tl, &signer, 1, vdata, vdata_size, vflags, &vtmp, NULL);
    1345          15 :                 if (ret < 0 || vtmp != 0) {
    1346             :                         /* could not construct a valid chain */
    1347           8 :                         _gnutls_reason_log("signer failed trust list verification", vtmp);
    1348           8 :                         gnutls_assert();
    1349           8 :                         goto fail;
    1350             :                 }
    1351             :         }
    1352             : 
    1353          11 :         if (signer == NULL) {
    1354           0 :                 gnutls_assert();
    1355           0 :                 goto fail;
    1356             :         }
    1357             : 
    1358          11 :         goto cleanup;
    1359             : 
    1360          13 :  fail:
    1361          13 :         if (signer != NULL) {
    1362          11 :                 if (issuer == signer)
    1363           3 :                         issuer = NULL;
    1364          11 :                 gnutls_x509_crt_deinit(signer);
    1365          11 :                 signer = NULL;
    1366             :         }
    1367             : 
    1368           2 :  cleanup:
    1369          24 :         if (issuer != NULL) {
    1370           5 :                 gnutls_x509_crt_deinit(issuer);
    1371           5 :                 issuer = NULL;
    1372             :         }
    1373          24 :         gnutls_free(tmp.data);
    1374             : 
    1375          24 :         return signer;
    1376             : }
    1377             : 
    1378             : /**
    1379             :  * gnutls_pkcs7_verify:
    1380             :  * @pkcs7: should contain a #gnutls_pkcs7_t type
    1381             :  * @tl: A list of trusted certificates
    1382             :  * @vdata: an array of typed data
    1383             :  * @vdata_size: the number of data elements
    1384             :  * @idx: the index of the signature info to check
    1385             :  * @data: The data to be verified or %NULL
    1386             :  * @flags: Zero or an OR list of #gnutls_certificate_verify_flags
    1387             :  *
    1388             :  * This function will verify the provided data against the signature
    1389             :  * present in the SignedData of the PKCS #7 structure. If the data
    1390             :  * provided are NULL then the data in the encapsulatedContent field
    1391             :  * will be used instead.
    1392             :  *
    1393             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1394             :  *   negative error value. A verification error results to a
    1395             :  *   %GNUTLS_E_PK_SIG_VERIFY_FAILED and the lack of encapsulated data
    1396             :  *   to verify to a %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE.
    1397             :  *
    1398             :  * Since: 3.4.2
    1399             :  **/
    1400          25 : int gnutls_pkcs7_verify(gnutls_pkcs7_t pkcs7,
    1401             :                         gnutls_x509_trust_list_t tl,
    1402             :                         gnutls_typed_vdata_st *vdata,
    1403             :                         unsigned int vdata_size,
    1404             :                         unsigned idx,
    1405             :                         const gnutls_datum_t *data, unsigned flags)
    1406             : {
    1407          25 :         int count, ret;
    1408          25 :         gnutls_datum_t tmpdata = { NULL, 0 };
    1409          25 :         gnutls_pkcs7_signature_info_st info;
    1410          25 :         gnutls_x509_crt_t signer;
    1411          25 :         gnutls_datum_t sigdata = { NULL, 0 };
    1412          25 :         char root[128];
    1413             : 
    1414          25 :         memset(&info, 0, sizeof(info));
    1415             : 
    1416          25 :         if (pkcs7 == NULL)
    1417             :                 return GNUTLS_E_INVALID_REQUEST;
    1418             : 
    1419          25 :         ret =
    1420          25 :             asn1_number_of_elements(pkcs7->signed_data, "signerInfos", &count);
    1421          25 :         if (ret != ASN1_SUCCESS || idx + 1 > (unsigned)count) {
    1422           0 :                 gnutls_assert();
    1423           0 :                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
    1424             :         }
    1425             : 
    1426             :         /* read data */
    1427          25 :         ret = gnutls_pkcs7_get_signature_info(pkcs7, idx, &info);
    1428          25 :         if (ret < 0) {
    1429           0 :                 gnutls_assert();
    1430           0 :                 goto cleanup;
    1431             :         }
    1432             : 
    1433          25 :         snprintf(root, sizeof(root), "signerInfos.?%u", idx + 1);
    1434          25 :         ret = figure_pkcs7_sigdata(pkcs7, root, data, info.algo, &sigdata);
    1435          25 :         if (ret < 0) {
    1436           1 :                 gnutls_assert();
    1437           1 :                 goto cleanup;
    1438             :         }
    1439             : 
    1440          24 :         signer = find_signer(pkcs7, tl, vdata, vdata_size, flags, &info);
    1441          24 :         if (signer) {
    1442          11 :                 ret =
    1443          11 :                     gnutls_x509_crt_verify_data3(signer, info.algo, vdata, vdata_size,
    1444             :                                                  &sigdata, &info.sig, flags);
    1445          11 :                 if (ret < 0) {
    1446           0 :                         _gnutls_cert_log("failed struct verification with", signer);
    1447           0 :                         gnutls_assert();
    1448             :                 }
    1449          11 :                 gnutls_x509_crt_deinit(signer);
    1450             :         } else {
    1451          13 :                 gnutls_assert();
    1452             :                 ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
    1453             :         }
    1454             : 
    1455          25 :  cleanup:
    1456          25 :         gnutls_free(tmpdata.data);
    1457          25 :         gnutls_free(sigdata.data);
    1458          25 :         gnutls_pkcs7_signature_info_deinit(&info);
    1459             : 
    1460          25 :         return ret;
    1461             : }
    1462             : 
    1463          39 : static void disable_opt_fields(gnutls_pkcs7_t pkcs7)
    1464             : {
    1465          39 :         int result;
    1466          39 :         int count;
    1467             : 
    1468             :         /* disable the optional fields */
    1469          39 :         result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
    1470          39 :         if (result != ASN1_SUCCESS || count == 0) {
    1471          39 :                 (void)asn1_write_value(pkcs7->signed_data, "crls", NULL, 0);
    1472             :         }
    1473             : 
    1474          39 :         result =
    1475          39 :             asn1_number_of_elements(pkcs7->signed_data, "certificates", &count);
    1476          39 :         if (result != ASN1_SUCCESS || count == 0) {
    1477           3 :                 (void)asn1_write_value(pkcs7->signed_data, "certificates", NULL, 0);
    1478             :         }
    1479             : 
    1480          39 :         return;
    1481             : }
    1482             : 
    1483          26 : static int reencode(gnutls_pkcs7_t pkcs7)
    1484             : {
    1485          26 :         int result;
    1486             : 
    1487          26 :         if (pkcs7->signed_data != ASN1_TYPE_EMPTY) {
    1488          26 :                 disable_opt_fields(pkcs7);
    1489             : 
    1490             :                 /* Replace the old content with the new
    1491             :                  */
    1492          26 :                 result =
    1493          26 :                     _gnutls_x509_der_encode_and_copy(pkcs7->signed_data, "",
    1494             :                                                      pkcs7->pkcs7, "content",
    1495             :                                                      0);
    1496          26 :                 if (result < 0) {
    1497           0 :                         return gnutls_assert_val(result);
    1498             :                 }
    1499             : 
    1500             :                 /* Write the content type of the signed data
    1501             :                  */
    1502          26 :                 result =
    1503          26 :                     asn1_write_value(pkcs7->pkcs7, "contentType",
    1504             :                                      SIGNED_DATA_OID, 1);
    1505          26 :                 if (result != ASN1_SUCCESS) {
    1506           0 :                         gnutls_assert();
    1507           0 :                         return _gnutls_asn2err(result);
    1508             :                 }
    1509             :         }
    1510             :         return 0;
    1511             : }
    1512             : 
    1513             : /**
    1514             :  * gnutls_pkcs7_export:
    1515             :  * @pkcs7: The pkcs7 type
    1516             :  * @format: the format of output params. One of PEM or DER.
    1517             :  * @output_data: will contain a structure PEM or DER encoded
    1518             :  * @output_data_size: holds the size of output_data (and will be
    1519             :  *   replaced by the actual size of parameters)
    1520             :  *
    1521             :  * This function will export the pkcs7 structure to DER or PEM format.
    1522             :  *
    1523             :  * If the buffer provided is not long enough to hold the output, then
    1524             :  * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
    1525             :  * will be returned.
    1526             :  *
    1527             :  * If the structure is PEM encoded, it will have a header
    1528             :  * of "BEGIN PKCS7".
    1529             :  *
    1530             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1531             :  *   negative error value.
    1532             :  **/
    1533             : int
    1534          24 : gnutls_pkcs7_export(gnutls_pkcs7_t pkcs7,
    1535             :                     gnutls_x509_crt_fmt_t format, void *output_data,
    1536             :                     size_t * output_data_size)
    1537             : {
    1538          24 :         int ret;
    1539          24 :         if (pkcs7 == NULL)
    1540             :                 return GNUTLS_E_INVALID_REQUEST;
    1541             : 
    1542          24 :         if ((ret = reencode(pkcs7)) < 0)
    1543           0 :                 return gnutls_assert_val(ret);
    1544             : 
    1545          24 :         return _gnutls_x509_export_int(pkcs7->pkcs7, format, PEM_PKCS7,
    1546             :                                        output_data, output_data_size);
    1547             : }
    1548             : 
    1549             : /**
    1550             :  * gnutls_pkcs7_export2:
    1551             :  * @pkcs7: The pkcs7 type
    1552             :  * @format: the format of output params. One of PEM or DER.
    1553             :  * @out: will contain a structure PEM or DER encoded
    1554             :  *
    1555             :  * This function will export the pkcs7 structure to DER or PEM format.
    1556             :  *
    1557             :  * The output buffer is allocated using gnutls_malloc().
    1558             :  *
    1559             :  * If the structure is PEM encoded, it will have a header
    1560             :  * of "BEGIN PKCS7".
    1561             :  *
    1562             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1563             :  *   negative error value.
    1564             :  *
    1565             :  * Since: 3.1.3
    1566             :  **/
    1567             : int
    1568           2 : gnutls_pkcs7_export2(gnutls_pkcs7_t pkcs7,
    1569             :                      gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
    1570             : {
    1571           2 :         int ret;
    1572           2 :         if (pkcs7 == NULL)
    1573             :                 return GNUTLS_E_INVALID_REQUEST;
    1574             : 
    1575           2 :         if ((ret = reencode(pkcs7)) < 0)
    1576           0 :                 return gnutls_assert_val(ret);
    1577             : 
    1578           2 :         return _gnutls_x509_export_int2(pkcs7->pkcs7, format, PEM_PKCS7, out);
    1579             : }
    1580             : 
    1581             : /* Creates an empty signed data structure in the pkcs7
    1582             :  * structure and returns a handle to the signed data.
    1583             :  */
    1584           1 : static int create_empty_signed_data(ASN1_TYPE pkcs7, ASN1_TYPE * sdata)
    1585             : {
    1586           1 :         int result;
    1587             : 
    1588           1 :         *sdata = ASN1_TYPE_EMPTY;
    1589             : 
    1590           1 :         if ((result = asn1_create_element
    1591             :              (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData",
    1592             :               sdata)) != ASN1_SUCCESS) {
    1593           0 :                 gnutls_assert();
    1594           0 :                 result = _gnutls_asn2err(result);
    1595           0 :                 goto cleanup;
    1596             :         }
    1597             : 
    1598             :         /* Use version 1
    1599             :          */
    1600           1 :         result = asn1_write_value(*sdata, "version", &one, 1);
    1601           1 :         if (result != ASN1_SUCCESS) {
    1602           0 :                 gnutls_assert();
    1603           0 :                 result = _gnutls_asn2err(result);
    1604           0 :                 goto cleanup;
    1605             :         }
    1606             : 
    1607             :         /* Use no digest algorithms
    1608             :          */
    1609             : 
    1610             :         /* id-data */
    1611           1 :         result =
    1612           1 :             asn1_write_value(*sdata, "encapContentInfo.eContentType",
    1613             :                              DIGESTED_DATA_OID, 1);
    1614           1 :         if (result != ASN1_SUCCESS) {
    1615           0 :                 gnutls_assert();
    1616           0 :                 result = _gnutls_asn2err(result);
    1617           0 :                 goto cleanup;
    1618             :         }
    1619             : 
    1620           1 :         result = asn1_write_value(*sdata, "encapContentInfo.eContent", NULL, 0);
    1621           1 :         if (result != ASN1_SUCCESS) {
    1622           0 :                 gnutls_assert();
    1623           0 :                 result = _gnutls_asn2err(result);
    1624           0 :                 goto cleanup;
    1625             :         }
    1626             : 
    1627             :         /* Add no certificates.
    1628             :          */
    1629             : 
    1630             :         /* Add no crls.
    1631             :          */
    1632             : 
    1633             :         /* Add no signerInfos.
    1634             :          */
    1635             : 
    1636             :         return 0;
    1637             : 
    1638           0 :  cleanup:
    1639           0 :         asn1_delete_structure(sdata);
    1640           0 :         return result;
    1641             : 
    1642             : }
    1643             : 
    1644             : /**
    1645             :  * gnutls_pkcs7_set_crt_raw:
    1646             :  * @pkcs7: The pkcs7 type
    1647             :  * @crt: the DER encoded certificate to be added
    1648             :  *
    1649             :  * This function will add a certificate to the PKCS7 or RFC2630
    1650             :  * certificate set.
    1651             :  *
    1652             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1653             :  *   negative error value.
    1654             :  **/
    1655          19 : int gnutls_pkcs7_set_crt_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crt)
    1656             : {
    1657          19 :         int result;
    1658             : 
    1659          19 :         if (pkcs7 == NULL)
    1660             :                 return GNUTLS_E_INVALID_REQUEST;
    1661             : 
    1662             :         /* If the signed data are uninitialized
    1663             :          * then create them.
    1664             :          */
    1665          19 :         if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
    1666             :                 /* The pkcs7 structure is new, so create the
    1667             :                  * signedData.
    1668             :                  */
    1669           1 :                 result =
    1670           1 :                     create_empty_signed_data(pkcs7->pkcs7, &pkcs7->signed_data);
    1671           1 :                 if (result < 0) {
    1672           0 :                         gnutls_assert();
    1673           0 :                         return result;
    1674             :                 }
    1675             :         }
    1676             : 
    1677             :         /* Step 2. Append the new certificate.
    1678             :          */
    1679             : 
    1680          19 :         result = asn1_write_value(pkcs7->signed_data, "certificates", "NEW", 1);
    1681          19 :         if (result != ASN1_SUCCESS) {
    1682           0 :                 gnutls_assert();
    1683           0 :                 result = _gnutls_asn2err(result);
    1684           0 :                 goto cleanup;
    1685             :         }
    1686             : 
    1687          19 :         result =
    1688          19 :             asn1_write_value(pkcs7->signed_data, "certificates.?LAST",
    1689             :                              "certificate", 1);
    1690          19 :         if (result != ASN1_SUCCESS) {
    1691           0 :                 gnutls_assert();
    1692           0 :                 result = _gnutls_asn2err(result);
    1693           0 :                 goto cleanup;
    1694             :         }
    1695             : 
    1696          19 :         result =
    1697          38 :             asn1_write_value(pkcs7->signed_data,
    1698          19 :                              "certificates.?LAST.certificate", crt->data,
    1699          19 :                              crt->size);
    1700          19 :         if (result != ASN1_SUCCESS) {
    1701           0 :                 gnutls_assert();
    1702           0 :                 result = _gnutls_asn2err(result);
    1703           0 :                 goto cleanup;
    1704             :         }
    1705             : 
    1706             :         result = 0;
    1707             : 
    1708             :  cleanup:
    1709             :         return result;
    1710             : }
    1711             : 
    1712             : /**
    1713             :  * gnutls_pkcs7_set_crt:
    1714             :  * @pkcs7: The pkcs7 type
    1715             :  * @crt: the certificate to be copied.
    1716             :  *
    1717             :  * This function will add a parsed certificate to the PKCS7 or
    1718             :  * RFC2630 certificate set.  This is a wrapper function over
    1719             :  * gnutls_pkcs7_set_crt_raw() .
    1720             :  *
    1721             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1722             :  *   negative error value.
    1723             :  **/
    1724          19 : int gnutls_pkcs7_set_crt(gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t crt)
    1725             : {
    1726          19 :         int ret;
    1727          19 :         gnutls_datum_t data;
    1728             : 
    1729          19 :         if (pkcs7 == NULL)
    1730             :                 return GNUTLS_E_INVALID_REQUEST;
    1731             : 
    1732          19 :         ret = _gnutls_x509_der_encode(crt->cert, "", &data, 0);
    1733          19 :         if (ret < 0) {
    1734           0 :                 gnutls_assert();
    1735           0 :                 return ret;
    1736             :         }
    1737             : 
    1738          19 :         ret = gnutls_pkcs7_set_crt_raw(pkcs7, &data);
    1739             : 
    1740          19 :         _gnutls_free_datum(&data);
    1741             : 
    1742          19 :         if (ret < 0) {
    1743           0 :                 gnutls_assert();
    1744           0 :                 return ret;
    1745             :         }
    1746             : 
    1747             :         return 0;
    1748             : }
    1749             : 
    1750             : /**
    1751             :  * gnutls_pkcs7_delete_crt:
    1752             :  * @pkcs7: The pkcs7 type
    1753             :  * @indx: the index of the certificate to delete
    1754             :  *
    1755             :  * This function will delete a certificate from a PKCS7 or RFC2630
    1756             :  * certificate set.  Index starts from 0. Returns 0 on success.
    1757             :  *
    1758             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1759             :  *   negative error value.
    1760             :  **/
    1761           0 : int gnutls_pkcs7_delete_crt(gnutls_pkcs7_t pkcs7, int indx)
    1762             : {
    1763           0 :         int result;
    1764           0 :         char root2[MAX_NAME_SIZE];
    1765             : 
    1766           0 :         if (pkcs7 == NULL)
    1767             :                 return GNUTLS_E_INVALID_REQUEST;
    1768             : 
    1769             :         /* Step 2. Delete the certificate.
    1770             :          */
    1771             : 
    1772           0 :         snprintf(root2, sizeof(root2), "certificates.?%u", indx + 1);
    1773             : 
    1774           0 :         result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
    1775           0 :         if (result != ASN1_SUCCESS) {
    1776           0 :                 gnutls_assert();
    1777           0 :                 result = _gnutls_asn2err(result);
    1778           0 :                 goto cleanup;
    1779             :         }
    1780             : 
    1781             :         return 0;
    1782             : 
    1783           0 :  cleanup:
    1784           0 :         return result;
    1785             : }
    1786             : 
    1787             : /* Read and write CRLs
    1788             :  */
    1789             : 
    1790             : /**
    1791             :  * gnutls_pkcs7_get_crl_raw2:
    1792             :  * @pkcs7: The pkcs7 type
    1793             :  * @indx: contains the index of the crl to extract
    1794             :  * @crl: will contain the contents of the CRL in an allocated buffer
    1795             :  *
    1796             :  * This function will return a DER encoded CRL of the PKCS7 or RFC2630 crl set.
    1797             :  *
    1798             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1799             :  *   negative error value.  After the last crl has been read
    1800             :  *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
    1801             :  *
    1802             :  * Since: 3.4.2
    1803             :  **/
    1804             : int
    1805         581 : gnutls_pkcs7_get_crl_raw2(gnutls_pkcs7_t pkcs7,
    1806             :                           unsigned indx, gnutls_datum_t * crl)
    1807             : {
    1808         581 :         int result;
    1809         581 :         char root2[MAX_NAME_SIZE];
    1810         581 :         gnutls_datum_t tmp = { NULL, 0 };
    1811         581 :         int start, end;
    1812             : 
    1813         581 :         if (pkcs7 == NULL || crl == NULL)
    1814             :                 return GNUTLS_E_INVALID_REQUEST;
    1815             : 
    1816         581 :         result = _gnutls_x509_read_value(pkcs7->pkcs7, "content", &tmp);
    1817         581 :         if (result < 0) {
    1818           0 :                 gnutls_assert();
    1819           0 :                 goto cleanup;
    1820             :         }
    1821             : 
    1822             :         /* Step 2. Parse the CertificateSet
    1823             :          */
    1824             : 
    1825         581 :         snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);
    1826             : 
    1827             :         /* Get the raw CRL
    1828             :          */
    1829         581 :         result =
    1830         581 :             asn1_der_decoding_startEnd(pkcs7->signed_data, tmp.data, tmp.size,
    1831             :                                        root2, &start, &end);
    1832             : 
    1833         581 :         if (result != ASN1_SUCCESS) {
    1834           0 :                 gnutls_assert();
    1835           0 :                 result = _gnutls_asn2err(result);
    1836           0 :                 goto cleanup;
    1837             :         }
    1838             : 
    1839         581 :         end = end - start + 1;
    1840             : 
    1841         581 :         result = _gnutls_set_datum(crl, &tmp.data[start], end);
    1842             : 
    1843         581 :  cleanup:
    1844         581 :         _gnutls_free_datum(&tmp);
    1845         581 :         return result;
    1846             : }
    1847             : 
    1848             : /**
    1849             :  * gnutls_pkcs7_get_crl_raw:
    1850             :  * @pkcs7: The pkcs7 type
    1851             :  * @indx: contains the index of the crl to extract
    1852             :  * @crl: the contents of the crl will be copied there (may be null)
    1853             :  * @crl_size: should hold the size of the crl
    1854             :  *
    1855             :  * This function will return a crl of the PKCS7 or RFC2630 crl set.
    1856             :  *
    1857             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1858             :  *   negative error value.  If the provided buffer is not long enough,
    1859             :  *   then @crl_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER is
    1860             :  *   returned.  After the last crl has been read
    1861             :  *   %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
    1862             :  **/
    1863             : int
    1864           0 : gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7,
    1865             :                          unsigned indx, void *crl, size_t * crl_size)
    1866             : {
    1867           0 :         int ret;
    1868           0 :         gnutls_datum_t tmp = { NULL, 0 };
    1869             : 
    1870           0 :         ret = gnutls_pkcs7_get_crl_raw2(pkcs7, indx, &tmp);
    1871           0 :         if (ret < 0)
    1872           0 :                 return gnutls_assert_val(ret);
    1873             : 
    1874           0 :         if ((unsigned)tmp.size > *crl_size) {
    1875           0 :                 *crl_size = tmp.size;
    1876           0 :                 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
    1877           0 :                 goto cleanup;
    1878             :         }
    1879             : 
    1880           0 :         assert(tmp.data != NULL);
    1881             : 
    1882           0 :         *crl_size = tmp.size;
    1883           0 :         if (crl)
    1884           0 :                 memcpy(crl, tmp.data, tmp.size);
    1885             : 
    1886           0 :  cleanup:
    1887           0 :         _gnutls_free_datum(&tmp);
    1888           0 :         return ret;
    1889             : }
    1890             : 
    1891             : /**
    1892             :  * gnutls_pkcs7_get_crl_count:
    1893             :  * @pkcs7: The pkcs7 type
    1894             :  *
    1895             :  * This function will return the number of certificates in the PKCS7
    1896             :  * or RFC2630 crl set.
    1897             :  *
    1898             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1899             :  *   negative error value.
    1900             :  **/
    1901         137 : int gnutls_pkcs7_get_crl_count(gnutls_pkcs7_t pkcs7)
    1902             : {
    1903         137 :         int result, count;
    1904             : 
    1905         137 :         if (pkcs7 == NULL)
    1906             :                 return GNUTLS_E_INVALID_REQUEST;
    1907             : 
    1908             :         /* Step 2. Count the CertificateSet */
    1909             : 
    1910         137 :         result = asn1_number_of_elements(pkcs7->signed_data, "crls", &count);
    1911         137 :         if (result != ASN1_SUCCESS) {
    1912         112 :                 gnutls_assert();
    1913         112 :                 return 0;       /* no crls */
    1914             :         }
    1915             : 
    1916          25 :         return count;
    1917             : 
    1918             : }
    1919             : 
    1920             : /**
    1921             :  * gnutls_pkcs7_set_crl_raw:
    1922             :  * @pkcs7: The pkcs7 type
    1923             :  * @crl: the DER encoded crl to be added
    1924             :  *
    1925             :  * This function will add a crl to the PKCS7 or RFC2630 crl set.
    1926             :  *
    1927             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1928             :  *   negative error value.
    1929             :  **/
    1930           0 : int gnutls_pkcs7_set_crl_raw(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crl)
    1931             : {
    1932           0 :         int result;
    1933             : 
    1934           0 :         if (pkcs7 == NULL)
    1935             :                 return GNUTLS_E_INVALID_REQUEST;
    1936             : 
    1937             :         /* If the signed data are uninitialized
    1938             :          * then create them.
    1939             :          */
    1940           0 :         if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
    1941             :                 /* The pkcs7 structure is new, so create the
    1942             :                  * signedData.
    1943             :                  */
    1944           0 :                 result =
    1945           0 :                     create_empty_signed_data(pkcs7->pkcs7, &pkcs7->signed_data);
    1946           0 :                 if (result < 0) {
    1947           0 :                         gnutls_assert();
    1948           0 :                         return result;
    1949             :                 }
    1950             :         }
    1951             : 
    1952             :         /* Step 2. Append the new crl.
    1953             :          */
    1954             : 
    1955           0 :         result = asn1_write_value(pkcs7->signed_data, "crls", "NEW", 1);
    1956           0 :         if (result != ASN1_SUCCESS) {
    1957           0 :                 gnutls_assert();
    1958           0 :                 result = _gnutls_asn2err(result);
    1959           0 :                 goto cleanup;
    1960             :         }
    1961             : 
    1962           0 :         result =
    1963           0 :             asn1_write_value(pkcs7->signed_data, "crls.?LAST", crl->data,
    1964           0 :                              crl->size);
    1965           0 :         if (result != ASN1_SUCCESS) {
    1966           0 :                 gnutls_assert();
    1967           0 :                 result = _gnutls_asn2err(result);
    1968           0 :                 goto cleanup;
    1969             :         }
    1970             : 
    1971             :         result = 0;
    1972             : 
    1973             :  cleanup:
    1974             :         return result;
    1975             : }
    1976             : 
    1977             : /**
    1978             :  * gnutls_pkcs7_set_crl:
    1979             :  * @pkcs7: The pkcs7 type
    1980             :  * @crl: the DER encoded crl to be added
    1981             :  *
    1982             :  * This function will add a parsed CRL to the PKCS7 or RFC2630 crl
    1983             :  * set.
    1984             :  *
    1985             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    1986             :  *   negative error value.
    1987             :  **/
    1988           0 : int gnutls_pkcs7_set_crl(gnutls_pkcs7_t pkcs7, gnutls_x509_crl_t crl)
    1989             : {
    1990           0 :         int ret;
    1991           0 :         gnutls_datum_t data;
    1992             : 
    1993           0 :         if (pkcs7 == NULL)
    1994             :                 return GNUTLS_E_INVALID_REQUEST;
    1995             : 
    1996           0 :         ret = _gnutls_x509_der_encode(crl->crl, "", &data, 0);
    1997           0 :         if (ret < 0) {
    1998           0 :                 gnutls_assert();
    1999           0 :                 return ret;
    2000             :         }
    2001             : 
    2002           0 :         ret = gnutls_pkcs7_set_crl_raw(pkcs7, &data);
    2003             : 
    2004           0 :         _gnutls_free_datum(&data);
    2005             : 
    2006           0 :         if (ret < 0) {
    2007           0 :                 gnutls_assert();
    2008           0 :                 return ret;
    2009             :         }
    2010             : 
    2011             :         return 0;
    2012             : }
    2013             : 
    2014             : /**
    2015             :  * gnutls_pkcs7_delete_crl:
    2016             :  * @pkcs7: The pkcs7 type
    2017             :  * @indx: the index of the crl to delete
    2018             :  *
    2019             :  * This function will delete a crl from a PKCS7 or RFC2630 crl set.
    2020             :  * Index starts from 0. Returns 0 on success.
    2021             :  *
    2022             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    2023             :  *   negative error value.
    2024             :  **/
    2025           0 : int gnutls_pkcs7_delete_crl(gnutls_pkcs7_t pkcs7, int indx)
    2026             : {
    2027           0 :         int result;
    2028           0 :         char root2[MAX_NAME_SIZE];
    2029             : 
    2030           0 :         if (pkcs7 == NULL)
    2031             :                 return GNUTLS_E_INVALID_REQUEST;
    2032             : 
    2033             :         /* Delete the crl.
    2034             :          */
    2035             : 
    2036           0 :         snprintf(root2, sizeof(root2), "crls.?%u", indx + 1);
    2037             : 
    2038           0 :         result = asn1_write_value(pkcs7->signed_data, root2, NULL, 0);
    2039           0 :         if (result != ASN1_SUCCESS) {
    2040           0 :                 gnutls_assert();
    2041           0 :                 result = _gnutls_asn2err(result);
    2042           0 :                 goto cleanup;
    2043             :         }
    2044             : 
    2045             :         return 0;
    2046             : 
    2047           0 :  cleanup:
    2048           0 :         return result;
    2049             : }
    2050             : 
    2051          13 : static int write_signer_id(ASN1_TYPE c2, const char *root,
    2052             :                            gnutls_x509_crt_t signer, unsigned flags)
    2053             : {
    2054          13 :         int result;
    2055          13 :         size_t serial_size;
    2056          13 :         uint8_t serial[128];
    2057          13 :         char name[256];
    2058             : 
    2059          13 :         if (flags & GNUTLS_PKCS7_WRITE_SPKI) {
    2060           0 :                 const uint8_t ver = 3;
    2061             : 
    2062           0 :                 snprintf(name, sizeof(name), "%s.version", root);
    2063           0 :                 result = asn1_write_value(c2, name, &ver, 1);
    2064           0 :                 if (result != ASN1_SUCCESS) {
    2065           0 :                         gnutls_assert();
    2066           0 :                         return _gnutls_asn2err(result);
    2067             :                 }
    2068             : 
    2069           0 :                 snprintf(name, sizeof(name), "%s.sid", root);
    2070           0 :                 result = asn1_write_value(c2, name, "subjectKeyIdentifier", 1);
    2071           0 :                 if (result != ASN1_SUCCESS) {
    2072           0 :                         gnutls_assert();
    2073           0 :                         return _gnutls_asn2err(result);
    2074             :                 }
    2075             : 
    2076           0 :                 serial_size = sizeof(serial);
    2077           0 :                 result =
    2078           0 :                     gnutls_x509_crt_get_subject_key_id(signer, serial,
    2079             :                                                        &serial_size, NULL);
    2080           0 :                 if (result < 0)
    2081           0 :                         return gnutls_assert_val(result);
    2082             : 
    2083           0 :                 snprintf(name, sizeof(name), "%s.subjectKeyIdentifier", root);
    2084           0 :                 result = asn1_write_value(c2, name, serial, serial_size);
    2085           0 :                 if (result != ASN1_SUCCESS) {
    2086           0 :                         gnutls_assert();
    2087           0 :                         return _gnutls_asn2err(result);
    2088             :                 }
    2089             :         } else {
    2090          13 :                 serial_size = sizeof(serial);
    2091          13 :                 result =
    2092          13 :                     gnutls_x509_crt_get_serial(signer, serial, &serial_size);
    2093          13 :                 if (result < 0)
    2094           0 :                         return gnutls_assert_val(result);
    2095             : 
    2096          13 :                 snprintf(name, sizeof(name), "%s.sid", root);
    2097          13 :                 result = asn1_write_value(c2, name, "issuerAndSerialNumber", 1);
    2098          13 :                 if (result != ASN1_SUCCESS) {
    2099           0 :                         gnutls_assert();
    2100           0 :                         return _gnutls_asn2err(result);
    2101             :                 }
    2102             : 
    2103          13 :                 snprintf(name, sizeof(name),
    2104             :                          "%s.sid.issuerAndSerialNumber.serialNumber", root);
    2105          13 :                 result = asn1_write_value(c2, name, serial, serial_size);
    2106          13 :                 if (result != ASN1_SUCCESS) {
    2107           0 :                         gnutls_assert();
    2108           0 :                         return _gnutls_asn2err(result);
    2109             :                 }
    2110             : 
    2111          13 :                 snprintf(name, sizeof(name),
    2112             :                          "%s.sid.issuerAndSerialNumber.issuer", root);
    2113          13 :                 result =
    2114          13 :                     asn1_copy_node(c2, name, signer->cert,
    2115             :                                    "tbsCertificate.issuer");
    2116          13 :                 if (result != ASN1_SUCCESS) {
    2117           0 :                         gnutls_assert();
    2118           0 :                         return _gnutls_asn2err(result);
    2119             :                 }
    2120             :         }
    2121             : 
    2122             :         return 0;
    2123             : }
    2124             : 
    2125          26 : static int add_attrs(ASN1_TYPE c2, const char *root, gnutls_pkcs7_attrs_t attrs,
    2126             :                      unsigned already_set)
    2127             : {
    2128          26 :         char name[256];
    2129          26 :         gnutls_pkcs7_attrs_st *p = attrs;
    2130          26 :         int result;
    2131             : 
    2132          26 :         if (attrs == NULL) {
    2133             :                 /* if there are no other attributes delete that field */
    2134          24 :                 if (already_set == 0)
    2135          22 :                         (void)asn1_write_value(c2, root, NULL, 0);
    2136             :         } else {
    2137           5 :                 while (p != NULL) {
    2138           3 :                         result = asn1_write_value(c2, root, "NEW", 1);
    2139           3 :                         if (result != ASN1_SUCCESS) {
    2140           0 :                                 gnutls_assert();
    2141           0 :                                 return _gnutls_asn2err(result);
    2142             :                         }
    2143             : 
    2144           3 :                         snprintf(name, sizeof(name), "%s.?LAST.type", root);
    2145           3 :                         result = asn1_write_value(c2, name, p->oid, 1);
    2146           3 :                         if (result != ASN1_SUCCESS) {
    2147           0 :                                 gnutls_assert();
    2148           0 :                                 return _gnutls_asn2err(result);
    2149             :                         }
    2150             : 
    2151           3 :                         snprintf(name, sizeof(name), "%s.?LAST.values", root);
    2152           3 :                         result = asn1_write_value(c2, name, "NEW", 1);
    2153           3 :                         if (result != ASN1_SUCCESS) {
    2154           0 :                                 gnutls_assert();
    2155           0 :                                 return _gnutls_asn2err(result);
    2156             :                         }
    2157             : 
    2158           3 :                         snprintf(name, sizeof(name), "%s.?LAST.values.?1",
    2159             :                                  root);
    2160           3 :                         result =
    2161           6 :                             asn1_write_value(c2, name, p->data.data,
    2162           3 :                                              p->data.size);
    2163           3 :                         if (result != ASN1_SUCCESS) {
    2164           0 :                                 gnutls_assert();
    2165           0 :                                 return _gnutls_asn2err(result);
    2166             :                         }
    2167             : 
    2168           3 :                         p = p->next;
    2169             :                 }
    2170             :         }
    2171             : 
    2172             :         return 0;
    2173             : }
    2174             : 
    2175          13 : static int write_attributes(ASN1_TYPE c2, const char *root,
    2176             :                             const gnutls_datum_t * data,
    2177             :                             const mac_entry_st * me,
    2178             :                             gnutls_pkcs7_attrs_t other_attrs, unsigned flags)
    2179             : {
    2180          13 :         char name[256];
    2181          13 :         int result, ret;
    2182          13 :         uint8_t digest[MAX_HASH_SIZE];
    2183          13 :         gnutls_datum_t tmp = { NULL, 0 };
    2184          13 :         unsigned digest_size;
    2185          13 :         unsigned already_set = 0;
    2186             : 
    2187          13 :         if (flags & GNUTLS_PKCS7_INCLUDE_TIME) {
    2188           2 :                 if (data == NULL || data->data == NULL) {
    2189           0 :                         gnutls_assert();
    2190           0 :                         return GNUTLS_E_INVALID_REQUEST;
    2191             :                 }
    2192             : 
    2193             :                 /* Add time */
    2194           2 :                 result = asn1_write_value(c2, root, "NEW", 1);
    2195           2 :                 if (result != ASN1_SUCCESS) {
    2196           0 :                         gnutls_assert();
    2197           0 :                         ret = _gnutls_asn2err(result);
    2198           0 :                         return ret;
    2199             :                 }
    2200             : 
    2201           2 :                 snprintf(name, sizeof(name), "%s.?LAST.type", root);
    2202           2 :                 result = asn1_write_value(c2, name, ATTR_SIGNING_TIME, 1);
    2203           2 :                 if (result != ASN1_SUCCESS) {
    2204           0 :                         gnutls_assert();
    2205           0 :                         ret = _gnutls_asn2err(result);
    2206           0 :                         return ret;
    2207             :                 }
    2208             : 
    2209           2 :                 snprintf(name, sizeof(name), "%s.?LAST.values", root);
    2210           2 :                 result = asn1_write_value(c2, name, "NEW", 1);
    2211           2 :                 if (result != ASN1_SUCCESS) {
    2212           0 :                         gnutls_assert();
    2213           0 :                         ret = _gnutls_asn2err(result);
    2214           0 :                         return ret;
    2215             :                 }
    2216             : 
    2217           2 :                 snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
    2218           2 :                 ret = _gnutls_x509_set_raw_time(c2, name, gnutls_time(0));
    2219           2 :                 if (ret < 0) {
    2220           0 :                         gnutls_assert();
    2221           0 :                         return ret;
    2222             :                 }
    2223             : 
    2224             :                 already_set = 1;
    2225             :         }
    2226             : 
    2227          13 :         ret = add_attrs(c2, root, other_attrs, already_set);
    2228          13 :         if (ret < 0) {
    2229           0 :                 gnutls_assert();
    2230           0 :                 return ret;
    2231             :         }
    2232             : 
    2233          13 :         if (already_set != 0 || other_attrs != NULL) {
    2234             :                 /* Add content type */
    2235           3 :                 result = asn1_write_value(c2, root, "NEW", 1);
    2236           3 :                 if (result != ASN1_SUCCESS) {
    2237           0 :                         gnutls_assert();
    2238           0 :                         ret = _gnutls_asn2err(result);
    2239           0 :                         return ret;
    2240             :                 }
    2241             : 
    2242           3 :                 snprintf(name, sizeof(name), "%s.?LAST.type", root);
    2243           3 :                 result = asn1_write_value(c2, name, ATTR_CONTENT_TYPE, 1);
    2244           3 :                 if (result != ASN1_SUCCESS) {
    2245           0 :                         gnutls_assert();
    2246           0 :                         ret = _gnutls_asn2err(result);
    2247           0 :                         return ret;
    2248             :                 }
    2249             : 
    2250           3 :                 snprintf(name, sizeof(name), "%s.?LAST.values", root);
    2251           3 :                 result = asn1_write_value(c2, name, "NEW", 1);
    2252           3 :                 if (result != ASN1_SUCCESS) {
    2253           0 :                         gnutls_assert();
    2254           0 :                         ret = _gnutls_asn2err(result);
    2255           0 :                         return ret;
    2256             :                 }
    2257             : 
    2258           3 :                 ret =
    2259           3 :                     _gnutls_x509_get_raw_field(c2,
    2260             :                                                "encapContentInfo.eContentType",
    2261             :                                                &tmp);
    2262           3 :                 if (ret < 0) {
    2263           0 :                         gnutls_assert();
    2264           0 :                         return ret;
    2265             :                 }
    2266             : 
    2267           3 :                 snprintf(name, sizeof(name), "%s.?LAST.values.?1", root);
    2268           3 :                 result = asn1_write_value(c2, name, tmp.data, tmp.size);
    2269           3 :                 gnutls_free(tmp.data);
    2270             : 
    2271           3 :                 if (result != ASN1_SUCCESS) {
    2272           0 :                         gnutls_assert();
    2273           0 :                         ret = _gnutls_asn2err(result);
    2274           0 :                         return ret;
    2275             :                 }
    2276             : 
    2277             :                 /* If we add any attribute we should add them all */
    2278             :                 /* Add hash */
    2279           3 :                 digest_size = _gnutls_hash_get_algo_len(me);
    2280           3 :                 ret = gnutls_hash_fast(MAC_TO_DIG(me->id), data->data, data->size, digest);
    2281           3 :                 if (ret < 0) {
    2282           0 :                         gnutls_assert();
    2283           0 :                         return ret;
    2284             :                 }
    2285             : 
    2286           3 :                 result = asn1_write_value(c2, root, "NEW", 1);
    2287           3 :                 if (result != ASN1_SUCCESS) {
    2288           0 :                         gnutls_assert();
    2289           0 :                         ret = _gnutls_asn2err(result);
    2290           0 :                         return ret;
    2291             :                 }
    2292             : 
    2293           3 :                 snprintf(name, sizeof(name), "%s.?LAST", root);
    2294           3 :                 ret =
    2295           3 :                     _gnutls_x509_encode_and_write_attribute(ATTR_MESSAGE_DIGEST,
    2296             :                                                             c2, name, digest,
    2297             :                                                             digest_size, 1);
    2298           3 :                 if (ret < 0) {
    2299           0 :                         gnutls_assert();
    2300           0 :                         return ret;
    2301             :                 }
    2302             :         }
    2303             : 
    2304             :         return 0;
    2305             : }
    2306             : 
    2307             : /**
    2308             :  * gnutls_pkcs7_sign:
    2309             :  * @pkcs7: should contain a #gnutls_pkcs7_t type
    2310             :  * @signer: the certificate to sign the structure
    2311             :  * @signer_key: the key to sign the structure
    2312             :  * @data: The data to be signed or %NULL if the data are already embedded
    2313             :  * @signed_attrs: Any additional attributes to be included in the signed ones (or %NULL)
    2314             :  * @unsigned_attrs: Any additional attributes to be included in the unsigned ones (or %NULL)
    2315             :  * @dig: The digest algorithm to use for signing
    2316             :  * @flags: Should be zero or one of %GNUTLS_PKCS7 flags
    2317             :  *
    2318             :  * This function will add a signature in the provided PKCS #7 structure
    2319             :  * for the provided data. Multiple signatures can be made with different
    2320             :  * signers.
    2321             :  *
    2322             :  * The available flags are:
    2323             :  *  %GNUTLS_PKCS7_EMBED_DATA, %GNUTLS_PKCS7_INCLUDE_TIME, %GNUTLS_PKCS7_INCLUDE_CERT,
    2324             :  *  and %GNUTLS_PKCS7_WRITE_SPKI. They are explained in the #gnutls_pkcs7_sign_flags
    2325             :  *  definition.
    2326             :  *
    2327             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
    2328             :  *   negative error value.
    2329             :  *
    2330             :  * Since: 3.4.2
    2331             :  **/
    2332          13 : int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7,
    2333             :                       gnutls_x509_crt_t signer,
    2334             :                       gnutls_privkey_t signer_key,
    2335             :                       const gnutls_datum_t *data,
    2336             :                       gnutls_pkcs7_attrs_t signed_attrs,
    2337             :                       gnutls_pkcs7_attrs_t unsigned_attrs,
    2338             :                       gnutls_digest_algorithm_t dig, unsigned flags)
    2339             : {
    2340          13 :         int ret, result;
    2341          13 :         gnutls_datum_t sigdata = { NULL, 0 };
    2342          13 :         gnutls_datum_t signature = { NULL, 0 };
    2343          13 :         const mac_entry_st *me = hash_to_entry(dig);
    2344          13 :         unsigned pk, sigalgo;
    2345          13 :         gnutls_x509_spki_st key_params, params;
    2346          13 :         const gnutls_sign_entry_st *se;
    2347             : 
    2348          13 :         if (pkcs7 == NULL || me == NULL)
    2349             :                 return GNUTLS_E_INVALID_REQUEST;
    2350             : 
    2351          13 :         if (pkcs7->signed_data == ASN1_TYPE_EMPTY) {
    2352          13 :                 result =
    2353          13 :                     asn1_create_element(_gnutls_get_pkix(),
    2354             :                                         "PKIX1.pkcs-7-SignedData",
    2355             :                                         &pkcs7->signed_data);
    2356          13 :                 if (result != ASN1_SUCCESS) {
    2357           0 :                         gnutls_assert();
    2358           0 :                         ret = _gnutls_asn2err(result);
    2359           0 :                         goto cleanup;
    2360             :                 }
    2361             : 
    2362          13 :                 if (!(flags & GNUTLS_PKCS7_EMBED_DATA)) {
    2363           4 :                         (void)asn1_write_value(pkcs7->signed_data,
    2364             :                                          "encapContentInfo.eContent", NULL, 0);
    2365             :                 }
    2366             :         }
    2367             : 
    2368          13 :         result = asn1_write_value(pkcs7->signed_data, "version", &one, 1);
    2369          13 :         if (result != ASN1_SUCCESS) {
    2370           0 :                 ret = _gnutls_asn2err(result);
    2371           0 :                 goto cleanup;
    2372             :         }
    2373             : 
    2374          13 :         result =
    2375          13 :             asn1_write_value(pkcs7->signed_data,
    2376             :                              "encapContentInfo.eContentType", DATA_OID,
    2377             :                              0);
    2378          13 :         if (result != ASN1_SUCCESS) {
    2379           0 :                 ret = _gnutls_asn2err(result);
    2380           0 :                 goto cleanup;
    2381             :         }
    2382             : 
    2383          13 :         if ((flags & GNUTLS_PKCS7_EMBED_DATA) && data->data) {   /* embed data */
    2384           9 :                 ret =
    2385           9 :                     _gnutls_x509_write_string(pkcs7->signed_data,
    2386             :                                      "encapContentInfo.eContent", data,
    2387             :                                      ASN1_ETYPE_OCTET_STRING);
    2388           9 :                 if (ret < 0) {
    2389           0 :                         goto cleanup;
    2390             :                 }
    2391             :         }
    2392             : 
    2393          13 :         if (flags & GNUTLS_PKCS7_INCLUDE_CERT) {
    2394          12 :                 ret = gnutls_pkcs7_set_crt(pkcs7, signer);
    2395          12 :                 if (ret < 0) {
    2396           0 :                         gnutls_assert();
    2397           0 :                         goto cleanup;
    2398             :                 }
    2399             :         }
    2400             : 
    2401             :         /* append digest info algorithm */
    2402          13 :         result =
    2403          13 :             asn1_write_value(pkcs7->signed_data, "digestAlgorithms", "NEW", 1);
    2404          13 :         if (result != ASN1_SUCCESS) {
    2405           0 :                 gnutls_assert();
    2406           0 :                 ret = _gnutls_asn2err(result);
    2407           0 :                 goto cleanup;
    2408             :         }
    2409             : 
    2410          13 :         result =
    2411          26 :             asn1_write_value(pkcs7->signed_data,
    2412             :                              "digestAlgorithms.?LAST.algorithm",
    2413          13 :                              _gnutls_x509_digest_to_oid(me), 1);
    2414          13 :         if (result != ASN1_SUCCESS) {
    2415           0 :                 gnutls_assert();
    2416           0 :                 ret = _gnutls_asn2err(result);
    2417           0 :                 goto cleanup;
    2418             :         }
    2419             : 
    2420          13 :         (void)asn1_write_value(pkcs7->signed_data,
    2421             :                          "digestAlgorithms.?LAST.parameters", NULL, 0);
    2422             : 
    2423             :         /* append signer's info */
    2424          13 :         result = asn1_write_value(pkcs7->signed_data, "signerInfos", "NEW", 1);
    2425          13 :         if (result != ASN1_SUCCESS) {
    2426           0 :                 gnutls_assert();
    2427           0 :                 ret = _gnutls_asn2err(result);
    2428           0 :                 goto cleanup;
    2429             :         }
    2430             : 
    2431          13 :         result =
    2432          13 :             asn1_write_value(pkcs7->signed_data, "signerInfos.?LAST.version",
    2433             :                              &one, 1);
    2434          13 :         if (result != ASN1_SUCCESS) {
    2435           0 :                 gnutls_assert();
    2436           0 :                 ret = _gnutls_asn2err(result);
    2437           0 :                 goto cleanup;
    2438             :         }
    2439             : 
    2440          13 :         result =
    2441          26 :             asn1_write_value(pkcs7->signed_data,
    2442             :                              "signerInfos.?LAST.digestAlgorithm.algorithm",
    2443          13 :                              _gnutls_x509_digest_to_oid(me), 1);
    2444          13 :         if (result != ASN1_SUCCESS) {
    2445           0 :                 gnutls_assert();
    2446           0 :                 ret = _gnutls_asn2err(result);
    2447           0 :                 goto cleanup;
    2448             :         }
    2449             : 
    2450          13 :         (void)asn1_write_value(pkcs7->signed_data,
    2451             :                          "signerInfos.?LAST.digestAlgorithm.parameters", NULL,
    2452             :                          0);
    2453             : 
    2454          13 :         ret =
    2455          13 :             write_signer_id(pkcs7->signed_data, "signerInfos.?LAST", signer,
    2456             :                             flags);
    2457          13 :         if (ret < 0) {
    2458           0 :                 gnutls_assert();
    2459           0 :                 goto cleanup;
    2460             :         }
    2461             : 
    2462          13 :         ret =
    2463          13 :             add_attrs(pkcs7->signed_data, "signerInfos.?LAST.unsignedAttrs",
    2464             :                       unsigned_attrs, 0);
    2465          13 :         if (ret < 0) {
    2466           0 :                 gnutls_assert();
    2467           0 :                 goto cleanup;
    2468             :         }
    2469             : 
    2470          13 :         ret =
    2471          13 :             write_attributes(pkcs7->signed_data,
    2472             :                              "signerInfos.?LAST.signedAttrs", data, me,
    2473             :                              signed_attrs, flags);
    2474          13 :         if (ret < 0) {
    2475           0 :                 gnutls_assert();
    2476           0 :                 goto cleanup;
    2477             :         }
    2478             : 
    2479          13 :         disable_opt_fields(pkcs7);
    2480             : 
    2481             :         /* write the signature algorithm */
    2482          13 :         pk = gnutls_x509_crt_get_pk_algorithm(signer, NULL);
    2483             : 
    2484          13 :         ret = _gnutls_privkey_get_spki_params(signer_key, &key_params);
    2485          13 :         if (ret < 0) {
    2486           0 :                 gnutls_assert();
    2487           0 :                 goto cleanup;
    2488             :         }
    2489             : 
    2490          13 :         ret = _gnutls_x509_crt_get_spki_params(signer, &key_params, &params);
    2491          13 :         if (ret < 0) {
    2492           0 :                 gnutls_assert();
    2493           0 :                 goto cleanup;
    2494             :         }
    2495             : 
    2496          13 :         ret = _gnutls_privkey_update_spki_params(signer_key, pk, dig, 0,
    2497             :                                                   &params);
    2498          13 :         if (ret < 0) {
    2499           0 :                 gnutls_assert();
    2500           0 :                 goto cleanup;
    2501             :         }
    2502             : 
    2503          13 :         se = _gnutls_pk_to_sign_entry(params.pk, dig);
    2504          13 :         if (se == NULL) {
    2505           0 :                 ret = gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
    2506           0 :                 goto cleanup;
    2507             :         }
    2508             : 
    2509             :         /* RFC5652 is silent on what the values would be and initially I assumed that
    2510             :          * typical signature algorithms should be set. However RFC2315 (PKCS#7) mentions
    2511             :          * that a generic RSA OID should be used. We switch to this "unexpected" value
    2512             :          * because some implementations cannot cope with the "expected" signature values.
    2513             :          */
    2514          13 :         params.legacy = 1;
    2515          13 :         ret =
    2516          13 :             _gnutls_x509_write_sign_params(pkcs7->signed_data,
    2517             :                                            "signerInfos.?LAST.signatureAlgorithm",
    2518             :                                            se, &params);
    2519          13 :         if (ret < 0) {
    2520           0 :                 gnutls_assert();
    2521           0 :                 goto cleanup;
    2522             :         }
    2523             : 
    2524          13 :         sigalgo = se->id;
    2525             : 
    2526             :         /* sign the data */
    2527          13 :         ret =
    2528          13 :             figure_pkcs7_sigdata(pkcs7, "signerInfos.?LAST", data, sigalgo,
    2529             :                                  &sigdata);
    2530          13 :         if (ret < 0) {
    2531           0 :                 gnutls_assert();
    2532           0 :                 goto cleanup;
    2533             :         }
    2534             : 
    2535          13 :         FIX_SIGN_PARAMS(params, flags, dig);
    2536             : 
    2537          13 :         ret = privkey_sign_and_hash_data(signer_key, se,
    2538             :                                          &sigdata, &signature, &params);
    2539          13 :         if (ret < 0) {
    2540           0 :                 gnutls_assert();
    2541           0 :                 goto cleanup;
    2542             :         }
    2543             : 
    2544          13 :         result =
    2545          26 :             asn1_write_value(pkcs7->signed_data, "signerInfos.?LAST.signature",
    2546          13 :                              signature.data, signature.size);
    2547          13 :         if (result != ASN1_SUCCESS) {
    2548           0 :                 gnutls_assert();
    2549           0 :                 ret = _gnutls_asn2err(result);
    2550           0 :                 goto cleanup;
    2551             :         }
    2552             : 
    2553             :         ret = 0;
    2554             : 
    2555          13 :  cleanup:
    2556          13 :         gnutls_free(sigdata.data);
    2557          13 :         gnutls_free(signature.data);
    2558          13 :         return ret;
    2559             : }

Generated by: LCOV version 1.14