root/source4/heimdal/lib/hx509/cms.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hx509_cms_wrap_ContentInfo
  2. hx509_cms_unwrap_ContentInfo
  3. fill_CMSIdentifier
  4. unparse_CMSIdentifier
  5. find_CMSIdentifier
  6. hx509_cms_unenvelope
  7. hx509_cms_envelope_1
  8. any_to_certs
  9. find_attribute
  10. hx509_cms_verify_signed
  11. add_one_attribute
  12. hx509_cms_create_signed_1
  13. hx509_cms_decrypt_encrypted

   1 /*
   2  * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "hx_locl.h"
  35 RCSID("$Id$");
  36 
  37 /**
  38  * @page page_cms CMS/PKCS7 message functions.
  39  *
  40  * CMS is defined in RFC 3369 and is an continuation of the RSA Labs
  41  * standard PKCS7. The basic messages in CMS is
  42  *
  43  * - SignedData
  44  *   Data signed with private key (RSA, DSA, ECDSA) or secret
  45  *   (symmetric) key
  46  * - EnvelopedData
  47  *   Data encrypted with private key (RSA)
  48  * - EncryptedData
  49  *   Data encrypted with secret (symmetric) key.
  50  * - ContentInfo
  51  *   Wrapper structure including type and data.
  52  *
  53  *
  54  * See the library functions here: @ref hx509_cms
  55  */
  56 
  57 #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
  58 #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
  59 
  60 /**
  61  * Wrap data and oid in a ContentInfo and encode it.
  62  *
  63  * @param oid type of the content.
  64  * @param buf data to be wrapped. If a NULL pointer is passed in, the
  65  * optional content field in the ContentInfo is not going be filled
  66  * in.
  67  * @param res the encoded buffer, the result should be freed with
  68  * der_free_octet_string().
  69  *
  70  * @return Returns an hx509 error code.
  71  *
  72  * @ingroup hx509_cms
  73  */
  74 
  75 int
  76 hx509_cms_wrap_ContentInfo(const heim_oid *oid,
     /* [<][>][^][v][top][bottom][index][help] */
  77                            const heim_octet_string *buf,
  78                            heim_octet_string *res)
  79 {
  80     ContentInfo ci;
  81     size_t size;
  82     int ret;
  83 
  84     memset(res, 0, sizeof(*res));
  85     memset(&ci, 0, sizeof(ci));
  86 
  87     ret = der_copy_oid(oid, &ci.contentType);
  88     if (ret)
  89         return ret;
  90     if (buf) {
  91         ALLOC(ci.content, 1);
  92         if (ci.content == NULL) {
  93             free_ContentInfo(&ci);
  94             return ENOMEM;
  95         }
  96         ci.content->data = malloc(buf->length);
  97         if (ci.content->data == NULL) {
  98             free_ContentInfo(&ci);
  99             return ENOMEM;
 100         }
 101         memcpy(ci.content->data, buf->data, buf->length);
 102         ci.content->length = buf->length;
 103     }
 104 
 105     ASN1_MALLOC_ENCODE(ContentInfo, res->data, res->length, &ci, &size, ret);
 106     free_ContentInfo(&ci);
 107     if (ret)
 108         return ret;
 109     if (res->length != size)
 110         _hx509_abort("internal ASN.1 encoder error");
 111 
 112     return 0;
 113 }
 114 
 115 /**
 116  * Decode an ContentInfo and unwrap data and oid it.
 117  *
 118  * @param in the encoded buffer.
 119  * @param oid type of the content.
 120  * @param out data to be wrapped.
 121  * @param have_data since the data is optional, this flags show dthe
 122  * diffrence between no data and the zero length data.
 123  *
 124  * @return Returns an hx509 error code.
 125  *
 126  * @ingroup hx509_cms
 127  */
 128 
 129 int
 130 hx509_cms_unwrap_ContentInfo(const heim_octet_string *in,
     /* [<][>][^][v][top][bottom][index][help] */
 131                              heim_oid *oid,
 132                              heim_octet_string *out,
 133                              int *have_data)
 134 {
 135     ContentInfo ci;
 136     size_t size;
 137     int ret;
 138 
 139     memset(oid, 0, sizeof(*oid));
 140     memset(out, 0, sizeof(*out));
 141 
 142     ret = decode_ContentInfo(in->data, in->length, &ci, &size);
 143     if (ret)
 144         return ret;
 145 
 146     ret = der_copy_oid(&ci.contentType, oid);
 147     if (ret) {
 148         free_ContentInfo(&ci);
 149         return ret;
 150     }
 151     if (ci.content) {
 152         ret = der_copy_octet_string(ci.content, out);
 153         if (ret) {
 154             der_free_oid(oid);
 155             free_ContentInfo(&ci);
 156             return ret;
 157         }
 158     } else
 159         memset(out, 0, sizeof(*out));
 160 
 161     if (have_data)
 162         *have_data = (ci.content != NULL) ? 1 : 0;
 163 
 164     free_ContentInfo(&ci);
 165 
 166     return 0;
 167 }
 168 
 169 #define CMS_ID_SKI      0
 170 #define CMS_ID_NAME     1
 171 
 172 static int
 173 fill_CMSIdentifier(const hx509_cert cert,
     /* [<][>][^][v][top][bottom][index][help] */
 174                    int type,
 175                    CMSIdentifier *id)
 176 {
 177     int ret;
 178 
 179     switch (type) {
 180     case CMS_ID_SKI:
 181         id->element = choice_CMSIdentifier_subjectKeyIdentifier;
 182         ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert),
 183                                                    &id->u.subjectKeyIdentifier);
 184         if (ret == 0)
 185             break;
 186         /* FALL THOUGH */
 187     case CMS_ID_NAME: {
 188         hx509_name name;
 189 
 190         id->element = choice_CMSIdentifier_issuerAndSerialNumber;
 191         ret = hx509_cert_get_issuer(cert, &name);
 192         if (ret)
 193             return ret;
 194         ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer);
 195         hx509_name_free(&name);
 196         if (ret)
 197             return ret;
 198 
 199         ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber);
 200         break;
 201     }
 202     default:
 203         _hx509_abort("CMS fill identifier with unknown type");
 204     }
 205     return ret;
 206 }
 207 
 208 static int
 209 unparse_CMSIdentifier(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 210                       CMSIdentifier *id,
 211                       char **str)
 212 {
 213     int ret;
 214 
 215     *str = NULL;
 216     switch (id->element) {
 217     case choice_CMSIdentifier_issuerAndSerialNumber: {
 218         IssuerAndSerialNumber *iasn;
 219         char *serial, *name;
 220 
 221         iasn = &id->u.issuerAndSerialNumber;
 222 
 223         ret = _hx509_Name_to_string(&iasn->issuer, &name);
 224         if(ret)
 225             return ret;
 226         ret = der_print_hex_heim_integer(&iasn->serialNumber, &serial);
 227         if (ret) {
 228             free(name);
 229             return ret;
 230         }
 231         asprintf(str, "certificate issued by %s with serial number %s",
 232                  name, serial);
 233         free(name);
 234         free(serial);
 235         break;
 236     }
 237     case choice_CMSIdentifier_subjectKeyIdentifier: {
 238         KeyIdentifier *ki  = &id->u.subjectKeyIdentifier;
 239         char *keyid;
 240         ssize_t len;
 241 
 242         len = hex_encode(ki->data, ki->length, &keyid);
 243         if (len < 0)
 244             return ENOMEM;
 245 
 246         asprintf(str, "certificate with id %s", keyid);
 247         free(keyid);
 248         break;
 249     }
 250     default:
 251         asprintf(str, "certificate have unknown CMSidentifier type");
 252         break;
 253     }
 254     if (*str == NULL)
 255         return ENOMEM;
 256     return 0;
 257 }
 258 
 259 static int
 260 find_CMSIdentifier(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 261                    CMSIdentifier *client,
 262                    hx509_certs certs,
 263                    time_t time_now,
 264                    hx509_cert *signer_cert,
 265                    int match)
 266 {
 267     hx509_query q;
 268     hx509_cert cert;
 269     Certificate c;
 270     int ret;
 271 
 272     memset(&c, 0, sizeof(c));
 273     _hx509_query_clear(&q);
 274 
 275     *signer_cert = NULL;
 276 
 277     switch (client->element) {
 278     case choice_CMSIdentifier_issuerAndSerialNumber:
 279         q.serial = &client->u.issuerAndSerialNumber.serialNumber;
 280         q.issuer_name = &client->u.issuerAndSerialNumber.issuer;
 281         q.match = HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
 282         break;
 283     case choice_CMSIdentifier_subjectKeyIdentifier:
 284         q.subject_id = &client->u.subjectKeyIdentifier;
 285         q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
 286         break;
 287     default:
 288         hx509_set_error_string(context, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE,
 289                                "unknown CMS identifier element");
 290         return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
 291     }
 292 
 293     q.match |= match;
 294 
 295     q.match |= HX509_QUERY_MATCH_TIME;
 296     if (time_now)
 297         q.timenow = time_now;
 298     else
 299         q.timenow = time(NULL);
 300 
 301     ret = hx509_certs_find(context, certs, &q, &cert);
 302     if (ret == HX509_CERT_NOT_FOUND) {
 303         char *str;
 304 
 305         ret = unparse_CMSIdentifier(context, client, &str);
 306         if (ret == 0) {
 307             hx509_set_error_string(context, 0,
 308                                    HX509_CMS_NO_RECIPIENT_CERTIFICATE,
 309                                    "Failed to find %s", str);
 310         } else
 311             hx509_clear_error_string(context);
 312         return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
 313     } else if (ret) {
 314         hx509_set_error_string(context, HX509_ERROR_APPEND,
 315                                HX509_CMS_NO_RECIPIENT_CERTIFICATE,
 316                                "Failed to find CMS id in cert store");
 317         return HX509_CMS_NO_RECIPIENT_CERTIFICATE;
 318     }
 319 
 320     *signer_cert = cert;
 321 
 322     return 0;
 323 }
 324 
 325 /**
 326  * Decode and unencrypt EnvelopedData.
 327  *
 328  * Extract data and parameteres from from the EnvelopedData. Also
 329  * supports using detached EnvelopedData.
 330  *
 331  * @param context A hx509 context.
 332  * @param certs Certificate that can decrypt the EnvelopedData
 333  * encryption key.
 334  * @param flags HX509_CMS_UE flags to control the behavior.
 335  * @param data pointer the structure the contains the DER/BER encoded
 336  * EnvelopedData stucture.
 337  * @param length length of the data that data point to.
 338  * @param encryptedContent in case of detached signature, this
 339  * contains the actual encrypted data, othersize its should be NULL.
 340  * @param time_now set the current time, if zero the library uses now as the date.
 341  * @param contentType output type oid, should be freed with der_free_oid().
 342  * @param content the data, free with der_free_octet_string().
 343  *
 344  * @ingroup hx509_cms
 345  */
 346 
 347 int
 348 hx509_cms_unenvelope(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 349                      hx509_certs certs,
 350                      int flags,
 351                      const void *data,
 352                      size_t length,
 353                      const heim_octet_string *encryptedContent,
 354                      time_t time_now,
 355                      heim_oid *contentType,
 356                      heim_octet_string *content)
 357 {
 358     heim_octet_string key;
 359     EnvelopedData ed;
 360     hx509_cert cert;
 361     AlgorithmIdentifier *ai;
 362     const heim_octet_string *enccontent;
 363     heim_octet_string *params, params_data;
 364     heim_octet_string ivec;
 365     size_t size;
 366     int ret, i, matched = 0, findflags = 0;
 367 
 368 
 369     memset(&key, 0, sizeof(key));
 370     memset(&ed, 0, sizeof(ed));
 371     memset(&ivec, 0, sizeof(ivec));
 372     memset(content, 0, sizeof(*content));
 373     memset(contentType, 0, sizeof(*contentType));
 374 
 375     if ((flags & HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT) == 0)
 376         findflags |= HX509_QUERY_KU_ENCIPHERMENT;
 377 
 378     ret = decode_EnvelopedData(data, length, &ed, &size);
 379     if (ret) {
 380         hx509_set_error_string(context, 0, ret,
 381                                "Failed to decode EnvelopedData");
 382         return ret;
 383     }
 384 
 385     if (ed.recipientInfos.len == 0) {
 386         ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;
 387         hx509_set_error_string(context, 0, ret,
 388                                "No recipient info in enveloped data");
 389         goto out;
 390     }
 391 
 392     enccontent = ed.encryptedContentInfo.encryptedContent;
 393     if (enccontent == NULL) {
 394         if (encryptedContent == NULL) {
 395             ret = HX509_CMS_NO_DATA_AVAILABLE;
 396             hx509_set_error_string(context, 0, ret,
 397                                    "Content missing from encrypted data");
 398             goto out;
 399         }
 400         enccontent = encryptedContent;
 401     } else if (encryptedContent != NULL) {
 402         ret = HX509_CMS_NO_DATA_AVAILABLE;
 403         hx509_set_error_string(context, 0, ret,
 404                                "Both internal and external encrypted data");
 405         goto out;
 406     }
 407 
 408     cert = NULL;
 409     for (i = 0; i < ed.recipientInfos.len; i++) {
 410         KeyTransRecipientInfo *ri;
 411         char *str;
 412         int ret2;
 413 
 414         ri = &ed.recipientInfos.val[i];
 415 
 416         ret = find_CMSIdentifier(context, &ri->rid, certs,
 417                                  time_now, &cert,
 418                                  HX509_QUERY_PRIVATE_KEY|findflags);
 419         if (ret)
 420             continue;
 421 
 422         matched = 1; /* found a matching certificate, let decrypt */
 423 
 424         ret = _hx509_cert_private_decrypt(context,
 425                                           &ri->encryptedKey,
 426                                           &ri->keyEncryptionAlgorithm.algorithm,
 427                                           cert, &key);
 428 
 429         hx509_cert_free(cert);
 430         if (ret == 0)
 431             break; /* succuessfully decrypted cert */
 432         cert = NULL;
 433         ret2 = unparse_CMSIdentifier(context, &ri->rid, &str);
 434         if (ret2 == 0) {
 435             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
 436                                    "Failed to decrypt with %s", str);
 437             free(str);
 438         }
 439     }
 440 
 441     if (!matched) {
 442         ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;
 443         hx509_set_error_string(context, 0, ret,
 444                                "No private key matched any certificate");
 445         goto out;
 446     }
 447 
 448     if (cert == NULL) {
 449         ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE;
 450         hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
 451                                "No private key decrypted the transfer key");
 452         goto out;
 453     }
 454 
 455     ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType);
 456     if (ret) {
 457         hx509_set_error_string(context, 0, ret,
 458                                "Failed to copy EnvelopedData content oid");
 459         goto out;
 460     }
 461 
 462     ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
 463     if (ai->parameters) {
 464         params_data.data = ai->parameters->data;
 465         params_data.length = ai->parameters->length;
 466         params = &params_data;
 467     } else
 468         params = NULL;
 469 
 470     {
 471         hx509_crypto crypto;
 472 
 473         ret = hx509_crypto_init(context, NULL, &ai->algorithm, &crypto);
 474         if (ret)
 475             goto out;
 476         
 477         if (params) {
 478             ret = hx509_crypto_set_params(context, crypto, params, &ivec);
 479             if (ret) {
 480                 hx509_crypto_destroy(crypto);
 481                 goto out;
 482             }
 483         }
 484 
 485         ret = hx509_crypto_set_key_data(crypto, key.data, key.length);
 486         if (ret) {
 487             hx509_crypto_destroy(crypto);
 488             hx509_set_error_string(context, 0, ret,
 489                                    "Failed to set key for decryption "
 490                                    "of EnvelopedData");
 491             goto out;
 492         }
 493         
 494         ret = hx509_crypto_decrypt(crypto,
 495                                    enccontent->data,
 496                                    enccontent->length,
 497                                    ivec.length ? &ivec : NULL,
 498                                    content);
 499         hx509_crypto_destroy(crypto);
 500         if (ret) {
 501             hx509_set_error_string(context, 0, ret,
 502                                    "Failed to decrypt EnvelopedData");
 503             goto out;
 504         }
 505     }
 506 
 507 out:
 508 
 509     free_EnvelopedData(&ed);
 510     der_free_octet_string(&key);
 511     if (ivec.length)
 512         der_free_octet_string(&ivec);
 513     if (ret) {
 514         der_free_oid(contentType);
 515         der_free_octet_string(content);
 516     }
 517 
 518     return ret;
 519 }
 520 
 521 /**
 522  * Encrypt end encode EnvelopedData.
 523  *
 524  * Encrypt and encode EnvelopedData. The data is encrypted with a
 525  * random key and the the random key is encrypted with the
 526  * certificates private key. This limits what private key type can be
 527  * used to RSA.
 528  *
 529  * @param context A hx509 context.
 530  * @param flags flags to control the behavior, no flags today
 531  * @param cert Certificate to encrypt the EnvelopedData encryption key
 532  * with.
 533  * @param data pointer the data to encrypt.
 534  * @param length length of the data that data point to.
 535  * @param encryption_type Encryption cipher to use for the bulk data,
 536  * use NULL to get default.
 537  * @param contentType type of the data that is encrypted
 538  * @param content the output of the function,
 539  * free with der_free_octet_string().
 540  *
 541  * @ingroup hx509_cms
 542  */
 543 
 544 int
 545 hx509_cms_envelope_1(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 546                      int flags,
 547                      hx509_cert cert,
 548                      const void *data,
 549                      size_t length,
 550                      const heim_oid *encryption_type,
 551                      const heim_oid *contentType,
 552                      heim_octet_string *content)
 553 {
 554     KeyTransRecipientInfo *ri;
 555     heim_octet_string ivec;
 556     heim_octet_string key;
 557     hx509_crypto crypto = NULL;
 558     EnvelopedData ed;
 559     size_t size;
 560     int ret;
 561 
 562     memset(&ivec, 0, sizeof(ivec));
 563     memset(&key, 0, sizeof(key));
 564     memset(&ed, 0, sizeof(ed));
 565     memset(content, 0, sizeof(*content));
 566 
 567     if (encryption_type == NULL)
 568         encryption_type = oid_id_aes_256_cbc();
 569 
 570     ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE);
 571     if (ret)
 572         goto out;
 573 
 574     ret = hx509_crypto_init(context, NULL, encryption_type, &crypto);
 575     if (ret)
 576         goto out;
 577 
 578     ret = hx509_crypto_set_random_key(crypto, &key);
 579     if (ret) {
 580         hx509_set_error_string(context, 0, ret,
 581                                "Create random key for EnvelopedData content");
 582         goto out;
 583     }
 584 
 585     ret = hx509_crypto_random_iv(crypto, &ivec);
 586     if (ret) {
 587         hx509_set_error_string(context, 0, ret,
 588                                "Failed to create a random iv");
 589         goto out;
 590     }
 591 
 592     ret = hx509_crypto_encrypt(crypto,
 593                                data,
 594                                length,
 595                                &ivec,
 596                                &ed.encryptedContentInfo.encryptedContent);
 597     if (ret) {
 598         hx509_set_error_string(context, 0, ret,
 599                                "Failed to encrypt EnvelopedData content");
 600         goto out;
 601     }
 602 
 603     {
 604         AlgorithmIdentifier *enc_alg;
 605         enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
 606         ret = der_copy_oid(encryption_type, &enc_alg->algorithm);
 607         if (ret) {
 608             hx509_set_error_string(context, 0, ret,
 609                                    "Failed to set crypto oid "
 610                                    "for EnvelopedData");
 611             goto out;
 612         }       
 613         ALLOC(enc_alg->parameters, 1);
 614         if (enc_alg->parameters == NULL) {
 615             ret = ENOMEM;
 616             hx509_set_error_string(context, 0, ret,
 617                                    "Failed to allocate crypto paramaters "
 618                                    "for EnvelopedData");
 619             goto out;
 620         }
 621 
 622         ret = hx509_crypto_get_params(context,
 623                                       crypto,
 624                                       &ivec,
 625                                       enc_alg->parameters);
 626         if (ret) {
 627             goto out;
 628         }
 629     }
 630 
 631     ALLOC_SEQ(&ed.recipientInfos, 1);
 632     if (ed.recipientInfos.val == NULL) {
 633         ret = ENOMEM;
 634         hx509_set_error_string(context, 0, ret,
 635                                "Failed to allocate recipients info "
 636                                "for EnvelopedData");
 637         goto out;
 638     }
 639 
 640     ri = &ed.recipientInfos.val[0];
 641 
 642     ri->version = 0;
 643     ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid);
 644     if (ret) {
 645         hx509_set_error_string(context, 0, ret,
 646                                "Failed to set CMS identifier info "
 647                                "for EnvelopedData");
 648         goto out;
 649     }
 650 
 651     ret = _hx509_cert_public_encrypt(context,
 652                                      &key, cert,
 653                                      &ri->keyEncryptionAlgorithm.algorithm,
 654                                      &ri->encryptedKey);
 655     if (ret) {
 656         hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
 657                                "Failed to encrypt transport key for "
 658                                "EnvelopedData");
 659         goto out;
 660     }
 661 
 662     /*
 663      *
 664      */
 665 
 666     ed.version = 0;
 667     ed.originatorInfo = NULL;
 668 
 669     ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType);
 670     if (ret) {
 671         hx509_set_error_string(context, 0, ret,
 672                                "Failed to copy content oid for "
 673                                "EnvelopedData");
 674         goto out;
 675     }
 676 
 677     ed.unprotectedAttrs = NULL;
 678 
 679     ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length,
 680                        &ed, &size, ret);
 681     if (ret) {
 682         hx509_set_error_string(context, 0, ret,
 683                                "Failed to encode EnvelopedData");
 684         goto out;
 685     }
 686     if (size != content->length)
 687         _hx509_abort("internal ASN.1 encoder error");
 688 
 689 out:
 690     if (crypto)
 691         hx509_crypto_destroy(crypto);
 692     if (ret)
 693         der_free_octet_string(content);
 694     der_free_octet_string(&key);
 695     der_free_octet_string(&ivec);
 696     free_EnvelopedData(&ed);
 697 
 698     return ret;
 699 }
 700 
 701 static int
 702 any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
     /* [<][>][^][v][top][bottom][index][help] */
 703 {
 704     int ret, i;
 705 
 706     if (sd->certificates == NULL)
 707         return 0;
 708 
 709     for (i = 0; i < sd->certificates->len; i++) {
 710         hx509_cert c;
 711 
 712         ret = hx509_cert_init_data(context,
 713                                    sd->certificates->val[i].data,
 714                                    sd->certificates->val[i].length,
 715                                    &c);
 716         if (ret)
 717             return ret;
 718         ret = hx509_certs_add(context, certs, c);
 719         hx509_cert_free(c);
 720         if (ret)
 721             return ret;
 722     }
 723 
 724     return 0;
 725 }
 726 
 727 static const Attribute *
 728 find_attribute(const CMSAttributes *attr, const heim_oid *oid)
     /* [<][>][^][v][top][bottom][index][help] */
 729 {
 730     int i;
 731     for (i = 0; i < attr->len; i++)
 732         if (der_heim_oid_cmp(&attr->val[i].type, oid) == 0)
 733             return &attr->val[i];
 734     return NULL;
 735 }
 736 
 737 /**
 738  * Decode SignedData and verify that the signature is correct.
 739  *
 740  * @param context A hx509 context.
 741  * @param ctx a hx509 version context
 742  * @param data
 743  * @param length length of the data that data point to.
 744  * @param signedContent
 745  * @param pool certificate pool to build certificates paths.
 746  * @param contentType free with der_free_oid()
 747  * @param content the output of the function, free with
 748  * der_free_octet_string().
 749  * @param signer_certs list of the cerficates used to sign this
 750  * request, free with hx509_certs_free().
 751  *
 752  * @ingroup hx509_cms
 753  */
 754 
 755 int
 756 hx509_cms_verify_signed(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 757                         hx509_verify_ctx ctx,
 758                         const void *data,
 759                         size_t length,
 760                         const heim_octet_string *signedContent,
 761                         hx509_certs pool,
 762                         heim_oid *contentType,
 763                         heim_octet_string *content,
 764                         hx509_certs *signer_certs)
 765 {
 766     SignerInfo *signer_info;
 767     hx509_cert cert = NULL;
 768     hx509_certs certs = NULL;
 769     SignedData sd;
 770     size_t size;
 771     int ret, i, found_valid_sig;
 772 
 773     *signer_certs = NULL;
 774     content->data = NULL;
 775     content->length = 0;
 776     contentType->length = 0;
 777     contentType->components = NULL;
 778 
 779     memset(&sd, 0, sizeof(sd));
 780 
 781     ret = decode_SignedData(data, length, &sd, &size);
 782     if (ret) {
 783         hx509_set_error_string(context, 0, ret,
 784                                "Failed to decode SignedData");
 785         goto out;
 786     }
 787 
 788     if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) {
 789         ret = HX509_CMS_NO_DATA_AVAILABLE;
 790         hx509_set_error_string(context, 0, ret,
 791                                "No content data in SignedData");
 792         goto out;
 793     }
 794     if (sd.encapContentInfo.eContent && signedContent) {
 795         ret = HX509_CMS_NO_DATA_AVAILABLE;
 796         hx509_set_error_string(context, 0, ret,
 797                                "Both external and internal SignedData");
 798         goto out;
 799     }
 800     if (sd.encapContentInfo.eContent)
 801         signedContent = sd.encapContentInfo.eContent;
 802 
 803     ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer",
 804                            0, NULL, &certs);
 805     if (ret)
 806         goto out;
 807 
 808     ret = hx509_certs_init(context, "MEMORY:cms-signer-certs",
 809                            0, NULL, signer_certs);
 810     if (ret)
 811         goto out;
 812 
 813     /* XXX Check CMS version */
 814 
 815     ret = any_to_certs(context, &sd, certs);
 816     if (ret)
 817         goto out;
 818 
 819     if (pool) {
 820         ret = hx509_certs_merge(context, certs, pool);
 821         if (ret)
 822             goto out;
 823     }
 824 
 825     for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) {
 826         heim_octet_string *signed_data;
 827         const heim_oid *match_oid;
 828         heim_oid decode_oid;
 829 
 830         signer_info = &sd.signerInfos.val[i];
 831         match_oid = NULL;
 832 
 833         if (signer_info->signature.length == 0) {
 834             ret = HX509_CMS_MISSING_SIGNER_DATA;
 835             hx509_set_error_string(context, 0, ret,
 836                                    "SignerInfo %d in SignedData "
 837                                    "missing sigature", i);
 838             continue;
 839         }
 840 
 841         ret = find_CMSIdentifier(context, &signer_info->sid, certs,
 842                                  _hx509_verify_get_time(ctx), &cert,
 843                                  HX509_QUERY_KU_DIGITALSIGNATURE);
 844         if (ret)
 845             continue;
 846 
 847         if (signer_info->signedAttrs) {
 848             const Attribute *attr;
 849         
 850             CMSAttributes sa;
 851             heim_octet_string os;
 852 
 853             sa.val = signer_info->signedAttrs->val;
 854             sa.len = signer_info->signedAttrs->len;
 855 
 856             /* verify that sigature exists */
 857             attr = find_attribute(&sa, oid_id_pkcs9_messageDigest());
 858             if (attr == NULL) {
 859                 ret = HX509_CRYPTO_SIGNATURE_MISSING;
 860                 hx509_set_error_string(context, 0, ret,
 861                                        "SignerInfo have signed attributes "
 862                                        "but messageDigest (signature) "
 863                                        "is missing");
 864                 goto next_sigature;
 865             }
 866             if (attr->value.len != 1) {
 867                 ret = HX509_CRYPTO_SIGNATURE_MISSING;
 868                 hx509_set_error_string(context, 0, ret,
 869                                        "SignerInfo have more then one "
 870                                        "messageDigest (signature)");
 871                 goto next_sigature;
 872             }
 873         
 874             ret = decode_MessageDigest(attr->value.val[0].data,
 875                                        attr->value.val[0].length,
 876                                        &os,
 877                                        &size);
 878             if (ret) {
 879                 hx509_set_error_string(context, 0, ret,
 880                                        "Failed to decode "
 881                                        "messageDigest (signature)");
 882                 goto next_sigature;
 883             }
 884 
 885             ret = _hx509_verify_signature(context,
 886                                           NULL,
 887                                           &signer_info->digestAlgorithm,
 888                                           signedContent,
 889                                           &os);
 890             der_free_octet_string(&os);
 891             if (ret) {
 892                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
 893                                        "Failed to verify messageDigest");
 894                 goto next_sigature;
 895             }
 896 
 897             /*
 898              * Fetch content oid inside signedAttrs or set it to
 899              * id-pkcs7-data.
 900              */
 901             attr = find_attribute(&sa, oid_id_pkcs9_contentType());
 902             if (attr == NULL) {
 903                 match_oid = oid_id_pkcs7_data();
 904             } else {
 905                 if (attr->value.len != 1) {
 906                     ret = HX509_CMS_DATA_OID_MISMATCH;
 907                     hx509_set_error_string(context, 0, ret,
 908                                            "More then one oid in signedAttrs");
 909                     goto next_sigature;
 910 
 911                 }
 912                 ret = decode_ContentType(attr->value.val[0].data,
 913                                          attr->value.val[0].length,
 914                                          &decode_oid,
 915                                          &size);
 916                 if (ret) {
 917                     hx509_set_error_string(context, 0, ret,
 918                                            "Failed to decode "
 919                                            "oid in signedAttrs");
 920                     goto next_sigature;
 921                 }
 922                 match_oid = &decode_oid;
 923             }
 924 
 925             ALLOC(signed_data, 1);
 926             if (signed_data == NULL) {
 927                 if (match_oid == &decode_oid)
 928                     der_free_oid(&decode_oid);
 929                 ret = ENOMEM;
 930                 hx509_clear_error_string(context);
 931                 goto next_sigature;
 932             }
 933         
 934             ASN1_MALLOC_ENCODE(CMSAttributes,
 935                                signed_data->data,
 936                                signed_data->length,
 937                                &sa,
 938                                &size, ret);
 939             if (ret) {
 940                 if (match_oid == &decode_oid)
 941                     der_free_oid(&decode_oid);
 942                 free(signed_data);
 943                 hx509_clear_error_string(context);
 944                 goto next_sigature;
 945             }
 946             if (size != signed_data->length)
 947                 _hx509_abort("internal ASN.1 encoder error");
 948 
 949         } else {
 950             signed_data = rk_UNCONST(signedContent);
 951             match_oid = oid_id_pkcs7_data();
 952         }
 953 
 954         if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType)) {
 955             ret = HX509_CMS_DATA_OID_MISMATCH;
 956             hx509_set_error_string(context, 0, ret,
 957                                    "Oid in message mismatch from the expected");
 958         }
 959         if (match_oid == &decode_oid)
 960             der_free_oid(&decode_oid);
 961 
 962         if (ret == 0) {
 963             ret = hx509_verify_signature(context,
 964                                          cert,
 965                                          &signer_info->signatureAlgorithm,
 966                                          signed_data,
 967                                          &signer_info->signature);
 968             if (ret)
 969                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
 970                                        "Failed to verify sigature in "
 971                                        "CMS SignedData");
 972         }
 973         if (signed_data != signedContent) {
 974             der_free_octet_string(signed_data);
 975             free(signed_data);
 976         }
 977         if (ret)
 978             goto next_sigature;
 979 
 980         ret = hx509_verify_path(context, ctx, cert, certs);
 981         if (ret)
 982             goto next_sigature;
 983 
 984         ret = hx509_certs_add(context, *signer_certs, cert);
 985         if (ret)
 986             goto next_sigature;
 987 
 988         found_valid_sig++;
 989 
 990     next_sigature:
 991         if (cert)
 992             hx509_cert_free(cert);
 993         cert = NULL;
 994     }
 995     if (found_valid_sig == 0) {
 996         if (ret == 0) {
 997             ret = HX509_CMS_SIGNER_NOT_FOUND;
 998             hx509_set_error_string(context, 0, ret,
 999                                    "No signers where found");
1000         }
1001         goto out;
1002     }
1003 
1004     ret = der_copy_oid(&sd.encapContentInfo.eContentType, contentType);
1005     if (ret) {
1006         hx509_clear_error_string(context);
1007         goto out;
1008     }
1009 
1010     content->data = malloc(signedContent->length);
1011     if (content->data == NULL) {
1012         hx509_clear_error_string(context);
1013         ret = ENOMEM;
1014         goto out;
1015     }
1016     content->length = signedContent->length;
1017     memcpy(content->data, signedContent->data, content->length);
1018 
1019 out:
1020     free_SignedData(&sd);
1021     if (certs)
1022         hx509_certs_free(&certs);
1023     if (ret) {
1024         if (*signer_certs)
1025             hx509_certs_free(signer_certs);
1026         der_free_oid(contentType);
1027         der_free_octet_string(content);
1028     }
1029 
1030     return ret;
1031 }
1032 
1033 static int
1034 add_one_attribute(Attribute **attr,
     /* [<][>][^][v][top][bottom][index][help] */
1035                   unsigned int *len,
1036                   const heim_oid *oid,
1037                   heim_octet_string *data)
1038 {
1039     void *d;
1040     int ret;
1041 
1042     d = realloc(*attr, sizeof((*attr)[0]) * (*len + 1));
1043     if (d == NULL)
1044         return ENOMEM;
1045     (*attr) = d;
1046 
1047     ret = der_copy_oid(oid, &(*attr)[*len].type);
1048     if (ret)
1049         return ret;
1050 
1051     ALLOC_SEQ(&(*attr)[*len].value, 1);
1052     if ((*attr)[*len].value.val == NULL) {
1053         der_free_oid(&(*attr)[*len].type);
1054         return ENOMEM;
1055     }
1056 
1057     (*attr)[*len].value.val[0].data = data->data;
1058     (*attr)[*len].value.val[0].length = data->length;
1059 
1060     *len += 1;
1061 
1062     return 0;
1063 }
1064         
1065 /**
1066  * Decode SignedData and verify that the signature is correct.
1067  *
1068  * @param context A hx509 context.
1069  * @param flags
1070  * @param eContentType the type of the data.
1071  * @param data data to sign
1072  * @param length length of the data that data point to.
1073  * @param digest_alg digest algorithm to use, use NULL to get the
1074  * default or the peer determined algorithm.
1075  * @param cert certificate to use for sign the data.
1076  * @param peer info about the peer the message to send the message to,
1077  * like what digest algorithm to use.
1078  * @param anchors trust anchors that the client will use, used to
1079  * polulate the certificates included in the message
1080  * @param pool certificates to use in try to build the path to the
1081  * trust anchors.
1082  * @param signed_data the output of the function, free with
1083  * der_free_octet_string().
1084  *
1085  * @ingroup hx509_cms
1086  */
1087 
1088 int
1089 hx509_cms_create_signed_1(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1090                           int flags,
1091                           const heim_oid *eContentType,
1092                           const void *data, size_t length,
1093                           const AlgorithmIdentifier *digest_alg,
1094                           hx509_cert cert,
1095                           hx509_peer_info peer,
1096                           hx509_certs anchors,
1097                           hx509_certs pool,
1098                           heim_octet_string *signed_data)
1099 {
1100     AlgorithmIdentifier digest;
1101     hx509_name name;
1102     SignerInfo *signer_info;
1103     heim_octet_string buf, content, sigdata = { 0, NULL };
1104     SignedData sd;
1105     int ret;
1106     size_t size;
1107     hx509_path path;
1108     int cmsidflag = CMS_ID_SKI;
1109 
1110     memset(&sd, 0, sizeof(sd));
1111     memset(&name, 0, sizeof(name));
1112     memset(&path, 0, sizeof(path));
1113     memset(&digest, 0, sizeof(digest));
1114 
1115     content.data = rk_UNCONST(data);
1116     content.length = length;
1117 
1118     if (flags & HX509_CMS_SIGATURE_ID_NAME)
1119         cmsidflag = CMS_ID_NAME;
1120 
1121     if (_hx509_cert_private_key(cert) == NULL) {
1122         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1123                                "Private key missing for signing");
1124         return HX509_PRIVATE_KEY_MISSING;
1125     }
1126 
1127     if (digest_alg == NULL) {
1128         ret = hx509_crypto_select(context, HX509_SELECT_DIGEST,
1129                                   _hx509_cert_private_key(cert), peer, &digest);
1130     } else {
1131         ret = copy_AlgorithmIdentifier(digest_alg, &digest);
1132         if (ret)
1133             hx509_clear_error_string(context);
1134     }
1135     if (ret)
1136         goto out;
1137 
1138     sd.version = CMSVersion_v3;
1139 
1140     if (eContentType == NULL)
1141         eContentType = oid_id_pkcs7_data();
1142 
1143     der_copy_oid(eContentType, &sd.encapContentInfo.eContentType);
1144 
1145     /* */
1146     if ((flags & HX509_CMS_SIGATURE_DETACHED) == 0) {
1147         ALLOC(sd.encapContentInfo.eContent, 1);
1148         if (sd.encapContentInfo.eContent == NULL) {
1149             hx509_clear_error_string(context);
1150             ret = ENOMEM;
1151             goto out;
1152         }
1153         
1154         sd.encapContentInfo.eContent->data = malloc(length);
1155         if (sd.encapContentInfo.eContent->data == NULL) {
1156             hx509_clear_error_string(context);
1157             ret = ENOMEM;
1158             goto out;
1159         }
1160         memcpy(sd.encapContentInfo.eContent->data, data, length);
1161         sd.encapContentInfo.eContent->length = length;
1162     }
1163 
1164     ALLOC_SEQ(&sd.signerInfos, 1);
1165     if (sd.signerInfos.val == NULL) {
1166         hx509_clear_error_string(context);
1167         ret = ENOMEM;
1168         goto out;
1169     }
1170 
1171     signer_info = &sd.signerInfos.val[0];
1172 
1173     signer_info->version = 1;
1174 
1175     ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid);
1176     if (ret) {
1177         hx509_clear_error_string(context);
1178         goto out;
1179     }                   
1180 
1181     signer_info->signedAttrs = NULL;
1182     signer_info->unsignedAttrs = NULL;
1183 
1184 
1185     ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm);
1186     if (ret) {
1187         hx509_clear_error_string(context);
1188         goto out;
1189     }
1190 
1191     /*
1192      * If it isn't pkcs7-data send signedAttributes
1193      */
1194 
1195     if (der_heim_oid_cmp(eContentType, oid_id_pkcs7_data()) != 0) {
1196         CMSAttributes sa;       
1197         heim_octet_string sig;
1198 
1199         ALLOC(signer_info->signedAttrs, 1);
1200         if (signer_info->signedAttrs == NULL) {
1201             ret = ENOMEM;
1202             goto out;
1203         }
1204 
1205         ret = _hx509_create_signature(context,
1206                                       NULL,
1207                                       &digest,
1208                                       &content,
1209                                       NULL,
1210                                       &sig);
1211         if (ret)
1212             goto out;
1213 
1214         ASN1_MALLOC_ENCODE(MessageDigest,
1215                            buf.data,
1216                            buf.length,
1217                            &sig,
1218                            &size,
1219                            ret);
1220         der_free_octet_string(&sig);
1221         if (ret) {
1222             hx509_clear_error_string(context);
1223             goto out;
1224         }
1225         if (size != buf.length)
1226             _hx509_abort("internal ASN.1 encoder error");
1227 
1228         ret = add_one_attribute(&signer_info->signedAttrs->val,
1229                                 &signer_info->signedAttrs->len,
1230                                 oid_id_pkcs9_messageDigest(),
1231                                 &buf);
1232         if (ret) {
1233             hx509_clear_error_string(context);
1234             goto out;
1235         }
1236 
1237 
1238         ASN1_MALLOC_ENCODE(ContentType,
1239                            buf.data,
1240                            buf.length,
1241                            eContentType,
1242                            &size,
1243                            ret);
1244         if (ret)
1245             goto out;
1246         if (size != buf.length)
1247             _hx509_abort("internal ASN.1 encoder error");
1248 
1249         ret = add_one_attribute(&signer_info->signedAttrs->val,
1250                                 &signer_info->signedAttrs->len,
1251                                 oid_id_pkcs9_contentType(),
1252                                 &buf);
1253         if (ret) {
1254             hx509_clear_error_string(context);
1255             goto out;
1256         }
1257 
1258         sa.val = signer_info->signedAttrs->val;
1259         sa.len = signer_info->signedAttrs->len;
1260         
1261         ASN1_MALLOC_ENCODE(CMSAttributes,
1262                            sigdata.data,
1263                            sigdata.length,
1264                            &sa,
1265                            &size,
1266                            ret);
1267         if (ret) {
1268             hx509_clear_error_string(context);
1269             goto out;
1270         }
1271         if (size != sigdata.length)
1272             _hx509_abort("internal ASN.1 encoder error");
1273     } else {
1274         sigdata.data = content.data;
1275         sigdata.length = content.length;
1276     }
1277 
1278 
1279     {
1280         AlgorithmIdentifier sigalg;
1281 
1282         ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG,
1283                                   _hx509_cert_private_key(cert), peer,
1284                                   &sigalg);
1285         if (ret)
1286             goto out;
1287 
1288         ret = _hx509_create_signature(context,
1289                                       _hx509_cert_private_key(cert),
1290                                       &sigalg,
1291                                       &sigdata,
1292                                       &signer_info->signatureAlgorithm,
1293                                       &signer_info->signature);
1294         free_AlgorithmIdentifier(&sigalg);
1295         if (ret)
1296             goto out;
1297     }
1298 
1299     ALLOC_SEQ(&sd.digestAlgorithms, 1);
1300     if (sd.digestAlgorithms.val == NULL) {
1301         ret = ENOMEM;
1302         hx509_clear_error_string(context);
1303         goto out;
1304     }
1305 
1306     ret = copy_AlgorithmIdentifier(&digest, &sd.digestAlgorithms.val[0]);
1307     if (ret) {
1308         hx509_clear_error_string(context);
1309         goto out;
1310     }
1311 
1312     /*
1313      * Provide best effort path
1314      */
1315     if (pool) {
1316         _hx509_calculate_path(context,
1317                               HX509_CALCULATE_PATH_NO_ANCHOR,                   
1318                               time(NULL),
1319                               anchors,
1320                               0,
1321                               cert,
1322                               pool,
1323                               &path);
1324     } else
1325         _hx509_path_append(context, &path, cert);
1326 
1327 
1328     if (path.len) {
1329         int i;
1330 
1331         ALLOC(sd.certificates, 1);
1332         if (sd.certificates == NULL) {
1333             hx509_clear_error_string(context);
1334             ret = ENOMEM;
1335             goto out;
1336         }
1337         ALLOC_SEQ(sd.certificates, path.len);
1338         if (sd.certificates->val == NULL) {
1339             hx509_clear_error_string(context);
1340             ret = ENOMEM;
1341             goto out;
1342         }
1343 
1344         for (i = 0; i < path.len; i++) {
1345             ret = hx509_cert_binary(context, path.val[i],
1346                                     &sd.certificates->val[i]);
1347             if (ret) {
1348                 hx509_clear_error_string(context);
1349                 goto out;
1350             }
1351         }
1352     }
1353 
1354     ASN1_MALLOC_ENCODE(SignedData,
1355                        signed_data->data, signed_data->length,
1356                        &sd, &size, ret);
1357     if (ret) {
1358         hx509_clear_error_string(context);
1359         goto out;
1360     }
1361     if (signed_data->length != size)
1362         _hx509_abort("internal ASN.1 encoder error");
1363 
1364 out:
1365     if (sigdata.data != content.data)
1366         der_free_octet_string(&sigdata);
1367     free_AlgorithmIdentifier(&digest);
1368     _hx509_path_free(&path);
1369     free_SignedData(&sd);
1370 
1371     return ret;
1372 }
1373 
1374 int
1375 hx509_cms_decrypt_encrypted(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
1376                             hx509_lock lock,
1377                             const void *data,
1378                             size_t length,
1379                             heim_oid *contentType,
1380                             heim_octet_string *content)
1381 {
1382     heim_octet_string cont;
1383     CMSEncryptedData ed;
1384     AlgorithmIdentifier *ai;
1385     int ret;
1386 
1387     memset(content, 0, sizeof(*content));
1388     memset(&cont, 0, sizeof(cont));
1389 
1390     ret = decode_CMSEncryptedData(data, length, &ed, NULL);
1391     if (ret) {
1392         hx509_set_error_string(context, 0, ret,
1393                                "Failed to decode CMSEncryptedData");
1394         return ret;
1395     }
1396 
1397     if (ed.encryptedContentInfo.encryptedContent == NULL) {
1398         ret = HX509_CMS_NO_DATA_AVAILABLE;
1399         hx509_set_error_string(context, 0, ret,
1400                                "No content in EncryptedData");
1401         goto out;
1402     }
1403 
1404     ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType);
1405     if (ret) {
1406         hx509_clear_error_string(context);
1407         goto out;
1408     }
1409 
1410     ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
1411     if (ai->parameters == NULL) {
1412         ret = HX509_ALG_NOT_SUPP;
1413         hx509_clear_error_string(context);
1414         goto out;
1415     }
1416 
1417     ret = _hx509_pbe_decrypt(context,
1418                              lock,
1419                              ai,
1420                              ed.encryptedContentInfo.encryptedContent,
1421                              &cont);
1422     if (ret)
1423         goto out;
1424 
1425     *content = cont;
1426 
1427 out:
1428     if (ret) {
1429         if (cont.data)
1430             free(cont.data);
1431     }
1432     free_CMSEncryptedData(&ed);
1433     return ret;
1434 }

/* [<][>][^][v][top][bottom][index][help] */