Tor 0.4.9.3-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
27 PK11Context *context;
28 // We need to keep a copy of the key here since we can't set the IV only.
29 // It would be nice to fix that, but NSS doesn't see a huge number of
30 // users.
31 uint8_t kbytes;
32 uint8_t key[32];
33};
34
35static PK11Context *
36aes_new_cipher_internal(const uint8_t *key, const uint8_t *iv,
37 int key_bits)
38{
39 const CK_MECHANISM_TYPE ckm = CKM_AES_CTR;
40 SECItem keyItem = { .type = siBuffer,
41 .data = (unsigned char *)key,
42 .len = (key_bits / 8) };
43 CK_AES_CTR_PARAMS params;
44 params.ulCounterBits = 128;
45 memcpy(params.cb, iv, 16);
46 SECItem ivItem = { .type = siBuffer,
47 .data = (unsigned char *)&params,
48 .len = sizeof(params) };
49 PK11SlotInfo *slot = NULL;
50 PK11SymKey *keyObj = NULL;
51 SECItem *ivObj = NULL;
52 PK11Context *result = NULL;
53
54 slot = PK11_GetBestSlot(ckm, NULL);
55 if (!slot)
56 goto err;
57
58 keyObj = PK11_ImportSymKey(slot, ckm, PK11_OriginUnwrap,
59 CKA_ENCRYPT, &keyItem, NULL);
60 if (!keyObj)
61 goto err;
62
63 ivObj = PK11_ParamFromIV(ckm, &ivItem);
64 if (!ivObj)
65 goto err;
66
67 PORT_SetError(SEC_ERROR_IO);
68 result = PK11_CreateContextBySymKey(ckm, CKA_ENCRYPT, keyObj, ivObj);
69
70 err:
71 memwipe(&params, 0, sizeof(params));
72 if (ivObj)
73 SECITEM_FreeItem(ivObj, PR_TRUE);
74 if (keyObj)
75 PK11_FreeSymKey(keyObj);
76 if (slot)
77 PK11_FreeSlot(slot);
78
79 tor_assert(result);
80 return result;
81}
82
84aes_new_cipher(const uint8_t *key, const uint8_t *iv,
85 int key_bits)
86{
87 aes_cnt_cipher_t *cipher = tor_malloc_zero(sizeof(*cipher));
88 cipher->context = aes_new_cipher_internal(key, iv, key_bits);
89 cipher->kbytes = key_bits / 8;
90 memcpy(cipher->key, key, cipher->kbytes);
91 return cipher;
92}
93
94void
95aes_cipher_free_(aes_cnt_cipher_t *cipher)
96{
97 if (!cipher)
98 return;
99 PK11_DestroyContext(cipher->context, PR_TRUE);
100 memwipe(cipher, 0, sizeof(*cipher));
101 tor_free(cipher);
102}
103
104void
106{
107 // For NSS, I could not find a method to change the IV
108 // of an existing context. Maybe I missed one?
109 PK11_DestroyContext(cipher->context, PR_TRUE);
110 cipher->context = aes_new_cipher_internal(cipher->key, iv,
111 8*(int)cipher->kbytes);
112}
113
114void
116 const uint8_t *key, int key_bits)
117{
118 const uint8_t iv[16] = {0};
119 // For NSS, I could not find a method to change the key
120 // of an existing context. Maybe I missed one?
121 PK11_DestroyContext(cipher->context, PR_TRUE);
122 memwipe(cipher->key, 0, sizeof(cipher->key));
123
124 cipher->context = aes_new_cipher_internal(key, iv, key_bits);
125 cipher->kbytes = key_bits / 8;
126 memcpy(cipher->key, key, cipher->kbytes);
127}
128
129void
130aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data_, size_t len_)
131{
132 tor_assert(len_ <= INT_MAX);
133
134 SECStatus s;
135 unsigned char *data = (unsigned char *)data_;
136 int len = (int) len_;
137 int result_len = 0;
138
139 s = PK11_CipherOp(cipher->context, data, &result_len, len, data, len);
140 tor_assert(s == SECSuccess);
141 tor_assert(result_len == len);
142}
143
144aes_raw_t *
145aes_raw_new(const uint8_t *key, int key_bits, bool encrypt)
146{
147 const CK_MECHANISM_TYPE ckm = CKM_AES_ECB;
148 SECItem keyItem = { .type = siBuffer, // ????
149 .data = (unsigned char *)key,
150 .len = (key_bits / 8) };
151 SECItem ivItem = { .type = siBuffer,
152 .data = NULL,
153 .len = 0 };
154 PK11SlotInfo *slot = NULL;
155 PK11SymKey *keyObj = NULL;
156 SECItem *ivObj = NULL;
157 PK11Context *result = NULL;
158
159 slot = PK11_GetBestSlot(ckm, NULL);
160 if (!slot)
161 goto err;
162
163 CK_ATTRIBUTE_TYPE mode = encrypt ? CKA_ENCRYPT : CKA_DECRYPT;
164
165 keyObj = PK11_ImportSymKey(slot, ckm, PK11_OriginUnwrap,
166 mode, &keyItem, NULL);
167 if (!keyObj)
168 goto err;
169
170 ivObj = PK11_ParamFromIV(ckm, &ivItem);
171 if (!ivObj)
172 goto err;
173
174 PORT_SetError(SEC_ERROR_IO);
175 result = PK11_CreateContextBySymKey(ckm, mode, keyObj, ivObj);
176
177 err:
178
179 if (ivObj)
180 SECITEM_FreeItem(ivObj, PR_TRUE);
181 if (keyObj)
182 PK11_FreeSymKey(keyObj);
183 if (slot)
184 PK11_FreeSlot(slot);
185
186 tor_assert(result);
187 return (aes_raw_t *)result;
188}
189void
190aes_raw_free_(aes_raw_t *cipher_)
191{
192 if (!cipher_)
193 return;
194 PK11Context *ctx = (PK11Context*)cipher_;
195 PK11_DestroyContext(ctx, PR_TRUE);
196}
197void
198aes_raw_set_key(aes_raw_t **cipher, const uint8_t *key,
199 int key_bits, bool encrypt)
200{
201 // For NSS, I could not find a method to change the key
202 // of an existing context.
203 aes_raw_free(*cipher);
204 *cipher = aes_raw_new(key, key_bits, encrypt);
205}
206void
207aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block)
208{
209 SECStatus s;
210 PK11Context *ctx = (PK11Context*)cipher;
211 int result_len = 0;
212 s = PK11_CipherOp(ctx, block, &result_len, 16, block, 16);
213 tor_assert(s == SECSuccess);
214 tor_assert(result_len == 16);
215}
216void
217aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block)
218{
219 /* This is the same function call for NSS. */
220 aes_raw_encrypt(cipher, block);
221}
Headers for aes.c.
void aes_cipher_set_key(aes_cnt_cipher_t *cipher_, const uint8_t *key, int key_bits)
Definition aes_nss.c:115
void aes_cipher_set_iv_aligned(aes_cnt_cipher_t *cipher_, const uint8_t *iv)
Definition aes_nss.c:105
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.
#define tor_free(p)
Definition malloc.h:56
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition util_bug.h:103