1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <assert.h> 11e1051a39Sopenharmony_ci#include <openssl/cms.h> 12e1051a39Sopenharmony_ci#include <openssl/err.h> 13e1051a39Sopenharmony_ci#include <openssl/core_names.h> 14e1051a39Sopenharmony_ci#include "crypto/asn1.h" 15e1051a39Sopenharmony_ci#include "crypto/rsa.h" 16e1051a39Sopenharmony_ci#include "cms_local.h" 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_cistatic RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg) 19e1051a39Sopenharmony_ci{ 20e1051a39Sopenharmony_ci RSA_OAEP_PARAMS *oaep; 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS), 23e1051a39Sopenharmony_ci alg->parameter); 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci if (oaep == NULL) 26e1051a39Sopenharmony_ci return NULL; 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ci if (oaep->maskGenFunc != NULL) { 29e1051a39Sopenharmony_ci oaep->maskHash = ossl_x509_algor_mgf1_decode(oaep->maskGenFunc); 30e1051a39Sopenharmony_ci if (oaep->maskHash == NULL) { 31e1051a39Sopenharmony_ci RSA_OAEP_PARAMS_free(oaep); 32e1051a39Sopenharmony_ci return NULL; 33e1051a39Sopenharmony_ci } 34e1051a39Sopenharmony_ci } 35e1051a39Sopenharmony_ci return oaep; 36e1051a39Sopenharmony_ci} 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_cistatic int rsa_cms_decrypt(CMS_RecipientInfo *ri) 39e1051a39Sopenharmony_ci{ 40e1051a39Sopenharmony_ci EVP_PKEY_CTX *pkctx; 41e1051a39Sopenharmony_ci X509_ALGOR *cmsalg; 42e1051a39Sopenharmony_ci int nid; 43e1051a39Sopenharmony_ci int rv = -1; 44e1051a39Sopenharmony_ci unsigned char *label = NULL; 45e1051a39Sopenharmony_ci int labellen = 0; 46e1051a39Sopenharmony_ci const EVP_MD *mgf1md = NULL, *md = NULL; 47e1051a39Sopenharmony_ci RSA_OAEP_PARAMS *oaep; 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_ci pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); 50e1051a39Sopenharmony_ci if (pkctx == NULL) 51e1051a39Sopenharmony_ci return 0; 52e1051a39Sopenharmony_ci if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg)) 53e1051a39Sopenharmony_ci return -1; 54e1051a39Sopenharmony_ci nid = OBJ_obj2nid(cmsalg->algorithm); 55e1051a39Sopenharmony_ci if (nid == NID_rsaEncryption) 56e1051a39Sopenharmony_ci return 1; 57e1051a39Sopenharmony_ci if (nid != NID_rsaesOaep) { 58e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_ENCRYPTION_TYPE); 59e1051a39Sopenharmony_ci return -1; 60e1051a39Sopenharmony_ci } 61e1051a39Sopenharmony_ci /* Decode OAEP parameters */ 62e1051a39Sopenharmony_ci oaep = rsa_oaep_decode(cmsalg); 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_ci if (oaep == NULL) { 65e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_OAEP_PARAMETERS); 66e1051a39Sopenharmony_ci goto err; 67e1051a39Sopenharmony_ci } 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ci mgf1md = ossl_x509_algor_get_md(oaep->maskHash); 70e1051a39Sopenharmony_ci if (mgf1md == NULL) 71e1051a39Sopenharmony_ci goto err; 72e1051a39Sopenharmony_ci md = ossl_x509_algor_get_md(oaep->hashFunc); 73e1051a39Sopenharmony_ci if (md == NULL) 74e1051a39Sopenharmony_ci goto err; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci if (oaep->pSourceFunc != NULL) { 77e1051a39Sopenharmony_ci X509_ALGOR *plab = oaep->pSourceFunc; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) { 80e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_LABEL_SOURCE); 81e1051a39Sopenharmony_ci goto err; 82e1051a39Sopenharmony_ci } 83e1051a39Sopenharmony_ci if (plab->parameter->type != V_ASN1_OCTET_STRING) { 84e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_LABEL); 85e1051a39Sopenharmony_ci goto err; 86e1051a39Sopenharmony_ci } 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci label = plab->parameter->value.octet_string->data; 89e1051a39Sopenharmony_ci /* Stop label being freed when OAEP parameters are freed */ 90e1051a39Sopenharmony_ci plab->parameter->value.octet_string->data = NULL; 91e1051a39Sopenharmony_ci labellen = plab->parameter->value.octet_string->length; 92e1051a39Sopenharmony_ci } 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0) 95e1051a39Sopenharmony_ci goto err; 96e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0) 97e1051a39Sopenharmony_ci goto err; 98e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) 99e1051a39Sopenharmony_ci goto err; 100e1051a39Sopenharmony_ci if (label != NULL 101e1051a39Sopenharmony_ci && EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0) 102e1051a39Sopenharmony_ci goto err; 103e1051a39Sopenharmony_ci /* Carry on */ 104e1051a39Sopenharmony_ci rv = 1; 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_ci err: 107e1051a39Sopenharmony_ci RSA_OAEP_PARAMS_free(oaep); 108e1051a39Sopenharmony_ci return rv; 109e1051a39Sopenharmony_ci} 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_cistatic int rsa_cms_encrypt(CMS_RecipientInfo *ri) 112e1051a39Sopenharmony_ci{ 113e1051a39Sopenharmony_ci const EVP_MD *md, *mgf1md; 114e1051a39Sopenharmony_ci RSA_OAEP_PARAMS *oaep = NULL; 115e1051a39Sopenharmony_ci ASN1_STRING *os = NULL; 116e1051a39Sopenharmony_ci X509_ALGOR *alg; 117e1051a39Sopenharmony_ci EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); 118e1051a39Sopenharmony_ci int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen; 119e1051a39Sopenharmony_ci unsigned char *label; 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ci if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0) 122e1051a39Sopenharmony_ci return 0; 123e1051a39Sopenharmony_ci if (pkctx != NULL) { 124e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) 125e1051a39Sopenharmony_ci return 0; 126e1051a39Sopenharmony_ci } 127e1051a39Sopenharmony_ci if (pad_mode == RSA_PKCS1_PADDING) { 128e1051a39Sopenharmony_ci X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); 129e1051a39Sopenharmony_ci return 1; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci /* Not supported */ 132e1051a39Sopenharmony_ci if (pad_mode != RSA_PKCS1_OAEP_PADDING) 133e1051a39Sopenharmony_ci return 0; 134e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0) 135e1051a39Sopenharmony_ci goto err; 136e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0) 137e1051a39Sopenharmony_ci goto err; 138e1051a39Sopenharmony_ci labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label); 139e1051a39Sopenharmony_ci if (labellen < 0) 140e1051a39Sopenharmony_ci goto err; 141e1051a39Sopenharmony_ci oaep = RSA_OAEP_PARAMS_new(); 142e1051a39Sopenharmony_ci if (oaep == NULL) 143e1051a39Sopenharmony_ci goto err; 144e1051a39Sopenharmony_ci if (!ossl_x509_algor_new_from_md(&oaep->hashFunc, md)) 145e1051a39Sopenharmony_ci goto err; 146e1051a39Sopenharmony_ci if (!ossl_x509_algor_md_to_mgf1(&oaep->maskGenFunc, mgf1md)) 147e1051a39Sopenharmony_ci goto err; 148e1051a39Sopenharmony_ci if (labellen > 0) { 149e1051a39Sopenharmony_ci ASN1_OCTET_STRING *los; 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_ci oaep->pSourceFunc = X509_ALGOR_new(); 152e1051a39Sopenharmony_ci if (oaep->pSourceFunc == NULL) 153e1051a39Sopenharmony_ci goto err; 154e1051a39Sopenharmony_ci los = ASN1_OCTET_STRING_new(); 155e1051a39Sopenharmony_ci if (los == NULL) 156e1051a39Sopenharmony_ci goto err; 157e1051a39Sopenharmony_ci if (!ASN1_OCTET_STRING_set(los, label, labellen)) { 158e1051a39Sopenharmony_ci ASN1_OCTET_STRING_free(los); 159e1051a39Sopenharmony_ci goto err; 160e1051a39Sopenharmony_ci } 161e1051a39Sopenharmony_ci X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified), 162e1051a39Sopenharmony_ci V_ASN1_OCTET_STRING, los); 163e1051a39Sopenharmony_ci } 164e1051a39Sopenharmony_ci /* create string with pss parameter encoding. */ 165e1051a39Sopenharmony_ci if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os)) 166e1051a39Sopenharmony_ci goto err; 167e1051a39Sopenharmony_ci X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os); 168e1051a39Sopenharmony_ci os = NULL; 169e1051a39Sopenharmony_ci rv = 1; 170e1051a39Sopenharmony_ci err: 171e1051a39Sopenharmony_ci RSA_OAEP_PARAMS_free(oaep); 172e1051a39Sopenharmony_ci ASN1_STRING_free(os); 173e1051a39Sopenharmony_ci return rv; 174e1051a39Sopenharmony_ci} 175e1051a39Sopenharmony_ci 176e1051a39Sopenharmony_ciint ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt) 177e1051a39Sopenharmony_ci{ 178e1051a39Sopenharmony_ci assert(decrypt == 0 || decrypt == 1); 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ci if (decrypt == 1) 181e1051a39Sopenharmony_ci return rsa_cms_decrypt(ri); 182e1051a39Sopenharmony_ci 183e1051a39Sopenharmony_ci if (decrypt == 0) 184e1051a39Sopenharmony_ci return rsa_cms_encrypt(ri); 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 187e1051a39Sopenharmony_ci return 0; 188e1051a39Sopenharmony_ci} 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_cistatic int rsa_cms_sign(CMS_SignerInfo *si) 191e1051a39Sopenharmony_ci{ 192e1051a39Sopenharmony_ci int pad_mode = RSA_PKCS1_PADDING; 193e1051a39Sopenharmony_ci X509_ALGOR *alg; 194e1051a39Sopenharmony_ci EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si); 195e1051a39Sopenharmony_ci unsigned char aid[128]; 196e1051a39Sopenharmony_ci const unsigned char *pp = aid; 197e1051a39Sopenharmony_ci size_t aid_len = 0; 198e1051a39Sopenharmony_ci OSSL_PARAM params[2]; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg); 201e1051a39Sopenharmony_ci if (pkctx != NULL) { 202e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) 203e1051a39Sopenharmony_ci return 0; 204e1051a39Sopenharmony_ci } 205e1051a39Sopenharmony_ci if (pad_mode == RSA_PKCS1_PADDING) { 206e1051a39Sopenharmony_ci X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); 207e1051a39Sopenharmony_ci return 1; 208e1051a39Sopenharmony_ci } 209e1051a39Sopenharmony_ci /* We don't support it */ 210e1051a39Sopenharmony_ci if (pad_mode != RSA_PKCS1_PSS_PADDING) 211e1051a39Sopenharmony_ci return 0; 212e1051a39Sopenharmony_ci 213e1051a39Sopenharmony_ci params[0] = OSSL_PARAM_construct_octet_string( 214e1051a39Sopenharmony_ci OSSL_SIGNATURE_PARAM_ALGORITHM_ID, aid, sizeof(aid)); 215e1051a39Sopenharmony_ci params[1] = OSSL_PARAM_construct_end(); 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ci if (EVP_PKEY_CTX_get_params(pkctx, params) <= 0) 218e1051a39Sopenharmony_ci return 0; 219e1051a39Sopenharmony_ci if ((aid_len = params[0].return_size) == 0) 220e1051a39Sopenharmony_ci return 0; 221e1051a39Sopenharmony_ci if (d2i_X509_ALGOR(&alg, &pp, aid_len) == NULL) 222e1051a39Sopenharmony_ci return 0; 223e1051a39Sopenharmony_ci return 1; 224e1051a39Sopenharmony_ci} 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_cistatic int rsa_cms_verify(CMS_SignerInfo *si) 227e1051a39Sopenharmony_ci{ 228e1051a39Sopenharmony_ci int nid, nid2; 229e1051a39Sopenharmony_ci X509_ALGOR *alg; 230e1051a39Sopenharmony_ci EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si); 231e1051a39Sopenharmony_ci EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pkctx); 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ci CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg); 234e1051a39Sopenharmony_ci nid = OBJ_obj2nid(alg->algorithm); 235e1051a39Sopenharmony_ci if (nid == EVP_PKEY_RSA_PSS) 236e1051a39Sopenharmony_ci return ossl_rsa_pss_to_ctx(NULL, pkctx, alg, NULL) > 0; 237e1051a39Sopenharmony_ci /* Only PSS allowed for PSS keys */ 238e1051a39Sopenharmony_ci if (EVP_PKEY_is_a(pkey, "RSA-PSS")) { 239e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE); 240e1051a39Sopenharmony_ci return 0; 241e1051a39Sopenharmony_ci } 242e1051a39Sopenharmony_ci if (nid == NID_rsaEncryption) 243e1051a39Sopenharmony_ci return 1; 244e1051a39Sopenharmony_ci /* Workaround for some implementation that use a signature OID */ 245e1051a39Sopenharmony_ci if (OBJ_find_sigid_algs(nid, NULL, &nid2)) { 246e1051a39Sopenharmony_ci if (nid2 == NID_rsaEncryption) 247e1051a39Sopenharmony_ci return 1; 248e1051a39Sopenharmony_ci } 249e1051a39Sopenharmony_ci return 0; 250e1051a39Sopenharmony_ci} 251e1051a39Sopenharmony_ci 252e1051a39Sopenharmony_ciint ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify) 253e1051a39Sopenharmony_ci{ 254e1051a39Sopenharmony_ci assert(verify == 0 || verify == 1); 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci if (verify == 1) 257e1051a39Sopenharmony_ci return rsa_cms_verify(si); 258e1051a39Sopenharmony_ci 259e1051a39Sopenharmony_ci if (verify == 0) 260e1051a39Sopenharmony_ci return rsa_cms_sign(si); 261e1051a39Sopenharmony_ci 262e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 263e1051a39Sopenharmony_ci return 0; 264e1051a39Sopenharmony_ci} 265