merge master code to build iotivity
[platform/upstream/iotivity.git] / resource / csdk / security / src / pbkdf2.c
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  * *****************************************************************/
20 #include <string.h>
21 #include <math.h>
22 #include "pbkdf2.h"
23 #include "hmac.h"
24 #include "debug.h"
25 #include "logger.h"
26
27 #define TAG "PBDKF2"
28 #define XOR_BUF(in, out, bufSize)\
29 do{\
30     size_t i=0;\
31     for(i=0; i< (bufSize); i++)\
32     {\
33         (out)[i] = (in)[i] ^ (out)[i];\
34     }\
35 }while(0)\
36
37
38 static int isLittle()
39 {
40     static int a = 1;
41     static int flag = -1;
42     if (flag == -1)
43     {
44         if (  ((uint8_t *)&a)[0]  == 0x1) // little
45             flag = 1;
46         else
47             flag = 0;
48     }
49     return flag;
50 }
51
52 static void GetBigEndianBuf(uint8_t *buf, int num)
53 {
54     uint8_t *nBuf = (uint8_t *)&num;
55     if ( isLittle() == 1 )
56     {
57         size_t i = 0;
58         for (i = 0; i < sizeof(int); i++)
59         {
60             buf[i] = nBuf[ sizeof(int) - i - 1];
61         }
62     }
63     else
64     {
65         memcpy(buf, nBuf, sizeof(int));
66     }
67 }
68
69 // TODO: Add comments to explain implementation.
70 int DeriveCryptoKeyFromPassword(const unsigned char *passwd, size_t pLen,
71                                 const uint8_t *salt, const size_t saltLen,
72                                 const size_t iterations,
73                                 const size_t keyLen, uint8_t *derivedKey)
74 {
75     int res = 0;
76     uint8_t buf[DTLS_HMAC_DIGEST_SIZE];
77     uint8_t uBuf[DTLS_HMAC_DIGEST_SIZE];
78
79     size_t nBlocks = 0;
80     size_t nOctetInLastBlock = 0;
81
82     nBlocks = (size_t)ceil ((double)keyLen / (double)DTLS_HMAC_DIGEST_SIZE);
83     nOctetInLastBlock = keyLen - (nBlocks - 1) * DTLS_HMAC_DIGEST_SIZE;
84
85     dtls_hmac_context_t *ctx = NULL;
86     ctx = dtls_hmac_new( (const unsigned char *)passwd, pLen);
87     if (NULL == ctx)
88     {
89         OC_LOG(ERROR, TAG, "DTLS HMAC Context is NULL");
90         goto bail;
91     }
92
93     size_t i = 1;
94     size_t idx = 0; //index for buffer
95     size_t counter = 0;
96     while (i != nBlocks + 1)
97     {
98         counter = 0 ;
99         dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
100         while (counter != iterations)
101         {
102             if (counter == 0)
103             {
104                 uint8_t intBuf[4] = {0x00, 0x00, 0x00, 0x00};
105                 dtls_hmac_update(ctx, salt, saltLen);
106                 GetBigEndianBuf(intBuf, i);
107                 dtls_hmac_update(ctx, intBuf, 4);
108
109                 int len = dtls_hmac_finalize(ctx, buf);
110                 if (DTLS_HMAC_DIGEST_SIZE != len)
111                 {
112                     OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
113                     res = -1;
114                 }
115                 memcpy(uBuf, buf, DTLS_HMAC_DIGEST_SIZE);
116             }
117             else
118             {
119                 dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
120                 dtls_hmac_update(ctx, buf, DTLS_HMAC_DIGEST_SIZE);
121                 int len = dtls_hmac_finalize(ctx, buf);
122                 if (DTLS_HMAC_DIGEST_SIZE != len)
123                 {
124                     OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
125                     res = -1;
126                 }
127                 XOR_BUF(buf, uBuf, DTLS_HMAC_DIGEST_SIZE);
128             }
129             counter++;
130         }
131
132
133         if (i == nBlocks)
134         {
135             memcpy(derivedKey + idx, uBuf, nOctetInLastBlock);
136         }
137         else
138         {
139             memcpy(derivedKey + idx, uBuf, DTLS_HMAC_DIGEST_SIZE);
140             idx += DTLS_HMAC_DIGEST_SIZE;
141         }
142         i++;
143     }
144
145 bail:
146     dtls_hmac_free(ctx);
147     return res;
148 }
149