1/*
2 * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include "internal/cryptlib.h"
11#include <openssl/asn1t.h>
12#include <openssl/pem.h>
13#include <openssl/x509v3.h>
14#include <openssl/err.h>
15#include <openssl/cms.h>
16#include <openssl/evp.h>
17#include "internal/sizes.h"
18#include "crypto/asn1.h"
19#include "crypto/evp.h"
20#include "crypto/x509.h"
21#include "cms_local.h"
22
23/* CMS EnvelopedData Utilities */
24static void cms_env_set_version(CMS_EnvelopedData *env);
25
26#define CMS_ENVELOPED_STANDARD 1
27#define CMS_ENVELOPED_AUTH     2
28
29static int cms_get_enveloped_type_simple(const CMS_ContentInfo *cms)
30{
31    int nid = OBJ_obj2nid(cms->contentType);
32
33    switch (nid) {
34    case NID_pkcs7_enveloped:
35        return CMS_ENVELOPED_STANDARD;
36
37    case NID_id_smime_ct_authEnvelopedData:
38        return CMS_ENVELOPED_AUTH;
39
40    default:
41        return 0;
42    }
43}
44
45static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
46{
47    int ret = cms_get_enveloped_type_simple(cms);
48
49    if (ret == 0)
50        ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
51    return ret;
52}
53
54void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf)
55{
56    if (cms_get_enveloped_type_simple(cinf) != 0) {
57        CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cinf);
58        if (ec != NULL)
59            OPENSSL_clear_free(ec->key, ec->keylen);
60    }
61}
62
63CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms)
64{
65    if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
66        ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
67        return NULL;
68    }
69    return cms->d.envelopedData;
70}
71
72CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms)
73{
74    if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_authEnvelopedData) {
75        ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
76        return NULL;
77    }
78    return cms->d.authEnvelopedData;
79}
80
81static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
82{
83    if (cms->d.other == NULL) {
84        cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);
85        if (cms->d.envelopedData == NULL) {
86            ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
87            return NULL;
88        }
89        cms->d.envelopedData->version = 0;
90        cms->d.envelopedData->encryptedContentInfo->contentType =
91            OBJ_nid2obj(NID_pkcs7_data);
92        ASN1_OBJECT_free(cms->contentType);
93        cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
94        return cms->d.envelopedData;
95    }
96    return ossl_cms_get0_enveloped(cms);
97}
98
99static CMS_AuthEnvelopedData *
100cms_auth_enveloped_data_init(CMS_ContentInfo *cms)
101{
102    if (cms->d.other == NULL) {
103        cms->d.authEnvelopedData = M_ASN1_new_of(CMS_AuthEnvelopedData);
104        if (cms->d.authEnvelopedData == NULL) {
105            ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
106            return NULL;
107        }
108        /* Defined in RFC 5083 - Section 2.1. "AuthEnvelopedData Type" */
109        cms->d.authEnvelopedData->version = 0;
110        cms->d.authEnvelopedData->authEncryptedContentInfo->contentType =
111            OBJ_nid2obj(NID_pkcs7_data);
112        ASN1_OBJECT_free(cms->contentType);
113        cms->contentType = OBJ_nid2obj(NID_id_smime_ct_authEnvelopedData);
114        return cms->d.authEnvelopedData;
115    }
116    return ossl_cms_get0_auth_enveloped(cms);
117}
118
119int ossl_cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
120{
121    EVP_PKEY *pkey;
122    int i;
123    if (ri->type == CMS_RECIPINFO_TRANS)
124        pkey = ri->d.ktri->pkey;
125    else if (ri->type == CMS_RECIPINFO_AGREE) {
126        EVP_PKEY_CTX *pctx = ri->d.kari->pctx;
127
128        if (pctx == NULL)
129            return 0;
130        pkey = EVP_PKEY_CTX_get0_pkey(pctx);
131        if (pkey == NULL)
132            return 0;
133    } else
134        return 0;
135
136    if (EVP_PKEY_is_a(pkey, "DHX") || EVP_PKEY_is_a(pkey, "DH"))
137        return ossl_cms_dh_envelope(ri, cmd);
138    else if (EVP_PKEY_is_a(pkey, "EC"))
139        return ossl_cms_ecdh_envelope(ri, cmd);
140    else if (EVP_PKEY_is_a(pkey, "RSA"))
141        return ossl_cms_rsa_envelope(ri, cmd);
142
143    /* Something else? We'll give engines etc a chance to handle this */
144    if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
145        return 1;
146    i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
147    if (i == -2) {
148        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
149        return 0;
150    }
151    if (i <= 0) {
152        ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
153        return 0;
154    }
155    return 1;
156}
157
158CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms)
159{
160    switch (cms_get_enveloped_type(cms)) {
161    case CMS_ENVELOPED_STANDARD:
162        return cms->d.envelopedData == NULL ? NULL
163            : cms->d.envelopedData->encryptedContentInfo;
164
165    case CMS_ENVELOPED_AUTH:
166        return cms->d.authEnvelopedData == NULL ? NULL
167            : cms->d.authEnvelopedData->authEncryptedContentInfo;
168
169    default:
170        return NULL;
171    }
172}
173
174STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
175{
176    switch (cms_get_enveloped_type(cms)) {
177    case CMS_ENVELOPED_STANDARD:
178        return cms->d.envelopedData->recipientInfos;
179
180    case CMS_ENVELOPED_AUTH:
181        return cms->d.authEnvelopedData->recipientInfos;
182
183    default:
184        return NULL;
185    }
186}
187
188void ossl_cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms)
189{
190    int i;
191    CMS_RecipientInfo *ri;
192    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
193    STACK_OF(CMS_RecipientInfo) *rinfos = CMS_get0_RecipientInfos(cms);
194
195    for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
196        ri = sk_CMS_RecipientInfo_value(rinfos, i);
197        if (ri != NULL) {
198            switch (ri->type) {
199            case CMS_RECIPINFO_AGREE:
200                ri->d.kari->cms_ctx = ctx;
201                break;
202            case CMS_RECIPINFO_TRANS:
203                ri->d.ktri->cms_ctx = ctx;
204                ossl_x509_set0_libctx(ri->d.ktri->recip,
205                                      ossl_cms_ctx_get0_libctx(ctx),
206                                      ossl_cms_ctx_get0_propq(ctx));
207                break;
208            case CMS_RECIPINFO_KEK:
209                ri->d.kekri->cms_ctx = ctx;
210                break;
211            case CMS_RECIPINFO_PASS:
212                ri->d.pwri->cms_ctx = ctx;
213                break;
214            default:
215                break;
216            }
217        }
218    }
219}
220
221int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
222{
223    return ri->type;
224}
225
226EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
227{
228    if (ri->type == CMS_RECIPINFO_TRANS)
229        return ri->d.ktri->pctx;
230    else if (ri->type == CMS_RECIPINFO_AGREE)
231        return ri->d.kari->pctx;
232    return NULL;
233}
234
235CMS_ContentInfo *CMS_EnvelopedData_create_ex(const EVP_CIPHER *cipher,
236                                             OSSL_LIB_CTX *libctx,
237                                             const char *propq)
238{
239    CMS_ContentInfo *cms;
240    CMS_EnvelopedData *env;
241
242    cms = CMS_ContentInfo_new_ex(libctx, propq);
243    if (cms == NULL)
244        goto merr;
245    env = cms_enveloped_data_init(cms);
246    if (env == NULL)
247        goto merr;
248
249    if (!ossl_cms_EncryptedContent_init(env->encryptedContentInfo, cipher, NULL,
250                                        0, ossl_cms_get0_cmsctx(cms)))
251        goto merr;
252    return cms;
253 merr:
254    CMS_ContentInfo_free(cms);
255    ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
256    return NULL;
257}
258
259CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
260{
261    return CMS_EnvelopedData_create_ex(cipher, NULL, NULL);
262}
263
264CMS_ContentInfo *
265CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx,
266                                const char *propq)
267{
268    CMS_ContentInfo *cms;
269    CMS_AuthEnvelopedData *aenv;
270
271    cms = CMS_ContentInfo_new_ex(libctx, propq);
272    if (cms == NULL)
273        goto merr;
274    aenv = cms_auth_enveloped_data_init(cms);
275    if (aenv == NULL)
276        goto merr;
277    if (!ossl_cms_EncryptedContent_init(aenv->authEncryptedContentInfo,
278                                        cipher, NULL, 0,
279                                        ossl_cms_get0_cmsctx(cms)))
280        goto merr;
281    return cms;
282 merr:
283    CMS_ContentInfo_free(cms);
284    ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
285    return NULL;
286}
287
288
289CMS_ContentInfo *CMS_AuthEnvelopedData_create(const EVP_CIPHER *cipher)
290{
291    return CMS_AuthEnvelopedData_create_ex(cipher, NULL, NULL);
292}
293
294/* Key Transport Recipient Info (KTRI) routines */
295
296/* Initialise a ktri based on passed certificate and key */
297
298static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
299                                       EVP_PKEY *pk, unsigned int flags,
300                                       const CMS_CTX *ctx)
301{
302    CMS_KeyTransRecipientInfo *ktri;
303    int idtype;
304
305    ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
306    if (!ri->d.ktri)
307        return 0;
308    ri->type = CMS_RECIPINFO_TRANS;
309
310    ktri = ri->d.ktri;
311    ktri->cms_ctx = ctx;
312
313    if (flags & CMS_USE_KEYID) {
314        ktri->version = 2;
315        idtype = CMS_RECIPINFO_KEYIDENTIFIER;
316    } else {
317        ktri->version = 0;
318        idtype = CMS_RECIPINFO_ISSUER_SERIAL;
319    }
320
321    /*
322     * Not a typo: RecipientIdentifier and SignerIdentifier are the same
323     * structure.
324     */
325
326    if (!ossl_cms_set1_SignerIdentifier(ktri->rid, recip, idtype, ctx))
327        return 0;
328
329    X509_up_ref(recip);
330    EVP_PKEY_up_ref(pk);
331
332    ktri->pkey = pk;
333    ktri->recip = recip;
334
335    if (flags & CMS_KEY_PARAM) {
336        ktri->pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
337                                                ktri->pkey,
338                                                ossl_cms_ctx_get0_propq(ctx));
339        if (ktri->pctx == NULL)
340            return 0;
341        if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
342            return 0;
343    } else if (!ossl_cms_env_asn1_ctrl(ri, 0))
344        return 0;
345    return 1;
346}
347
348/*
349 * Add a recipient certificate using appropriate type of RecipientInfo
350 */
351
352CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
353                                      EVP_PKEY *originatorPrivKey,
354                                      X509 *originator, unsigned int flags)
355{
356    CMS_RecipientInfo *ri = NULL;
357    STACK_OF(CMS_RecipientInfo) *ris;
358    EVP_PKEY *pk = NULL;
359    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
360
361    ris = CMS_get0_RecipientInfos(cms);
362    if (ris == NULL)
363        goto err;
364
365    /* Initialize recipient info */
366    ri = M_ASN1_new_of(CMS_RecipientInfo);
367    if (ri == NULL)
368        goto merr;
369
370    pk = X509_get0_pubkey(recip);
371    if (pk == NULL) {
372        ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_GETTING_PUBLIC_KEY);
373        goto err;
374    }
375
376    switch (ossl_cms_pkey_get_ri_type(pk)) {
377
378    case CMS_RECIPINFO_TRANS:
379        if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags, ctx))
380            goto err;
381        break;
382
383    case CMS_RECIPINFO_AGREE:
384        if (!ossl_cms_RecipientInfo_kari_init(ri, recip, pk, originator,
385                                              originatorPrivKey, flags, ctx))
386            goto err;
387        break;
388
389    default:
390        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
391        goto err;
392
393    }
394
395    if (!sk_CMS_RecipientInfo_push(ris, ri))
396        goto merr;
397
398    return ri;
399
400 merr:
401    ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
402 err:
403    M_ASN1_free_of(ri, CMS_RecipientInfo);
404    return NULL;
405
406}
407
408CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip,
409                                           unsigned int flags)
410{
411     return CMS_add1_recipient(cms, recip, NULL, NULL, flags);
412}
413
414int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
415                                     EVP_PKEY **pk, X509 **recip,
416                                     X509_ALGOR **palg)
417{
418    CMS_KeyTransRecipientInfo *ktri;
419    if (ri->type != CMS_RECIPINFO_TRANS) {
420        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
421        return 0;
422    }
423
424    ktri = ri->d.ktri;
425
426    if (pk)
427        *pk = ktri->pkey;
428    if (recip)
429        *recip = ktri->recip;
430    if (palg)
431        *palg = ktri->keyEncryptionAlgorithm;
432    return 1;
433}
434
435int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
436                                          ASN1_OCTET_STRING **keyid,
437                                          X509_NAME **issuer,
438                                          ASN1_INTEGER **sno)
439{
440    CMS_KeyTransRecipientInfo *ktri;
441    if (ri->type != CMS_RECIPINFO_TRANS) {
442        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
443        return 0;
444    }
445    ktri = ri->d.ktri;
446
447    return ossl_cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer,
448                                                    sno);
449}
450
451int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
452{
453    if (ri->type != CMS_RECIPINFO_TRANS) {
454        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
455        return -2;
456    }
457    return ossl_cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
458}
459
460int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
461{
462    if (ri->type != CMS_RECIPINFO_TRANS) {
463        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
464        return 0;
465    }
466    EVP_PKEY_free(ri->d.ktri->pkey);
467    ri->d.ktri->pkey = pkey;
468    return 1;
469}
470
471/* Encrypt content key in key transport recipient info */
472
473static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
474                                          CMS_RecipientInfo *ri)
475{
476    CMS_KeyTransRecipientInfo *ktri;
477    CMS_EncryptedContentInfo *ec;
478    EVP_PKEY_CTX *pctx;
479    unsigned char *ek = NULL;
480    size_t eklen;
481    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
482
483    int ret = 0;
484
485    if (ri->type != CMS_RECIPINFO_TRANS) {
486        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEY_TRANSPORT);
487        return 0;
488    }
489    ktri = ri->d.ktri;
490    ec = ossl_cms_get0_env_enc_content(cms);
491
492    pctx = ktri->pctx;
493
494    if (pctx) {
495        if (!ossl_cms_env_asn1_ctrl(ri, 0))
496            goto err;
497    } else {
498        pctx = EVP_PKEY_CTX_new_from_pkey(ossl_cms_ctx_get0_libctx(ctx),
499                                          ktri->pkey,
500                                          ossl_cms_ctx_get0_propq(ctx));
501        if (pctx == NULL)
502            return 0;
503
504        if (EVP_PKEY_encrypt_init(pctx) <= 0)
505            goto err;
506    }
507
508    if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
509        goto err;
510
511    ek = OPENSSL_malloc(eklen);
512
513    if (ek == NULL) {
514        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
515        goto err;
516    }
517
518    if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
519        goto err;
520
521    ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
522    ek = NULL;
523
524    ret = 1;
525
526 err:
527    EVP_PKEY_CTX_free(pctx);
528    ktri->pctx = NULL;
529    OPENSSL_free(ek);
530    return ret;
531}
532
533/* Decrypt content key from KTRI */
534
535static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
536                                          CMS_RecipientInfo *ri)
537{
538    CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
539    EVP_PKEY *pkey = ktri->pkey;
540    unsigned char *ek = NULL;
541    size_t eklen;
542    int ret = 0;
543    size_t fixlen = 0;
544    const EVP_CIPHER *cipher = NULL;
545    EVP_CIPHER *fetched_cipher = NULL;
546    CMS_EncryptedContentInfo *ec;
547    const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms);
548    OSSL_LIB_CTX *libctx = ossl_cms_ctx_get0_libctx(ctx);
549    const char *propq = ossl_cms_ctx_get0_propq(ctx);
550
551    ec = ossl_cms_get0_env_enc_content(cms);
552
553    if (ktri->pkey == NULL) {
554        ERR_raise(ERR_LIB_CMS, CMS_R_NO_PRIVATE_KEY);
555        return 0;
556    }
557
558    if (cms->d.envelopedData->encryptedContentInfo->havenocert
559            && !cms->d.envelopedData->encryptedContentInfo->debug) {
560        X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
561        char name[OSSL_MAX_NAME_SIZE];
562
563        OBJ_obj2txt(name, sizeof(name), calg->algorithm, 0);
564
565        (void)ERR_set_mark();
566        fetched_cipher = EVP_CIPHER_fetch(libctx, name, propq);
567
568        if (fetched_cipher != NULL)
569            cipher = fetched_cipher;
570        else
571            cipher = EVP_get_cipherbyobj(calg->algorithm);
572        if (cipher == NULL) {
573            (void)ERR_clear_last_mark();
574            ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER);
575            return 0;
576        }
577        (void)ERR_pop_to_mark();
578
579        fixlen = EVP_CIPHER_get_key_length(cipher);
580        EVP_CIPHER_free(fetched_cipher);
581    }
582
583    ktri->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
584    if (ktri->pctx == NULL)
585        goto err;
586
587    if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
588        goto err;
589
590    if (!ossl_cms_env_asn1_ctrl(ri, 1))
591        goto err;
592
593    if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
594                         ktri->encryptedKey->data,
595                         ktri->encryptedKey->length) <= 0)
596        goto err;
597
598    ek = OPENSSL_malloc(eklen);
599    if (ek == NULL) {
600        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
601        goto err;
602    }
603
604    if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
605                         ktri->encryptedKey->data,
606                         ktri->encryptedKey->length) <= 0
607            || eklen == 0
608            || (fixlen != 0 && eklen != fixlen)) {
609        ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
610        goto err;
611    }
612
613    ret = 1;
614
615    OPENSSL_clear_free(ec->key, ec->keylen);
616    ec->key = ek;
617    ec->keylen = eklen;
618
619 err:
620    EVP_PKEY_CTX_free(ktri->pctx);
621    ktri->pctx = NULL;
622    if (!ret)
623        OPENSSL_free(ek);
624
625    return ret;
626}
627
628/* Key Encrypted Key (KEK) RecipientInfo routines */
629
630int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri,
631                                   const unsigned char *id, size_t idlen)
632{
633    ASN1_OCTET_STRING tmp_os;
634    CMS_KEKRecipientInfo *kekri;
635    if (ri->type != CMS_RECIPINFO_KEK) {
636        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
637        return -2;
638    }
639    kekri = ri->d.kekri;
640    tmp_os.type = V_ASN1_OCTET_STRING;
641    tmp_os.flags = 0;
642    tmp_os.data = (unsigned char *)id;
643    tmp_os.length = (int)idlen;
644    return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
645}
646
647/* For now hard code AES key wrap info */
648
649static size_t aes_wrap_keylen(int nid)
650{
651    switch (nid) {
652    case NID_id_aes128_wrap:
653        return 16;
654
655    case NID_id_aes192_wrap:
656        return 24;
657
658    case NID_id_aes256_wrap:
659        return 32;
660
661    default:
662        return 0;
663    }
664}
665
666CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
667                                          unsigned char *key, size_t keylen,
668                                          unsigned char *id, size_t idlen,
669                                          ASN1_GENERALIZEDTIME *date,
670                                          ASN1_OBJECT *otherTypeId,
671                                          ASN1_TYPE *otherType)
672{
673    CMS_RecipientInfo *ri = NULL;
674    CMS_KEKRecipientInfo *kekri;
675    STACK_OF(CMS_RecipientInfo) *ris = CMS_get0_RecipientInfos(cms);
676
677    if (ris == NULL)
678        goto err;
679
680    if (nid == NID_undef) {
681        switch (keylen) {
682        case 16:
683            nid = NID_id_aes128_wrap;
684            break;
685
686        case 24:
687            nid = NID_id_aes192_wrap;
688            break;
689
690        case 32:
691            nid = NID_id_aes256_wrap;
692            break;
693
694        default:
695            ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
696            goto err;
697        }
698
699    } else {
700
701        size_t exp_keylen = aes_wrap_keylen(nid);
702
703        if (!exp_keylen) {
704            ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEK_ALGORITHM);
705            goto err;
706        }
707
708        if (keylen != exp_keylen) {
709            ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
710            goto err;
711        }
712
713    }
714
715    /* Initialize recipient info */
716    ri = M_ASN1_new_of(CMS_RecipientInfo);
717    if (!ri)
718        goto merr;
719
720    ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);
721    if (!ri->d.kekri)
722        goto merr;
723    ri->type = CMS_RECIPINFO_KEK;
724
725    kekri = ri->d.kekri;
726
727    if (otherTypeId) {
728        kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);
729        if (kekri->kekid->other == NULL)
730            goto merr;
731    }
732
733    if (!sk_CMS_RecipientInfo_push(ris, ri))
734        goto merr;
735
736    /* After this point no calls can fail */
737
738    kekri->version = 4;
739
740    kekri->key = key;
741    kekri->keylen = keylen;
742
743    ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
744
745    kekri->kekid->date = date;
746
747    if (kekri->kekid->other) {
748        kekri->kekid->other->keyAttrId = otherTypeId;
749        kekri->kekid->other->keyAttr = otherType;
750    }
751
752    X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
753                    OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
754
755    return ri;
756
757 merr:
758    ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
759 err:
760    M_ASN1_free_of(ri, CMS_RecipientInfo);
761    return NULL;
762}
763
764int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
765                                    X509_ALGOR **palg,
766                                    ASN1_OCTET_STRING **pid,
767                                    ASN1_GENERALIZEDTIME **pdate,
768                                    ASN1_OBJECT **potherid,
769                                    ASN1_TYPE **pothertype)
770{
771    CMS_KEKIdentifier *rkid;
772    if (ri->type != CMS_RECIPINFO_KEK) {
773        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
774        return 0;
775    }
776    rkid = ri->d.kekri->kekid;
777    if (palg)
778        *palg = ri->d.kekri->keyEncryptionAlgorithm;
779    if (pid)
780        *pid = rkid->keyIdentifier;
781    if (pdate)
782        *pdate = rkid->date;
783    if (potherid) {
784        if (rkid->other)
785            *potherid = rkid->other->keyAttrId;
786        else
787            *potherid = NULL;
788    }
789    if (pothertype) {
790        if (rkid->other)
791            *pothertype = rkid->other->keyAttr;
792        else
793            *pothertype = NULL;
794    }
795    return 1;
796}
797
798int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
799                               unsigned char *key, size_t keylen)
800{
801    CMS_KEKRecipientInfo *kekri;
802    if (ri->type != CMS_RECIPINFO_KEK) {
803        ERR_raise(ERR_LIB_CMS, CMS_R_NOT_KEK);
804        return 0;
805    }
806
807    kekri = ri->d.kekri;
808    kekri->key = key;
809    kekri->keylen = keylen;
810    return 1;
811}
812
813static EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen, const CMS_CTX *ctx)
814{
815    const char *alg = NULL;
816
817    switch(keylen) {
818    case 16:
819        alg = "AES-128-WRAP";
820        break;
821    case 24:
822        alg = "AES-192-WRAP";
823        break;
824    case 32:
825        alg = "AES-256-WRAP";
826        break;
827    default:
828        return NULL;
829    }
830    return EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(ctx), alg,
831                            ossl_cms_ctx_get0_propq(ctx));
832}
833
834
835/* Encrypt content key in KEK recipient info */
836
837static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
838                                           CMS_RecipientInfo *ri)
839{
840    CMS_EncryptedContentInfo *ec;
841    CMS_KEKRecipientInfo *kekri;
842    unsigned char *wkey = NULL;
843    int wkeylen;
844    int r = 0;
845    EVP_CIPHER *cipher = NULL;
846    int outlen = 0;
847    EVP_CIPHER_CTX *ctx = NULL;
848    const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
849
850    ec = ossl_cms_get0_env_enc_content(cms);
851    if (ec == NULL)
852        return 0;
853
854    kekri = ri->d.kekri;
855
856    if (kekri->key == NULL) {
857        ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
858        return 0;
859    }
860
861    cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
862    if (cipher == NULL) {
863        ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
864        goto err;
865    }
866
867    /* 8 byte prefix for AES wrap ciphers */
868    wkey = OPENSSL_malloc(ec->keylen + 8);
869    if (wkey == NULL) {
870        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
871        goto err;
872    }
873
874    ctx = EVP_CIPHER_CTX_new();
875    if (ctx == NULL) {
876        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
877        goto err;
878    }
879
880    EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
881    if (!EVP_EncryptInit_ex(ctx, cipher, NULL, kekri->key, NULL)
882            || !EVP_EncryptUpdate(ctx, wkey, &wkeylen, ec->key, ec->keylen)
883            || !EVP_EncryptFinal_ex(ctx, wkey + wkeylen, &outlen)) {
884        ERR_raise(ERR_LIB_CMS, CMS_R_WRAP_ERROR);
885        goto err;
886    }
887    wkeylen += outlen;
888    if (!ossl_assert((size_t)wkeylen == ec->keylen + 8)) {
889        ERR_raise(ERR_LIB_CMS, CMS_R_WRAP_ERROR);
890        goto err;
891    }
892
893    ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
894
895    r = 1;
896
897 err:
898    EVP_CIPHER_free(cipher);
899    if (!r)
900        OPENSSL_free(wkey);
901    EVP_CIPHER_CTX_free(ctx);
902
903    return r;
904}
905
906/* Decrypt content key in KEK recipient info */
907
908static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
909                                           CMS_RecipientInfo *ri)
910{
911    CMS_EncryptedContentInfo *ec;
912    CMS_KEKRecipientInfo *kekri;
913    unsigned char *ukey = NULL;
914    int ukeylen;
915    int r = 0, wrap_nid;
916    EVP_CIPHER *cipher = NULL;
917    int outlen = 0;
918    EVP_CIPHER_CTX *ctx = NULL;
919    const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms);
920
921    ec = ossl_cms_get0_env_enc_content(cms);
922    if (ec == NULL)
923        return 0;
924
925    kekri = ri->d.kekri;
926
927    if (!kekri->key) {
928        ERR_raise(ERR_LIB_CMS, CMS_R_NO_KEY);
929        return 0;
930    }
931
932    wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
933    if (aes_wrap_keylen(wrap_nid) != kekri->keylen) {
934        ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
935        return 0;
936    }
937
938    /* If encrypted key length is invalid don't bother */
939
940    if (kekri->encryptedKey->length < 16) {
941        ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
942        goto err;
943    }
944
945    cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
946    if (cipher == NULL) {
947        ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_LENGTH);
948        goto err;
949    }
950
951    ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);
952    if (ukey == NULL) {
953        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
954        goto err;
955    }
956
957    ctx = EVP_CIPHER_CTX_new();
958    if (ctx == NULL) {
959        ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
960        goto err;
961    }
962
963    if (!EVP_DecryptInit_ex(ctx, cipher, NULL, kekri->key, NULL)
964            || !EVP_DecryptUpdate(ctx, ukey, &ukeylen,
965                                  kekri->encryptedKey->data,
966                                  kekri->encryptedKey->length)
967            || !EVP_DecryptFinal_ex(ctx, ukey + ukeylen, &outlen)) {
968        ERR_raise(ERR_LIB_CMS, CMS_R_UNWRAP_ERROR);
969        goto err;
970    }
971    ukeylen += outlen;
972
973    OPENSSL_clear_free(ec->key, ec->keylen);
974    ec->key = ukey;
975    ec->keylen = ukeylen;
976
977    r = 1;
978
979 err:
980    EVP_CIPHER_free(cipher);
981    if (!r)
982        OPENSSL_free(ukey);
983    EVP_CIPHER_CTX_free(ctx);
984
985    return r;
986}
987
988int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
989{
990    switch (ri->type) {
991    case CMS_RECIPINFO_TRANS:
992        return cms_RecipientInfo_ktri_decrypt(cms, ri);
993
994    case CMS_RECIPINFO_KEK:
995        return cms_RecipientInfo_kekri_decrypt(cms, ri);
996
997    case CMS_RECIPINFO_PASS:
998        return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 0);
999
1000    default:
1001        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE);
1002        return 0;
1003    }
1004}
1005
1006int CMS_RecipientInfo_encrypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
1007{
1008    switch (ri->type) {
1009    case CMS_RECIPINFO_TRANS:
1010        return cms_RecipientInfo_ktri_encrypt(cms, ri);
1011
1012    case CMS_RECIPINFO_AGREE:
1013        return ossl_cms_RecipientInfo_kari_encrypt(cms, ri);
1014
1015    case CMS_RECIPINFO_KEK:
1016        return cms_RecipientInfo_kekri_encrypt(cms, ri);
1017
1018    case CMS_RECIPINFO_PASS:
1019        return ossl_cms_RecipientInfo_pwri_crypt(cms, ri, 1);
1020
1021    default:
1022        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
1023        return 0;
1024    }
1025}
1026
1027/* Check structures and fixup version numbers (if necessary) */
1028
1029static void cms_env_set_originfo_version(CMS_EnvelopedData *env)
1030{
1031    CMS_OriginatorInfo *org = env->originatorInfo;
1032    int i;
1033    if (org == NULL)
1034        return;
1035    for (i = 0; i < sk_CMS_CertificateChoices_num(org->certificates); i++) {
1036        CMS_CertificateChoices *cch;
1037        cch = sk_CMS_CertificateChoices_value(org->certificates, i);
1038        if (cch->type == CMS_CERTCHOICE_OTHER) {
1039            env->version = 4;
1040            return;
1041        } else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
1042            if (env->version < 3)
1043                env->version = 3;
1044        }
1045    }
1046
1047    for (i = 0; i < sk_CMS_RevocationInfoChoice_num(org->crls); i++) {
1048        CMS_RevocationInfoChoice *rch;
1049        rch = sk_CMS_RevocationInfoChoice_value(org->crls, i);
1050        if (rch->type == CMS_REVCHOICE_OTHER) {
1051            env->version = 4;
1052            return;
1053        }
1054    }
1055}
1056
1057static void cms_env_set_version(CMS_EnvelopedData *env)
1058{
1059    int i;
1060    CMS_RecipientInfo *ri;
1061
1062    /*
1063     * Can't set version higher than 4 so if 4 or more already nothing to do.
1064     */
1065    if (env->version >= 4)
1066        return;
1067
1068    cms_env_set_originfo_version(env);
1069
1070    if (env->version >= 3)
1071        return;
1072
1073    for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++) {
1074        ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i);
1075        if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER) {
1076            env->version = 3;
1077            return;
1078        } else if (ri->type != CMS_RECIPINFO_TRANS
1079                   || ri->d.ktri->version != 0) {
1080            env->version = 2;
1081        }
1082    }
1083    if (env->originatorInfo || env->unprotectedAttrs)
1084        env->version = 2;
1085    if (env->version == 2)
1086        return;
1087    env->version = 0;
1088}
1089
1090static int cms_env_encrypt_content_key(const CMS_ContentInfo *cms,
1091                                       STACK_OF(CMS_RecipientInfo) *ris)
1092{
1093    int i;
1094    CMS_RecipientInfo *ri;
1095
1096    for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
1097        ri = sk_CMS_RecipientInfo_value(ris, i);
1098        if (CMS_RecipientInfo_encrypt(cms, ri) <= 0)
1099            return -1;
1100    }
1101    return 1;
1102}
1103
1104static void cms_env_clear_ec(CMS_EncryptedContentInfo *ec)
1105{
1106    ec->cipher = NULL;
1107    OPENSSL_clear_free(ec->key, ec->keylen);
1108    ec->key = NULL;
1109    ec->keylen = 0;
1110}
1111
1112static BIO *cms_EnvelopedData_Decryption_init_bio(CMS_ContentInfo *cms)
1113{
1114    CMS_EncryptedContentInfo *ec = cms->d.envelopedData->encryptedContentInfo;
1115    BIO *contentBio = ossl_cms_EncryptedContent_init_bio(ec,
1116                                                         ossl_cms_get0_cmsctx(cms));
1117    EVP_CIPHER_CTX *ctx = NULL;
1118
1119    if (contentBio == NULL)
1120        return NULL;
1121
1122    BIO_get_cipher_ctx(contentBio, &ctx);
1123    if (ctx == NULL) {
1124        BIO_free(contentBio);
1125        return NULL;
1126    }
1127    /*
1128     * If the selected cipher supports unprotected attributes,
1129     * deal with it using special ctrl function
1130     */
1131    if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
1132                & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0
1133         && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED, 0,
1134                                cms->d.envelopedData->unprotectedAttrs) <= 0) {
1135        BIO_free(contentBio);
1136        return NULL;
1137    }
1138    return contentBio;
1139}
1140
1141static BIO *cms_EnvelopedData_Encryption_init_bio(CMS_ContentInfo *cms)
1142{
1143    CMS_EncryptedContentInfo *ec;
1144    STACK_OF(CMS_RecipientInfo) *rinfos;
1145    int ok = 0;
1146    BIO *ret;
1147    CMS_EnvelopedData *env = cms->d.envelopedData;
1148
1149    /* Get BIO first to set up key */
1150
1151    ec = env->encryptedContentInfo;
1152    ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms));
1153
1154    /* If error end of processing */
1155    if (!ret)
1156        return ret;
1157
1158    /* Now encrypt content key according to each RecipientInfo type */
1159    rinfos = env->recipientInfos;
1160    if (cms_env_encrypt_content_key(cms, rinfos) < 0) {
1161        ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO);
1162        goto err;
1163    }
1164
1165    /* And finally set the version */
1166    cms_env_set_version(env);
1167
1168    ok = 1;
1169
1170 err:
1171    cms_env_clear_ec(ec);
1172    if (ok)
1173        return ret;
1174    BIO_free(ret);
1175    return NULL;
1176}
1177
1178BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
1179{
1180    if (cms->d.envelopedData->encryptedContentInfo->cipher != NULL) {
1181         /* If cipher is set it's encryption */
1182         return cms_EnvelopedData_Encryption_init_bio(cms);
1183    }
1184
1185    /* If cipher is not set it's decryption */
1186    return cms_EnvelopedData_Decryption_init_bio(cms);
1187}
1188
1189BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms)
1190{
1191    CMS_EncryptedContentInfo *ec;
1192    STACK_OF(CMS_RecipientInfo) *rinfos;
1193    int ok = 0;
1194    BIO *ret;
1195    CMS_AuthEnvelopedData *aenv = cms->d.authEnvelopedData;
1196
1197    /* Get BIO first to set up key */
1198    ec = aenv->authEncryptedContentInfo;
1199    /* Set tag for decryption */
1200    if (ec->cipher == NULL) {
1201        ec->tag = aenv->mac->data;
1202        ec->taglen = aenv->mac->length;
1203    }
1204    ret = ossl_cms_EncryptedContent_init_bio(ec, ossl_cms_get0_cmsctx(cms));
1205
1206    /* If error or no cipher end of processing */
1207    if (ret == NULL || ec->cipher == NULL)
1208        return ret;
1209
1210    /* Now encrypt content key according to each RecipientInfo type */
1211    rinfos = aenv->recipientInfos;
1212    if (cms_env_encrypt_content_key(cms, rinfos) < 0) {
1213        ERR_raise(ERR_LIB_CMS, CMS_R_ERROR_SETTING_RECIPIENTINFO);
1214        goto err;
1215    }
1216
1217    /* And finally set the version */
1218    aenv->version = 0;
1219
1220    ok = 1;
1221
1222 err:
1223    cms_env_clear_ec(ec);
1224    if (ok)
1225        return ret;
1226    BIO_free(ret);
1227    return NULL;
1228}
1229
1230int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
1231{
1232    CMS_EnvelopedData *env = NULL;
1233    EVP_CIPHER_CTX *ctx = NULL;
1234    BIO *mbio = BIO_find_type(chain, BIO_TYPE_CIPHER);
1235
1236    env = ossl_cms_get0_enveloped(cms);
1237    if (env == NULL)
1238        return 0;
1239
1240    if (mbio == NULL) {
1241        ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND);
1242        return 0;
1243    }
1244
1245    BIO_get_cipher_ctx(mbio, &ctx);
1246
1247    /*
1248     * If the selected cipher supports unprotected attributes,
1249     * deal with it using special ctrl function
1250     */
1251    if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx))
1252            & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) {
1253        if (env->unprotectedAttrs == NULL)
1254            env->unprotectedAttrs = sk_X509_ATTRIBUTE_new_null();
1255
1256        if (env->unprotectedAttrs == NULL) {
1257            ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
1258            return 0;
1259        }
1260
1261        if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PROCESS_UNPROTECTED,
1262                                1, env->unprotectedAttrs) <= 0) {
1263            ERR_raise(ERR_LIB_CMS, CMS_R_CTRL_FAILURE);
1264            return 0;
1265        }
1266    }
1267
1268    cms_env_set_version(cms->d.envelopedData);
1269    return 1;
1270}
1271
1272int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio)
1273{
1274    EVP_CIPHER_CTX *ctx;
1275    unsigned char *tag = NULL;
1276    int taglen, ok = 0;
1277
1278    BIO_get_cipher_ctx(cmsbio, &ctx);
1279
1280    /*
1281     * The tag is set only for encryption. There is nothing to do for
1282     * decryption.
1283     */
1284    if (!EVP_CIPHER_CTX_is_encrypting(ctx))
1285        return 1;
1286
1287    taglen = EVP_CIPHER_CTX_get_tag_length(ctx);
1288    if (taglen <= 0
1289            || (tag = OPENSSL_malloc(taglen)) == NULL
1290            || EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen,
1291                                   tag) <= 0) {
1292        ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_GET_TAG);
1293        goto err;
1294    }
1295
1296    if (!ASN1_OCTET_STRING_set(cms->d.authEnvelopedData->mac, tag, taglen))
1297        goto err;
1298
1299    ok = 1;
1300err:
1301    OPENSSL_free(tag);
1302    return ok;
1303}
1304
1305/*
1306 * Get RecipientInfo type (if any) supported by a key (public or private). To
1307 * retain compatibility with previous behaviour if the ctrl value isn't
1308 * supported we assume key transport.
1309 */
1310int ossl_cms_pkey_get_ri_type(EVP_PKEY *pk)
1311{
1312    /* Check types that we know about */
1313    if (EVP_PKEY_is_a(pk, "DH"))
1314        return CMS_RECIPINFO_AGREE;
1315    else if (EVP_PKEY_is_a(pk, "DHX"))
1316        return CMS_RECIPINFO_AGREE;
1317    else if (EVP_PKEY_is_a(pk, "DSA"))
1318        return CMS_RECIPINFO_NONE;
1319    else if (EVP_PKEY_is_a(pk, "EC"))
1320        return CMS_RECIPINFO_AGREE;
1321    else if (EVP_PKEY_is_a(pk, "RSA"))
1322        return CMS_RECIPINFO_TRANS;
1323
1324    /*
1325     * Otherwise this might ben an engine implementation, so see if we can get
1326     * the type from the ameth.
1327     */
1328    if (pk->ameth && pk->ameth->pkey_ctrl) {
1329        int i, r;
1330        i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r);
1331        if (i > 0)
1332            return r;
1333    }
1334    return CMS_RECIPINFO_TRANS;
1335}
1336
1337int ossl_cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
1338{
1339    int supportedRiType;
1340
1341    if (pk->ameth != NULL && pk->ameth->pkey_ctrl != NULL) {
1342        int i, r;
1343
1344        i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED,
1345                                 ri_type, &r);
1346        if (i > 0)
1347            return r;
1348    }
1349
1350    supportedRiType = ossl_cms_pkey_get_ri_type(pk);
1351    if (supportedRiType < 0)
1352        return 0;
1353
1354    return (supportedRiType == ri_type);
1355}
1356