Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: nss/lib/freebl/chacha20poly1305.c

Issue 27510015: Support ChaCha20+Poly1305 cipher suites. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Make ChaCha20Poly1305 function conform to freebl API, undo changes to chacha20.c, use generic code … Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #ifdef FREEBL_NO_DEPEND
6 #include "stubs.h"
7 #endif
8
9 #include <string.h>
10 #include <stdio.h>
11
12 #include "seccomon.h"
13 #include "secerr.h"
14 #include "blapit.h"
15 #include "poly1305/poly1305.h"
16 #include "chacha20/chacha20.h"
17
18 /* ChaCha20Poly1305ContextStr saves the key and additional data for a
19 * ChaCha20+Poly1305 AEAD operation. */
20 struct ChaCha20Poly1305ContextStr {
21 unsigned char key[32];
22 unsigned char nonce[8];
23 unsigned char ad[16];
24 unsigned char *adOverflow;
25 unsigned int adLen;
26 unsigned char tagLen;
27 };
28
29 /* Poly1305Do writes the Poly1305 authenticator of the given additional data
30 * and ciphertext to |out|. */
31 static void
32 Poly1305Do(unsigned char *out,
33 const unsigned char *ad, unsigned int adLen,
34 const unsigned char *ciphertext, unsigned int ciphertextLen,
35 const unsigned char key[32])
36 {
37 poly1305_state state;
38 unsigned int j;
39 unsigned char lengthBytes[8];
40 unsigned int i;
41
42 Poly1305Init(&state, key);
43 j = adLen;
44 for (i = 0; i < sizeof(lengthBytes); i++) {
45 lengthBytes[i] = j;
46 j >>= 8;
47 }
48 Poly1305Update(&state, ad, adLen);
49 Poly1305Update(&state, lengthBytes, sizeof(lengthBytes));
50 j = ciphertextLen;
51 for (i = 0; i < sizeof(lengthBytes); i++) {
52 lengthBytes[i] = j;
53 j >>= 8;
54 }
55 Poly1305Update(&state, ciphertext, ciphertextLen);
56 Poly1305Update(&state, lengthBytes, sizeof(lengthBytes));
57 Poly1305Finish(&state, out);
58 }
59
60 ChaCha20Poly1305Context *
61 ChaCha20Poly1305_CreateContext(const unsigned char *key, unsigned int keyLen,
62 const unsigned char *nonce, unsigned int nonceLen ,
63 const unsigned char *ad, unsigned int adLen,
64 unsigned int tagBits)
65 {
66 ChaCha20Poly1305Context *ctx;
67
68 if (keyLen != 32) {
69 PORT_SetError(SEC_ERROR_BAD_KEY);
70 return NULL;
71 }
72 if (nonceLen != sizeof(ctx->nonce)) {
73 PORT_SetError(SEC_ERROR_INPUT_LEN);
74 return NULL;
75 }
76 if (tagBits == 0 || tagBits > 128 || (tagBits & 7) != 0) {
77 PORT_SetError(SEC_ERROR_INPUT_LEN);
78 return NULL;
79 }
80
81 ctx = PORT_New(ChaCha20Poly1305Context);
82 if (ctx == NULL) {
83 return NULL;
84 }
85
86 memcpy(ctx->key, key, sizeof(ctx->key));
87 memcpy(ctx->nonce, nonce, sizeof(ctx->nonce));
88 ctx->tagLen = tagBits >> 3;
89
90 if (adLen > sizeof(ctx->ad)) {
91 /* Need to allocate an overflow buffer for the additional data. */
92 ctx->adOverflow = (unsigned char *)PORT_Alloc(adLen);
93 if (!ctx->adOverflow) {
94 PORT_Free(ctx);
95 return NULL;
96 }
97 memcpy(ctx->adOverflow, ad, adLen);
98 } else {
99 ctx->adOverflow = NULL;
100 memcpy(ctx->ad, ad, adLen);
101 }
102 ctx->adLen = adLen;
103
104 return ctx;
105 }
106
107 void
108 ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit)
109 {
110 if (ctx->adOverflow != NULL) {
111 PORT_Free(ctx->adOverflow);
112 ctx->adOverflow = NULL;
113 }
114 if (freeit) {
115 PORT_Free(ctx);
116 }
117 }
118
119 SECStatus
120 ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx,
121 unsigned char *output, unsigned int *outputLen,
122 unsigned int maxOutputLen,
123 const unsigned char *input, unsigned int inputLen)
124 {
125 const unsigned char *ad = ctx->adOverflow;
126 unsigned char block[64];
127 unsigned char tag[16];
128
129 if (ctx->tagLen == 0 || ctx->tagLen > sizeof(tag)) {
agl 2013/10/21 21:53:39 This test shouldn't be needed now?
wtc 2013/10/22 22:36:42 Done.
130 PORT_SetError(SEC_ERROR_INPUT_LEN);
131 return SECFailure;
132 }
133 *outputLen = inputLen + ctx->tagLen;
134 if (maxOutputLen < *outputLen) {
135 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
136 return SECFailure;
137 }
138
139 if (ad == NULL) {
140 ad = ctx->ad;
141 }
142
143 memset(block, 0, sizeof(block));
144 // Generate a block of keystream. The first 32 bytes will be the poly1305
145 // key. The remainder of the block is discarded.
146 ChaCha20XOR(block, block, sizeof(block), ctx->key, ctx->nonce, 0);
147 ChaCha20XOR(output, input, inputLen, ctx->key, ctx->nonce, 1);
148
149 Poly1305Do(tag, ad, ctx->adLen, output, inputLen, block);
150 memcpy(output + inputLen, tag, ctx->tagLen);
151
152 return SECSuccess;
153 }
154
155 SECStatus
156 ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx,
157 unsigned char *output, unsigned int *outputLen,
158 unsigned int maxOutputLen,
159 const unsigned char *input, unsigned int inputLen)
160 {
161 const unsigned char *ad = ctx->adOverflow;
162 unsigned char block[64];
163 unsigned int i;
164 unsigned char tag[16];
165
166 if (ctx->tagLen == 0 || ctx->tagLen > sizeof(tag)) {
agl 2013/10/21 21:53:39 This test shouldn't be needed now?
wtc 2013/10/22 22:36:42 Done.
167 PORT_SetError(SEC_ERROR_INPUT_LEN);
168 return SECFailure;
169 }
170 if (inputLen < ctx->tagLen) {
171 PORT_SetError(SEC_ERROR_INPUT_LEN);
172 return SECFailure;
173 }
174 *outputLen = inputLen - ctx->tagLen;
175 if (maxOutputLen < *outputLen) {
176 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
177 return SECFailure;
178 }
179
180 if (ad == NULL) {
181 ad = ctx->ad;
182 }
183
184 memset(block, 0, sizeof(block));
185 // Generate a block of keystream. The first 32 bytes will be the poly1305
186 // key. The remainder of the block is discarded.
187 ChaCha20XOR(block, block, sizeof(block), ctx->key, ctx->nonce, 0);
188 Poly1305Do(tag, ad, ctx->adLen, input, inputLen - ctx->tagLen, block);
189 if (NSS_SecureMemcmp(tag, &input[inputLen - ctx->tagLen], ctx->tagLen) != 0) {
190 PORT_SetError(SEC_ERROR_BAD_DATA);
191 return SECFailure;
192 }
193
194 ChaCha20XOR(output, input, inputLen - ctx->tagLen, ctx->key, ctx->nonce, 1);
195
196 return SECSuccess;
197 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698