2 // Copyright (c) 2013 Samsung Electronics Co., Ltd.
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.
18 * @file FSecRsaKeyConverter.cpp
19 * @brief This is the implementation file for RsaKeyConverter class.
22 #include <unique_ptr.h>
23 #include <openssl/bn.h>
24 #include <openssl/evp.h>
25 #include <openssl/dh.h>
26 #include <openssl/rsa.h>
27 #include <openssl/x509.h>
28 #include <openssl/pem.h>
29 #include <FBaseResult.h>
30 #include <FBaseErrors.h>
31 #include <FSecIPublicKey.h>
32 #include <FSecIPrivateKey.h>
33 #include <FSecPrivateKey.h>
34 #include <FSecPublicKey.h>
35 #include <FBaseSysLog.h>
36 #include <FSecRsaKeyConverter.h>
38 using namespace Tizen::Base;
39 using namespace Tizen::Security;
42 namespace Tizen { namespace Security
45 RsaKeyConverter::RsaKeyConverter(void)
50 RsaKeyConverter::~RsaKeyConverter(void)
55 RsaKeyConverter::ConvertPrivateKeyFormatN(RsaKeyFormat format, const IPrivateKey& key)
59 const byte* pKey = null;
60 std::unique_ptr< ByteBuffer > pOutBuffer;
62 EVP_PKEY* pEvpKey = null;
65 bool isPemFormat = false;
67 SysTryReturn(NID_SEC, format != RSA_KEY_FORMAT_UNKNOWN, null, E_INVALID_ARG, " [E_INVALID_ARG] The specified input parameter is invalid.");
69 std::unique_ptr< ByteBuffer > pPrivateKey(key.GetEncodedN());
70 SysTryReturn(NID_SEC, pPrivateKey != null, null, r, "[%s] Failed to get the public key", GetErrorMessage(r));
72 pKey = pPrivateKey->GetPointer();
73 SysTryReturn(NID_SEC, pKey != null, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
75 keyLen = pPrivateKey->GetRemaining();
76 SysTryReturn(NID_SEC, keyLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
78 pEvpKey = d2i_PrivateKey(EVP_PKEY_RSA, null, &pKey, keyLen);
82 PKCS8_PRIV_KEY_INFO* pPrivKeyInfo = d2i_PKCS8_PRIV_KEY_INFO(null, &pKey, keyLen);
83 if (pPrivKeyInfo != null)
85 pEvpKey = EVP_PKCS82PKEY(pPrivKeyInfo);
86 PKCS8_PRIV_KEY_INFO_free(pPrivKeyInfo);
92 pBio = BIO_new(BIO_s_mem());
93 SysTryReturn(NID_SEC, pBio != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
95 int readCount = BIO_write(pBio, (const void*) pKey, keyLen);
96 SysTryCatch(NID_SEC, readCount > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
98 pEvpKey = PEM_read_bio_PrivateKey(pBio, null, 0, null);
105 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
109 case RSA_KEY_FORMAT_PKCS01_PRIVATE_KEY:
111 ret = i2d_PrivateKey(pEvpKey, &pBuffer);
112 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
116 case RSA_KEY_FORMAT_PKCS08_PRIVATE_KEY:
118 PKCS8_PRIV_KEY_INFO* pPrivKeyInfo = EVP_PKEY2PKCS8(pEvpKey);
119 SysTryCatch(NID_SEC, pPrivKeyInfo != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
121 ret = i2d_PKCS8_PRIV_KEY_INFO(pPrivKeyInfo, &pBuffer);
122 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
127 SysTryCatch(NID_SEC, false, r = E_INVALID_ARG, E_INVALID_ARG, " [E_INVALID_ARG] The specified input parameter is invalid.");
131 pOutBuffer = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
132 SysTryCatch(NID_SEC, pOutBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
134 r = pOutBuffer->Construct(ret);
135 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
137 r = pOutBuffer->SetArray(pBuffer, 0, ret);
138 SysTryCatch(NID_SEC, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
141 if (isPemFormat == true)
144 r = key.SetKey(*pOutBuffer.get());
145 SysTryCatch(NID_SEC, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
146 pOutBuffer = std::unique_ptr< ByteBuffer >(ConvertDerToPemN(format, key));
147 SysTryCatch(NID_SEC, pOutBuffer != null, r = GetLastResult(), GetLastResult(), "[%s] Failed to convert der to pem encoded byte buffer");
150 OPENSSL_free(pBuffer);
157 EVP_PKEY_free(pEvpKey);
165 return pOutBuffer.release();
169 RsaKeyConverter::ConvertPublicKeyFormatN(RsaKeyFormat format, const IPublicKey& key)
171 result r = E_SUCCESS;
172 byte* pBuffer = null;
173 const byte* pKey = null;
174 std::unique_ptr< ByteBuffer > pOutBuffer;
176 EVP_PKEY* pEvpKey = null;
179 bool isPemFormat = false;
181 SysTryReturn(NID_SEC, format != RSA_KEY_FORMAT_UNKNOWN, null, E_INVALID_ARG, " [E_INVALID_ARG] The specified input parameter is invalid.");
183 std::unique_ptr< ByteBuffer > pPublicKey(key.GetEncodedN());
184 SysTryReturn(NID_SEC, pPublicKey, null, r, "[%s] Failed to get the public key", GetErrorMessage(r));
186 pKey = pPublicKey->GetPointer();
187 SysTryReturn(NID_SEC, pKey != null, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
189 keyLen = pPublicKey->GetRemaining();
190 SysTryReturn(NID_SEC, keyLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
192 pEvpKey = d2i_PUBKEY(null, &pKey, keyLen);
196 pEvpKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pKey, keyLen);
201 pBio = BIO_new(BIO_s_mem());
202 SysTryReturn(NID_SEC, pBio != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
204 int readCount = BIO_write(pBio, (const void*) pKey, keyLen);
207 pEvpKey = PEM_read_bio_PUBKEY(pBio, null, 0, null);
215 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
218 case RSA_KEY_FORMAT_PKCS01_PUBLIC_KEY:
220 ret = i2d_PublicKey(pEvpKey, &pBuffer);
221 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
225 case RSA_KEY_FORMAT_X509_PUBLIC_KEY:
227 ret = i2d_PUBKEY(pEvpKey, &pBuffer);
228 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
233 SysTryCatch(NID_SEC, false, r = E_INVALID_ARG, E_INVALID_ARG, " [E_INVALID_ARG] The specified input parameter is invalid.");
237 pOutBuffer = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
238 SysTryCatch(NID_SEC, pOutBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
240 r = pOutBuffer->Construct(ret);
241 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
243 r = pOutBuffer->SetArray(pBuffer, 0, ret);
244 SysTryCatch(NID_SEC, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
248 if (isPemFormat == true)
251 r = key.SetKey(*pOutBuffer);
252 SysTryCatch(NID_SEC, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
253 pOutBuffer.reset(ConvertDerToPemN(format, key));
254 //pOutBuffer = std::unique_ptr< ByteBuffer >(ConvertDerToPemN(format, key));
255 SysTryCatch(NID_SEC, pOutBuffer != null, r = GetLastResult(), GetLastResult(), "[%s] Failed to convert der to pem encoded byte buffer");
258 OPENSSL_free(pBuffer);
265 EVP_PKEY_free(pEvpKey);
275 pOutBuffer.reset(null);
278 return pOutBuffer.release();
283 RsaKeyConverter::ConvertDerToPemN(RsaKeyFormat format, const IKey& key)
285 result r = E_SUCCESS;
286 const byte* pKey = null;
288 EVP_PKEY* pEvpKey = null;
289 std::unique_ptr< byte[] > pData;
290 std::unique_ptr< ByteBuffer > pOutBuffer;
291 std::unique_ptr< ByteBuffer > pEncodedInputBuffer;
296 pEncodedInputBuffer = std::unique_ptr< ByteBuffer >(key.GetEncodedN());
297 SysTryReturn(NID_SEC, pEncodedInputBuffer != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
299 pKey = pEncodedInputBuffer->GetPointer();
300 SysTryReturn(NID_SEC, pKey != null, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
302 keyLen = pEncodedInputBuffer->GetRemaining();
303 SysTryReturn(NID_SEC, keyLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
307 case RSA_KEY_FORMAT_PKCS01_PRIVATE_KEY:
309 pEvpKey = d2i_PrivateKey(EVP_PKEY_RSA, null, &pKey, keyLen);
310 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
312 pBio = BIO_new(BIO_s_mem());
313 SysTryCatch(NID_SEC, pBio != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
315 ret = PEM_write_bio_PrivateKey(pBio, pEvpKey, null, null, 0, null, null);
316 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
321 case RSA_KEY_FORMAT_PKCS01_PUBLIC_KEY:
323 pEvpKey = d2i_PublicKey(EVP_PKEY_RSA, null, &pKey, keyLen);
324 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
326 pBio = BIO_new(BIO_s_mem());
327 SysTryCatch(NID_SEC, pBio != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
329 ret = PEM_write_bio_PUBKEY(pBio, pEvpKey);
330 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
335 case RSA_KEY_FORMAT_X509_PUBLIC_KEY:
337 pEvpKey = d2i_PUBKEY(null, &pKey, keyLen);
338 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
340 pBio = BIO_new(BIO_s_mem());
341 SysTryCatch(NID_SEC, pBio != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
343 ret = PEM_write_bio_PUBKEY(pBio, pEvpKey);
344 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
348 case RSA_KEY_FORMAT_PKCS08_PRIVATE_KEY:
350 PKCS8_PRIV_KEY_INFO* pPrivKeyInfo = d2i_PKCS8_PRIV_KEY_INFO(null, &pKey, keyLen);
351 if (pPrivKeyInfo != null)
353 pEvpKey = EVP_PKCS82PKEY(pPrivKeyInfo);
354 PKCS8_PRIV_KEY_INFO_free(pPrivKeyInfo);
356 pBio = BIO_new(BIO_s_mem());
357 SysTryCatch(NID_SEC, pBio != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
359 ret = PEM_write_bio_PrivateKey(pBio, pEvpKey, null, null, 0, null, null);
360 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
367 SysTryCatch(NID_SEC, false, r = E_INVALID_ARG, E_INVALID_ARG, " [E_INVALID_ARG] The specified input parameter is invalid.");
370 dataLen = BIO_get_mem_data(pBio, null);
371 SysTryCatch(NID_SEC, dataLen > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
373 pData = std::unique_ptr< byte[] >(new (std::nothrow) byte[dataLen]);
374 SysTryCatch(NID_SEC, pData != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
376 ret = BIO_read(pBio, pData.get(), dataLen);
377 SysTryCatch(NID_SEC, ret > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
379 pOutBuffer = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
380 SysTryCatch(NID_SEC, pOutBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
382 r = pOutBuffer->Construct(ret);
383 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
385 r = pOutBuffer->SetArray(pData.get(), 0, ret);
386 SysTryCatch(NID_SEC, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
394 EVP_PKEY_free(pEvpKey);
402 return pOutBuffer.release();
406 RsaKeyConverter::ConvertPemToDerN(RsaKeyFormat format, const IKey& key)
408 result r = E_SUCCESS;
411 const byte* pKey = null;
412 byte* pBuffer = null;
414 EVP_PKEY* pEvpKey = null;
415 std::unique_ptr< ByteBuffer > pOutBuffer;
416 std::unique_ptr< ByteBuffer > pEncodedInputBuffer;
418 pEncodedInputBuffer = std::unique_ptr< ByteBuffer >(key.GetEncodedN());
419 SysTryReturn(NID_SEC, pEncodedInputBuffer != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
421 pKey = pEncodedInputBuffer->GetPointer();
422 SysTryReturn(NID_SEC, pKey != null, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
424 keyLen = pEncodedInputBuffer->GetRemaining();
425 SysTryReturn(NID_SEC, keyLen > 0, null, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
427 pBio = BIO_new(BIO_s_mem());
428 SysTryReturn(NID_SEC, pBio != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
430 int readCount = BIO_write(pBio, (const void*) pKey, keyLen);
431 SysTryCatch(NID_SEC, readCount > 0, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
435 case RSA_KEY_FORMAT_PKCS01_PRIVATE_KEY:
437 pEvpKey = PEM_read_bio_PrivateKey(pBio, null, 0, null);
438 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
440 ret = i2d_PrivateKey(pEvpKey, &pBuffer);
441 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
445 case RSA_KEY_FORMAT_PKCS01_PUBLIC_KEY:
447 pEvpKey = PEM_read_bio_PUBKEY(pBio, null, 0, null);
448 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
450 ret = i2d_PublicKey(pEvpKey, &pBuffer);
451 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
455 case RSA_KEY_FORMAT_X509_PUBLIC_KEY:
457 pEvpKey = PEM_read_bio_PUBKEY(pBio, null, 0, null);
458 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
460 ret = i2d_PUBKEY(pEvpKey, &pBuffer);
461 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
465 case RSA_KEY_FORMAT_PKCS08_PRIVATE_KEY:
467 pEvpKey = PEM_read_bio_PrivateKey(pBio, null, 0, null);
468 SysTryCatch(NID_SEC, pEvpKey != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
470 PKCS8_PRIV_KEY_INFO* pPrivKeyInfo = EVP_PKEY2PKCS8(pEvpKey);
471 SysTryCatch(NID_SEC, pPrivKeyInfo != null, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
473 ret = i2d_PKCS8_PRIV_KEY_INFO(pPrivKeyInfo, &pBuffer);
474 SysTryCatch(NID_SEC, ret != -1, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
479 SysTryCatch(NID_SEC, false, r = E_INVALID_ARG, E_INVALID_ARG, " [E_INVALID_ARG] The specified input parameter is invalid.");
483 pOutBuffer = std::unique_ptr< ByteBuffer >(new (std::nothrow) ByteBuffer());
484 SysTryCatch(NID_SEC, pOutBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
486 r = pOutBuffer->Construct(ret);
487 SysTryCatch(NID_SEC, !IsFailed(r), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
489 r = pOutBuffer->SetArray(pBuffer, 0, ret);
490 SysTryCatch(NID_SEC, !IsFailed(r), r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The specified input parameter is invalid.");
494 OPENSSL_free(pBuffer);
501 EVP_PKEY_free(pEvpKey);
509 return pOutBuffer.release();
513 } } //Tizen::Security