Merge branch 'upstream' into tizen
[platform/upstream/cryptsetup.git] / lib / crypto_backend / crypto_nss.c
1 /*
2  * NSS crypto backend implementation
3  *
4  * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2010-2023 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_internal.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 struct crypt_cipher {
63         struct crypt_cipher_kernel ck;
64 };
65
66 static struct hash_alg *_get_alg(const char *name)
67 {
68         int i = 0;
69
70         while (name && hash_algs[i].name) {
71                 if (!strcmp(name, hash_algs[i].name))
72                         return &hash_algs[i];
73                 i++;
74         }
75         return NULL;
76 }
77
78 int crypt_backend_init(bool fips __attribute__((unused)))
79 {
80         int r;
81
82         if (crypto_backend_initialised)
83                 return 0;
84
85         if (NSS_NoDB_Init(".") != SECSuccess)
86                 return -EINVAL;
87
88 #if HAVE_DECL_NSS_GETVERSION
89         r = snprintf(version, sizeof(version), "NSS %s", NSS_GetVersion());
90 #else
91         r = snprintf(version, sizeof(version), "NSS");
92 #endif
93         if (r < 0 || (size_t)r >= sizeof(version))
94                 return -EINVAL;
95
96         crypto_backend_initialised = 1;
97         return 0;
98 }
99
100 void crypt_backend_destroy(void)
101 {
102         crypto_backend_initialised = 0;
103 }
104
105 uint32_t crypt_backend_flags(void)
106 {
107         return 0;
108 }
109
110 const char *crypt_backend_version(void)
111 {
112         return crypto_backend_initialised ? version : "";
113 }
114
115 /* HASH */
116 int crypt_hash_size(const char *name)
117 {
118         struct hash_alg *ha = _get_alg(name);
119
120         return ha ? ha->length : -EINVAL;
121 }
122
123 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
124 {
125         struct crypt_hash *h;
126
127         h = malloc(sizeof(*h));
128         if (!h)
129                 return -ENOMEM;
130
131         h->hash = _get_alg(name);
132         if (!h->hash) {
133                 free(h);
134                 return -EINVAL;
135         }
136
137         h->md = PK11_CreateDigestContext(h->hash->oid);
138         if (!h->md) {
139                 free(h);
140                 return -EINVAL;
141         }
142
143         if (PK11_DigestBegin(h->md) != SECSuccess) {
144                 PK11_DestroyContext(h->md, PR_TRUE);
145                 free(h);
146                 return -EINVAL;
147         }
148
149         *ctx = h;
150         return 0;
151 }
152
153 static int crypt_hash_restart(struct crypt_hash *ctx)
154 {
155         if (PK11_DigestBegin(ctx->md) != SECSuccess)
156                 return -EINVAL;
157
158         return 0;
159 }
160
161 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
162 {
163         if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
164                 return -EINVAL;
165
166         return 0;
167 }
168
169 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
170 {
171         unsigned char tmp[64];
172         unsigned int tmp_len;
173
174         if (length > (size_t)ctx->hash->length)
175                 return -EINVAL;
176
177         if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
178                 return -EINVAL;
179
180         memcpy(buffer, tmp, length);
181         crypt_backend_memzero(tmp, sizeof(tmp));
182
183         if (tmp_len < length)
184                 return -EINVAL;
185
186         if (crypt_hash_restart(ctx))
187                 return -EINVAL;
188
189         return 0;
190 }
191
192 void crypt_hash_destroy(struct crypt_hash *ctx)
193 {
194         PK11_DestroyContext(ctx->md, PR_TRUE);
195         memset(ctx, 0, sizeof(*ctx));
196         free(ctx);
197 }
198
199 /* HMAC */
200 int crypt_hmac_size(const char *name)
201 {
202         return crypt_hash_size(name);
203 }
204
205 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
206                     const void *key, size_t key_length)
207 {
208         struct crypt_hmac *h;
209         SECItem keyItem;
210         SECItem noParams;
211
212         keyItem.type = siBuffer;
213         keyItem.data = CONST_CAST(unsigned char *)key;
214         keyItem.len = (int)key_length;
215
216         noParams.type = siBuffer;
217         noParams.data = 0;
218         noParams.len = 0;
219
220         h = malloc(sizeof(*h));
221         if (!h)
222                 return -ENOMEM;
223         memset(ctx, 0, sizeof(*ctx));
224
225
226         h->hash = _get_alg(name);
227         if (!h->hash)
228                 goto err;
229
230         h->slot = PK11_GetInternalKeySlot();
231         if (!h->slot)
232                 goto err;
233
234         h->key = PK11_ImportSymKey(h->slot, h->hash->ck_type, PK11_OriginUnwrap,
235                                    CKA_SIGN,  &keyItem, NULL);
236         if (!h->key)
237                 goto err;
238
239         h->md = PK11_CreateContextBySymKey(h->hash->ck_type, CKA_SIGN, h->key,
240                                            &noParams);
241         if (!h->md)
242                 goto err;
243
244         if (PK11_DigestBegin(h->md) != SECSuccess)
245                 goto err;
246
247         *ctx = h;
248         return 0;
249 err:
250         crypt_hmac_destroy(h);
251         return -EINVAL;
252 }
253
254 static int crypt_hmac_restart(struct crypt_hmac *ctx)
255 {
256         if (PK11_DigestBegin(ctx->md) != SECSuccess)
257                 return -EINVAL;
258
259         return 0;
260 }
261
262 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
263 {
264         if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
265                 return -EINVAL;
266
267         return 0;
268 }
269
270 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
271 {
272         unsigned char tmp[64];
273         unsigned int tmp_len;
274
275         if (length > (size_t)ctx->hash->length)
276                 return -EINVAL;
277
278         if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
279                 return -EINVAL;
280
281         memcpy(buffer, tmp, length);
282         crypt_backend_memzero(tmp, sizeof(tmp));
283
284         if (tmp_len < length)
285                 return -EINVAL;
286
287         if (crypt_hmac_restart(ctx))
288                 return -EINVAL;
289
290         return 0;
291 }
292
293 void crypt_hmac_destroy(struct crypt_hmac *ctx)
294 {
295         if (ctx->key)
296                 PK11_FreeSymKey(ctx->key);
297         if (ctx->slot)
298                 PK11_FreeSlot(ctx->slot);
299         if (ctx->md)
300                 PK11_DestroyContext(ctx->md, PR_TRUE);
301         memset(ctx, 0, sizeof(*ctx));
302         free(ctx);
303 }
304
305 /* RNG */
306 int crypt_backend_rng(char *buffer, size_t length, int quality __attribute__((unused)), int fips)
307 {
308         if (fips)
309                 return -EINVAL;
310
311         if (PK11_GenerateRandom((unsigned char *)buffer, length) != SECSuccess)
312                 return -EINVAL;
313
314         return 0;
315 }
316
317 /* PBKDF */
318 int crypt_pbkdf(const char *kdf, const char *hash,
319                 const char *password, size_t password_length,
320                 const char *salt, size_t salt_length,
321                 char *key, size_t key_length,
322                 uint32_t iterations, uint32_t memory, uint32_t parallel)
323 {
324         struct hash_alg *ha;
325
326         if (!kdf)
327                 return -EINVAL;
328
329         if (!strcmp(kdf, "pbkdf2")) {
330                 ha = _get_alg(hash);
331                 if (!ha)
332                         return -EINVAL;
333
334                 return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
335                                     iterations, key_length, key, ha->block_length);
336         } else if (!strncmp(kdf, "argon2", 6)) {
337                 return argon2(kdf, password, password_length, salt, salt_length,
338                               key, key_length, iterations, memory, parallel);
339         }
340
341         return -EINVAL;
342 }
343
344 /* Block ciphers */
345 int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
346                     const char *mode, const void *key, size_t key_length)
347 {
348         struct crypt_cipher *h;
349         int r;
350
351         h = malloc(sizeof(*h));
352         if (!h)
353                 return -ENOMEM;
354
355         r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
356         if (r < 0) {
357                 free(h);
358                 return r;
359         }
360
361         *ctx = h;
362         return 0;
363 }
364
365 void crypt_cipher_destroy(struct crypt_cipher *ctx)
366 {
367         crypt_cipher_destroy_kernel(&ctx->ck);
368         free(ctx);
369 }
370
371 int crypt_cipher_encrypt(struct crypt_cipher *ctx,
372                          const char *in, char *out, size_t length,
373                          const char *iv, size_t iv_length)
374 {
375         return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
376 }
377
378 int crypt_cipher_decrypt(struct crypt_cipher *ctx,
379                          const char *in, char *out, size_t length,
380                          const char *iv, size_t iv_length)
381 {
382         return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
383 }
384
385 bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
386 {
387         return true;
388 }
389
390 int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
391                             const char *in, char *out, size_t length,
392                             const char *iv, size_t iv_length,
393                             const char *tag, size_t tag_length)
394 {
395         return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
396                                               iv, iv_length, tag, tag_length);
397 }
398
399 int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
400 {
401         return NSS_SecureMemcmp(m1, m2, n);
402 }
403
404 bool crypt_fips_mode(void)
405 {
406         return false;
407 }