/* * Copyright 2014-2021 The GmSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include "internal/skf_int.h" #include "../../e_os.h" ULONG DEVAPI SKF_NewECCCipher(ULONG ulCipherLen, ECCCIPHERBLOB **cipherBlob) { ECCCIPHERBLOB *ret = NULL; if (!(ret = OPENSSL_malloc(sizeof(ECCCIPHERBLOB) - 1 + ulCipherLen))) { SKFerr(SKF_F_SKF_NEWECCCIPHER, ERR_R_MALLOC_FAILURE); return SAR_MEMORYERR; } ret->CipherLen = ulCipherLen; *cipherBlob = ret; return SAR_OK; } ULONG DEVAPI SKF_NewEnvelopedKey(ULONG ulCipherLen, ENVELOPEDKEYBLOB **envelopedKeyBlob) { ENVELOPEDKEYBLOB *ret = NULL; if (!(ret = OPENSSL_zalloc(sizeof(ENVELOPEDKEYBLOB) - 1 + ulCipherLen))) { SKFerr(SKF_F_SKF_NEWENVELOPEDKEY, ERR_R_MALLOC_FAILURE); return SAR_MEMORYERR; } ret->ECCCipherBlob.CipherLen = ulCipherLen; *envelopedKeyBlob = ret; return SAR_OK; } ULONG DEVAPI SKF_OpenDevice(LPSTR devName, BYTE authKey[16], DEVINFO *devInfo, DEVHANDLE *phDev) { ULONG rv; DEVHANDLE hDev = NULL; HANDLE hKey = NULL; ULONG ulTimeOut = 0xffffffff; BYTE authRand[16] = {0}; BYTE authData[16] = {0}; ULONG authRandLen = SKF_AUTHRAND_LENGTH; ULONG authDataLen = sizeof(authData); BLOCKCIPHERPARAM encParam = {{0}, 0, 0, 0}; if ((rv = SKF_ConnectDev((LPSTR)devName, &hDev)) != SAR_OK || (rv = SKF_GetDevInfo(hDev, devInfo)) != SAR_OK || (rv = SKF_LockDev(hDev, ulTimeOut)) != SAR_OK || (rv = SKF_GenRandom(hDev, authRand, authRandLen)) != SAR_OK || (rv = SKF_SetSymmKey(hDev, authKey, devInfo->DevAuthAlgId, &hKey)) != SAR_OK || (rv = SKF_EncryptInit(hKey, encParam)) != SAR_OK || (rv = SKF_Encrypt(hKey, authRand, sizeof(authRand), authData, &authDataLen)) != SAR_OK || (rv =SKF_DevAuth(hDev, authData, authDataLen)) != SAR_OK) { SKFerr(SKF_F_SKF_OPENDEVICE, ERR_R_SKF_LIB); goto end; } *phDev = hDev; hDev = NULL; end: OPENSSL_cleanse(authRand, sizeof(authRand)); OPENSSL_cleanse(authData, sizeof(authData)); if (hKey && (rv = SKF_CloseHandle(hKey)) != SAR_OK) { SKFerr(SKF_F_SKF_OPENDEVICE, ERR_R_SKF_LIB); } if (hDev && (rv = SKF_DisConnectDev(hDev)) != SAR_OK) { SKFerr(SKF_F_SKF_OPENDEVICE, ERR_R_SKF_LIB); } return rv; } ULONG DEVAPI SKF_CloseDevice(DEVHANDLE hDev) { ULONG rv; if ((rv = SKF_UnlockDev(hDev)) != SAR_OK) { SKFerr(SKF_F_SKF_CLOSEDEVICE, ERR_R_SKF_LIB); } if ((rv = SKF_DisConnectDev(hDev)) != SAR_OK) { SKFerr(SKF_F_SKF_CLOSEDEVICE, ERR_R_SKF_LIB); } return rv; } ULONG DEVAPI SKF_ImportECCPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, EC_KEY *ec_key, ULONG symmAlgId) { int ret = 0; ULONG rv; ULONG containerType; ECCPRIVATEKEYBLOB eccPriKeyBlob; BYTE symmKey[16]; HANDLE hSymmKey = NULL; BLOCKCIPHERPARAM encParam; ULONG encedPriKeyLen; SKF_PUBLICKEYBLOB signPubKeyBlob; ULONG signPubKeyLen = sizeof(signPubKeyBlob); ENVELOPEDKEYBLOB envelopedKeyBlob; /* check container type */ if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); return rv; } if (containerType != SKF_CONTAINER_TYPE_ECC) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, SKF_R_CONTAINER_TYPE_NOT_MATCH); return SAR_FAIL; } /* get private key and public key */ if (!EC_KEY_get_ECCPRIVATEKEYBLOB(ec_key, &eccPriKeyBlob) || !EC_KEY_get_ECCPUBLICKEYBLOB(ec_key, &(envelopedKeyBlob.PubKey))) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_GMAPI_LIB); rv = SAR_FAIL; goto end; } /* set Version, ulSymmAlgID, ulBits */ envelopedKeyBlob.Version = SKF_ENVELOPEDKEYBLOB_VERSION; envelopedKeyBlob.ulSymmAlgID = symmAlgId; envelopedKeyBlob.ulBits = eccPriKeyBlob.BitLen; /* encrypt private key with random generated symmkey */ if (!RAND_bytes(symmKey, sizeof(symmKey))) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); rv = SAR_FAIL; goto end; } if ((rv = SKF_SetSymmKey(hDev, symmKey, symmAlgId, &hSymmKey)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); goto end; } encParam.IVLen = 0; encParam.PaddingType = SKF_NO_PADDING; if ((rv = SKF_EncryptInit(hSymmKey, encParam)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); goto end; } encedPriKeyLen = sizeof(envelopedKeyBlob.cbEncryptedPriKey); if ((rv = SKF_Encrypt(hSymmKey, eccPriKeyBlob.PrivateKey, sizeof(eccPriKeyBlob.PrivateKey), (BYTE *)&(envelopedKeyBlob.cbEncryptedPriKey), &encedPriKeyLen)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); goto end; } if (encedPriKeyLen != sizeof(eccPriKeyBlob.PrivateKey)) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); rv = SAR_FAIL; goto end; } /* encrypt symmKey */ if ((rv = SKF_ExportPublicKey(hContainer, TRUE, (BYTE *)&signPubKeyBlob, &signPubKeyLen)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); goto end; } if (signPubKeyLen != sizeof(ECCPUBLICKEYBLOB)) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); rv = SAR_FAIL; goto end; } if ((rv = SKF_ExtECCEncrypt(hDev, (ECCPUBLICKEYBLOB *)&signPubKeyBlob, symmKey, sizeof(symmKey), &(envelopedKeyBlob.ECCCipherBlob))) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); goto end; } ret = 1; end: OPENSSL_cleanse(&eccPriKeyBlob, sizeof(eccPriKeyBlob)); OPENSSL_cleanse(symmKey, sizeof(symmKey)); if (hSymmKey && SKF_CloseHandle(hSymmKey) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTECCPRIVATEKEY, ERR_R_SKF_LIB); ret = 0; } return ret; } ULONG DEVAPI SKF_ImportRSAPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, RSA *rsa, ULONG symmAlgId) { ULONG rv; ULONG containerType; RSAPRIVATEKEYBLOB rsaPriKeyBlob; unsigned char symmKey[16]; RSAPUBLICKEYBLOB rsaPubKeyBlob; ULONG rsaPubKeyLen = sizeof(rsaPubKeyBlob); BYTE wrappedKey[MAX_RSA_MODULUS_LEN]; ULONG wrappedKeyLen = sizeof(wrappedKey); EVP_CIPHER_CTX *cctx = NULL; unsigned char *p; int len; BYTE encedPriKey[sizeof(RSAPRIVATEKEYBLOB) + 16*2]; ULONG encedPriKeyLen = sizeof(encedPriKey); if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); return rv; } if (containerType != SKF_CONTAINER_TYPE_RSA) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); return SAR_FAIL; } if (!RSA_get_RSAPRIVATEKEYBLOB(rsa, &rsaPriKeyBlob)) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); goto end; } /* generate symmkey */ /* wrap symmkey with signing public key */ if (!RAND_bytes(symmKey, sizeof(symmKey))) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); goto end; } if ((rv = SKF_ExportPublicKey(hContainer, SGD_TRUE, (BYTE *)&rsaPubKeyBlob, &rsaPubKeyLen)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); goto end; } if (!(rsa = RSA_new_from_RSAPUBLICKEYBLOB(&rsaPubKeyBlob))) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); goto end; } if ((len = RSA_public_encrypt(sizeof(symmKey), symmKey, wrappedKey, rsa, RSA_PKCS1_PADDING)) != rsaPriKeyBlob.BitLen / 8) { goto end; } wrappedKeyLen = (ULONG)len; /* encrypt private key with symmkey in ECB mode */ if (!(cctx = EVP_CIPHER_CTX_new())) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_MALLOC_FAILURE); goto end; } if (!EVP_EncryptInit_ex(cctx, EVP_sms4_ecb(), NULL, symmKey, NULL)) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_EVP_LIB); goto end; } p = encedPriKey; if (!EVP_EncryptUpdate(cctx, p, &len, (unsigned char *)&rsaPriKeyBlob, sizeof(RSAPRIVATEKEYBLOB))) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_EVP_LIB); goto end; } p += len; if (!EVP_EncryptFinal_ex(cctx, p, &len)) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_EVP_LIB); goto end; } p += len; encedPriKeyLen = p - encedPriKey; /* import */ if ((rv = SKF_ImportRSAKeyPair(hContainer, symmAlgId, wrappedKey, wrappedKeyLen, encedPriKey, encedPriKeyLen)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTRSAPRIVATEKEY, ERR_R_SKF_LIB); goto end; } end: OPENSSL_cleanse(&rsaPriKeyBlob, sizeof(rsaPriKeyBlob)); OPENSSL_cleanse(symmKey, sizeof(symmKey)); OPENSSL_cleanse(wrappedKey, sizeof(wrappedKey)); EVP_CIPHER_CTX_free(cctx); return rv; } ULONG DEVAPI SKF_ImportPrivateKey(DEVHANDLE hDev, HCONTAINER hContainer, EVP_PKEY *pkey, ULONG symmAlgId) { ULONG rv; switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_EC: if ((rv = SKF_ImportECCPrivateKey(hDev, hContainer, EVP_PKEY_get0_EC_KEY(pkey), symmAlgId)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTPRIVATEKEY, ERR_R_SKF_LIB); return rv; } break; case EVP_PKEY_RSA: if ((rv = SKF_ImportRSAPrivateKey(hDev, hContainer, EVP_PKEY_get0_RSA(pkey), symmAlgId)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTPRIVATEKEY, ERR_R_SKF_LIB); return rv; } break; default: SKFerr(SKF_F_SKF_IMPORTPRIVATEKEY, SKF_R_UNSUPPORTED_PRIVATE_KEY_TYPE); return SAR_FAIL; } return SAR_OK; } ULONG DEVAPI SKF_ExportECCPublicKey(HCONTAINER hContainer, BOOL bSign, EC_KEY **ec_key) { ULONG rv; ULONG containerType; BYTE pubKeyBlob[sizeof(SKF_PUBLICKEYBLOB)]; ECCPUBLICKEYBLOB *pubKey = (ECCPUBLICKEYBLOB *)pubKeyBlob; ULONG pubKeyLen = sizeof(SKF_PUBLICKEYBLOB); if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, ERR_R_SKF_LIB); return rv; } if (containerType != SKF_CONTAINER_TYPE_ECC) { SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, SKF_R_CONTAINER_TYPE_NOT_MATCH); return SAR_FAIL; } if ((rv = SKF_ExportPublicKey(hContainer, bSign, pubKeyBlob, &pubKeyLen)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, ERR_R_SKF_LIB); return rv; } if (pubKeyLen != sizeof(ECCPUBLICKEYBLOB)) { SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, ERR_R_SKF_LIB); return SAR_FAIL; } if (!(*ec_key = EC_KEY_new_from_ECCPUBLICKEYBLOB(pubKey))) { SKFerr(SKF_F_SKF_EXPORTECCPUBLICKEY, SKF_R_INVALID_ECC_PUBLIC_KEY); return SAR_FAIL; } return SAR_OK; } ULONG DEVAPI SKF_ExportRSAPublicKey(HCONTAINER hContainer, BOOL bSign, RSA **rsa) { ULONG rv; ULONG containerType; BYTE pubKeyBlob[sizeof(SKF_PUBLICKEYBLOB)]; RSAPUBLICKEYBLOB *pubKey = (RSAPUBLICKEYBLOB *)pubKeyBlob; ULONG pubKeyLen = sizeof(SKF_PUBLICKEYBLOB); if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, ERR_R_SKF_LIB); return rv; } if (containerType != SKF_CONTAINER_TYPE_RSA) { SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, SKF_R_CONTAINER_TYPE_NOT_MATCH); return SAR_FAIL; } if ((rv = SKF_ExportPublicKey(hContainer, bSign, pubKeyBlob, &pubKeyLen)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, ERR_R_SKF_LIB); return rv; } if (pubKeyLen != sizeof(RSAPUBLICKEYBLOB)) { SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, ERR_R_SKF_LIB); return SAR_FAIL; } if (!(*rsa = RSA_new_from_RSAPUBLICKEYBLOB(pubKey))) { SKFerr(SKF_F_SKF_EXPORTRSAPUBLICKEY, SKF_R_INVALID_RSA_PUBLIC_KEY); return SAR_FAIL; } return SAR_OK; } ULONG DEVAPI SKF_ExportEVPPublicKey(HCONTAINER hContainer, BOOL bSign, EVP_PKEY **pp) { ULONG rv; ULONG containerType; EVP_PKEY *pkey = NULL; if ((rv = SKF_GetContainerType(hContainer, &containerType)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_SKF_LIB); return rv; } if (!(pkey = EVP_PKEY_new())) { SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_MALLOC_FAILURE); return SAR_MEMORYERR; } if (containerType == SKF_CONTAINER_TYPE_ECC) { EC_KEY *ec_key = NULL; if ((rv = SKF_ExportECCPublicKey(hContainer, bSign, &ec_key)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_SKF_LIB); goto end; } if (!EVP_PKEY_assign_EC_KEY(pkey, ec_key)) { EC_KEY_free(ec_key); rv = SAR_FAIL; goto end; } } else if (containerType == SKF_CONTAINER_TYPE_RSA) { RSA *rsa = NULL; if ((rv = SKF_ExportRSAPublicKey(hContainer, bSign, &rsa)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, ERR_R_SKF_LIB); goto end; } if (!EVP_PKEY_assign_RSA(pkey, rsa)) { RSA_free(rsa); rv = SAR_FAIL; goto end; } } else { SKFerr(SKF_F_SKF_EXPORTEVPPUBLICKEY, SKF_R_INVALID_CONTAINER_TYPE); rv = SAR_FAIL; goto end; } *pp = pkey; pkey = NULL; rv = SAR_OK; end: EVP_PKEY_free(pkey); return rv; } ULONG DEVAPI SKF_ImportX509Certificate(HCONTAINER hContainer, BOOL bSign, X509 *x509) { int ret = 0; ULONG containerType; unsigned char *cert = NULL; unsigned char *p; int len; if (SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { return 0; } if (containerType == SKF_CONTAINER_TYPE_UNDEF) { return 0; } switch (EVP_PKEY_id(X509_get0_pubkey(x509))) { case EVP_PKEY_EC: if (containerType != SKF_CONTAINER_TYPE_ECC) { goto end; } if (!EC_KEY_is_sm2p256v1(EVP_PKEY_get0_EC_KEY(X509_get0_pubkey(x509)))) { goto end; } break; case EVP_PKEY_RSA: if (containerType != SKF_CONTAINER_TYPE_RSA) { goto end; } break; default: goto end; } if (X509_get_key_usage(x509) & (KU_DIGITAL_SIGNATURE| KU_NON_REPUDIATION|KU_KEY_CERT_SIGN|KU_CRL_SIGN)) { bSign = SGD_TRUE; } else if (X509_get_key_usage(x509) & (KU_KEY_ENCIPHERMENT| KU_DATA_ENCIPHERMENT|KU_KEY_AGREEMENT|KU_ENCIPHER_ONLY)) { bSign = SGD_FALSE; } else { goto end; } if ((len = i2d_X509(x509, NULL)) <= 0 || !(p = cert = OPENSSL_malloc(len)) || (len = i2d_X509(x509, &p)) <= 0) { goto end; } if (SKF_ImportCertificate(hContainer, bSign, cert, (ULONG)len) != SAR_OK) { goto end; } ret = 1; end: X509_free(x509); OPENSSL_free(cert); return ret; } ULONG DEVAPI SKF_ImportX509CertificateByKeyUsage(HCONTAINER hContainer, X509 *x509) { ULONG rv; BOOL bSign; if (X509_get_key_usage(x509) & (KU_DIGITAL_SIGNATURE| KU_NON_REPUDIATION|KU_KEY_CERT_SIGN|KU_CRL_SIGN)) { bSign = SGD_TRUE; } else if (X509_get_key_usage(x509) & (KU_KEY_ENCIPHERMENT| KU_DATA_ENCIPHERMENT|KU_KEY_AGREEMENT|KU_ENCIPHER_ONLY)) { bSign = SGD_FALSE; } else { SKFerr(SKF_F_SKF_IMPORTX509CERTIFICATEBYKEYUSAGE, SKF_R_UNKNOWN_CERTIFICATE_KEYUSAGE); return SAR_FAIL; } if ((rv = SKF_ImportX509Certificate(hContainer, bSign, x509)) != SAR_OK) { SKFerr(SKF_F_SKF_IMPORTX509CERTIFICATEBYKEYUSAGE, ERR_R_SKF_LIB); return rv; } return SAR_OK; } ULONG DEVAPI SKF_ExportX509Certificate(HCONTAINER hContainer, BOOL bSign, X509 **px509) { ULONG rv = SAR_FAIL; BYTE *pbCert = NULL; ULONG ulCertLen; const unsigned char *p; X509 *x509 = NULL; ulCertLen = SKF_MAX_CERTIFICATE_SIZE; if (!(pbCert = OPENSSL_zalloc(ulCertLen))) { SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, ERR_R_MALLOC_FAILURE); rv = SAR_MEMORYERR; goto end; } if ((rv = SKF_ExportCertificate(hContainer, bSign, pbCert, &ulCertLen)) != SAR_OK) { SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, ERR_R_SKF_LIB); goto end; } p = pbCert; if (!(x509 = d2i_X509(NULL, &p, (long)ulCertLen))) { SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, SKF_R_PARSE_CERTIFICATE_FAILURE); goto end; } if (p - pbCert != ulCertLen) { SKFerr(SKF_F_SKF_EXPORTX509CERTIFICATE, SKF_R_PARSE_CERTIFICATE_FAILURE); goto end; } *px509 = x509; x509 = NULL; rv = SAR_OK; end: OPENSSL_free(pbCert); X509_free(x509); return rv; }