Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_pbkdf2.c
Go to the documentation of this file.
1
2/*******************************************************************************
3 * Ledger Nano S - Secure firmware
4 * (c) 2022 Ledger
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 ********************************************************************************/
18
19#ifdef HAVE_PBKDF2
20
21#include <string.h>
22
23#include "errors.h"
24#include "exceptions.h"
25#include "cx_pbkdf2.h"
26#include "cx_hash.h"
27#include "cx_ram.h"
28
29cx_err_t cx_pbkdf2_hmac(cx_md_t md_type,
30 const uint8_t *password,
31 size_t password_len,
32 const uint8_t *salt,
33 size_t salt_len,
34 uint32_t iterations,
35 uint8_t *key,
36 size_t key_len)
37{
38 cx_hmac_t *hmac_ctx = &G_cx.pbkdf2.hmac_ctx;
39 uint8_t counter[4];
40 uint8_t *work = G_cx.pbkdf2.work;
41 size_t work_size;
42 uint8_t *md1 = G_cx.pbkdf2.md1;
43 size_t copy_len;
44 size_t digest_size;
45 cx_err_t error = CX_OK;
46
47 if (password == NULL || salt == NULL || key == NULL) {
48 return CX_INVALID_PARAMETER;
49 }
50
51 const cx_hash_info_t *info = cx_hash_get_info(md_type);
52 digest_size = info->output_size;
53
54 memset(counter, 0, sizeof(counter));
55 counter[sizeof(counter) - 1] = 1;
56
57 while (key_len) {
58 CX_CHECK(cx_hmac_init(hmac_ctx, md_type, password, password_len));
59 CX_CHECK(cx_hmac_update(hmac_ctx, salt, salt_len));
60 CX_CHECK(cx_hmac_update(hmac_ctx, counter, 4));
61
62 work_size = digest_size;
63 CX_CHECK(cx_hmac_final(hmac_ctx, work, &work_size));
64
65 memcpy(md1, work, digest_size);
66 for (uint32_t i = 1; i < iterations; i++) {
67 CX_CHECK(cx_hmac_init(hmac_ctx, md_type, password, password_len));
68 CX_CHECK(cx_hmac_update(hmac_ctx, md1, digest_size));
69 work_size = digest_size;
70 CX_CHECK(cx_hmac_final(hmac_ctx, md1, &work_size));
71
72 for (unsigned int j = 0; j < digest_size; j++) {
73 work[j] ^= md1[j];
74 }
75 }
76
77 if (key_len < digest_size) {
78 copy_len = key_len;
79 }
80 else {
81 copy_len = digest_size;
82 }
83 memcpy(key, work, copy_len);
84 key += copy_len;
85 key_len -= copy_len;
86
87 // Increment counter
88 for (int i = 3; i >= 0; i--) {
89 if (++counter[i] != 0) {
90 break;
91 }
92 }
93 }
94end:
95 return error;
96}
97
98cx_err_t cx_pbkdf2_no_throw(cx_md_t md_type,
99 const uint8_t *password,
100 size_t password_len,
101 uint8_t *salt,
102 size_t salt_len,
103 uint32_t iterations,
104 uint8_t *out,
105 size_t out_len)
106{
107 return cx_pbkdf2_hmac(
108 md_type, password, password_len, salt, salt_len, iterations, out, out_len);
109}
110
111#endif // HAVE_PBKDF2
union cx_u G_cx
Definition cx_ram.c:21
unsigned char uint8_t
Definition usbd_conf.h:53