4b9f943bb20b4fa938e4f7d2764f392f7eb7938f
[platform/upstream/cryptsetup.git] / lib / crypto_backend / crypto_nss.c
1 /*
2  * NSS crypto backend implementation
3  *
4  * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2010-2014, Milan Broz
6  *
7  * This file is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this file; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <string.h>
23 #include <errno.h>
24 #include <nss.h>
25 #include <pk11pub.h>
26 #include "crypto_backend.h"
27
28 #define CONST_CAST(x) (x)(uintptr_t)
29
30 static int crypto_backend_initialised = 0;
31 static char version[64];
32
33 struct hash_alg {
34         const char *name;
35         SECOidTag oid;
36         CK_MECHANISM_TYPE ck_type;
37         int length;
38         unsigned int block_length;
39 };
40
41 static struct hash_alg hash_algs[] = {
42         { "sha1",   SEC_OID_SHA1,   CKM_SHA_1_HMAC,  20,  64 },
43         { "sha256", SEC_OID_SHA256, CKM_SHA256_HMAC, 32,  64 },
44         { "sha384", SEC_OID_SHA384, CKM_SHA384_HMAC, 48, 128 },
45         { "sha512", SEC_OID_SHA512, CKM_SHA512_HMAC, 64, 128 },
46 //      { "ripemd160", SEC_OID_RIPEMD160, CKM_RIPEMD160_HMAC, 20, 64 },
47         { NULL, 0, 0, 0 }
48 };
49
50 struct crypt_hash {
51         PK11Context *md;
52         const struct hash_alg *hash;
53 };
54
55 struct crypt_hmac {
56         PK11Context *md;
57         PK11SymKey *key;
58         PK11SlotInfo *slot;
59         const struct hash_alg *hash;
60 };
61
62 static struct hash_alg *_get_alg(const char *name)
63 {
64         int i = 0;
65
66         while (name && hash_algs[i].name) {
67                 if (!strcmp(name, hash_algs[i].name))
68                         return &hash_algs[i];
69                 i++;
70         }
71         return NULL;
72 }
73
74 int crypt_backend_init(struct crypt_device *ctx)
75 {
76         if (crypto_backend_initialised)
77                 return 0;
78
79         if (NSS_NoDB_Init(".") != SECSuccess)
80                 return -EINVAL;
81
82 #if HAVE_DECL_NSS_GETVERSION
83         snprintf(version, 64, "NSS %s", NSS_GetVersion());
84 #else
85         snprintf(version, 64, "NSS");
86 #endif
87         crypto_backend_initialised = 1;
88         return 0;
89 }
90
91 uint32_t crypt_backend_flags(void)
92 {
93         return 0;
94 }
95
96 const char *crypt_backend_version(void)
97 {
98         return crypto_backend_initialised ? version : "";
99 }
100
101 /* HASH */
102 int crypt_hash_size(const char *name)
103 {
104         struct hash_alg *ha = _get_alg(name);
105
106         return ha ? ha->length : -EINVAL;
107 }
108
109 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
110 {
111         struct crypt_hash *h;
112
113         h = malloc(sizeof(*h));
114         if (!h)
115                 return -ENOMEM;
116
117         h->hash = _get_alg(name);
118         if (!h->hash) {
119                 free(h);
120                 return -EINVAL;
121         }
122
123         h->md = PK11_CreateDigestContext(h->hash->oid);
124         if (!h->md) {
125                 free(h);
126                 return -EINVAL;
127         }
128
129         if (PK11_DigestBegin(h->md) != SECSuccess) {
130                 PK11_DestroyContext(h->md, PR_TRUE);
131                 free(h);
132                 return -EINVAL;
133         }
134
135         *ctx = h;
136         return 0;
137 }
138
139 static int crypt_hash_restart(struct crypt_hash *ctx)
140 {
141         if (PK11_DigestBegin(ctx->md) != SECSuccess)
142                 return -EINVAL;
143
144         return 0;
145 }
146
147 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
148 {
149         if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
150                 return -EINVAL;
151
152         return 0;
153 }
154
155 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
156 {
157         unsigned char tmp[64];
158         unsigned int tmp_len;
159
160         if (length > (size_t)ctx->hash->length)
161                 return -EINVAL;
162
163         if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
164                 return -EINVAL;
165
166         memcpy(buffer, tmp, length);
167         crypt_backend_memzero(tmp, sizeof(tmp));
168
169         if (tmp_len < length)
170                 return -EINVAL;
171
172         if (crypt_hash_restart(ctx))
173                 return -EINVAL;
174
175         return 0;
176 }
177
178 int crypt_hash_destroy(struct crypt_hash *ctx)
179 {
180         PK11_DestroyContext(ctx->md, PR_TRUE);
181         memset(ctx, 0, sizeof(*ctx));
182         free(ctx);
183         return 0;
184 }
185
186 /* HMAC */
187 int crypt_hmac_size(const char *name)
188 {
189         return crypt_hash_size(name);
190 }
191
192 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
193                     const void *buffer, size_t length)
194 {
195         struct crypt_hmac *h;
196         SECItem keyItem;
197         SECItem noParams;
198
199         keyItem.type = siBuffer;
200         keyItem.data = CONST_CAST(unsigned char *)buffer;
201         keyItem.len = (int)length;
202
203         noParams.type = siBuffer;
204         noParams.data = 0;
205         noParams.len = 0;
206
207         h = malloc(sizeof(*h));
208         if (!h)
209                 return -ENOMEM;
210         memset(ctx, 0, sizeof(*ctx));
211
212
213         h->hash = _get_alg(name);
214         if (!h->hash)
215                 goto bad;
216
217         h->slot = PK11_GetInternalKeySlot();
218         if (!h->slot)
219                 goto bad;
220
221         h->key = PK11_ImportSymKey(h->slot, h->hash->ck_type, PK11_OriginUnwrap,
222                                    CKA_SIGN,  &keyItem, NULL);
223         if (!h->key)
224                 goto bad;
225
226         h->md = PK11_CreateContextBySymKey(h->hash->ck_type, CKA_SIGN, h->key,
227                                            &noParams);
228         if (!h->md)
229                 goto bad;
230
231         if (PK11_DigestBegin(h->md) != SECSuccess)
232                 goto bad;
233
234         *ctx = h;
235         return 0;
236 bad:
237         crypt_hmac_destroy(h);
238         return -EINVAL;
239 }
240
241 static int crypt_hmac_restart(struct crypt_hmac *ctx)
242 {
243         if (PK11_DigestBegin(ctx->md) != SECSuccess)
244                 return -EINVAL;
245
246         return 0;
247 }
248
249 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
250 {
251         if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
252                 return -EINVAL;
253
254         return 0;
255 }
256
257 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
258 {
259         unsigned char tmp[64];
260         unsigned int tmp_len;
261
262         if (length > (size_t)ctx->hash->length)
263                 return -EINVAL;
264
265         if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
266                 return -EINVAL;
267
268         memcpy(buffer, tmp, length);
269         crypt_backend_memzero(tmp, sizeof(tmp));
270
271         if (tmp_len < length)
272                 return -EINVAL;
273
274         if (crypt_hmac_restart(ctx))
275                 return -EINVAL;
276
277         return 0;
278 }
279
280 int crypt_hmac_destroy(struct crypt_hmac *ctx)
281 {
282         if (ctx->key)
283                 PK11_FreeSymKey(ctx->key);
284         if (ctx->slot)
285                 PK11_FreeSlot(ctx->slot);
286         if (ctx->md)
287                 PK11_DestroyContext(ctx->md, PR_TRUE);
288         memset(ctx, 0, sizeof(*ctx));
289         free(ctx);
290         return 0;
291 }
292
293 /* RNG */
294 int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
295 {
296         if (fips)
297                 return -EINVAL;
298
299         if (PK11_GenerateRandom((unsigned char *)buffer, length) != SECSuccess)
300                 return -EINVAL;
301
302         return 0;
303 }
304
305 /* PBKDF */
306 int crypt_pbkdf(const char *kdf, const char *hash,
307                 const char *password, size_t password_length,
308                 const char *salt, size_t salt_length,
309                 char *key, size_t key_length,
310                 unsigned int iterations)
311 {
312         struct hash_alg *ha = _get_alg(hash);
313
314         if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6))
315                 return -EINVAL;
316
317         return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
318                             iterations, key_length, key, ha->block_length);
319 }