Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
aes_nss.c
Go to the documentation of this file.
1/* Copyright (c) 2001, Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5/* See LICENSE for licensing information */
6
7/**
8 * \file aes_nss.c
9 * \brief Use NSS to implement AES_CTR.
10 **/
11
12#define USE_AES_RAW
13#define TOR_AES_PRIVATE
14
15#include "orconfig.h"
16#include "lib/crypt_ops/aes.h"
19#include "lib/log/util_bug.h"
20
21DISABLE_GCC_WARNING("-Wstrict-prototypes")
22#include <pk11pub.h>
23#include <secerr.h>
24ENABLE_GCC_WARNING("-Wstrict-prototypes")
25
26aes_cnt_cipher_t *
27aes_new_cipher(const uint8_t *key, const uint8_t *iv,
28 int key_bits)
29{
30 const CK_MECHANISM_TYPE ckm = CKM_AES_CTR;
31 SECItem keyItem = { .type = siBuffer,
32 .data = (unsigned char *)key,
33 .len = (key_bits / 8) };
34 CK_AES_CTR_PARAMS params;
35 params.ulCounterBits = 128;
36 memcpy(params.cb, iv, 16);
37 SECItem ivItem = { .type = siBuffer,
38 .data = (unsigned char *)&params,
39 .len = sizeof(params) };
40 PK11SlotInfo *slot = NULL;
41 PK11SymKey *keyObj = NULL;
42 SECItem *ivObj = NULL;
43 PK11Context *result = NULL;
44
45 slot = PK11_GetBestSlot(ckm, NULL);
46 if (!slot)
47 goto err;
48
49 keyObj = PK11_ImportSymKey(slot, ckm, PK11_OriginUnwrap,
50 CKA_ENCRYPT, &keyItem, NULL);
51 if (!keyObj)
52 goto err;
53
54 ivObj = PK11_ParamFromIV(ckm, &ivItem);
55 if (!ivObj)
56 goto err;
57
58 PORT_SetError(SEC_ERROR_IO);
59 result = PK11_CreateContextBySymKey(ckm, CKA_ENCRYPT, keyObj, ivObj);
60
61 err:
62 memwipe(&params, 0, sizeof(params));
63 if (ivObj)
64 SECITEM_FreeItem(ivObj, PR_TRUE);
65 if (keyObj)
66 PK11_FreeSymKey(keyObj);
67 if (slot)
68 PK11_FreeSlot(slot);
69
70 tor_assert(result);
71 return (aes_cnt_cipher_t *)result;
72}
73
74void
75aes_cipher_free_(aes_cnt_cipher_t *cipher)
76{
77 if (!cipher)
78 return;
79 PK11_DestroyContext((PK11Context*) cipher, PR_TRUE);
80}
81
82void
83aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data_, size_t len_)
84{
85 tor_assert(len_ <= INT_MAX);
86
87 SECStatus s;
88 PK11Context *ctx = (PK11Context*)cipher;
89 unsigned char *data = (unsigned char *)data_;
90 int len = (int) len_;
91 int result_len = 0;
92
93 s = PK11_CipherOp(ctx, data, &result_len, len, data, len);
94 tor_assert(s == SECSuccess);
95 tor_assert(result_len == len);
96}
97
98int
99evaluate_evp_for_aes(int force_value)
100{
101 (void)force_value;
102 return 0;
103}
104
105int
106evaluate_ctr_for_aes(void)
107{
108 return 0;
109}
110
111aes_raw_t *
112aes_raw_new(const uint8_t *key, int key_bits, bool encrypt)
113{
114 const CK_MECHANISM_TYPE ckm = CKM_AES_ECB;
115 SECItem keyItem = { .type = siBuffer, // ????
116 .data = (unsigned char *)key,
117 .len = (key_bits / 8) };
118 SECItem ivItem = { .type = siBuffer,
119 .data = NULL,
120 .len = 0 };
121 PK11SlotInfo *slot = NULL;
122 PK11SymKey *keyObj = NULL;
123 SECItem *ivObj = NULL;
124 PK11Context *result = NULL;
125
126 slot = PK11_GetBestSlot(ckm, NULL);
127 if (!slot)
128 goto err;
129
130 CK_ATTRIBUTE_TYPE mode = encrypt ? CKA_ENCRYPT : CKA_DECRYPT;
131
132 keyObj = PK11_ImportSymKey(slot, ckm, PK11_OriginUnwrap,
133 mode, &keyItem, NULL);
134 if (!keyObj)
135 goto err;
136
137 ivObj = PK11_ParamFromIV(ckm, &ivItem);
138 if (!ivObj)
139 goto err;
140
141 PORT_SetError(SEC_ERROR_IO);
142 result = PK11_CreateContextBySymKey(ckm, mode, keyObj, ivObj);
143
144 err:
145
146 if (ivObj)
147 SECITEM_FreeItem(ivObj, PR_TRUE);
148 if (keyObj)
149 PK11_FreeSymKey(keyObj);
150 if (slot)
151 PK11_FreeSlot(slot);
152
153 tor_assert(result);
154 return (aes_raw_t *)result;
155}
156void
157aes_raw_free_(aes_raw_t *cipher_)
158{
159 if (!cipher_)
160 return;
161 PK11Context *ctx = (PK11Context*)cipher_;
162 PK11_DestroyContext(ctx, PR_TRUE);
163}
164void
165aes_raw_set_key(aes_raw_t **cipher, const uint8_t *key,
166 int key_bits, bool encrypt)
167{
168 // For NSS, I could not find a method to change the key
169 // of an existing context.
170 aes_raw_free(*cipher);
171 *cipher = aes_raw_new(key, key_bits, encrypt);
172}
173void
174aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block)
175{
176 SECStatus s;
177 PK11Context *ctx = (PK11Context*)cipher;
178 int result_len = 0;
179 s = PK11_CipherOp(ctx, block, &result_len, 16, block, 16);
180 tor_assert(s == SECSuccess);
181 tor_assert(result_len == 16);
182}
183void
184aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block)
185{
186 /* This is the same function call for NSS. */
187 aes_raw_encrypt(cipher, block);
188}
189
190static inline void
191xor_bytes(uint8_t *outp, const uint8_t *inp, size_t n)
192{
193 for (size_t i = 0; i < n; ++i) {
194 outp[i] ^= inp[i];
195 }
196}
197
198void
199aes_raw_counter_xor(const aes_raw_t *cipher,
200 const uint8_t *iv, uint32_t iv_offset,
201 uint8_t *data, size_t n)
202{
203 uint8_t counter[16];
204 uint8_t buf[16];
205
206 memcpy(counter, iv, 16);
207 aes_ctr_add_iv_offset(counter, iv_offset);
208
209 while (n) {
210 memcpy(buf, counter, 16);
211 aes_raw_encrypt(cipher, buf);
212 if (n >= 16) {
213 xor_bytes(data, buf, 16);
214 n -= 16;
215 data += 16;
216 } else {
217 xor_bytes(data, buf, n);
218 break;
219 }
220 aes_ctr_add_iv_offset(counter, 1);
221 }
222}
Headers for aes.c.
void aes_raw_set_key(aes_raw_t **cipher_, const uint8_t *key, int key_bits, bool encrypt)
Definition: aes_openssl.c:430
void aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block)
Definition: aes_openssl.c:471
void aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block)
Definition: aes_openssl.c:483
void aes_raw_free_(aes_raw_t *cipher_)
Definition: aes_openssl.c:452
aes_raw_t * aes_raw_new(const uint8_t *key, int key_bits, bool encrypt)
Definition: aes_openssl.c:407
void aes_raw_counter_xor(const aes_raw_t *cipher, const uint8_t *iv, uint32_t iv_offset, uint8_t *data, size_t n)
Definition: aes_openssl.c:500
Headers for crypto_nss_mgt.c.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103