]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - module/icp/algs/modes/ccm.c
Vendor import of openzfs master @ 184df27eef0abdc7ab2105b21257f753834b936b
[FreeBSD/FreeBSD.git] / module / icp / algs / modes / ccm.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26 #include <sys/zfs_context.h>
27 #include <modes/modes.h>
28 #include <sys/crypto/common.h>
29 #include <sys/crypto/impl.h>
30
31 #ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
32 #include <sys/byteorder.h>
33 #define UNALIGNED_POINTERS_PERMITTED
34 #endif
35
36 /*
37  * Encrypt multiple blocks of data in CCM mode.  Decrypt for CCM mode
38  * is done in another function.
39  */
40 int
41 ccm_mode_encrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length,
42     crypto_data_t *out, size_t block_size,
43     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
44     void (*copy_block)(uint8_t *, uint8_t *),
45     void (*xor_block)(uint8_t *, uint8_t *))
46 {
47         size_t remainder = length;
48         size_t need = 0;
49         uint8_t *datap = (uint8_t *)data;
50         uint8_t *blockp;
51         uint8_t *lastp;
52         void *iov_or_mp;
53         offset_t offset;
54         uint8_t *out_data_1;
55         uint8_t *out_data_2;
56         size_t out_data_1_len;
57         uint64_t counter;
58         uint8_t *mac_buf;
59
60         if (length + ctx->ccm_remainder_len < block_size) {
61                 /* accumulate bytes here and return */
62                 bcopy(datap,
63                     (uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len,
64                     length);
65                 ctx->ccm_remainder_len += length;
66                 ctx->ccm_copy_to = datap;
67                 return (CRYPTO_SUCCESS);
68         }
69
70         lastp = (uint8_t *)ctx->ccm_cb;
71         crypto_init_ptrs(out, &iov_or_mp, &offset);
72
73         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
74
75         do {
76                 /* Unprocessed data from last call. */
77                 if (ctx->ccm_remainder_len > 0) {
78                         need = block_size - ctx->ccm_remainder_len;
79
80                         if (need > remainder)
81                                 return (CRYPTO_DATA_LEN_RANGE);
82
83                         bcopy(datap, &((uint8_t *)ctx->ccm_remainder)
84                             [ctx->ccm_remainder_len], need);
85
86                         blockp = (uint8_t *)ctx->ccm_remainder;
87                 } else {
88                         blockp = datap;
89                 }
90
91                 /*
92                  * do CBC MAC
93                  *
94                  * XOR the previous cipher block current clear block.
95                  * mac_buf always contain previous cipher block.
96                  */
97                 xor_block(blockp, mac_buf);
98                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
99
100                 /* ccm_cb is the counter block */
101                 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb,
102                     (uint8_t *)ctx->ccm_tmp);
103
104                 lastp = (uint8_t *)ctx->ccm_tmp;
105
106                 /*
107                  * Increment counter. Counter bits are confined
108                  * to the bottom 64 bits of the counter block.
109                  */
110 #ifdef _ZFS_LITTLE_ENDIAN
111                 counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask);
112                 counter = htonll(counter + 1);
113 #else
114                 counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask;
115                 counter++;
116 #endif  /* _ZFS_LITTLE_ENDIAN */
117                 counter &= ctx->ccm_counter_mask;
118                 ctx->ccm_cb[1] =
119                     (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
120
121                 /*
122                  * XOR encrypted counter block with the current clear block.
123                  */
124                 xor_block(blockp, lastp);
125
126                 ctx->ccm_processed_data_len += block_size;
127
128                 crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
129                     &out_data_1_len, &out_data_2, block_size);
130
131                 /* copy block to where it belongs */
132                 if (out_data_1_len == block_size) {
133                         copy_block(lastp, out_data_1);
134                 } else {
135                         bcopy(lastp, out_data_1, out_data_1_len);
136                         if (out_data_2 != NULL) {
137                                 bcopy(lastp + out_data_1_len,
138                                     out_data_2,
139                                     block_size - out_data_1_len);
140                         }
141                 }
142                 /* update offset */
143                 out->cd_offset += block_size;
144
145                 /* Update pointer to next block of data to be processed. */
146                 if (ctx->ccm_remainder_len != 0) {
147                         datap += need;
148                         ctx->ccm_remainder_len = 0;
149                 } else {
150                         datap += block_size;
151                 }
152
153                 remainder = (size_t)&data[length] - (size_t)datap;
154
155                 /* Incomplete last block. */
156                 if (remainder > 0 && remainder < block_size) {
157                         bcopy(datap, ctx->ccm_remainder, remainder);
158                         ctx->ccm_remainder_len = remainder;
159                         ctx->ccm_copy_to = datap;
160                         goto out;
161                 }
162                 ctx->ccm_copy_to = NULL;
163
164         } while (remainder > 0);
165
166 out:
167         return (CRYPTO_SUCCESS);
168 }
169
170 void
171 calculate_ccm_mac(ccm_ctx_t *ctx, uint8_t *ccm_mac,
172     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
173 {
174         uint64_t counter;
175         uint8_t *counterp, *mac_buf;
176         int i;
177
178         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
179
180         /* first counter block start with index 0 */
181         counter = 0;
182         ctx->ccm_cb[1] = (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
183
184         counterp = (uint8_t *)ctx->ccm_tmp;
185         encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp);
186
187         /* calculate XOR of MAC with first counter block */
188         for (i = 0; i < ctx->ccm_mac_len; i++) {
189                 ccm_mac[i] = mac_buf[i] ^ counterp[i];
190         }
191 }
192
193 /* ARGSUSED */
194 int
195 ccm_encrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
196     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
197     void (*xor_block)(uint8_t *, uint8_t *))
198 {
199         uint8_t *lastp, *mac_buf, *ccm_mac_p, *macp = NULL;
200         void *iov_or_mp;
201         offset_t offset;
202         uint8_t *out_data_1;
203         uint8_t *out_data_2;
204         size_t out_data_1_len;
205         int i;
206
207         if (out->cd_length < (ctx->ccm_remainder_len + ctx->ccm_mac_len)) {
208                 return (CRYPTO_DATA_LEN_RANGE);
209         }
210
211         /*
212          * When we get here, the number of bytes of payload processed
213          * plus whatever data remains, if any,
214          * should be the same as the number of bytes that's being
215          * passed in the argument during init time.
216          */
217         if ((ctx->ccm_processed_data_len + ctx->ccm_remainder_len)
218             != (ctx->ccm_data_len)) {
219                 return (CRYPTO_DATA_LEN_RANGE);
220         }
221
222         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
223
224         if (ctx->ccm_remainder_len > 0) {
225
226                 /* ccm_mac_input_buf is not used for encryption */
227                 macp = (uint8_t *)ctx->ccm_mac_input_buf;
228                 bzero(macp, block_size);
229
230                 /* copy remainder to temporary buffer */
231                 bcopy(ctx->ccm_remainder, macp, ctx->ccm_remainder_len);
232
233                 /* calculate the CBC MAC */
234                 xor_block(macp, mac_buf);
235                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
236
237                 /* calculate the counter mode */
238                 lastp = (uint8_t *)ctx->ccm_tmp;
239                 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, lastp);
240
241                 /* XOR with counter block */
242                 for (i = 0; i < ctx->ccm_remainder_len; i++) {
243                         macp[i] ^= lastp[i];
244                 }
245                 ctx->ccm_processed_data_len += ctx->ccm_remainder_len;
246         }
247
248         /* Calculate the CCM MAC */
249         ccm_mac_p = (uint8_t *)ctx->ccm_tmp;
250         calculate_ccm_mac(ctx, ccm_mac_p, encrypt_block);
251
252         crypto_init_ptrs(out, &iov_or_mp, &offset);
253         crypto_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
254             &out_data_1_len, &out_data_2,
255             ctx->ccm_remainder_len + ctx->ccm_mac_len);
256
257         if (ctx->ccm_remainder_len > 0) {
258
259                 /* copy temporary block to where it belongs */
260                 if (out_data_2 == NULL) {
261                         /* everything will fit in out_data_1 */
262                         bcopy(macp, out_data_1, ctx->ccm_remainder_len);
263                         bcopy(ccm_mac_p, out_data_1 + ctx->ccm_remainder_len,
264                             ctx->ccm_mac_len);
265                 } else {
266
267                         if (out_data_1_len < ctx->ccm_remainder_len) {
268
269                                 size_t data_2_len_used;
270
271                                 bcopy(macp, out_data_1, out_data_1_len);
272
273                                 data_2_len_used = ctx->ccm_remainder_len
274                                     - out_data_1_len;
275
276                                 bcopy((uint8_t *)macp + out_data_1_len,
277                                     out_data_2, data_2_len_used);
278                                 bcopy(ccm_mac_p, out_data_2 + data_2_len_used,
279                                     ctx->ccm_mac_len);
280                         } else {
281                                 bcopy(macp, out_data_1, out_data_1_len);
282                                 if (out_data_1_len == ctx->ccm_remainder_len) {
283                                         /* mac will be in out_data_2 */
284                                         bcopy(ccm_mac_p, out_data_2,
285                                             ctx->ccm_mac_len);
286                                 } else {
287                                         size_t len_not_used = out_data_1_len -
288                                             ctx->ccm_remainder_len;
289                                         /*
290                                          * part of mac in will be in
291                                          * out_data_1, part of the mac will be
292                                          * in out_data_2
293                                          */
294                                         bcopy(ccm_mac_p,
295                                             out_data_1 + ctx->ccm_remainder_len,
296                                             len_not_used);
297                                         bcopy(ccm_mac_p + len_not_used,
298                                             out_data_2,
299                                             ctx->ccm_mac_len - len_not_used);
300
301                                 }
302                         }
303                 }
304         } else {
305                 /* copy block to where it belongs */
306                 bcopy(ccm_mac_p, out_data_1, out_data_1_len);
307                 if (out_data_2 != NULL) {
308                         bcopy(ccm_mac_p + out_data_1_len, out_data_2,
309                             block_size - out_data_1_len);
310                 }
311         }
312         out->cd_offset += ctx->ccm_remainder_len + ctx->ccm_mac_len;
313         ctx->ccm_remainder_len = 0;
314         return (CRYPTO_SUCCESS);
315 }
316
317 /*
318  * This will only deal with decrypting the last block of the input that
319  * might not be a multiple of block length.
320  */
321 static void
322 ccm_decrypt_incomplete_block(ccm_ctx_t *ctx,
323     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *))
324 {
325         uint8_t *datap, *outp, *counterp;
326         int i;
327
328         datap = (uint8_t *)ctx->ccm_remainder;
329         outp = &((ctx->ccm_pt_buf)[ctx->ccm_processed_data_len]);
330
331         counterp = (uint8_t *)ctx->ccm_tmp;
332         encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, counterp);
333
334         /* XOR with counter block */
335         for (i = 0; i < ctx->ccm_remainder_len; i++) {
336                 outp[i] = datap[i] ^ counterp[i];
337         }
338 }
339
340 /*
341  * This will decrypt the cipher text.  However, the plaintext won't be
342  * returned to the caller.  It will be returned when decrypt_final() is
343  * called if the MAC matches
344  */
345 /* ARGSUSED */
346 int
347 ccm_mode_decrypt_contiguous_blocks(ccm_ctx_t *ctx, char *data, size_t length,
348     crypto_data_t *out, size_t block_size,
349     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
350     void (*copy_block)(uint8_t *, uint8_t *),
351     void (*xor_block)(uint8_t *, uint8_t *))
352 {
353         size_t remainder = length;
354         size_t need = 0;
355         uint8_t *datap = (uint8_t *)data;
356         uint8_t *blockp;
357         uint8_t *cbp;
358         uint64_t counter;
359         size_t pt_len, total_decrypted_len, mac_len, pm_len, pd_len;
360         uint8_t *resultp;
361
362
363         pm_len = ctx->ccm_processed_mac_len;
364
365         if (pm_len > 0) {
366                 uint8_t *tmp;
367                 /*
368                  * all ciphertext has been processed, just waiting for
369                  * part of the value of the mac
370                  */
371                 if ((pm_len + length) > ctx->ccm_mac_len) {
372                         return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
373                 }
374                 tmp = (uint8_t *)ctx->ccm_mac_input_buf;
375
376                 bcopy(datap, tmp + pm_len, length);
377
378                 ctx->ccm_processed_mac_len += length;
379                 return (CRYPTO_SUCCESS);
380         }
381
382         /*
383          * If we decrypt the given data, what total amount of data would
384          * have been decrypted?
385          */
386         pd_len = ctx->ccm_processed_data_len;
387         total_decrypted_len = pd_len + length + ctx->ccm_remainder_len;
388
389         if (total_decrypted_len >
390             (ctx->ccm_data_len + ctx->ccm_mac_len)) {
391                 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
392         }
393
394         pt_len = ctx->ccm_data_len;
395
396         if (total_decrypted_len > pt_len) {
397                 /*
398                  * part of the input will be the MAC, need to isolate that
399                  * to be dealt with later.  The left-over data in
400                  * ccm_remainder_len from last time will not be part of the
401                  * MAC.  Otherwise, it would have already been taken out
402                  * when this call is made last time.
403                  */
404                 size_t pt_part = pt_len - pd_len - ctx->ccm_remainder_len;
405
406                 mac_len = length - pt_part;
407
408                 ctx->ccm_processed_mac_len = mac_len;
409                 bcopy(data + pt_part, ctx->ccm_mac_input_buf, mac_len);
410
411                 if (pt_part + ctx->ccm_remainder_len < block_size) {
412                         /*
413                          * since this is last of the ciphertext, will
414                          * just decrypt with it here
415                          */
416                         bcopy(datap, &((uint8_t *)ctx->ccm_remainder)
417                             [ctx->ccm_remainder_len], pt_part);
418                         ctx->ccm_remainder_len += pt_part;
419                         ccm_decrypt_incomplete_block(ctx, encrypt_block);
420                         ctx->ccm_processed_data_len += ctx->ccm_remainder_len;
421                         ctx->ccm_remainder_len = 0;
422                         return (CRYPTO_SUCCESS);
423                 } else {
424                         /* let rest of the code handle this */
425                         length = pt_part;
426                 }
427         } else if (length + ctx->ccm_remainder_len < block_size) {
428                         /* accumulate bytes here and return */
429                 bcopy(datap,
430                     (uint8_t *)ctx->ccm_remainder + ctx->ccm_remainder_len,
431                     length);
432                 ctx->ccm_remainder_len += length;
433                 ctx->ccm_copy_to = datap;
434                 return (CRYPTO_SUCCESS);
435         }
436
437         do {
438                 /* Unprocessed data from last call. */
439                 if (ctx->ccm_remainder_len > 0) {
440                         need = block_size - ctx->ccm_remainder_len;
441
442                         if (need > remainder)
443                                 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
444
445                         bcopy(datap, &((uint8_t *)ctx->ccm_remainder)
446                             [ctx->ccm_remainder_len], need);
447
448                         blockp = (uint8_t *)ctx->ccm_remainder;
449                 } else {
450                         blockp = datap;
451                 }
452
453                 /* Calculate the counter mode, ccm_cb is the counter block */
454                 cbp = (uint8_t *)ctx->ccm_tmp;
455                 encrypt_block(ctx->ccm_keysched, (uint8_t *)ctx->ccm_cb, cbp);
456
457                 /*
458                  * Increment counter.
459                  * Counter bits are confined to the bottom 64 bits
460                  */
461 #ifdef _ZFS_LITTLE_ENDIAN
462                 counter = ntohll(ctx->ccm_cb[1] & ctx->ccm_counter_mask);
463                 counter = htonll(counter + 1);
464 #else
465                 counter = ctx->ccm_cb[1] & ctx->ccm_counter_mask;
466                 counter++;
467 #endif  /* _ZFS_LITTLE_ENDIAN */
468                 counter &= ctx->ccm_counter_mask;
469                 ctx->ccm_cb[1] =
470                     (ctx->ccm_cb[1] & ~(ctx->ccm_counter_mask)) | counter;
471
472                 /* XOR with the ciphertext */
473                 xor_block(blockp, cbp);
474
475                 /* Copy the plaintext to the "holding buffer" */
476                 resultp = (uint8_t *)ctx->ccm_pt_buf +
477                     ctx->ccm_processed_data_len;
478                 copy_block(cbp, resultp);
479
480                 ctx->ccm_processed_data_len += block_size;
481
482                 ctx->ccm_lastp = blockp;
483
484                 /* Update pointer to next block of data to be processed. */
485                 if (ctx->ccm_remainder_len != 0) {
486                         datap += need;
487                         ctx->ccm_remainder_len = 0;
488                 } else {
489                         datap += block_size;
490                 }
491
492                 remainder = (size_t)&data[length] - (size_t)datap;
493
494                 /* Incomplete last block */
495                 if (remainder > 0 && remainder < block_size) {
496                         bcopy(datap, ctx->ccm_remainder, remainder);
497                         ctx->ccm_remainder_len = remainder;
498                         ctx->ccm_copy_to = datap;
499                         if (ctx->ccm_processed_mac_len > 0) {
500                                 /*
501                                  * not expecting anymore ciphertext, just
502                                  * compute plaintext for the remaining input
503                                  */
504                                 ccm_decrypt_incomplete_block(ctx,
505                                     encrypt_block);
506                                 ctx->ccm_processed_data_len += remainder;
507                                 ctx->ccm_remainder_len = 0;
508                         }
509                         goto out;
510                 }
511                 ctx->ccm_copy_to = NULL;
512
513         } while (remainder > 0);
514
515 out:
516         return (CRYPTO_SUCCESS);
517 }
518
519 int
520 ccm_decrypt_final(ccm_ctx_t *ctx, crypto_data_t *out, size_t block_size,
521     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
522     void (*copy_block)(uint8_t *, uint8_t *),
523     void (*xor_block)(uint8_t *, uint8_t *))
524 {
525         size_t mac_remain, pt_len;
526         uint8_t *pt, *mac_buf, *macp, *ccm_mac_p;
527         int rv;
528
529         pt_len = ctx->ccm_data_len;
530
531         /* Make sure output buffer can fit all of the plaintext */
532         if (out->cd_length < pt_len) {
533                 return (CRYPTO_DATA_LEN_RANGE);
534         }
535
536         pt = ctx->ccm_pt_buf;
537         mac_remain = ctx->ccm_processed_data_len;
538         mac_buf = (uint8_t *)ctx->ccm_mac_buf;
539
540         macp = (uint8_t *)ctx->ccm_tmp;
541
542         while (mac_remain > 0) {
543
544                 if (mac_remain < block_size) {
545                         bzero(macp, block_size);
546                         bcopy(pt, macp, mac_remain);
547                         mac_remain = 0;
548                 } else {
549                         copy_block(pt, macp);
550                         mac_remain -= block_size;
551                         pt += block_size;
552                 }
553
554                 /* calculate the CBC MAC */
555                 xor_block(macp, mac_buf);
556                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
557         }
558
559         /* Calculate the CCM MAC */
560         ccm_mac_p = (uint8_t *)ctx->ccm_tmp;
561         calculate_ccm_mac((ccm_ctx_t *)ctx, ccm_mac_p, encrypt_block);
562
563         /* compare the input CCM MAC value with what we calculated */
564         if (bcmp(ctx->ccm_mac_input_buf, ccm_mac_p, ctx->ccm_mac_len)) {
565                 /* They don't match */
566                 return (CRYPTO_INVALID_MAC);
567         } else {
568                 rv = crypto_put_output_data(ctx->ccm_pt_buf, out, pt_len);
569                 if (rv != CRYPTO_SUCCESS)
570                         return (rv);
571                 out->cd_offset += pt_len;
572         }
573         return (CRYPTO_SUCCESS);
574 }
575
576 static int
577 ccm_validate_args(CK_AES_CCM_PARAMS *ccm_param, boolean_t is_encrypt_init)
578 {
579         size_t macSize, nonceSize;
580         uint8_t q;
581         uint64_t maxValue;
582
583         /*
584          * Check the length of the MAC.  The only valid
585          * lengths for the MAC are: 4, 6, 8, 10, 12, 14, 16
586          */
587         macSize = ccm_param->ulMACSize;
588         if ((macSize < 4) || (macSize > 16) || ((macSize % 2) != 0)) {
589                 return (CRYPTO_MECHANISM_PARAM_INVALID);
590         }
591
592         /* Check the nonce length.  Valid values are 7, 8, 9, 10, 11, 12, 13 */
593         nonceSize = ccm_param->ulNonceSize;
594         if ((nonceSize < 7) || (nonceSize > 13)) {
595                 return (CRYPTO_MECHANISM_PARAM_INVALID);
596         }
597
598         /* q is the length of the field storing the length, in bytes */
599         q = (uint8_t)((15 - nonceSize) & 0xFF);
600
601
602         /*
603          * If it is decrypt, need to make sure size of ciphertext is at least
604          * bigger than MAC len
605          */
606         if ((!is_encrypt_init) && (ccm_param->ulDataSize < macSize)) {
607                 return (CRYPTO_MECHANISM_PARAM_INVALID);
608         }
609
610         /*
611          * Check to make sure the length of the payload is within the
612          * range of values allowed by q
613          */
614         if (q < 8) {
615                 maxValue = (1ULL << (q * 8)) - 1;
616         } else {
617                 maxValue = ULONG_MAX;
618         }
619
620         if (ccm_param->ulDataSize > maxValue) {
621                 return (CRYPTO_MECHANISM_PARAM_INVALID);
622         }
623         return (CRYPTO_SUCCESS);
624 }
625
626 /*
627  * Format the first block used in CBC-MAC (B0) and the initial counter
628  * block based on formatting functions and counter generation functions
629  * specified in RFC 3610 and NIST publication 800-38C, appendix A
630  *
631  * b0 is the first block used in CBC-MAC
632  * cb0 is the first counter block
633  *
634  * It's assumed that the arguments b0 and cb0 are preallocated AES blocks
635  *
636  */
637 static void
638 ccm_format_initial_blocks(uchar_t *nonce, ulong_t nonceSize,
639     ulong_t authDataSize, uint8_t *b0, ccm_ctx_t *aes_ctx)
640 {
641         uint64_t payloadSize;
642         uint8_t t, q, have_adata = 0;
643         size_t limit;
644         int i, j, k;
645         uint64_t mask = 0;
646         uint8_t *cb;
647
648         q = (uint8_t)((15 - nonceSize) & 0xFF);
649         t = (uint8_t)((aes_ctx->ccm_mac_len) & 0xFF);
650
651         /* Construct the first octet of b0 */
652         if (authDataSize > 0) {
653                 have_adata = 1;
654         }
655         b0[0] = (have_adata << 6) | (((t - 2)  / 2) << 3) | (q - 1);
656
657         /* copy the nonce value into b0 */
658         bcopy(nonce, &(b0[1]), nonceSize);
659
660         /* store the length of the payload into b0 */
661         bzero(&(b0[1+nonceSize]), q);
662
663         payloadSize = aes_ctx->ccm_data_len;
664         limit = 8 < q ? 8 : q;
665
666         for (i = 0, j = 0, k = 15; i < limit; i++, j += 8, k--) {
667                 b0[k] = (uint8_t)((payloadSize >> j) & 0xFF);
668         }
669
670         /* format the counter block */
671
672         cb = (uint8_t *)aes_ctx->ccm_cb;
673
674         cb[0] = 0x07 & (q-1); /* first byte */
675
676         /* copy the nonce value into the counter block */
677         bcopy(nonce, &(cb[1]), nonceSize);
678
679         bzero(&(cb[1+nonceSize]), q);
680
681         /* Create the mask for the counter field based on the size of nonce */
682         q <<= 3;
683         while (q-- > 0) {
684                 mask |= (1ULL << q);
685         }
686
687 #ifdef _ZFS_LITTLE_ENDIAN
688         mask = htonll(mask);
689 #endif
690         aes_ctx->ccm_counter_mask = mask;
691
692         /*
693          * During calculation, we start using counter block 1, we will
694          * set it up right here.
695          * We can just set the last byte to have the value 1, because
696          * even with the biggest nonce of 13, the last byte of the
697          * counter block will be used for the counter value.
698          */
699         cb[15] = 0x01;
700 }
701
702 /*
703  * Encode the length of the associated data as
704  * specified in RFC 3610 and NIST publication 800-38C, appendix A
705  */
706 static void
707 encode_adata_len(ulong_t auth_data_len, uint8_t *encoded, size_t *encoded_len)
708 {
709 #ifdef UNALIGNED_POINTERS_PERMITTED
710         uint32_t        *lencoded_ptr;
711 #ifdef _LP64
712         uint64_t        *llencoded_ptr;
713 #endif
714 #endif  /* UNALIGNED_POINTERS_PERMITTED */
715
716         if (auth_data_len < ((1ULL<<16) - (1ULL<<8))) {
717                 /* 0 < a < (2^16-2^8) */
718                 *encoded_len = 2;
719                 encoded[0] = (auth_data_len & 0xff00) >> 8;
720                 encoded[1] = auth_data_len & 0xff;
721
722         } else if ((auth_data_len >= ((1ULL<<16) - (1ULL<<8))) &&
723             (auth_data_len < (1ULL << 31))) {
724                 /* (2^16-2^8) <= a < 2^32 */
725                 *encoded_len = 6;
726                 encoded[0] = 0xff;
727                 encoded[1] = 0xfe;
728 #ifdef UNALIGNED_POINTERS_PERMITTED
729                 lencoded_ptr = (uint32_t *)&encoded[2];
730                 *lencoded_ptr = htonl(auth_data_len);
731 #else
732                 encoded[2] = (auth_data_len & 0xff000000) >> 24;
733                 encoded[3] = (auth_data_len & 0xff0000) >> 16;
734                 encoded[4] = (auth_data_len & 0xff00) >> 8;
735                 encoded[5] = auth_data_len & 0xff;
736 #endif  /* UNALIGNED_POINTERS_PERMITTED */
737
738 #ifdef _LP64
739         } else {
740                 /* 2^32 <= a < 2^64 */
741                 *encoded_len = 10;
742                 encoded[0] = 0xff;
743                 encoded[1] = 0xff;
744 #ifdef UNALIGNED_POINTERS_PERMITTED
745                 llencoded_ptr = (uint64_t *)&encoded[2];
746                 *llencoded_ptr = htonl(auth_data_len);
747 #else
748                 encoded[2] = (auth_data_len & 0xff00000000000000) >> 56;
749                 encoded[3] = (auth_data_len & 0xff000000000000) >> 48;
750                 encoded[4] = (auth_data_len & 0xff0000000000) >> 40;
751                 encoded[5] = (auth_data_len & 0xff00000000) >> 32;
752                 encoded[6] = (auth_data_len & 0xff000000) >> 24;
753                 encoded[7] = (auth_data_len & 0xff0000) >> 16;
754                 encoded[8] = (auth_data_len & 0xff00) >> 8;
755                 encoded[9] = auth_data_len & 0xff;
756 #endif  /* UNALIGNED_POINTERS_PERMITTED */
757 #endif  /* _LP64 */
758         }
759 }
760
761 static int
762 ccm_init(ccm_ctx_t *ctx, unsigned char *nonce, size_t nonce_len,
763     unsigned char *auth_data, size_t auth_data_len, size_t block_size,
764     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
765     void (*xor_block)(uint8_t *, uint8_t *))
766 {
767         uint8_t *mac_buf, *datap, *ivp, *authp;
768         size_t remainder, processed;
769         uint8_t encoded_a[10]; /* max encoded auth data length is 10 octets */
770         size_t encoded_a_len = 0;
771
772         mac_buf = (uint8_t *)&(ctx->ccm_mac_buf);
773
774         /*
775          * Format the 1st block for CBC-MAC and construct the
776          * 1st counter block.
777          *
778          * aes_ctx->ccm_iv is used for storing the counter block
779          * mac_buf will store b0 at this time.
780          */
781         ccm_format_initial_blocks(nonce, nonce_len,
782             auth_data_len, mac_buf, ctx);
783
784         /* The IV for CBC MAC for AES CCM mode is always zero */
785         ivp = (uint8_t *)ctx->ccm_tmp;
786         bzero(ivp, block_size);
787
788         xor_block(ivp, mac_buf);
789
790         /* encrypt the nonce */
791         encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
792
793         /* take care of the associated data, if any */
794         if (auth_data_len == 0) {
795                 return (CRYPTO_SUCCESS);
796         }
797
798         encode_adata_len(auth_data_len, encoded_a, &encoded_a_len);
799
800         remainder = auth_data_len;
801
802         /* 1st block: it contains encoded associated data, and some data */
803         authp = (uint8_t *)ctx->ccm_tmp;
804         bzero(authp, block_size);
805         bcopy(encoded_a, authp, encoded_a_len);
806         processed = block_size - encoded_a_len;
807         if (processed > auth_data_len) {
808                 /* in case auth_data is very small */
809                 processed = auth_data_len;
810         }
811         bcopy(auth_data, authp+encoded_a_len, processed);
812         /* xor with previous buffer */
813         xor_block(authp, mac_buf);
814         encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
815         remainder -= processed;
816         if (remainder == 0) {
817                 /* a small amount of associated data, it's all done now */
818                 return (CRYPTO_SUCCESS);
819         }
820
821         do {
822                 if (remainder < block_size) {
823                         /*
824                          * There's not a block full of data, pad rest of
825                          * buffer with zero
826                          */
827                         bzero(authp, block_size);
828                         bcopy(&(auth_data[processed]), authp, remainder);
829                         datap = (uint8_t *)authp;
830                         remainder = 0;
831                 } else {
832                         datap = (uint8_t *)(&(auth_data[processed]));
833                         processed += block_size;
834                         remainder -= block_size;
835                 }
836
837                 xor_block(datap, mac_buf);
838                 encrypt_block(ctx->ccm_keysched, mac_buf, mac_buf);
839
840         } while (remainder > 0);
841
842         return (CRYPTO_SUCCESS);
843 }
844
845 /*
846  * The following function should be call at encrypt or decrypt init time
847  * for AES CCM mode.
848  */
849 int
850 ccm_init_ctx(ccm_ctx_t *ccm_ctx, char *param, int kmflag,
851     boolean_t is_encrypt_init, size_t block_size,
852     int (*encrypt_block)(const void *, const uint8_t *, uint8_t *),
853     void (*xor_block)(uint8_t *, uint8_t *))
854 {
855         int rv;
856         CK_AES_CCM_PARAMS *ccm_param;
857
858         if (param != NULL) {
859                 ccm_param = (CK_AES_CCM_PARAMS *)param;
860
861                 if ((rv = ccm_validate_args(ccm_param,
862                     is_encrypt_init)) != 0) {
863                         return (rv);
864                 }
865
866                 ccm_ctx->ccm_mac_len = ccm_param->ulMACSize;
867                 if (is_encrypt_init) {
868                         ccm_ctx->ccm_data_len = ccm_param->ulDataSize;
869                 } else {
870                         ccm_ctx->ccm_data_len =
871                             ccm_param->ulDataSize - ccm_ctx->ccm_mac_len;
872                         ccm_ctx->ccm_processed_mac_len = 0;
873                 }
874                 ccm_ctx->ccm_processed_data_len = 0;
875
876                 ccm_ctx->ccm_flags |= CCM_MODE;
877         } else {
878                 return (CRYPTO_MECHANISM_PARAM_INVALID);
879         }
880
881         if (ccm_init(ccm_ctx, ccm_param->nonce, ccm_param->ulNonceSize,
882             ccm_param->authData, ccm_param->ulAuthDataSize, block_size,
883             encrypt_block, xor_block) != 0) {
884                 return (CRYPTO_MECHANISM_PARAM_INVALID);
885         }
886         if (!is_encrypt_init) {
887                 /* allocate buffer for storing decrypted plaintext */
888                 ccm_ctx->ccm_pt_buf = vmem_alloc(ccm_ctx->ccm_data_len,
889                     kmflag);
890                 if (ccm_ctx->ccm_pt_buf == NULL) {
891                         rv = CRYPTO_HOST_MEMORY;
892                 }
893         }
894         return (rv);
895 }
896
897 void *
898 ccm_alloc_ctx(int kmflag)
899 {
900         ccm_ctx_t *ccm_ctx;
901
902         if ((ccm_ctx = kmem_zalloc(sizeof (ccm_ctx_t), kmflag)) == NULL)
903                 return (NULL);
904
905         ccm_ctx->ccm_flags = CCM_MODE;
906         return (ccm_ctx);
907 }