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