2 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
25 #include <openssl/evp.h>
26 #include <openssl/obj_mac.h>
27 #include <openssl/ec.h>
28 #include <openssl/dsa.h>
29 #include <openssl/rsa.h>
30 #include <openssl/bio.h>
31 #include <openssl/rand.h>
32 #include <openssl/crypto.h>
33 #include <openssl/err.h>
34 #include <openssl/x509v3.h>
35 #include <openssl/obj_mac.h>
37 #include <ckm/ckm-error.h>
39 #include <dpl/log/log.h>
41 #include <generic-backend/exception.h>
42 #include <sw-backend/internals.h>
44 #define OPENSSL_SUCCESS 1 // DO NOTCHANGE THIS VALUE
45 #define OPENSSL_FAIL 0 // DO NOTCHANGE THIS VALUE
46 #define DEV_HW_RANDOM_FILE "/dev/hwrng"
47 #define DEV_URANDOM_FILE "/dev/urandom"
50 typedef std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> EvpMdCtxUPtr;
51 typedef std::unique_ptr<EVP_PKEY_CTX, std::function<void(EVP_PKEY_CTX*)>> EvpPkeyCtxUPtr;
52 typedef std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY*)>> EvpPkeyUPtr;
54 typedef std::unique_ptr<BIO, std::function<void(BIO*)>> BioUniquePtr;
55 typedef int(*I2D_CONV)(BIO*, EVP_PKEY*);
56 CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) {
57 BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
60 ThrowErr(CKM::Exc::Crypto::InternalError, "attempt to parse an empty key!");
63 if (NULL == bio.get()) {
64 ThrowErr(CKM::Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new.");
67 if (1 != fun(bio.get(), pkey)) {
68 ThrowErr(CKM::Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER");
71 CKM::RawBuffer output(8196);
73 int size = BIO_read(bio.get(), output.data(), output.size());
76 ThrowErr(CKM::Exc::Crypto::InternalError, "Error in BIO_read: ", size);
82 } // anonymous namespace
93 // try to initialize using ERR_load_crypto_strings and OpenSSL_add_all_algorithms
94 ERR_load_crypto_strings();
95 OpenSSL_add_all_algorithms();
98 std::ifstream ifile(DEV_HW_RANDOM_FILE);
100 u_rand_ret= RAND_load_file(DEV_HW_RANDOM_FILE, 32);
102 if(u_rand_ret != 32 ){
103 LogError("Error in HW_RAND file load");
104 hw_rand_ret = RAND_load_file(DEV_URANDOM_FILE, 32);
106 if(hw_rand_ret != 32) {
107 ThrowErr(Exc::Crypto::InternalError, "Error in U_RAND_file_load");
111 return CKM_CRYPTO_INIT_SUCCESS;
114 const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
115 const EVP_MD *md_algo=NULL;
117 case HashAlgorithm::NONE:
120 case HashAlgorithm::SHA1:
121 md_algo = EVP_sha1();
123 case HashAlgorithm::SHA256:
124 md_algo = EVP_sha256();
126 case HashAlgorithm::SHA384:
127 md_algo = EVP_sha384();
129 case HashAlgorithm::SHA512:
130 md_algo = EVP_sha512();
133 ThrowErr(Exc::Crypto::InternalError, "Error in hashAlgorithm value");
138 int getRsaPadding(const RSAPaddingAlgorithm padAlgo) {
139 int rsa_padding = -1;
141 case RSAPaddingAlgorithm::NONE:
142 rsa_padding = RSA_NO_PADDING;
144 case RSAPaddingAlgorithm::PKCS1:
145 rsa_padding = RSA_PKCS1_PADDING;
147 case RSAPaddingAlgorithm::X931:
148 rsa_padding = RSA_X931_PADDING;
151 ThrowErr(Exc::Crypto::InternalError, "Error in RSAPaddingAlgorithm value");
156 TokenPair createKeyPairRSA(CryptoBackend backendId, const int size)
160 // check the parameters of functions
161 if(size!=1024 && size!=2048 && size!=4096) {
162 ThrowErr(Exc::Crypto::InputParam, "Error in RSA input size");
165 EvpPkeyCtxUPtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL), EVP_PKEY_CTX_free);
167 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function !!");
170 if(EVP_PKEY_keygen_init(ctx.get()) <= 0) {
171 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function !!");
174 if(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), size) <= 0) {
175 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_keygen_bits function !!");
178 EVP_PKEY *pkeyTmp = NULL;
179 if(!EVP_PKEY_keygen(ctx.get(), &pkeyTmp)) {
180 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
182 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
184 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_RSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
185 Token(backendId, DataType(KeyType::KEY_RSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
189 TokenPair createKeyPairDSA(CryptoBackend backendId, const int size)
194 // check the parameters of functions
195 if(size!=1024 && size!=2048 && size!=3072 && size!=4096) {
196 ThrowErr(Exc::Crypto::InputParam, "Error in DSA input size");
199 /* Create the context for generating the parameters */
200 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL), EVP_PKEY_CTX_free);
202 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
205 if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
206 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
209 if(EVP_SUCCESS != EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx.get(), size)) {
210 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_dsa_paramgen_bits(", size, ") function");
213 /* Generate parameters */
214 EVP_PKEY *pparamTmp = NULL;
215 if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
216 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
218 pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
220 // Start to generate key
221 EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
223 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
226 if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
227 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
230 /* Generate the key */
231 EVP_PKEY *pkeyTmp = NULL;
232 if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
233 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
235 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
237 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_DSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
238 Token(backendId, DataType(KeyType::KEY_DSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
241 TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type)
243 int ecCurve = NOT_DEFINED;
248 case ElipticCurve::prime192v1:
249 ecCurve = NID_X9_62_prime192v1;
251 case ElipticCurve::prime256v1:
252 ecCurve = NID_X9_62_prime256v1;
254 case ElipticCurve::secp384r1:
255 ecCurve = NID_secp384r1;
258 ThrowErr(Exc::Crypto::InputParam, "Error in EC type");
261 /* Create the context for generating the parameters */
262 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free);
264 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new_id function");
267 if(EVP_SUCCESS != EVP_PKEY_paramgen_init(pctx.get())) {
268 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen_init function");
271 if(EVP_SUCCESS != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx.get(), ecCurve)) {
272 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_ec_paramgen_curve_nid function");
275 /* Generate parameters */
276 EVP_PKEY *pparamTmp = NULL;
277 if(EVP_SUCCESS != EVP_PKEY_paramgen(pctx.get(), &pparamTmp)) {
278 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_paramgen function");
280 pparam = EvpPkeyUPtr(pparamTmp, EVP_PKEY_free);
282 // Start to generate key
283 EvpPkeyCtxUPtr kctx(EVP_PKEY_CTX_new(pparam.get(), NULL), EVP_PKEY_CTX_free);
285 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
288 if(EVP_SUCCESS != EVP_PKEY_keygen_init(kctx.get())) {
289 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen_init function");
292 /* Generate the key */
293 EVP_PKEY *pkeyTmp = NULL;
294 if(!EVP_PKEY_keygen(kctx.get(), &pkeyTmp)) {
295 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function !!");
297 pkey = EvpPkeyUPtr(pkeyTmp, EVP_PKEY_free);
299 return std::make_pair<Token, Token>(Token(backendId, DataType(KeyType::KEY_ECDSA_PRIVATE), i2d(i2d_PrivateKey_bio, pkey.get())),
300 Token(backendId, DataType(KeyType::KEY_ECDSA_PUBLIC), i2d(i2d_PUBKEY_bio, pkey.get())));
303 Token createKeyAES(CryptoBackend backendId, const int sizeBits)
305 // check the parameters of functions
306 if(sizeBits!=128 && sizeBits!=192 && sizeBits!=256) {
307 LogError("Error in AES input size");
308 ThrowMsg(Exc::Crypto::InputParam, "Error in AES input size");
312 int sizeBytes = sizeBits/8;
313 if (!RAND_bytes(key, sizeBytes)) {
314 LogError("Error in AES key generation");
315 ThrowMsg(Exc::Crypto::InternalError, "Error in AES key generation");
318 return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes));
321 RawBuffer sign(EVP_PKEY *pkey,
322 const CryptoAlgorithm &alg,
323 const RawBuffer &message)
325 int rsa_padding = NOT_DEFINED;
326 const EVP_MD *md_algo = NULL;
328 HashAlgorithm hashTmp = HashAlgorithm::NONE;
329 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
330 md_algo = getMdAlgo(hashTmp);
332 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
333 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
334 rsa_padding = getRsaPadding(rsaPad);
337 // if((privateKey.getType() != KeyType::KEY_RSA_PRIVATE) &&
338 // (privateKey.getType() != KeyType::KEY_DSA_PRIVATE) &&
339 // (privateKey.getType() != KeyType::KEY_ECDSA_PRIVATE))
341 // LogError("Error in private key type");
342 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
345 // if(privateKey.getType()==KeyType::KEY_RSA_PRIVATE) {
346 // rsa_padding = getRsaPadding(padAlgo);
350 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_keygen function");
353 if(md_algo == NULL) {
354 return signMessage(pkey, message, rsa_padding);
357 return digestSignMessage(pkey,message, md_algo, rsa_padding);
360 RawBuffer signMessage(EVP_PKEY *privKey,
361 const RawBuffer &message,
362 const int rsa_padding)
364 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(privKey, NULL), EVP_PKEY_CTX_free);
367 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
370 if(EVP_PKEY_sign_init(pctx.get()) != EVP_SUCCESS) {
371 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign_init function");
374 /* Set padding algorithm */
375 if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
376 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
377 ThrowErr(Exc::Crypto::InternalError,
378 "Error in EVP_PKEY_CTX_set_rsa_padding function");
382 /* Finalize the Sign operation */
383 /* First call EVP_PKEY_sign with a NULL sig parameter to obtain the length of the
384 * signature. Length is returned in slen */
386 if(EVP_SUCCESS != EVP_PKEY_sign(pctx.get(), NULL, &slen, message.data(), message.size())) {
387 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_sign function");
390 /* Allocate memory for the signature based on size in slen */
393 if(EVP_SUCCESS == EVP_PKEY_sign(pctx.get(),
399 // Set value to return RawData
404 ThrowErr(Exc::Crypto::InputParam, "Error in EVP_PKEY_sign function. Input param error.");
407 RawBuffer digestSignMessage(EVP_PKEY *privKey,
408 const RawBuffer &message,
409 const EVP_MD *md_algo,
410 const int rsa_padding)
412 EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
414 EVP_PKEY_CTX *pctx = NULL;
416 // Create the Message Digest Context
418 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
421 if(EVP_SUCCESS != EVP_DigestSignInit(mdctx.get(), &pctx, md_algo, NULL, privKey)) {
422 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignInit function");
425 /* Set padding algorithm */
426 if(EVP_PKEY_type(privKey->type) == EVP_PKEY_RSA) {
427 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
428 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
432 /* Call update with the message */
433 if(EVP_SUCCESS != EVP_DigestSignUpdate(mdctx.get(), message.data(), message.size())) {
434 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignUpdate function");
437 /* Finalize the DigestSign operation */
438 /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
439 * signature. Length is returned in slen */
441 if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), NULL, &slen)) {
442 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
445 /* Allocate memory for the signature based on size in slen */
448 /* Obtain the signature */
449 if(EVP_SUCCESS != EVP_DigestSignFinal(mdctx.get(), sig.data(), &slen)) {
450 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestSignFinal function");
453 // Set value to return RawData
458 int verify(EVP_PKEY *pkey,
459 const CryptoAlgorithm &alg,
460 const RawBuffer &message,
461 const RawBuffer &signature)
463 int rsa_padding = NOT_DEFINED;
464 const EVP_MD *md_algo = NULL;
466 HashAlgorithm hashTmp = HashAlgorithm::NONE;
467 alg.getParam(ParamName::SV_HASH_ALGO, hashTmp);
468 md_algo = getMdAlgo(hashTmp);
470 RSAPaddingAlgorithm rsaPad = RSAPaddingAlgorithm::NONE;
471 alg.getParam(ParamName::SV_RSA_PADDING, rsaPad);
472 rsa_padding = getRsaPadding(rsaPad);
475 // if((publicKey.getType() != KeyType::KEY_RSA_PUBLIC) &&
476 // (publicKey.getType() != KeyType::KEY_DSA_PUBLIC) &&
477 // (publicKey.getType() != KeyType::KEY_ECDSA_PUBLIC))
479 // LogError("Error in private key type");
480 // ThrowErr(CryptoService::Exception::Crypto_internal, "Error in private key type");
483 // if(publicKey.getType()==KeyType::KEY_RSA_PUBLIC) {
484 // rsa_padding = getRsaPadding(padAlgo);
487 // auto shrPKey = publicKey.getEvpShPtr();
489 ThrowErr(Exc::Crypto::InternalError, "Error in getEvpShPtr function");
492 if (md_algo == NULL) {
493 return verifyMessage(pkey, message, signature, rsa_padding);
496 return digestVerifyMessage(pkey, message, signature, md_algo, rsa_padding);
499 int verifyMessage(EVP_PKEY *pubKey,
500 const RawBuffer &message,
501 const RawBuffer &signature,
502 const int rsa_padding)
504 EvpPkeyCtxUPtr pctx(EVP_PKEY_CTX_new(pubKey, NULL), EVP_PKEY_CTX_free);
507 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_new function");
510 if(EVP_PKEY_verify_init(pctx.get()) != EVP_SUCCESS) {
511 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_verify_init function");
514 /* Set padding algorithm */
515 if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
516 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx.get(), rsa_padding)) {
517 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
521 if(EVP_SUCCESS == EVP_PKEY_verify(pctx.get(), signature.data(), signature.size(), message.data(), message.size())) {
522 return CKM_API_SUCCESS;
525 LogError("EVP_PKEY_verify Failed");
526 return CKM_API_ERROR_VERIFICATION_FAILED;
529 int digestVerifyMessage(EVP_PKEY *pubKey,
530 const RawBuffer &message,
531 const RawBuffer &signature,
532 const EVP_MD *md_algo,
533 const int rsa_padding)
535 EvpMdCtxUPtr mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy);
536 EVP_PKEY_CTX *pctx = NULL;
538 /* Create the Message Digest Context */
540 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_MD_CTX_create function");
543 if(EVP_SUCCESS != EVP_DigestVerifyInit(mdctx.get(), &pctx, md_algo, NULL, pubKey)) {
544 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyInit function");
547 if(EVP_PKEY_type(pubKey->type) == EVP_PKEY_RSA) {
548 if(EVP_SUCCESS != EVP_PKEY_CTX_set_rsa_padding(pctx, rsa_padding)) {
549 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_PKEY_CTX_set_rsa_padding function");
553 if(EVP_SUCCESS != EVP_DigestVerifyUpdate(mdctx.get(), message.data(), message.size()) ) {
554 ThrowErr(Exc::Crypto::InternalError, "Error in EVP_DigestVerifyUpdate function");
557 if(EVP_SUCCESS == EVP_DigestVerifyFinal(mdctx.get(), const_cast<unsigned char*>(signature.data()), signature.size()) ) {
558 return CKM_API_SUCCESS;
561 LogError("EVP_PKEY_verify Failed");
562 return CKM_API_ERROR_VERIFICATION_FAILED;
565 } // namespace Internals
567 } // namespace Crypto