1 /******************************************************************
3 * Copyright 2017 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
28 #include "psinterface.h"
29 #include "oic_malloc.h"
30 #include "mbedtls/entropy.h"
31 #include "mbedtls/ctr_drbg.h"
32 #include "mbedtls/aes.h"
33 #include "mbedtls/md.h"
35 #define TAG "OIC_SEC_PSIUTIL"
37 /*Internal to this File only*/
43 #define VERIFY_NON_NULL(tag, arg, logLevel) do{ if (NULL == (arg)) \
44 { OIC_LOG((logLevel), tag, #arg " is NULL"); goto exit; } }while(0)
46 static unsigned char aesKey[AES_KEY_SIZE];
47 bool isKeySet = false;
49 OCStackResult psiSetKey(const unsigned char* key)
53 return OC_STACK_INVALID_PARAM;
55 memcpy(aesKey,key,AES_KEY_SIZE);
60 OCStackResult psiGetKey(unsigned char* key)
64 return OC_STACK_ERROR;
66 memcpy(key, aesKey, AES_KEY_SIZE);
75 static int GenerateIV(unsigned char *IV)
77 mbedtls_ctr_drbg_context ctr_drbg;
78 mbedtls_entropy_context entropy;
79 char *pers = "generate psi iv vector";
82 mbedtls_entropy_init( &entropy );
83 mbedtls_ctr_drbg_init(&ctr_drbg);
85 if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
86 (unsigned char *) pers, strlen(pers))) != 0 )
88 OIC_LOG(ERROR, TAG, "mbedtls_ctr_drbg_init() Failed!!");
92 if((ret = mbedtls_ctr_drbg_random(&ctr_drbg, IV, 16)) != 0 )
94 OIC_LOG(ERROR, TAG, "mbedtls_ctr_drbg_random Failed!!");
101 * User need to OICFree() *ciphertext after using it.
103 int psiEncrypt(const unsigned char *plaintext, size_t pt_len,
104 unsigned char **ciphertext, size_t *ct_len)
106 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
108 unsigned char IV[IV_LEN];
109 unsigned char digest[DIGEST_LEN] , key[AES_KEY_SIZE];
110 unsigned char *tempBuf = NULL;
111 size_t padLen = BLOCK_LEN - (pt_len % BLOCK_LEN);
113 int tempBufSize, mod;
115 if (!plaintext || !pt_len || !ciphertext || *ciphertext || !ct_len)
117 OIC_LOG_V(ERROR, TAG, "%s: %s is NULL",
118 __func__, !plaintext ? "plaintext" : !pt_len ? "pt_len"
119 : !ciphertext || *ciphertext ? "ciphertext" : "ct_len");
125 -----------------------------------------
126 | 16 Bytes | Plain/cipher |32 Bytes|
127 | IV | text + PadLen | (H)MAC |
128 -----------------------------------------
130 tempBufSize = (IV_LEN + pt_len + padLen + DIGEST_LEN);
131 tempBuf = (unsigned char*)OICCalloc(1, sizeof(unsigned char) * tempBufSize);
132 VERIFY_NON_NULL(TAG, tempBuf, ERROR);
134 if (OC_STACK_OK != psiGetKey(key))
136 OIC_LOG(ERROR, TAG, "Failed to get Key");
141 /* first IV_LEN bytes for Init. vector*/
142 memcpy(tempBuf + IV_LEN , plaintext, pt_len);
144 for (i = 0; i < padLen; ++i)
146 tempBuf[IV_LEN + pt_len + i] = padLen;
151 OIC_LOG(ERROR, TAG, "IV Generation Failed!!");
156 //last 4 bits of IV will store pt_len%BLOCK_LEN
157 //we will use these to recover padLen in decryption.
158 mod = (int)(pt_len & 0x0F);
159 IV[IV_LEN-1] = (unsigned char)((IV[IV_LEN -1] & 0xF0) | mod);
162 memcpy(tempBuf, IV, IV_LEN);
164 mbedtls_aes_context aes_ctx;
165 mbedtls_aes_init(&aes_ctx);
167 mbedtls_aes_setkey_enc(&aes_ctx, key, KEY_LEN);
169 /*plain data start at an offset of IV_LEN*/
170 mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, (pt_len + padLen),
171 IV, (tempBuf+IV_LEN), (tempBuf+IV_LEN));
173 mbedtls_md_context_t sha_ctx;
174 mbedtls_md_init(&sha_ctx);
176 if(0 != mbedtls_md_setup(&sha_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1))
178 OIC_LOG(ERROR, TAG, "mbedtls_md_setup() Failed!!");
183 /* setup the AES and HMAC context*/
184 memset(digest, 0, DIGEST_LEN);
186 mbedtls_md_hmac_starts(&sha_ctx, key, DIGEST_LEN);
187 ret = mbedtls_md_hmac_update(&sha_ctx, tempBuf + IV_LEN, (pt_len+padLen));
190 OIC_LOG(ERROR, TAG, "mbedtls_md_hmac_update() Failed");
191 mbedtls_md_free(&sha_ctx);
194 mbedtls_md_hmac_finish(&sha_ctx, digest);
195 mbedtls_md_free(&sha_ctx);
197 //copy last 32 bytes for MAC
198 memcpy((tempBuf + IV_LEN + pt_len + padLen), digest, DIGEST_LEN);
200 memset(key, 0, AES_KEY_SIZE); //destroy key
202 *ciphertext = tempBuf;
204 *ct_len = tempBufSize;
210 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
215 * plaintext will be free by App
217 int psiDecrypt(const unsigned char *ciphertext, size_t ct_len,
218 unsigned char **plaintext, size_t *pt_len)
220 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
223 unsigned char IV[IV_LEN], digest[DIGEST_LEN];
224 unsigned char key[AES_KEY_SIZE];
225 unsigned char *pt = NULL;
228 if (!ciphertext || !ct_len || !plaintext || *plaintext || !pt_len)
230 OIC_LOG_V(ERROR, TAG, "%s: %s is NULL",
231 __func__, !ciphertext ? "ciphertext" : !ct_len ? "ct_len"
232 : !plaintext || *plaintext ? "plaintext" : "pt_len");
238 if (OC_STACK_OK != psiGetKey(key))
240 OIC_LOG(ERROR, TAG, "Failed to get Key");
245 memcpy(IV, ciphertext, IV_LEN);
247 mod = IV[IV_LEN-1] & 0x0F;
249 //Length of original data was..
250 //Avoid writing Padding, IV & HMAC into the SVR DB File
251 len = ct_len - (BLOCK_LEN - mod) - (IV_LEN + DIGEST_LEN);
252 pt = (unsigned char*)OICCalloc(1, ct_len *sizeof(unsigned char));
253 VERIFY_NON_NULL(TAG, pt, ERROR);
256 mbedtls_aes_context aes_ctx;
257 mbedtls_aes_init(&aes_ctx);
259 mbedtls_aes_setkey_dec(&aes_ctx, key, KEY_LEN);
260 mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, ct_len - IV_LEN,
261 IV, (ciphertext+IV_LEN), pt);
264 mbedtls_md_context_t sha_ctx;
265 mbedtls_md_init(&sha_ctx);
267 if (0 != mbedtls_md_setup(&sha_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1))
269 OIC_LOG(ERROR, TAG, "mbedtls_md_setup() Failed!!");
274 memset(digest, 0, DIGEST_LEN);
275 mbedtls_md_hmac_starts(&sha_ctx, key, DIGEST_LEN);
276 ret = mbedtls_md_hmac_update(&sha_ctx, ciphertext + IV_LEN, (ct_len - DIGEST_LEN - IV_LEN));
279 OIC_LOG(ERROR, TAG, "mbedtls_md_hmac_update() Failed");
280 mbedtls_md_free(&sha_ctx);
283 mbedtls_md_hmac_finish(&sha_ctx, digest);
284 mbedtls_md_free(&sha_ctx);
285 memset(key, 0, AES_KEY_SIZE); //destroy key
288 for (int i = 0; i < DIGEST_LEN; i++)
290 diff |= digest[i] ^ ciphertext[ct_len - DIGEST_LEN + i];
294 OIC_LOG(ERROR, TAG, "HMAC check failed: wrong key, "
295 "or file corrupted.");
307 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);