1 // Copyright 2019 The BoringSSL Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <map>
16 #include <memory>
17 #include <string>
18 #include <string_view>
19 #include <vector>
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <limits.h>
24 #include <string.h>
25 #include <sys/uio.h>
26 #include <unistd.h>
27 #include <cstdarg>
28
29 #include <openssl/aead.h>
30 #include <openssl/aes.h>
31 #include <openssl/bn.h>
32 #include <openssl/bytestring.h>
33 #include <openssl/cipher.h>
34 #include <openssl/cmac.h>
35 #include <openssl/ctrdrbg.h>
36 #include <openssl/dh.h>
37 #include <openssl/digest.h>
38 #include <openssl/ec.h>
39 #include <openssl/ec_key.h>
40 #include <openssl/ecdh.h>
41 #include <openssl/ecdsa.h>
42 #include <openssl/err.h>
43 #include <openssl/hkdf.h>
44 #include <openssl/hmac.h>
45 #include <openssl/obj.h>
46 #include <openssl/rsa.h>
47 #include <openssl/sha.h>
48 #include <openssl/span.h>
49
50 #include "../../../../crypto/fipsmodule/bcm_interface.h"
51 #include "../../../../crypto/fipsmodule/ec/internal.h"
52 #include "../../../../crypto/fipsmodule/rand/internal.h"
53 #include "../../../../crypto/fipsmodule/tls/internal.h"
54 #include "modulewrapper.h"
55
56
57 namespace bssl {
58 namespace acvp {
59
60 #if defined(OPENSSL_TRUSTY)
61 #include <trusty_log.h>
62 #define LOG_ERROR(...) TLOGE(__VA_ARGS__)
63 #define TLOG_TAG "modulewrapper"
64 #else
65 #define LOG_ERROR(...) fprintf(stderr, __VA_ARGS__)
66 #endif // OPENSSL_TRUSTY
67
68 constexpr size_t kMaxArgLength = (1 << 20);
69
70 RequestBuffer::~RequestBuffer() = default;
71
72 class RequestBufferImpl : public RequestBuffer {
73 public:
74 ~RequestBufferImpl() = default;
75
76 std::vector<uint8_t> buf;
77 Span<const uint8_t> args[kMaxArgs];
78 };
79
80 // static
New()81 std::unique_ptr<RequestBuffer> RequestBuffer::New() {
82 return std::make_unique<RequestBufferImpl>();
83 }
84
ReadAll(int fd,void * in_data,size_t data_len)85 static bool ReadAll(int fd, void *in_data, size_t data_len) {
86 uint8_t *data = reinterpret_cast<uint8_t *>(in_data);
87 size_t done = 0;
88
89 while (done < data_len) {
90 ssize_t r;
91 do {
92 r = read(fd, &data[done], data_len - done);
93 } while (r == -1 && errno == EINTR);
94
95 if (r <= 0) {
96 return false;
97 }
98
99 done += r;
100 }
101
102 return true;
103 }
104
ParseArgsFromFd(int fd,RequestBuffer * in_buffer)105 Span<const Span<const uint8_t>> ParseArgsFromFd(int fd,
106 RequestBuffer *in_buffer) {
107 RequestBufferImpl *buffer = reinterpret_cast<RequestBufferImpl *>(in_buffer);
108 uint32_t nums[1 + kMaxArgs];
109 const Span<const Span<const uint8_t>> empty_span;
110
111 if (!ReadAll(fd, nums, sizeof(uint32_t) * 2)) {
112 return empty_span;
113 }
114
115 const size_t num_args = nums[0];
116 if (num_args == 0) {
117 LOG_ERROR("Invalid, zero-argument operation requested.\n");
118 return empty_span;
119 } else if (num_args > kMaxArgs) {
120 LOG_ERROR("Operation requested with %zu args, but %zu is the limit.\n",
121 num_args, kMaxArgs);
122 return empty_span;
123 }
124
125 if (num_args > 1 &&
126 !ReadAll(fd, &nums[2], sizeof(uint32_t) * (num_args - 1))) {
127 return empty_span;
128 }
129
130 size_t need = 0;
131 for (size_t i = 0; i < num_args; i++) {
132 const size_t arg_length = nums[i + 1];
133 if (i == 0 && arg_length > kMaxNameLength) {
134 LOG_ERROR("Operation with name of length %zu exceeded limit of %zu.\n",
135 arg_length, kMaxNameLength);
136 return empty_span;
137 } else if (arg_length > kMaxArgLength) {
138 LOG_ERROR(
139 "Operation with argument of length %zu exceeded limit of %zu.\n",
140 arg_length, kMaxArgLength);
141 return empty_span;
142 }
143
144 // This static_assert confirms that the following addition doesn't
145 // overflow.
146 static_assert((kMaxArgs - 1 * kMaxArgLength) + kMaxNameLength > (1 << 30),
147 "Argument limits permit excessive messages");
148 need += arg_length;
149 }
150
151 if (need > buffer->buf.size()) {
152 size_t alloced = need + (need >> 1);
153 if (alloced < need) {
154 abort();
155 }
156 buffer->buf.resize(alloced);
157 }
158
159 if (!ReadAll(fd, buffer->buf.data(), need)) {
160 return empty_span;
161 }
162
163 size_t offset = 0;
164 for (size_t i = 0; i < num_args; i++) {
165 buffer->args[i] = Span<const uint8_t>(&buffer->buf[offset], nums[i + 1]);
166 offset += nums[i + 1];
167 }
168
169 return Span<const Span<const uint8_t>>(buffer->args, num_args);
170 }
171
172 // g_reply_buffer contains buffered replies which will be flushed when acvp
173 // requests.
174 static std::vector<uint8_t> g_reply_buffer;
175
WriteReplyToBuffer(const std::vector<Span<const uint8_t>> & spans)176 bool WriteReplyToBuffer(const std::vector<Span<const uint8_t>> &spans) {
177 if (spans.size() > kMaxArgs) {
178 abort();
179 }
180
181 uint8_t buf[4];
182 CRYPTO_store_u32_le(buf, spans.size());
183 g_reply_buffer.insert(g_reply_buffer.end(), buf, buf + sizeof(buf));
184 for (const auto &span : spans) {
185 CRYPTO_store_u32_le(buf, span.size());
186 g_reply_buffer.insert(g_reply_buffer.end(), buf, buf + sizeof(buf));
187 }
188 for (const auto &span : spans) {
189 g_reply_buffer.insert(g_reply_buffer.end(), span.begin(), span.end());
190 }
191
192 return true;
193 }
194
FlushBuffer(int fd)195 bool FlushBuffer(int fd) {
196 size_t done = 0;
197
198 while (done < g_reply_buffer.size()) {
199 ssize_t n;
200 do {
201 n = write(fd, g_reply_buffer.data() + done, g_reply_buffer.size() - done);
202 } while (n < 0 && errno == EINTR);
203
204 if (n < 0) {
205 return false;
206 }
207 done += static_cast<size_t>(n);
208 }
209
210 g_reply_buffer.clear();
211
212 return true;
213 }
214
WriteReplyToFd(int fd,const std::vector<Span<const uint8_t>> & spans)215 bool WriteReplyToFd(int fd, const std::vector<Span<const uint8_t>> &spans) {
216 if (spans.size() > kMaxArgs) {
217 abort();
218 }
219
220 uint32_t nums[1 + kMaxArgs];
221 iovec iovs[kMaxArgs + 1];
222 nums[0] = spans.size();
223 iovs[0].iov_base = nums;
224 iovs[0].iov_len = sizeof(uint32_t) * (1 + spans.size());
225
226 size_t num_iov = 1;
227 for (size_t i = 0; i < spans.size(); i++) {
228 const auto &span = spans[i];
229 nums[i + 1] = span.size();
230 if (span.empty()) {
231 continue;
232 }
233
234 iovs[num_iov].iov_base = const_cast<uint8_t *>(span.data());
235 iovs[num_iov].iov_len = span.size();
236 num_iov++;
237 }
238
239 size_t iov_done = 0;
240 while (iov_done < num_iov) {
241 ssize_t r;
242 do {
243 r = writev(fd, &iovs[iov_done], num_iov - iov_done);
244 } while (r == -1 && errno == EINTR);
245
246 if (r <= 0) {
247 return false;
248 }
249
250 size_t written = r;
251 for (size_t i = iov_done; i < num_iov && written > 0; i++) {
252 iovec &iov = iovs[i];
253
254 size_t done = written;
255 if (done > iov.iov_len) {
256 done = iov.iov_len;
257 }
258
259 iov.iov_base = reinterpret_cast<uint8_t *>(iov.iov_base) + done;
260 iov.iov_len -= done;
261 written -= done;
262
263 if (iov.iov_len == 0) {
264 iov_done++;
265 }
266 }
267
268 assert(written == 0);
269 }
270
271 return true;
272 }
273
GetConfig(const Span<const uint8_t> args[],ReplyCallback write_reply)274 static bool GetConfig(const Span<const uint8_t> args[],
275 ReplyCallback write_reply) {
276 static constexpr char kConfig[] =
277 R"([
278 {
279 "algorithm": "acvptool",
280 "features": ["batch"]
281 },
282 {
283 "algorithm": "SHA2-224",
284 "revision": "1.0",
285 "messageLength": [{
286 "min": 0, "max": 65528, "increment": 8
287 }]
288 },
289 {
290 "algorithm": "SHA2-256",
291 "revision": "1.0",
292 "messageLength": [{
293 "min": 0, "max": 65528, "increment": 8
294 }]
295 },
296 {
297 "algorithm": "SHA2-384",
298 "revision": "1.0",
299 "messageLength": [{
300 "min": 0, "max": 65528, "increment": 8
301 }]
302 },
303 {
304 "algorithm": "SHA2-512",
305 "revision": "1.0",
306 "messageLength": [{
307 "min": 0, "max": 65528, "increment": 8
308 }]
309 },
310 {
311 "algorithm": "SHA2-512/256",
312 "revision": "1.0",
313 "messageLength": [{
314 "min": 0, "max": 65528, "increment": 8
315 }]
316 },
317 {
318 "algorithm": "SHA-1",
319 "revision": "1.0",
320 "messageLength": [{
321 "min": 0, "max": 65528, "increment": 8
322 }]
323 },
324 {
325 "algorithm": "ACVP-AES-ECB",
326 "revision": "1.0",
327 "direction": ["encrypt", "decrypt"],
328 "keyLen": [128, 192, 256]
329 },
330 {
331 "algorithm": "ACVP-AES-CTR",
332 "revision": "1.0",
333 "direction": ["encrypt", "decrypt"],
334 "keyLen": [128, 192, 256],
335 "payloadLen": [{
336 "min": 8, "max": 128, "increment": 8
337 }],
338 "incrementalCounter": true,
339 "overflowCounter": true,
340 "performCounterTests": true
341 },
342 {
343 "algorithm": "ACVP-AES-CBC",
344 "revision": "1.0",
345 "direction": ["encrypt", "decrypt"],
346 "keyLen": [128, 192, 256]
347 },
348 {
349 "algorithm": "ACVP-AES-GCM",
350 "revision": "1.0",
351 "direction": ["encrypt", "decrypt"],
352 "keyLen": [128, 256],
353 "payloadLen": [{
354 "min": 0, "max": 65536, "increment": 8
355 }],
356 "aadLen": [{
357 "min": 0, "max": 65536, "increment": 8
358 }],
359 "tagLen": [32, 64, 96, 104, 112, 120, 128],
360 "ivLen": [96],
361 "ivGen": "internal",
362 "ivGenMode": "8.2.2"
363 },
364 {
365 "algorithm": "ACVP-AES-GCM",
366 "revision": "1.0",
367 "direction": ["encrypt", "decrypt"],
368 "keyLen": [128, 192, 256],
369 "payloadLen": [{
370 "min": 0, "max": 65536, "increment": 8
371 }],
372 "aadLen": [{
373 "min": 0, "max": 65536, "increment": 8
374 }],
375 "tagLen": [32, 64, 96, 104, 112, 120, 128],
376 "ivLen": [96],
377 "ivGen": "external"
378 },
379 {
380 "algorithm": "ACVP-AES-GMAC",
381 "revision": "1.0",
382 "direction": ["encrypt", "decrypt"],
383 "keyLen": [128, 192, 256],
384 "payloadLen": [{
385 "min": 0, "max": 65536, "increment": 8
386 }],
387 "aadLen": [{
388 "min": 0, "max": 65536, "increment": 8
389 }],
390 "tagLen": [32, 64, 96, 104, 112, 120, 128],
391 "ivLen": [96],
392 "ivGen": "external"
393 },
394 {
395 "algorithm": "ACVP-AES-KW",
396 "revision": "1.0",
397 "direction": [
398 "encrypt",
399 "decrypt"
400 ],
401 "kwCipher": [
402 "cipher"
403 ],
404 "keyLen": [
405 128, 192, 256
406 ],
407 "payloadLen": [{"min": 128, "max": 4096, "increment": 64}]
408 },
409 {
410 "algorithm": "ACVP-AES-KWP",
411 "revision": "1.0",
412 "direction": [
413 "encrypt",
414 "decrypt"
415 ],
416 "kwCipher": [
417 "cipher"
418 ],
419 "keyLen": [
420 128, 192, 256
421 ],
422 "payloadLen": [{"min": 8, "max": 4096, "increment": 8}]
423 },
424 {
425 "algorithm": "ACVP-AES-CCM",
426 "revision": "1.0",
427 "direction": [
428 "encrypt",
429 "decrypt"
430 ],
431 "keyLen": [
432 128
433 ],
434 "payloadLen": [{"min": 0, "max": 256, "increment": 8}],
435 "ivLen": [104],
436 "tagLen": [32, 64],
437 "aadLen": [{"min": 0, "max": 524288, "increment": 8}]
438 },
439 {
440 "algorithm": "HMAC-SHA-1",
441 "revision": "1.0",
442 "keyLen": [{
443 "min": 8, "max": 524288, "increment": 8
444 }],
445 "macLen": [160]
446 },
447 {
448 "algorithm": "HMAC-SHA2-224",
449 "revision": "1.0",
450 "keyLen": [{
451 "min": 8, "max": 524288, "increment": 8
452 }],
453 "macLen": [224]
454 },
455 {
456 "algorithm": "HMAC-SHA2-256",
457 "revision": "1.0",
458 "keyLen": [{
459 "min": 8, "max": 524288, "increment": 8
460 }],
461 "macLen": [256]
462 },
463 {
464 "algorithm": "HMAC-SHA2-384",
465 "revision": "1.0",
466 "keyLen": [{
467 "min": 8, "max": 524288, "increment": 8
468 }],
469 "macLen": [384]
470 },
471 {
472 "algorithm": "HMAC-SHA2-512",
473 "revision": "1.0",
474 "keyLen": [{
475 "min": 8, "max": 524288, "increment": 8
476 }],
477 "macLen": [512]
478 },
479 {
480 "algorithm": "HMAC-SHA2-512/256",
481 "revision": "1.0",
482 "keyLen": [{
483 "min": 8, "max": 524288, "increment": 8
484 }],
485 "macLen": [256]
486 },
487 {
488 "algorithm": "ctrDRBG",
489 "revision": "1.0",
490 "predResistanceEnabled": [false],
491 "reseedImplemented": true,
492 "capabilities": [{
493 "mode": "AES-256",
494 "derFuncEnabled": true,
495 "entropyInputLen": [{"min": 256, "max": 512, "increment": 16}],
496 "nonceLen": [128],
497 "persoStringLen": [{"min": 0, "max": 384, "increment": 16}],
498 "additionalInputLen": [
499 {"min": 0, "max": 384, "increment": 16}
500 ],
501 "returnedBitsLen": 2048
502 }, {
503 "mode": "AES-256",
504 "derFuncEnabled": false,
505 "entropyInputLen": [384],
506 "nonceLen": [0],
507 "persoStringLen": [{"min": 0, "max": 384, "increment": 16}],
508 "additionalInputLen": [
509 {"min": 0, "max": 384, "increment": 16}
510 ],
511 "returnedBitsLen": 2048
512 }]
513 },
514 {
515 "algorithm": "ECDSA",
516 "mode": "keyGen",
517 "revision": "FIPS186-5",
518 "curve": [
519 "P-224",
520 "P-256",
521 "P-384",
522 "P-521"
523 ],
524 "secretGenerationMode": [
525 "testing candidates"
526 ]
527 },
528 {
529 "algorithm": "ECDSA",
530 "mode": "keyVer",
531 "revision": "FIPS186-5",
532 "curve": [
533 "P-224",
534 "P-256",
535 "P-384",
536 "P-521"
537 ]
538 },
539 {
540 "algorithm": "ECDSA",
541 "mode": "sigGen",
542 "revision": "FIPS186-5",
543 "capabilities": [{
544 "curve": [
545 "P-224",
546 "P-256",
547 "P-384",
548 "P-521"
549 ],
550 "hashAlg": [
551 "SHA2-224",
552 "SHA2-256",
553 "SHA2-384",
554 "SHA2-512",
555 "SHA2-512/256"
556 ]
557 }]
558 },
559 {
560 "algorithm": "ECDSA",
561 "mode": "sigVer",
562 "revision": "FIPS186-5",
563 "capabilities": [{
564 "curve": [
565 "P-224",
566 "P-256",
567 "P-384",
568 "P-521"
569 ],
570 "hashAlg": [
571 "SHA2-224",
572 "SHA2-256",
573 "SHA2-384",
574 "SHA2-512",
575 "SHA2-512/256"
576 ]
577 }]
578 },
579 {
580 "algorithm": "RSA",
581 "mode": "keyGen",
582 "revision": "FIPS186-5",
583 "infoGeneratedByServer": true,
584 "pubExpMode": "fixed",
585 "fixedPubExp": "010001",
586 "keyFormat": "standard",
587 "capabilities": [{
588 "randPQ": "probable",
589 "properties": [{
590 "modulo": 2048,
591 "primeTest": [
592 "2powSecStr"
593 ]
594 },{
595 "modulo": 3072,
596 "primeTest": [
597 "2powSecStr"
598 ]
599 },{
600 "modulo": 4096,
601 "primeTest": [
602 "2powSecStr"
603 ]
604 }]
605 }]
606 },
607 {
608 "algorithm": "RSA",
609 "mode": "sigGen",
610 "revision": "FIPS186-5",
611 "capabilities": [{
612 "sigType": "pkcs1v1.5",
613 "properties": [{
614 "modulo": 2048,
615 "hashPair": [{
616 "hashAlg": "SHA2-224"
617 }, {
618 "hashAlg": "SHA2-256"
619 }, {
620 "hashAlg": "SHA2-384"
621 }, {
622 "hashAlg": "SHA2-512"
623 }]
624 }]
625 },{
626 "sigType": "pkcs1v1.5",
627 "properties": [{
628 "modulo": 3072,
629 "hashPair": [{
630 "hashAlg": "SHA2-224"
631 }, {
632 "hashAlg": "SHA2-256"
633 }, {
634 "hashAlg": "SHA2-384"
635 }, {
636 "hashAlg": "SHA2-512"
637 }]
638 }]
639 },{
640 "sigType": "pkcs1v1.5",
641 "properties": [{
642 "modulo": 4096,
643 "hashPair": [{
644 "hashAlg": "SHA2-224"
645 }, {
646 "hashAlg": "SHA2-256"
647 }, {
648 "hashAlg": "SHA2-384"
649 }, {
650 "hashAlg": "SHA2-512"
651 }]
652 }]
653 },{
654 "sigType": "pss",
655 "properties": [{
656 "maskFunction": ["mgf1"],
657 "modulo": 2048,
658 "hashPair": [{
659 "hashAlg": "SHA2-224",
660 "saltLen": 28
661 }, {
662 "hashAlg": "SHA2-256",
663 "saltLen": 32
664 }, {
665 "hashAlg": "SHA2-384",
666 "saltLen": 48
667 }, {
668 "hashAlg": "SHA2-512",
669 "saltLen": 64
670 }, {
671 "hashAlg": "SHA2-512/256",
672 "saltLen": 32
673 }]
674 }]
675 },{
676 "sigType": "pss",
677 "properties": [{
678 "maskFunction": ["mgf1"],
679 "modulo": 3072,
680 "hashPair": [{
681 "hashAlg": "SHA2-224",
682 "saltLen": 28
683 }, {
684 "hashAlg": "SHA2-256",
685 "saltLen": 32
686 }, {
687 "hashAlg": "SHA2-384",
688 "saltLen": 48
689 }, {
690 "hashAlg": "SHA2-512",
691 "saltLen": 64
692 }, {
693 "hashAlg": "SHA2-512/256",
694 "saltLen": 32
695 }]
696 }]
697 },{
698 "sigType": "pss",
699 "properties": [{
700 "maskFunction": ["mgf1"],
701 "modulo": 4096,
702 "hashPair": [{
703 "hashAlg": "SHA2-224",
704 "saltLen": 28
705 }, {
706 "hashAlg": "SHA2-256",
707 "saltLen": 32
708 }, {
709 "hashAlg": "SHA2-384",
710 "saltLen": 48
711 }, {
712 "hashAlg": "SHA2-512",
713 "saltLen": 64
714 }, {
715 "hashAlg": "SHA2-512/256",
716 "saltLen": 32
717 }]
718 }]
719 }]
720 },
721 {
722 "algorithm": "RSA",
723 "mode": "sigVer",
724 "revision": "FIPS186-5",
725 "pubExpMode": "fixed",
726 "fixedPubExp": "010001",
727 "capabilities": [{
728 "sigType": "pkcs1v1.5",
729 "properties": [{
730 "modulo": 2048,
731 "hashPair": [{
732 "hashAlg": "SHA2-224"
733 }, {
734 "hashAlg": "SHA2-256"
735 }, {
736 "hashAlg": "SHA2-384"
737 }, {
738 "hashAlg": "SHA2-512"
739 }]
740 }]
741 },{
742 "sigType": "pkcs1v1.5",
743 "properties": [{
744 "modulo": 3072,
745 "hashPair": [{
746 "hashAlg": "SHA2-224"
747 }, {
748 "hashAlg": "SHA2-256"
749 }, {
750 "hashAlg": "SHA2-384"
751 }, {
752 "hashAlg": "SHA2-512"
753 }]
754 }]
755 },{
756 "sigType": "pkcs1v1.5",
757 "properties": [{
758 "modulo": 4096,
759 "hashPair": [{
760 "hashAlg": "SHA2-224"
761 }, {
762 "hashAlg": "SHA2-256"
763 }, {
764 "hashAlg": "SHA2-384"
765 }, {
766 "hashAlg": "SHA2-512"
767 }]
768 }]
769 },{
770 "sigType": "pss",
771 "properties": [{
772 "maskFunction": ["mgf1"],
773 "modulo": 2048,
774 "hashPair": [{
775 "hashAlg": "SHA2-224",
776 "saltLen": 28
777 }, {
778 "hashAlg": "SHA2-256",
779 "saltLen": 32
780 }, {
781 "hashAlg": "SHA2-384",
782 "saltLen": 48
783 }, {
784 "hashAlg": "SHA2-512",
785 "saltLen": 64
786 }, {
787 "hashAlg": "SHA2-512/256",
788 "saltLen": 32
789 }]
790 }]
791 },{
792 "sigType": "pss",
793 "properties": [{
794 "maskFunction": ["mgf1"],
795 "modulo": 3072,
796 "hashPair": [{
797 "hashAlg": "SHA2-224",
798 "saltLen": 28
799 }, {
800 "hashAlg": "SHA2-256",
801 "saltLen": 32
802 }, {
803 "hashAlg": "SHA2-384",
804 "saltLen": 48
805 }, {
806 "hashAlg": "SHA2-512",
807 "saltLen": 64
808 }, {
809 "hashAlg": "SHA2-512/256",
810 "saltLen": 32
811 }]
812 }]
813 },{
814 "sigType": "pss",
815 "properties": [{
816 "maskFunction": ["mgf1"],
817 "modulo": 4096,
818 "hashPair": [{
819 "hashAlg": "SHA2-224",
820 "saltLen": 28
821 }, {
822 "hashAlg": "SHA2-256",
823 "saltLen": 32
824 }, {
825 "hashAlg": "SHA2-384",
826 "saltLen": 48
827 }, {
828 "hashAlg": "SHA2-512",
829 "saltLen": 64
830 }, {
831 "hashAlg": "SHA2-512/256",
832 "saltLen": 32
833 }]
834 }]
835 }]
836 },
837 {
838 "algorithm": "CMAC-AES",
839 "acvptoolTestOnly": true,
840 "revision": "1.0",
841 "capabilities": [{
842 "direction": ["gen", "ver"],
843 "msgLen": [{
844 "min": 0,
845 "max": 524288,
846 "increment": 8
847 }],
848 "keyLen": [128, 256],
849 "macLen": [128]
850 }]
851 },
852 {
853 "algorithm": "KAS-ECC-SSC",
854 "revision": "Sp800-56Ar3",
855 "scheme": {
856 "ephemeralUnified": {
857 "kasRole": [
858 "initiator",
859 "responder"
860 ]
861 },
862 "staticUnified": {
863 "kasRole": [
864 "initiator",
865 "responder"
866 ]
867 }
868 },
869 "domainParameterGenerationMethods": [
870 "P-224",
871 "P-256",
872 "P-384",
873 "P-521"
874 ]
875 },
876 {
877 "algorithm": "KAS-FFC-SSC",
878 "revision": "Sp800-56Ar3",
879 "scheme": {
880 "dhEphem": {
881 "kasRole": [
882 "initiator"
883 ]
884 }
885 },
886 "domainParameterGenerationMethods": [
887 "FB",
888 "FC"
889 ]
890 },
891 {
892 "algorithm": "KDA",
893 "mode": "HKDF",
894 "revision": "Sp800-56Cr1",
895 "fixedInfoPattern": "uPartyInfo||vPartyInfo",
896 "encoding": [
897 "concatenation"
898 ],
899 "hmacAlg": [
900 "SHA2-224",
901 "SHA2-256",
902 "SHA2-384",
903 "SHA2-512",
904 "SHA2-512/256"
905 ],
906 "macSaltMethods": [
907 "default",
908 "random"
909 ],
910 "l": 2048,
911 "z": [
912 {
913 "min": 224,
914 "max": 65336,
915 "increment": 8
916 }
917 ]
918 },
919 {
920 "algorithm": "TLS-v1.2",
921 "mode": "KDF",
922 "revision": "RFC7627",
923 "hashAlg": [
924 "SHA2-256",
925 "SHA2-384",
926 "SHA2-512"
927 ]
928 },
929 {
930 "algorithm": "TLS-v1.3",
931 "mode": "KDF",
932 "revision": "RFC8446",
933 "hmacAlg": [
934 "SHA2-256",
935 "SHA2-384"
936 ],
937 "runningMode": [
938 "DHE",
939 "PSK",
940 "PSK-DHE"
941 ]
942 },
943 {
944 "algorithm": "ML-DSA",
945 "mode": "keyGen",
946 "revision": "FIPS204",
947 "parameterSets": [
948 "ML-DSA-44",
949 "ML-DSA-65",
950 "ML-DSA-87"
951 ]
952 },
953 {
954 "algorithm": "ML-DSA",
955 "mode": "sigGen",
956 "revision": "FIPS204",
957 "signatureInterfaces": ["internal"],
958 "deterministic": [
959 true,
960 false
961 ],
962 "externalMu": [
963 false
964 ],
965 "capabilities": [{
966 "parameterSets": [
967 "ML-DSA-44",
968 "ML-DSA-65",
969 "ML-DSA-87"
970 ],
971 "messageLength": [{
972 "min": 8,
973 "max": 65536,
974 "increment": 8
975 }]
976 }]
977 },
978 {
979 "algorithm": "ML-DSA",
980 "mode": "sigVer",
981 "revision": "FIPS204",
982 "signatureInterfaces": ["internal"],
983 "capabilities": [{
984 "messageLength": [{
985 "min": 8,
986 "max": 65536,
987 "increment": 8
988 }],
989 "parameterSets": [
990 "ML-DSA-44",
991 "ML-DSA-65",
992 "ML-DSA-87"
993 ]
994 }]
995 },
996 {
997 "algorithm": "ML-KEM",
998 "mode": "keyGen",
999 "revision": "FIPS203",
1000 "parameterSets": [
1001 "ML-KEM-768",
1002 "ML-KEM-1024"
1003 ]
1004 },
1005 {
1006 "algorithm": "ML-KEM",
1007 "mode": "encapDecap",
1008 "revision": "FIPS203",
1009 "parameterSets": [
1010 "ML-KEM-768",
1011 "ML-KEM-1024"
1012 ],
1013 "functions": [
1014 "encapsulation",
1015 "decapsulation"
1016 ]
1017 },
1018 {
1019 "algorithm": "SLH-DSA",
1020 "mode": "keyGen",
1021 "revision": "FIPS205",
1022 "parameterSets": [
1023 "SLH-DSA-SHA2-128s"
1024 ]
1025 },
1026 {
1027 "algorithm": "SLH-DSA",
1028 "mode": "sigGen",
1029 "revision": "FIPS205",
1030 "deterministic": [
1031 true,
1032 false
1033 ],
1034 "signatureInterfaces": [ "internal" ],
1035 "capabilities": [
1036 {
1037 "parameterSets": [
1038 "SLH-DSA-SHA2-128s"
1039 ],
1040 "messageLength": [
1041 {
1042 "min": 8,
1043 "max": 65536,
1044 "increment": 8
1045 }
1046 ]
1047 }
1048 ]
1049 },
1050 {
1051 "algorithm": "SLH-DSA",
1052 "mode": "sigVer",
1053 "revision": "FIPS205",
1054 "signatureInterfaces": [ "internal" ],
1055 "deterministic": [
1056 true,
1057 false
1058 ],
1059 "capabilities": [
1060 {
1061 "parameterSets": [
1062 "SLH-DSA-SHA2-128s"
1063 ],
1064 "messageLength": [
1065 {
1066 "min": 8,
1067 "max": 65536,
1068 "increment": 8
1069 }
1070 ]
1071 }
1072 ]
1073 }
1074 ])";
1075 return write_reply({bssl::StringAsBytes(kConfig)});
1076 }
1077
Flush(const Span<const uint8_t> args[],ReplyCallback write_reply)1078 static bool Flush(const Span<const uint8_t> args[], ReplyCallback write_reply) {
1079 fprintf(
1080 stderr,
1081 "modulewrapper code processed a `flush` command but this must be handled "
1082 "at a higher-level. See the example in main.cc in BoringSSL\n");
1083 abort();
1084 }
1085
1086 template <uint8_t *(*OneShotHash)(const uint8_t *, size_t, uint8_t *),
1087 size_t DigestLength>
Hash(const Span<const uint8_t> args[],ReplyCallback write_reply)1088 static bool Hash(const Span<const uint8_t> args[], ReplyCallback write_reply) {
1089 uint8_t digest[DigestLength];
1090 OneShotHash(args[0].data(), args[0].size(), digest);
1091 return write_reply({Span<const uint8_t>(digest)});
1092 }
1093
1094 template <uint8_t *(*OneShotHash)(const uint8_t *, size_t, uint8_t *),
1095 size_t DigestLength>
HashMCT(const Span<const uint8_t> args[],ReplyCallback write_reply)1096 static bool HashMCT(const Span<const uint8_t> args[],
1097 ReplyCallback write_reply) {
1098 if (args[0].size() != DigestLength) {
1099 return false;
1100 }
1101
1102 uint8_t buf[DigestLength * 3];
1103 memcpy(buf, args[0].data(), DigestLength);
1104 memcpy(buf + DigestLength, args[0].data(), DigestLength);
1105 memcpy(buf + 2 * DigestLength, args[0].data(), DigestLength);
1106
1107 for (size_t i = 0; i < 1000; i++) {
1108 uint8_t digest[DigestLength];
1109 OneShotHash(buf, sizeof(buf), digest);
1110 memmove(buf, buf + DigestLength, DigestLength * 2);
1111 memcpy(buf + DigestLength * 2, digest, DigestLength);
1112 }
1113
1114 return write_reply({Span(buf).subspan(2 * DigestLength, DigestLength)});
1115 }
1116
GetIterations(const Span<const uint8_t> iterations_bytes)1117 static uint32_t GetIterations(const Span<const uint8_t> iterations_bytes) {
1118 uint32_t iterations;
1119 if (iterations_bytes.size() != sizeof(iterations)) {
1120 LOG_ERROR(
1121 "Expected %u-byte input for number of iterations, but found %u "
1122 "bytes.\n",
1123 static_cast<unsigned>(sizeof(iterations)),
1124 static_cast<unsigned>(iterations_bytes.size()));
1125 abort();
1126 }
1127
1128 memcpy(&iterations, iterations_bytes.data(), sizeof(iterations));
1129 if (iterations == 0 || iterations == UINT32_MAX) {
1130 LOG_ERROR("Invalid number of iterations: %x.\n",
1131 static_cast<unsigned>(iterations));
1132 abort();
1133 }
1134
1135 return iterations;
1136 }
1137
1138 template <int (*SetKey)(const uint8_t *key, unsigned bits, AES_KEY *out),
1139 void (*Block)(const uint8_t *in, uint8_t *out, const AES_KEY *key)>
AES(const Span<const uint8_t> args[],ReplyCallback write_reply)1140 static bool AES(const Span<const uint8_t> args[], ReplyCallback write_reply) {
1141 AES_KEY key;
1142 if (SetKey(args[0].data(), args[0].size() * 8, &key) != 0) {
1143 return false;
1144 }
1145 if (args[1].size() % AES_BLOCK_SIZE != 0) {
1146 return false;
1147 }
1148 std::vector<uint8_t> result(args[1].begin(), args[1].end());
1149 const uint32_t iterations = GetIterations(args[2]);
1150
1151 std::vector<uint8_t> prev_result;
1152 for (uint32_t j = 0; j < iterations; j++) {
1153 if (j == iterations - 1) {
1154 prev_result = result;
1155 }
1156
1157 for (size_t i = 0; i < args[1].size(); i += AES_BLOCK_SIZE) {
1158 Block(result.data() + i, result.data() + i, &key);
1159 }
1160 }
1161
1162 return write_reply(
1163 {Span<const uint8_t>(result), Span<const uint8_t>(prev_result)});
1164 }
1165
1166 template <int (*SetKey)(const uint8_t *key, unsigned bits, AES_KEY *out),
1167 int Direction>
AES_CBC(const Span<const uint8_t> args[],ReplyCallback write_reply)1168 static bool AES_CBC(const Span<const uint8_t> args[],
1169 ReplyCallback write_reply) {
1170 AES_KEY key;
1171 if (SetKey(args[0].data(), args[0].size() * 8, &key) != 0) {
1172 return false;
1173 }
1174 if (args[1].size() % AES_BLOCK_SIZE != 0 || args[1].empty() ||
1175 args[2].size() != AES_BLOCK_SIZE) {
1176 return false;
1177 }
1178 std::vector<uint8_t> input(args[1].begin(), args[1].end());
1179 std::vector<uint8_t> iv(args[2].begin(), args[2].end());
1180 const uint32_t iterations = GetIterations(args[3]);
1181
1182 std::vector<uint8_t> result(input.size());
1183 std::vector<uint8_t> prev_result, prev_input;
1184
1185 for (uint32_t j = 0; j < iterations; j++) {
1186 prev_result = result;
1187 if (j > 0) {
1188 if (Direction == AES_ENCRYPT) {
1189 iv = result;
1190 } else {
1191 iv = prev_input;
1192 }
1193 }
1194
1195 // AES_cbc_encrypt will mutate the given IV, but we need it later.
1196 uint8_t iv_copy[AES_BLOCK_SIZE];
1197 memcpy(iv_copy, iv.data(), sizeof(iv_copy));
1198 AES_cbc_encrypt(input.data(), result.data(), input.size(), &key, iv_copy,
1199 Direction);
1200
1201 if (Direction == AES_DECRYPT) {
1202 prev_input = input;
1203 }
1204
1205 if (j == 0) {
1206 input = iv;
1207 } else {
1208 input = prev_result;
1209 }
1210 }
1211
1212 return write_reply(
1213 {Span<const uint8_t>(result), Span<const uint8_t>(prev_result)});
1214 }
1215
AES_CTR(const Span<const uint8_t> args[],ReplyCallback write_reply)1216 static bool AES_CTR(const Span<const uint8_t> args[],
1217 ReplyCallback write_reply) {
1218 static const uint32_t kOneIteration = 1;
1219 if (args[3].size() != sizeof(kOneIteration) ||
1220 memcmp(args[3].data(), &kOneIteration, sizeof(kOneIteration))) {
1221 LOG_ERROR("Only a single iteration supported with AES-CTR\n");
1222 return false;
1223 }
1224
1225 AES_KEY key;
1226 if (AES_set_encrypt_key(args[0].data(), args[0].size() * 8, &key) != 0) {
1227 return false;
1228 }
1229 if (args[2].size() != AES_BLOCK_SIZE) {
1230 return false;
1231 }
1232 uint8_t iv[AES_BLOCK_SIZE];
1233 memcpy(iv, args[2].data(), AES_BLOCK_SIZE);
1234 if (GetIterations(args[3]) != 1) {
1235 LOG_ERROR("Multiple iterations of AES-CTR is not supported.\n");
1236 return false;
1237 }
1238
1239 std::vector<uint8_t> out;
1240 out.resize(args[1].size());
1241 unsigned num = 0;
1242 uint8_t ecount_buf[AES_BLOCK_SIZE];
1243 AES_ctr128_encrypt(args[1].data(), out.data(), args[1].size(), &key, iv,
1244 ecount_buf, &num);
1245 return write_reply({Span<const uint8_t>(out)});
1246 }
1247
AESGCMSetup(EVP_AEAD_CTX * ctx,Span<const uint8_t> tag_len_span,Span<const uint8_t> key)1248 static bool AESGCMSetup(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
1249 Span<const uint8_t> key) {
1250 if (tag_len_span.size() != sizeof(uint32_t)) {
1251 LOG_ERROR("Tag size value is %u bytes, not an uint32_t\n",
1252 static_cast<unsigned>(tag_len_span.size()));
1253 return false;
1254 }
1255 const uint32_t tag_len_32 = CRYPTO_load_u32_le(tag_len_span.data());
1256
1257 const EVP_AEAD *aead;
1258 switch (key.size()) {
1259 case 16:
1260 aead = EVP_aead_aes_128_gcm();
1261 break;
1262 case 24:
1263 aead = EVP_aead_aes_192_gcm();
1264 break;
1265 case 32:
1266 aead = EVP_aead_aes_256_gcm();
1267 break;
1268 default:
1269 LOG_ERROR("Bad AES-GCM key length %u\n",
1270 static_cast<unsigned>(key.size()));
1271 return false;
1272 }
1273
1274 if (!EVP_AEAD_CTX_init(ctx, aead, key.data(), key.size(), tag_len_32,
1275 nullptr)) {
1276 LOG_ERROR("Failed to setup AES-GCM with tag length %u\n",
1277 static_cast<unsigned>(tag_len_32));
1278 return false;
1279 }
1280
1281 return true;
1282 }
1283
AESGCMRandNonceSetup(EVP_AEAD_CTX * ctx,Span<const uint8_t> tag_len_span,Span<const uint8_t> key)1284 static bool AESGCMRandNonceSetup(EVP_AEAD_CTX *ctx,
1285 Span<const uint8_t> tag_len_span,
1286 Span<const uint8_t> key) {
1287 if (tag_len_span.size() != sizeof(uint32_t)) {
1288 LOG_ERROR("Tag size value is %u bytes, not an uint32_t\n",
1289 static_cast<unsigned>(tag_len_span.size()));
1290 return false;
1291 }
1292 const uint32_t tag_len_32 = CRYPTO_load_u32_le(tag_len_span.data());
1293
1294 const EVP_AEAD *aead;
1295 switch (key.size()) {
1296 case 16:
1297 aead = EVP_aead_aes_128_gcm_randnonce();
1298 break;
1299 case 32:
1300 aead = EVP_aead_aes_256_gcm_randnonce();
1301 break;
1302 default:
1303 LOG_ERROR("Bad AES-GCM key length %u\n",
1304 static_cast<unsigned>(key.size()));
1305 return false;
1306 }
1307
1308 constexpr size_t kNonceLength = 12;
1309 if (!EVP_AEAD_CTX_init(ctx, aead, key.data(), key.size(),
1310 tag_len_32 + kNonceLength, nullptr)) {
1311 LOG_ERROR("Failed to setup AES-GCM with tag length %u\n",
1312 static_cast<unsigned>(tag_len_32));
1313 return false;
1314 }
1315
1316 return true;
1317 }
1318
AESCCMSetup(EVP_AEAD_CTX * ctx,Span<const uint8_t> tag_len_span,Span<const uint8_t> key)1319 static bool AESCCMSetup(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
1320 Span<const uint8_t> key) {
1321 uint32_t tag_len_32;
1322 if (tag_len_span.size() != sizeof(tag_len_32)) {
1323 LOG_ERROR("Tag size value is %u bytes, not an uint32_t\n",
1324 static_cast<unsigned>(tag_len_span.size()));
1325 return false;
1326 }
1327 memcpy(&tag_len_32, tag_len_span.data(), sizeof(tag_len_32));
1328 const EVP_AEAD *aead;
1329 switch (tag_len_32) {
1330 case 4:
1331 aead = EVP_aead_aes_128_ccm_bluetooth();
1332 break;
1333
1334 case 8:
1335 aead = EVP_aead_aes_128_ccm_bluetooth_8();
1336 break;
1337
1338 default:
1339 LOG_ERROR(
1340 "AES-CCM only supports 4- and 8-byte tags, but %u was requested\n",
1341 static_cast<unsigned>(tag_len_32));
1342 return false;
1343 }
1344
1345 if (key.size() != 16) {
1346 LOG_ERROR("AES-CCM only supports 128-bit keys, but %u bits were given\n",
1347 static_cast<unsigned>(key.size() * 8));
1348 return false;
1349 }
1350
1351 if (!EVP_AEAD_CTX_init(ctx, aead, key.data(), key.size(), tag_len_32,
1352 nullptr)) {
1353 LOG_ERROR("Failed to setup AES-CCM with tag length %u\n",
1354 static_cast<unsigned>(tag_len_32));
1355 return false;
1356 }
1357
1358 return true;
1359 }
1360
1361 template <bool (*SetupFunc)(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
1362 Span<const uint8_t> key)>
AEADSeal(const Span<const uint8_t> args[],ReplyCallback write_reply)1363 static bool AEADSeal(const Span<const uint8_t> args[],
1364 ReplyCallback write_reply) {
1365 Span<const uint8_t> tag_len_span = args[0];
1366 Span<const uint8_t> key = args[1];
1367 Span<const uint8_t> plaintext = args[2];
1368 Span<const uint8_t> nonce = args[3];
1369 Span<const uint8_t> ad = args[4];
1370
1371 bssl::ScopedEVP_AEAD_CTX ctx;
1372 if (!SetupFunc(ctx.get(), tag_len_span, key)) {
1373 return false;
1374 }
1375
1376 if (EVP_AEAD_MAX_OVERHEAD + plaintext.size() < EVP_AEAD_MAX_OVERHEAD) {
1377 return false;
1378 }
1379 std::vector<uint8_t> out(EVP_AEAD_MAX_OVERHEAD + plaintext.size());
1380
1381 size_t out_len;
1382 if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
1383 nonce.data(), nonce.size(), plaintext.data(),
1384 plaintext.size(), ad.data(), ad.size())) {
1385 return false;
1386 }
1387
1388 out.resize(out_len);
1389 return write_reply({Span<const uint8_t>(out)});
1390 }
1391
1392 template <bool (*SetupFunc)(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
1393 Span<const uint8_t> key)>
AEADOpen(const Span<const uint8_t> args[],ReplyCallback write_reply)1394 static bool AEADOpen(const Span<const uint8_t> args[],
1395 ReplyCallback write_reply) {
1396 Span<const uint8_t> tag_len_span = args[0];
1397 Span<const uint8_t> key = args[1];
1398 Span<const uint8_t> ciphertext = args[2];
1399 Span<const uint8_t> nonce = args[3];
1400 Span<const uint8_t> ad = args[4];
1401
1402 bssl::ScopedEVP_AEAD_CTX ctx;
1403 if (!SetupFunc(ctx.get(), tag_len_span, key)) {
1404 return false;
1405 }
1406
1407 std::vector<uint8_t> out(ciphertext.size());
1408 size_t out_len;
1409 uint8_t success_flag[1] = {0};
1410
1411 if (!EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
1412 nonce.data(), nonce.size(), ciphertext.data(),
1413 ciphertext.size(), ad.data(), ad.size())) {
1414 return write_reply(
1415 {Span<const uint8_t>(success_flag), Span<const uint8_t>()});
1416 }
1417
1418 out.resize(out_len);
1419 success_flag[0] = 1;
1420 return write_reply(
1421 {Span<const uint8_t>(success_flag), Span<const uint8_t>(out)});
1422 }
1423
AESPaddedKeyWrapSetup(AES_KEY * out,bool decrypt,Span<const uint8_t> key)1424 static bool AESPaddedKeyWrapSetup(AES_KEY *out, bool decrypt,
1425 Span<const uint8_t> key) {
1426 if ((decrypt ? AES_set_decrypt_key : AES_set_encrypt_key)(
1427 key.data(), key.size() * 8, out) != 0) {
1428 LOG_ERROR("Invalid AES key length for AES-KW(P): %u\n",
1429 static_cast<unsigned>(key.size()));
1430 return false;
1431 }
1432 return true;
1433 }
1434
AESKeyWrapSetup(AES_KEY * out,bool decrypt,Span<const uint8_t> key,Span<const uint8_t> input)1435 static bool AESKeyWrapSetup(AES_KEY *out, bool decrypt, Span<const uint8_t> key,
1436 Span<const uint8_t> input) {
1437 if (!AESPaddedKeyWrapSetup(out, decrypt, key)) {
1438 return false;
1439 }
1440
1441 if (input.size() % 8) {
1442 LOG_ERROR("Invalid AES-KW input length: %u\n",
1443 static_cast<unsigned>(input.size()));
1444 return false;
1445 }
1446
1447 return true;
1448 }
1449
AESKeyWrapSeal(const Span<const uint8_t> args[],ReplyCallback write_reply)1450 static bool AESKeyWrapSeal(const Span<const uint8_t> args[],
1451 ReplyCallback write_reply) {
1452 Span<const uint8_t> key = args[1];
1453 Span<const uint8_t> plaintext = args[2];
1454
1455 AES_KEY aes;
1456 if (!AESKeyWrapSetup(&aes, /*decrypt=*/false, key, plaintext) ||
1457 plaintext.size() > INT_MAX - 8) {
1458 return false;
1459 }
1460
1461 std::vector<uint8_t> out(plaintext.size() + 8);
1462 if (AES_wrap_key(&aes, /*iv=*/nullptr, out.data(), plaintext.data(),
1463 plaintext.size()) != static_cast<int>(out.size())) {
1464 LOG_ERROR("AES-KW failed\n");
1465 return false;
1466 }
1467
1468 return write_reply({Span<const uint8_t>(out)});
1469 }
1470
AESKeyWrapOpen(const Span<const uint8_t> args[],ReplyCallback write_reply)1471 static bool AESKeyWrapOpen(const Span<const uint8_t> args[],
1472 ReplyCallback write_reply) {
1473 Span<const uint8_t> key = args[1];
1474 Span<const uint8_t> ciphertext = args[2];
1475
1476 AES_KEY aes;
1477 if (!AESKeyWrapSetup(&aes, /*decrypt=*/true, key, ciphertext) ||
1478 ciphertext.size() < 8 || ciphertext.size() > INT_MAX) {
1479 return false;
1480 }
1481
1482 std::vector<uint8_t> out(ciphertext.size() - 8);
1483 uint8_t success_flag[1] = {0};
1484 if (AES_unwrap_key(&aes, /*iv=*/nullptr, out.data(), ciphertext.data(),
1485 ciphertext.size()) != static_cast<int>(out.size())) {
1486 return write_reply(
1487 {Span<const uint8_t>(success_flag), Span<const uint8_t>()});
1488 }
1489
1490 success_flag[0] = 1;
1491 return write_reply(
1492 {Span<const uint8_t>(success_flag), Span<const uint8_t>(out)});
1493 }
1494
AESPaddedKeyWrapSeal(const Span<const uint8_t> args[],ReplyCallback write_reply)1495 static bool AESPaddedKeyWrapSeal(const Span<const uint8_t> args[],
1496 ReplyCallback write_reply) {
1497 Span<const uint8_t> key = args[1];
1498 Span<const uint8_t> plaintext = args[2];
1499
1500 AES_KEY aes;
1501 if (!AESPaddedKeyWrapSetup(&aes, /*decrypt=*/false, key) ||
1502 plaintext.size() + 15 < 15) {
1503 return false;
1504 }
1505
1506 std::vector<uint8_t> out(plaintext.size() + 15);
1507 size_t out_len;
1508 if (!AES_wrap_key_padded(&aes, out.data(), &out_len, out.size(),
1509 plaintext.data(), plaintext.size())) {
1510 LOG_ERROR("AES-KWP failed\n");
1511 return false;
1512 }
1513
1514 out.resize(out_len);
1515 return write_reply({Span<const uint8_t>(out)});
1516 }
1517
AESPaddedKeyWrapOpen(const Span<const uint8_t> args[],ReplyCallback write_reply)1518 static bool AESPaddedKeyWrapOpen(const Span<const uint8_t> args[],
1519 ReplyCallback write_reply) {
1520 Span<const uint8_t> key = args[1];
1521 Span<const uint8_t> ciphertext = args[2];
1522
1523 AES_KEY aes;
1524 if (!AESPaddedKeyWrapSetup(&aes, /*decrypt=*/true, key) ||
1525 ciphertext.size() % 8) {
1526 return false;
1527 }
1528
1529 std::vector<uint8_t> out(ciphertext.size());
1530 size_t out_len;
1531 uint8_t success_flag[1] = {0};
1532 if (!AES_unwrap_key_padded(&aes, out.data(), &out_len, out.size(),
1533 ciphertext.data(), ciphertext.size())) {
1534 return write_reply(
1535 {Span<const uint8_t>(success_flag), Span<const uint8_t>()});
1536 }
1537
1538 success_flag[0] = 1;
1539 out.resize(out_len);
1540 return write_reply(
1541 {Span<const uint8_t>(success_flag), Span<const uint8_t>(out)});
1542 }
1543
1544 template <bool Encrypt>
TDES(const Span<const uint8_t> args[],ReplyCallback write_reply)1545 static bool TDES(const Span<const uint8_t> args[], ReplyCallback write_reply) {
1546 const EVP_CIPHER *cipher = EVP_des_ede3();
1547
1548 if (args[0].size() != 24) {
1549 LOG_ERROR("Bad key length %u for 3DES.\n",
1550 static_cast<unsigned>(args[0].size()));
1551 return false;
1552 }
1553 bssl::ScopedEVP_CIPHER_CTX ctx;
1554 if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, args[0].data(), nullptr,
1555 Encrypt ? 1 : 0) ||
1556 !EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) {
1557 return false;
1558 }
1559
1560 if (args[1].size() % 8) {
1561 LOG_ERROR("Bad input length %u for 3DES.\n",
1562 static_cast<unsigned>(args[1].size()));
1563 return false;
1564 }
1565 std::vector<uint8_t> result(args[1].begin(), args[1].end());
1566
1567 const uint32_t iterations = GetIterations(args[2]);
1568 std::vector<uint8_t> prev_result, prev_prev_result;
1569
1570 for (uint32_t j = 0; j < iterations; j++) {
1571 if (j == iterations - 1) {
1572 prev_result = result;
1573 } else if (iterations >= 2 && j == iterations - 2) {
1574 prev_prev_result = result;
1575 }
1576
1577 int out_len;
1578 if (!EVP_CipherUpdate(ctx.get(), result.data(), &out_len, result.data(),
1579 result.size()) ||
1580 out_len != static_cast<int>(result.size())) {
1581 return false;
1582 }
1583 }
1584
1585 return write_reply({Span<const uint8_t>(result),
1586 Span<const uint8_t>(prev_result),
1587 Span<const uint8_t>(prev_prev_result)});
1588 }
1589
1590 template <bool Encrypt>
TDES_CBC(const Span<const uint8_t> args[],ReplyCallback write_reply)1591 static bool TDES_CBC(const Span<const uint8_t> args[],
1592 ReplyCallback write_reply) {
1593 const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
1594
1595 if (args[0].size() != 24) {
1596 LOG_ERROR("Bad key length %u for 3DES.\n",
1597 static_cast<unsigned>(args[0].size()));
1598 return false;
1599 }
1600
1601 if (args[1].size() % 8 || args[1].size() == 0) {
1602 LOG_ERROR("Bad input length %u for 3DES.\n",
1603 static_cast<unsigned>(args[1].size()));
1604 return false;
1605 }
1606 std::vector<uint8_t> input(args[1].begin(), args[1].end());
1607
1608 if (args[2].size() != EVP_CIPHER_iv_length(cipher)) {
1609 LOG_ERROR("Bad IV length %u for 3DES.\n",
1610 static_cast<unsigned>(args[2].size()));
1611 return false;
1612 }
1613 std::vector<uint8_t> iv(args[2].begin(), args[2].end());
1614 const uint32_t iterations = GetIterations(args[3]);
1615
1616 std::vector<uint8_t> result(input.size());
1617 std::vector<uint8_t> prev_result, prev_prev_result;
1618 bssl::ScopedEVP_CIPHER_CTX ctx;
1619 if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, args[0].data(), iv.data(),
1620 Encrypt ? 1 : 0) ||
1621 !EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) {
1622 return false;
1623 }
1624
1625 for (uint32_t j = 0; j < iterations; j++) {
1626 prev_prev_result = prev_result;
1627 prev_result = result;
1628
1629 int out_len, out_len2;
1630 if (!EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, nullptr, iv.data(),
1631 -1) ||
1632 !EVP_CipherUpdate(ctx.get(), result.data(), &out_len, input.data(),
1633 input.size()) ||
1634 !EVP_CipherFinal_ex(ctx.get(), result.data() + out_len, &out_len2) ||
1635 (out_len + out_len2) != static_cast<int>(result.size())) {
1636 return false;
1637 }
1638
1639 if (Encrypt) {
1640 if (j == 0) {
1641 input = iv;
1642 } else {
1643 input = prev_result;
1644 }
1645 iv = result;
1646 } else {
1647 iv = input;
1648 input = result;
1649 }
1650 }
1651
1652 return write_reply({Span<const uint8_t>(result),
1653 Span<const uint8_t>(prev_result),
1654 Span<const uint8_t>(prev_prev_result)});
1655 }
1656
1657 template <const EVP_MD *HashFunc()>
HMAC(const Span<const uint8_t> args[],ReplyCallback write_reply)1658 static bool HMAC(const Span<const uint8_t> args[], ReplyCallback write_reply) {
1659 const EVP_MD *const md = HashFunc();
1660 uint8_t digest[EVP_MAX_MD_SIZE];
1661 unsigned digest_len;
1662 if (::HMAC(md, args[1].data(), args[1].size(), args[0].data(), args[0].size(),
1663 digest, &digest_len) == nullptr) {
1664 return false;
1665 }
1666 return write_reply({Span<const uint8_t>(digest, digest_len)});
1667 }
1668
1669 template <const EVP_MD *HashFunc()>
HKDF(const Span<const uint8_t> args[],ReplyCallback write_reply)1670 static bool HKDF(const Span<const uint8_t> args[], ReplyCallback write_reply) {
1671 const EVP_MD *const md = HashFunc();
1672 const auto key = args[0];
1673 const auto salt = args[1];
1674 const auto info = args[2];
1675 const auto out_len_bytes = args[3];
1676
1677 if (out_len_bytes.size() != sizeof(uint32_t)) {
1678 return false;
1679 }
1680 const uint32_t out_len = CRYPTO_load_u32_le(out_len_bytes.data());
1681 if (out_len > (1 << 24)) {
1682 return false;
1683 }
1684
1685 std::vector<uint8_t> out(out_len);
1686 if (!::HKDF(out.data(), out_len, md, key.data(), key.size(), salt.data(),
1687 salt.size(), info.data(), info.size())) {
1688 return false;
1689 }
1690 return write_reply({out});
1691 }
1692
1693 template <const EVP_MD *HashFunc()>
HKDFExtract(const Span<const uint8_t> args[],ReplyCallback write_reply)1694 static bool HKDFExtract(const Span<const uint8_t> args[],
1695 ReplyCallback write_reply) {
1696 const EVP_MD *const md = HashFunc();
1697 const auto secret = args[0];
1698 const auto salt = args[1];
1699
1700 std::vector<uint8_t> out(EVP_MD_size(md));
1701 size_t out_len;
1702 if (!HKDF_extract(out.data(), &out_len, md, secret.data(), secret.size(),
1703 salt.data(), salt.size())) {
1704 return false;
1705 }
1706 assert(out_len == out.size());
1707 return write_reply({out});
1708 }
1709
1710 template <const EVP_MD *HashFunc()>
HKDFExpandLabel(const Span<const uint8_t> args[],ReplyCallback write_reply)1711 static bool HKDFExpandLabel(const Span<const uint8_t> args[],
1712 ReplyCallback write_reply) {
1713 const EVP_MD *const md = HashFunc();
1714 const auto out_len_bytes = args[0];
1715 const auto secret = args[1];
1716 const auto label = args[2];
1717 const auto hash = args[3];
1718
1719 if (out_len_bytes.size() != sizeof(uint32_t)) {
1720 return false;
1721 }
1722 const uint32_t out_len = CRYPTO_load_u32_le(out_len_bytes.data());
1723 if (out_len > (1 << 24)) {
1724 return false;
1725 }
1726
1727 std::vector<uint8_t> out(out_len);
1728 if (!CRYPTO_tls13_hkdf_expand_label(out.data(), out_len, md, secret.data(),
1729 secret.size(), label.data(), label.size(),
1730 hash.data(), hash.size())) {
1731 return false;
1732 }
1733 return write_reply({out});
1734 }
1735
1736 template <bool WithReseed>
DRBG(const Span<const uint8_t> args[],ReplyCallback write_reply)1737 static bool DRBG(const Span<const uint8_t> args[], ReplyCallback write_reply) {
1738 const auto out_len_bytes = args[0];
1739 const auto entropy = args[1];
1740 const auto personalisation = args[2];
1741
1742 Span<const uint8_t> reseed_additional_data, reseed_entropy, additional_data1,
1743 additional_data2, nonce;
1744 if (!WithReseed) {
1745 additional_data1 = args[3];
1746 additional_data2 = args[4];
1747 nonce = args[5];
1748 } else {
1749 reseed_additional_data = args[3];
1750 reseed_entropy = args[4];
1751 additional_data1 = args[5];
1752 additional_data2 = args[6];
1753 nonce = args[7];
1754 }
1755
1756 uint32_t out_len;
1757 if (out_len_bytes.size() != sizeof(out_len) ||
1758 entropy.size() < CTR_DRBG_MIN_ENTROPY_LEN ||
1759 entropy.size() > CTR_DRBG_MAX_ENTROPY_LEN ||
1760 (!reseed_entropy.empty() &&
1761 (reseed_entropy.size() < CTR_DRBG_MIN_ENTROPY_LEN ||
1762 reseed_entropy.size() > CTR_DRBG_MAX_ENTROPY_LEN)) ||
1763 (nonce.size() != CTR_DRBG_NONCE_LEN && nonce.size() != 0)) {
1764 return false;
1765 }
1766 memcpy(&out_len, out_len_bytes.data(), sizeof(out_len));
1767 if (out_len > (1 << 24)) {
1768 return false;
1769 }
1770 std::vector<uint8_t> out(out_len);
1771
1772 CTR_DRBG_STATE drbg;
1773 if (!CTR_DRBG_init(&drbg, /*df=*/nonce.size() != 0, entropy.data(),
1774 entropy.size(), nonce.empty() ? nullptr : nonce.data(),
1775 personalisation.data(), personalisation.size()) ||
1776 (!reseed_entropy.empty() &&
1777 !CTR_DRBG_reseed_ex(&drbg, reseed_entropy.data(), reseed_entropy.size(),
1778 reseed_additional_data.data(),
1779 reseed_additional_data.size())) ||
1780 !CTR_DRBG_generate(&drbg, out.data(), out_len, additional_data1.data(),
1781 additional_data1.size()) ||
1782 !CTR_DRBG_generate(&drbg, out.data(), out_len, additional_data2.data(),
1783 additional_data2.size())) {
1784 return false;
1785 }
1786
1787 return write_reply({Span<const uint8_t>(out)});
1788 }
1789
StringEq(Span<const uint8_t> a,const char * b)1790 static bool StringEq(Span<const uint8_t> a, const char *b) {
1791 const size_t len = strlen(b);
1792 return a.size() == len && memcmp(a.data(), b, len) == 0;
1793 }
1794
ECKeyFromName(Span<const uint8_t> name)1795 static bssl::UniquePtr<EC_KEY> ECKeyFromName(Span<const uint8_t> name) {
1796 int nid;
1797 if (StringEq(name, "P-224")) {
1798 nid = NID_secp224r1;
1799 } else if (StringEq(name, "P-256")) {
1800 nid = NID_X9_62_prime256v1;
1801 } else if (StringEq(name, "P-384")) {
1802 nid = NID_secp384r1;
1803 } else if (StringEq(name, "P-521")) {
1804 nid = NID_secp521r1;
1805 } else {
1806 return nullptr;
1807 }
1808
1809 return bssl::UniquePtr<EC_KEY>(EC_KEY_new_by_curve_name(nid));
1810 }
1811
BIGNUMBytes(const BIGNUM * bn)1812 static std::vector<uint8_t> BIGNUMBytes(const BIGNUM *bn) {
1813 const size_t len = BN_num_bytes(bn);
1814 std::vector<uint8_t> ret(len);
1815 BN_bn2bin(bn, ret.data());
1816 return ret;
1817 }
1818
GetPublicKeyBytes(const EC_KEY * key)1819 static std::pair<std::vector<uint8_t>, std::vector<uint8_t>> GetPublicKeyBytes(
1820 const EC_KEY *key) {
1821 bssl::UniquePtr<BIGNUM> x(BN_new());
1822 bssl::UniquePtr<BIGNUM> y(BN_new());
1823 if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key),
1824 EC_KEY_get0_public_key(key), x.get(),
1825 y.get(), /*ctx=*/nullptr)) {
1826 abort();
1827 }
1828
1829 std::vector<uint8_t> x_bytes = BIGNUMBytes(x.get());
1830 std::vector<uint8_t> y_bytes = BIGNUMBytes(y.get());
1831
1832 return std::make_pair(std::move(x_bytes), std::move(y_bytes));
1833 }
1834
ECDSAKeyGen(const Span<const uint8_t> args[],ReplyCallback write_reply)1835 static bool ECDSAKeyGen(const Span<const uint8_t> args[],
1836 ReplyCallback write_reply) {
1837 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1838 if (!key || !EC_KEY_generate_key_fips(key.get())) {
1839 return false;
1840 }
1841
1842 const auto pub_key = GetPublicKeyBytes(key.get());
1843 std::vector<uint8_t> d_bytes =
1844 BIGNUMBytes(EC_KEY_get0_private_key(key.get()));
1845
1846 return write_reply({Span<const uint8_t>(d_bytes),
1847 Span<const uint8_t>(pub_key.first),
1848 Span<const uint8_t>(pub_key.second)});
1849 }
1850
BytesToBIGNUM(Span<const uint8_t> bytes)1851 static bssl::UniquePtr<BIGNUM> BytesToBIGNUM(Span<const uint8_t> bytes) {
1852 bssl::UniquePtr<BIGNUM> bn(BN_new());
1853 BN_bin2bn(bytes.data(), bytes.size(), bn.get());
1854 return bn;
1855 }
1856
ECDSAKeyVer(const Span<const uint8_t> args[],ReplyCallback write_reply)1857 static bool ECDSAKeyVer(const Span<const uint8_t> args[],
1858 ReplyCallback write_reply) {
1859 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1860 if (!key) {
1861 return false;
1862 }
1863
1864 bssl::UniquePtr<BIGNUM> x(BytesToBIGNUM(args[1]));
1865 bssl::UniquePtr<BIGNUM> y(BytesToBIGNUM(args[2]));
1866
1867 uint8_t reply[1];
1868 if (!EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()) ||
1869 !EC_KEY_check_fips(key.get())) {
1870 reply[0] = 0;
1871 } else {
1872 reply[0] = 1;
1873 }
1874
1875 return write_reply({Span<const uint8_t>(reply)});
1876 }
1877
HashFromName(Span<const uint8_t> name)1878 static const EVP_MD *HashFromName(Span<const uint8_t> name) {
1879 if (StringEq(name, "SHA-1")) {
1880 return EVP_sha1();
1881 } else if (StringEq(name, "SHA2-224")) {
1882 return EVP_sha224();
1883 } else if (StringEq(name, "SHA2-256")) {
1884 return EVP_sha256();
1885 } else if (StringEq(name, "SHA2-384")) {
1886 return EVP_sha384();
1887 } else if (StringEq(name, "SHA2-512")) {
1888 return EVP_sha512();
1889 } else if (StringEq(name, "SHA2-512/256")) {
1890 return EVP_sha512_256();
1891 } else {
1892 return nullptr;
1893 }
1894 }
1895
ECDSASigGen(const Span<const uint8_t> args[],ReplyCallback write_reply)1896 static bool ECDSASigGen(const Span<const uint8_t> args[],
1897 ReplyCallback write_reply) {
1898 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1899 bssl::UniquePtr<BIGNUM> d = BytesToBIGNUM(args[1]);
1900 const EVP_MD *hash = HashFromName(args[2]);
1901 uint8_t digest[EVP_MAX_MD_SIZE];
1902 unsigned digest_len;
1903 if (!key || !hash ||
1904 !EVP_Digest(args[3].data(), args[3].size(), digest, &digest_len, hash,
1905 /*impl=*/nullptr) ||
1906 !EC_KEY_set_private_key(key.get(), d.get())) {
1907 return false;
1908 }
1909
1910 bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, key.get()));
1911 if (!sig) {
1912 return false;
1913 }
1914
1915 std::vector<uint8_t> r_bytes(BIGNUMBytes(sig->r));
1916 std::vector<uint8_t> s_bytes(BIGNUMBytes(sig->s));
1917
1918 return write_reply(
1919 {Span<const uint8_t>(r_bytes), Span<const uint8_t>(s_bytes)});
1920 }
1921
ECDSASigVer(const Span<const uint8_t> args[],ReplyCallback write_reply)1922 static bool ECDSASigVer(const Span<const uint8_t> args[],
1923 ReplyCallback write_reply) {
1924 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1925 const EVP_MD *hash = HashFromName(args[1]);
1926 auto msg = args[2];
1927 bssl::UniquePtr<BIGNUM> x(BytesToBIGNUM(args[3]));
1928 bssl::UniquePtr<BIGNUM> y(BytesToBIGNUM(args[4]));
1929 bssl::UniquePtr<BIGNUM> r(BytesToBIGNUM(args[5]));
1930 bssl::UniquePtr<BIGNUM> s(BytesToBIGNUM(args[6]));
1931 ECDSA_SIG sig;
1932 sig.r = r.get();
1933 sig.s = s.get();
1934
1935 uint8_t digest[EVP_MAX_MD_SIZE];
1936 unsigned digest_len;
1937 if (!key || !hash ||
1938 !EVP_Digest(msg.data(), msg.size(), digest, &digest_len, hash,
1939 /*impl=*/nullptr)) {
1940 return false;
1941 }
1942
1943 uint8_t reply[1];
1944 if (!EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()) ||
1945 !EC_KEY_check_fips(key.get()) ||
1946 !ECDSA_do_verify(digest, digest_len, &sig, key.get())) {
1947 reply[0] = 0;
1948 } else {
1949 reply[0] = 1;
1950 }
1951
1952 return write_reply({Span<const uint8_t>(reply)});
1953 }
1954
CMAC_AES(const Span<const uint8_t> args[],ReplyCallback write_reply)1955 static bool CMAC_AES(const Span<const uint8_t> args[],
1956 ReplyCallback write_reply) {
1957 uint8_t mac[16];
1958 if (!AES_CMAC(mac, args[1].data(), args[1].size(), args[2].data(),
1959 args[2].size())) {
1960 return false;
1961 }
1962
1963 uint32_t mac_len;
1964 if (args[0].size() != sizeof(mac_len)) {
1965 return false;
1966 }
1967 memcpy(&mac_len, args[0].data(), sizeof(mac_len));
1968 if (mac_len != sizeof(mac)) {
1969 return false;
1970 }
1971
1972 return write_reply({Span<const uint8_t>(mac, sizeof(mac))});
1973 }
1974
CMAC_AESVerify(const Span<const uint8_t> args[],ReplyCallback write_reply)1975 static bool CMAC_AESVerify(const Span<const uint8_t> args[],
1976 ReplyCallback write_reply) {
1977 // This function is just for testing since libcrypto doesn't do the
1978 // verification itself. The regcap doesn't advertise "ver" support.
1979 uint8_t mac[16];
1980 if (!AES_CMAC(mac, args[0].data(), args[0].size(), args[1].data(),
1981 args[1].size()) ||
1982 args[2].size() > sizeof(mac)) {
1983 return false;
1984 }
1985
1986 const uint8_t ok = (OPENSSL_memcmp(mac, args[2].data(), args[2].size()) == 0);
1987 return write_reply({Span<const uint8_t>(&ok, sizeof(ok))});
1988 }
1989
CachedRSAKeys()1990 static std::map<unsigned, bssl::UniquePtr<RSA>> &CachedRSAKeys() {
1991 static std::map<unsigned, bssl::UniquePtr<RSA>> keys;
1992 return keys;
1993 }
1994
GetRSAKey(unsigned bits)1995 static RSA *GetRSAKey(unsigned bits) {
1996 auto it = CachedRSAKeys().find(bits);
1997 if (it != CachedRSAKeys().end()) {
1998 return it->second.get();
1999 }
2000
2001 bssl::UniquePtr<RSA> key(RSA_new());
2002 if (!RSA_generate_key_fips(key.get(), bits, nullptr)) {
2003 abort();
2004 }
2005
2006 RSA *const ret = key.get();
2007 CachedRSAKeys().emplace(static_cast<unsigned>(bits), std::move(key));
2008
2009 return ret;
2010 }
2011
RSAKeyGen(const Span<const uint8_t> args[],ReplyCallback write_reply)2012 static bool RSAKeyGen(const Span<const uint8_t> args[],
2013 ReplyCallback write_reply) {
2014 uint32_t bits;
2015 if (args[0].size() != sizeof(bits)) {
2016 return false;
2017 }
2018 memcpy(&bits, args[0].data(), sizeof(bits));
2019
2020 bssl::UniquePtr<RSA> key(RSA_new());
2021 if (!RSA_generate_key_fips(key.get(), bits, nullptr)) {
2022 LOG_ERROR("RSA_generate_key_fips failed for modulus length %u.\n", bits);
2023 return false;
2024 }
2025
2026 const BIGNUM *n, *e, *d, *p, *q;
2027 RSA_get0_key(key.get(), &n, &e, &d);
2028 RSA_get0_factors(key.get(), &p, &q);
2029
2030 if (!write_reply({BIGNUMBytes(e), BIGNUMBytes(p), BIGNUMBytes(q),
2031 BIGNUMBytes(n), BIGNUMBytes(d)})) {
2032 return false;
2033 }
2034
2035 CachedRSAKeys().emplace(static_cast<unsigned>(bits), std::move(key));
2036 return true;
2037 }
2038
2039 template <const EVP_MD *(MDFunc)(), bool UsePSS>
RSASigGen(const Span<const uint8_t> args[],ReplyCallback write_reply)2040 static bool RSASigGen(const Span<const uint8_t> args[],
2041 ReplyCallback write_reply) {
2042 uint32_t bits;
2043 if (args[0].size() != sizeof(bits)) {
2044 return false;
2045 }
2046 memcpy(&bits, args[0].data(), sizeof(bits));
2047 const Span<const uint8_t> msg = args[1];
2048
2049 RSA *const key = GetRSAKey(bits);
2050 const EVP_MD *const md = MDFunc();
2051 uint8_t digest_buf[EVP_MAX_MD_SIZE];
2052 unsigned digest_len;
2053 if (!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
2054 return false;
2055 }
2056
2057 std::vector<uint8_t> sig(RSA_size(key));
2058 size_t sig_len;
2059 if (UsePSS) {
2060 if (!RSA_sign_pss_mgf1(key, &sig_len, sig.data(), sig.size(), digest_buf,
2061 digest_len, md, md, RSA_PSS_SALTLEN_DIGEST)) {
2062 return false;
2063 }
2064 } else {
2065 unsigned sig_len_u;
2066 if (!RSA_sign(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
2067 &sig_len_u, key)) {
2068 return false;
2069 }
2070 sig_len = sig_len_u;
2071 }
2072
2073 sig.resize(sig_len);
2074
2075 return write_reply(
2076 {BIGNUMBytes(RSA_get0_n(key)), BIGNUMBytes(RSA_get0_e(key)), sig});
2077 }
2078
2079 template <const EVP_MD *(MDFunc)(), bool UsePSS>
RSASigVer(const Span<const uint8_t> args[],ReplyCallback write_reply)2080 static bool RSASigVer(const Span<const uint8_t> args[],
2081 ReplyCallback write_reply) {
2082 const Span<const uint8_t> n_bytes = args[0];
2083 const Span<const uint8_t> e_bytes = args[1];
2084 const Span<const uint8_t> msg = args[2];
2085 const Span<const uint8_t> sig = args[3];
2086
2087 BIGNUM *n = BN_new();
2088 BIGNUM *e = BN_new();
2089 bssl::UniquePtr<RSA> key(RSA_new());
2090 if (!BN_bin2bn(n_bytes.data(), n_bytes.size(), n) ||
2091 !BN_bin2bn(e_bytes.data(), e_bytes.size(), e) ||
2092 !RSA_set0_key(key.get(), n, e, /*d=*/nullptr)) {
2093 return false;
2094 }
2095
2096 const EVP_MD *const md = MDFunc();
2097 uint8_t digest_buf[EVP_MAX_MD_SIZE];
2098 unsigned digest_len;
2099 if (!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
2100 return false;
2101 }
2102
2103 uint8_t ok;
2104 if (UsePSS) {
2105 ok = RSA_verify_pss_mgf1(key.get(), digest_buf, digest_len, md, md,
2106 RSA_PSS_SALTLEN_DIGEST, sig.data(), sig.size());
2107 } else {
2108 ok = RSA_verify(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
2109 sig.size(), key.get());
2110 }
2111 ERR_clear_error();
2112
2113 return write_reply({Span<const uint8_t>(&ok, 1)});
2114 }
2115
2116 template <const EVP_MD *(MDFunc)()>
TLSKDF(const Span<const uint8_t> args[],ReplyCallback write_reply)2117 static bool TLSKDF(const Span<const uint8_t> args[],
2118 ReplyCallback write_reply) {
2119 const Span<const uint8_t> out_len_bytes = args[0];
2120 const Span<const uint8_t> secret = args[1];
2121 const std::string_view label = bssl::BytesAsStringView(args[2]);
2122 const Span<const uint8_t> seed1 = args[3];
2123 const Span<const uint8_t> seed2 = args[4];
2124 const EVP_MD *md = MDFunc();
2125
2126 uint32_t out_len;
2127 if (out_len_bytes.size() != sizeof(out_len)) {
2128 return 0;
2129 }
2130 memcpy(&out_len, out_len_bytes.data(), sizeof(out_len));
2131
2132 std::vector<uint8_t> out(size_t{out_len});
2133 if (!CRYPTO_tls1_prf(md, out.data(), out.size(), secret.data(), secret.size(),
2134 label.data(), label.size(), seed1.data(), seed1.size(),
2135 seed2.data(), seed2.size())) {
2136 return 0;
2137 }
2138
2139 return write_reply({out});
2140 }
2141
2142 template <int Nid>
ECDH(const Span<const uint8_t> args[],ReplyCallback write_reply)2143 static bool ECDH(const Span<const uint8_t> args[], ReplyCallback write_reply) {
2144 bssl::UniquePtr<BIGNUM> their_x(BytesToBIGNUM(args[0]));
2145 bssl::UniquePtr<BIGNUM> their_y(BytesToBIGNUM(args[1]));
2146 const Span<const uint8_t> private_key = args[2];
2147
2148 bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(Nid));
2149 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
2150
2151 const EC_GROUP *const group = EC_KEY_get0_group(ec_key.get());
2152 bssl::UniquePtr<EC_POINT> their_point(EC_POINT_new(group));
2153 if (!EC_POINT_set_affine_coordinates_GFp(
2154 group, their_point.get(), their_x.get(), their_y.get(), ctx.get())) {
2155 LOG_ERROR("Invalid peer point for ECDH.\n");
2156 return false;
2157 }
2158
2159 if (!private_key.empty()) {
2160 bssl::UniquePtr<BIGNUM> our_k(BytesToBIGNUM(private_key));
2161 if (!EC_KEY_set_private_key(ec_key.get(), our_k.get())) {
2162 LOG_ERROR("EC_KEY_set_private_key failed.\n");
2163 return false;
2164 }
2165
2166 bssl::UniquePtr<EC_POINT> our_pub(EC_POINT_new(group));
2167 if (!EC_POINT_mul(group, our_pub.get(), our_k.get(), nullptr, nullptr,
2168 ctx.get()) ||
2169 !EC_KEY_set_public_key(ec_key.get(), our_pub.get())) {
2170 LOG_ERROR("Calculating public key failed.\n");
2171 return false;
2172 }
2173 } else if (!EC_KEY_generate_key_fips(ec_key.get())) {
2174 LOG_ERROR("EC_KEY_generate_key_fips failed.\n");
2175 return false;
2176 }
2177
2178 // The output buffer is one larger than |EC_MAX_BYTES| so that truncation
2179 // can be detected.
2180 std::vector<uint8_t> output(EC_MAX_BYTES + 1);
2181 const int out_len =
2182 ECDH_compute_key(output.data(), output.size(), their_point.get(),
2183 ec_key.get(), /*kdf=*/nullptr);
2184 if (out_len < 0) {
2185 LOG_ERROR("ECDH_compute_key failed.\n");
2186 return false;
2187 } else if (static_cast<size_t>(out_len) == output.size()) {
2188 LOG_ERROR("ECDH_compute_key output may have been truncated.\n");
2189 return false;
2190 }
2191 output.resize(static_cast<size_t>(out_len));
2192
2193 const EC_POINT *pub = EC_KEY_get0_public_key(ec_key.get());
2194 bssl::UniquePtr<BIGNUM> x(BN_new());
2195 bssl::UniquePtr<BIGNUM> y(BN_new());
2196 if (!EC_POINT_get_affine_coordinates_GFp(group, pub, x.get(), y.get(),
2197 ctx.get())) {
2198 LOG_ERROR("EC_POINT_get_affine_coordinates_GFp failed.\n");
2199 return false;
2200 }
2201
2202 return write_reply({BIGNUMBytes(x.get()), BIGNUMBytes(y.get()), output});
2203 }
2204
FFDH(const Span<const uint8_t> args[],ReplyCallback write_reply)2205 static bool FFDH(const Span<const uint8_t> args[], ReplyCallback write_reply) {
2206 bssl::UniquePtr<BIGNUM> p(BytesToBIGNUM(args[0]));
2207 bssl::UniquePtr<BIGNUM> q(BytesToBIGNUM(args[1]));
2208 bssl::UniquePtr<BIGNUM> g(BytesToBIGNUM(args[2]));
2209 bssl::UniquePtr<BIGNUM> their_pub(BytesToBIGNUM(args[3]));
2210 const Span<const uint8_t> private_key_span = args[4];
2211 const Span<const uint8_t> public_key_span = args[5];
2212
2213 bssl::UniquePtr<DH> dh(DH_new());
2214 if (!DH_set0_pqg(dh.get(), p.get(), q.get(), g.get())) {
2215 LOG_ERROR("DH_set0_pqg failed.\n");
2216 return 0;
2217 }
2218
2219 // DH_set0_pqg took ownership of these values.
2220 p.release();
2221 q.release();
2222 g.release();
2223
2224 if (!private_key_span.empty()) {
2225 bssl::UniquePtr<BIGNUM> private_key(BytesToBIGNUM(private_key_span));
2226 bssl::UniquePtr<BIGNUM> public_key(BytesToBIGNUM(public_key_span));
2227
2228 if (!DH_set0_key(dh.get(), public_key.get(), private_key.get())) {
2229 LOG_ERROR("DH_set0_key failed.\n");
2230 return 0;
2231 }
2232
2233 // DH_set0_key took ownership of these values.
2234 public_key.release();
2235 private_key.release();
2236 } else if (!DH_generate_key(dh.get())) {
2237 LOG_ERROR("DH_generate_key failed.\n");
2238 return false;
2239 }
2240
2241 std::vector<uint8_t> z(DH_size(dh.get()));
2242 if (DH_compute_key_padded(z.data(), their_pub.get(), dh.get()) !=
2243 static_cast<int>(z.size())) {
2244 LOG_ERROR("DH_compute_key_hashed failed.\n");
2245 return false;
2246 }
2247
2248 return write_reply({BIGNUMBytes(DH_get0_pub_key(dh.get())), z});
2249 }
2250
2251 template <typename PrivateKey, size_t PublicKeyBytes,
2252 bcm_status (*KeyGen)(uint8_t *, PrivateKey *, const uint8_t *),
2253 bcm_status (*MarshalPrivateKey)(CBB *, const PrivateKey *)>
MLDSAKeyGen(const Span<const uint8_t> args[],ReplyCallback write_reply)2254 static bool MLDSAKeyGen(const Span<const uint8_t> args[],
2255 ReplyCallback write_reply) {
2256 const Span<const uint8_t> seed = args[0];
2257 if (seed.size() != BCM_MLDSA_SEED_BYTES) {
2258 LOG_ERROR("Bad seed size.\n");
2259 return false;
2260 }
2261
2262 auto priv = std::make_unique<PrivateKey>();
2263 uint8_t pub_key_bytes[PublicKeyBytes];
2264 if (KeyGen(pub_key_bytes, priv.get(), seed.data()) != bcm_status::approved) {
2265 LOG_ERROR("ML-DSA key gen failed.\n");
2266 return false;
2267 }
2268
2269 ScopedCBB cbb;
2270 if (!CBB_init(cbb.get(), 1024) ||
2271 MarshalPrivateKey(cbb.get(), priv.get()) != bcm_status::approved ||
2272 !CBB_flush(cbb.get())) {
2273 LOG_ERROR("ML-DSA marshal failed.\n");
2274 return false;
2275 }
2276
2277 return write_reply(
2278 {pub_key_bytes, Span(CBB_data(cbb.get()), CBB_len(cbb.get()))});
2279 }
2280
2281 template <typename PrivateKey, size_t SignatureBytes,
2282 bcm_status (*ParsePrivateKey)(PrivateKey *, CBS *),
2283 bcm_status (*SignInternal)(uint8_t *, const PrivateKey *,
2284 const uint8_t *, size_t, const uint8_t *,
2285 size_t, const uint8_t *, size_t,
2286 const uint8_t *)>
MLDSASigGen(const Span<const uint8_t> args[],ReplyCallback write_reply)2287 static bool MLDSASigGen(const Span<const uint8_t> args[],
2288 ReplyCallback write_reply) {
2289 CBS cbs = args[0];
2290 auto priv = std::make_unique<PrivateKey>();
2291 if (ParsePrivateKey(priv.get(), &cbs) != bcm_status::approved) {
2292 LOG_ERROR("Failed to parse ML-DSA private key.\n");
2293 return false;
2294 }
2295
2296 const Span<const uint8_t> msg = args[1];
2297 const Span<const uint8_t> randomizer = args[2];
2298
2299 if (randomizer.size() != BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES) {
2300 LOG_ERROR("Bad randomizer size.\n");
2301 return false;
2302 }
2303
2304 uint8_t signature[SignatureBytes];
2305 if (SignInternal(signature, priv.get(), msg.data(), msg.size(),
2306 // It's not just an empty context, the context prefix
2307 // is omitted too.
2308 nullptr, 0, nullptr, 0,
2309 randomizer.data()) != bcm_status::approved) {
2310 LOG_ERROR("ML-DSA signing failed.\n");
2311 return false;
2312 }
2313
2314 return write_reply({signature});
2315 }
2316
2317 template <typename PublicKey, size_t SignatureBytes,
2318 bcm_status (*ParsePublicKey)(PublicKey *, CBS *),
2319 bcm_status (*VerifyInternal)(const PublicKey *, const uint8_t *,
2320 const uint8_t *, size_t, const uint8_t *,
2321 size_t, const uint8_t *, size_t)>
MLDSASigVer(const Span<const uint8_t> args[],ReplyCallback write_reply)2322 static bool MLDSASigVer(const Span<const uint8_t> args[],
2323 ReplyCallback write_reply) {
2324 const Span<const uint8_t> pub_key_bytes = args[0];
2325 const Span<const uint8_t> msg = args[1];
2326 const Span<const uint8_t> signature = args[2];
2327
2328 CBS cbs = pub_key_bytes;
2329 auto pub = std::make_unique<PublicKey>();
2330 if (ParsePublicKey(pub.get(), &cbs) != bcm_status::approved) {
2331 LOG_ERROR("Failed to parse ML-DSA public key.\n");
2332 return false;
2333 }
2334
2335 if (signature.size() != SignatureBytes) {
2336 LOG_ERROR("Bad signature size.\n");
2337 return false;
2338 }
2339
2340 const uint8_t ok = bcm_success(
2341 VerifyInternal(pub.get(), signature.data(), msg.data(), msg.size(),
2342 // It's not just an empty context, the context
2343 // prefix is omitted too.
2344 nullptr, 0, nullptr, 0));
2345
2346 return write_reply({Span<const uint8_t>(&ok, sizeof(ok))});
2347 }
2348
2349 template <typename PrivateKey, size_t PublicKeyBytes,
2350 bcm_infallible (*KeyGen)(uint8_t *, PrivateKey *, const uint8_t *),
2351 bcm_status (*MarshalPrivate)(CBB *, const PrivateKey *)>
MLKEMKeyGen(const Span<const uint8_t> args[],ReplyCallback write_reply)2352 static bool MLKEMKeyGen(const Span<const uint8_t> args[],
2353 ReplyCallback write_reply) {
2354 const Span<const uint8_t> seed = args[0];
2355 if (seed.size() != BCM_MLKEM_SEED_BYTES) {
2356 LOG_ERROR("Bad seed size.\n");
2357 return false;
2358 }
2359
2360 auto priv = std::make_unique<PrivateKey>();
2361 uint8_t pub_key_bytes[PublicKeyBytes];
2362 KeyGen(pub_key_bytes, priv.get(), seed.data());
2363
2364 ScopedCBB cbb;
2365 if (!CBB_init(cbb.get(), BCM_MLKEM768_PRIVATE_KEY_BYTES) ||
2366 !bcm_success(MarshalPrivate(cbb.get(), priv.get()))) {
2367 LOG_ERROR("Failed to serialize private key.\n");
2368 return false;
2369 }
2370
2371 return write_reply(
2372 {pub_key_bytes, Span(CBB_data(cbb.get()), CBB_len(cbb.get()))});
2373 }
2374
2375 template <typename PublicKey, bcm_status (*ParsePublic)(PublicKey *, CBS *),
2376 size_t CiphertextBytes,
2377 bcm_infallible (*Encap)(uint8_t *, uint8_t *, const PublicKey *,
2378 const uint8_t *)>
MLKEMEncap(const Span<const uint8_t> args[],ReplyCallback write_reply)2379 static bool MLKEMEncap(const Span<const uint8_t> args[],
2380 ReplyCallback write_reply) {
2381 const Span<const uint8_t> pub_key_bytes = args[0];
2382 const Span<const uint8_t> entropy = args[1];
2383
2384 if (entropy.size() != BCM_MLKEM_ENCAP_ENTROPY) {
2385 LOG_ERROR("Bad entropy size.\n");
2386 return false;
2387 }
2388
2389 auto pub = std::make_unique<PublicKey>();
2390 CBS cbs = pub_key_bytes;
2391 if (!bcm_success(ParsePublic(pub.get(), &cbs)) || CBS_len(&cbs) != 0) {
2392 LOG_ERROR("Failed to parse public key.\n");
2393 return false;
2394 }
2395
2396 uint8_t ciphertext[CiphertextBytes];
2397 uint8_t shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
2398 Encap(ciphertext, shared_secret, pub.get(), entropy.data());
2399
2400 return write_reply({ciphertext, shared_secret});
2401 }
2402
2403 template <typename PrivateKey, bcm_status (*ParsePrivate)(PrivateKey *, CBS *),
2404 bcm_status (*Decap)(uint8_t *, const uint8_t *, size_t,
2405 const PrivateKey *)>
MLKEMDecap(const Span<const uint8_t> args[],ReplyCallback write_reply)2406 static bool MLKEMDecap(const Span<const uint8_t> args[],
2407 ReplyCallback write_reply) {
2408 const Span<const uint8_t> priv_key_bytes = args[0];
2409 const Span<const uint8_t> ciphertext = args[1];
2410
2411 auto priv = std::make_unique<PrivateKey>();
2412 CBS cbs = priv_key_bytes;
2413 if (!bcm_success(ParsePrivate(priv.get(), &cbs))) {
2414 LOG_ERROR("Failed to parse private key.\n");
2415 return false;
2416 }
2417
2418 uint8_t shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
2419 if (!bcm_success(Decap(shared_secret, ciphertext.data(), ciphertext.size(),
2420 priv.get()))) {
2421 LOG_ERROR("ML-KEM decapsulation failed.\n");
2422 return false;
2423 }
2424
2425 return write_reply({shared_secret});
2426 }
2427
SLHDSAKeyGen(const Span<const uint8_t> args[],ReplyCallback write_reply)2428 static bool SLHDSAKeyGen(const Span<const uint8_t> args[],
2429 ReplyCallback write_reply) {
2430 const Span<const uint8_t> seed = args[0];
2431
2432 if (seed.size() != 3 * BCM_SLHDSA_SHA2_128S_N) {
2433 LOG_ERROR("Bad seed size.\n");
2434 return false;
2435 }
2436
2437 uint8_t public_key[BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES];
2438 uint8_t private_key[BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES];
2439 BCM_slhdsa_sha2_128s_generate_key_from_seed(public_key, private_key,
2440 seed.data());
2441
2442 return write_reply({private_key, public_key});
2443 }
2444
SLHDSASigGen(const Span<const uint8_t> args[],ReplyCallback write_reply)2445 static bool SLHDSASigGen(const Span<const uint8_t> args[],
2446 ReplyCallback write_reply) {
2447 const Span<const uint8_t> private_key = args[0];
2448 const Span<const uint8_t> msg = args[1];
2449 const Span<const uint8_t> entropy_span = args[2];
2450
2451 if (private_key.size() != BCM_SLHDSA_SHA2_128S_PRIVATE_KEY_BYTES) {
2452 LOG_ERROR("Bad private key size.\n");
2453 return false;
2454 }
2455
2456 uint8_t entropy[BCM_SLHDSA_SHA2_128S_N];
2457 if (!entropy_span.empty()) {
2458 if (entropy_span.size() != BCM_SLHDSA_SHA2_128S_N) {
2459 LOG_ERROR("Bad entropy size.\n");
2460 return false;
2461 }
2462 memcpy(entropy, entropy_span.data(), entropy_span.size());
2463 } else {
2464 memcpy(entropy, private_key.data() + 32, 16);
2465 }
2466
2467 uint8_t signature[BCM_SLHDSA_SHA2_128S_SIGNATURE_BYTES];
2468 BCM_slhdsa_sha2_128s_sign_internal(signature, private_key.data(), nullptr,
2469 nullptr, 0, msg.data(), msg.size(),
2470 entropy);
2471
2472 return write_reply({signature});
2473 }
2474
SLHDSASigVer(const Span<const uint8_t> args[],ReplyCallback write_reply)2475 static bool SLHDSASigVer(const Span<const uint8_t> args[],
2476 ReplyCallback write_reply) {
2477 const Span<const uint8_t> public_key = args[0];
2478 const Span<const uint8_t> msg = args[1];
2479 const Span<const uint8_t> signature = args[2];
2480
2481 if (public_key.size() != BCM_SLHDSA_SHA2_128S_PUBLIC_KEY_BYTES) {
2482 LOG_ERROR("Bad public key size.\n");
2483 return false;
2484 }
2485
2486 const int ok = bcm_success(BCM_slhdsa_sha2_128s_verify_internal(
2487 signature.data(), signature.size(), public_key.data(), nullptr, nullptr,
2488 0, msg.data(), msg.size()));
2489
2490 const uint8_t ok_byte = ok ? 1 : 0;
2491 return write_reply({Span<const uint8_t>(&ok_byte, 1)});
2492 }
2493
2494 static constexpr struct {
2495 char name[kMaxNameLength + 1];
2496 uint8_t num_expected_args;
2497 bool (*handler)(const Span<const uint8_t> args[], ReplyCallback write_reply);
2498 } kFunctions[] = {
2499 {"getConfig", 0, GetConfig},
2500 {"flush", 0, Flush},
2501 {"SHA-1", 1, Hash<SHA1, SHA_DIGEST_LENGTH>},
2502 {"SHA2-224", 1, Hash<SHA224, SHA224_DIGEST_LENGTH>},
2503 {"SHA2-256", 1, Hash<SHA256, SHA256_DIGEST_LENGTH>},
2504 {"SHA2-384", 1, Hash<SHA384, SHA384_DIGEST_LENGTH>},
2505 {"SHA2-512", 1, Hash<SHA512, SHA512_DIGEST_LENGTH>},
2506 {"SHA2-512/256", 1, Hash<SHA512_256, SHA512_256_DIGEST_LENGTH>},
2507 {"SHA-1/MCT", 1, HashMCT<SHA1, SHA_DIGEST_LENGTH>},
2508 {"SHA2-224/MCT", 1, HashMCT<SHA224, SHA224_DIGEST_LENGTH>},
2509 {"SHA2-256/MCT", 1, HashMCT<SHA256, SHA256_DIGEST_LENGTH>},
2510 {"SHA2-384/MCT", 1, HashMCT<SHA384, SHA384_DIGEST_LENGTH>},
2511 {"SHA2-512/MCT", 1, HashMCT<SHA512, SHA512_DIGEST_LENGTH>},
2512 {"SHA2-512/256/MCT", 1, HashMCT<SHA512_256, SHA512_256_DIGEST_LENGTH>},
2513 {"AES/encrypt", 3, AES<AES_set_encrypt_key, AES_encrypt>},
2514 {"AES/decrypt", 3, AES<AES_set_decrypt_key, AES_decrypt>},
2515 {"AES-CBC/encrypt", 4, AES_CBC<AES_set_encrypt_key, AES_ENCRYPT>},
2516 {"AES-CBC/decrypt", 4, AES_CBC<AES_set_decrypt_key, AES_DECRYPT>},
2517 {"AES-CTR/encrypt", 4, AES_CTR},
2518 {"AES-CTR/decrypt", 4, AES_CTR},
2519 {"AES-GCM/seal", 5, AEADSeal<AESGCMSetup>},
2520 {"AES-GCM/open", 5, AEADOpen<AESGCMSetup>},
2521 {"AES-GCM-randnonce/seal", 5, AEADSeal<AESGCMRandNonceSetup>},
2522 {"AES-GCM-randnonce/open", 5, AEADOpen<AESGCMRandNonceSetup>},
2523 {"AES-KW/seal", 5, AESKeyWrapSeal},
2524 {"AES-KW/open", 5, AESKeyWrapOpen},
2525 {"AES-KWP/seal", 5, AESPaddedKeyWrapSeal},
2526 {"AES-KWP/open", 5, AESPaddedKeyWrapOpen},
2527 {"AES-CCM/seal", 5, AEADSeal<AESCCMSetup>},
2528 {"AES-CCM/open", 5, AEADOpen<AESCCMSetup>},
2529 {"3DES-ECB/encrypt", 3, TDES<true>},
2530 {"3DES-ECB/decrypt", 3, TDES<false>},
2531 {"3DES-CBC/encrypt", 4, TDES_CBC<true>},
2532 {"3DES-CBC/decrypt", 4, TDES_CBC<false>},
2533 {"HKDF/SHA2-224", 4, HKDF<EVP_sha224>},
2534 {"HKDF/SHA2-256", 4, HKDF<EVP_sha256>},
2535 {"HKDF/SHA2-384", 4, HKDF<EVP_sha384>},
2536 {"HKDF/SHA2-512", 4, HKDF<EVP_sha512>},
2537 {"HKDF/SHA2-512/256", 4, HKDF<EVP_sha512_256>},
2538 {"HKDFExpandLabel/SHA2-256", 4, HKDFExpandLabel<EVP_sha256>},
2539 {"HKDFExpandLabel/SHA2-384", 4, HKDFExpandLabel<EVP_sha384>},
2540 {"HKDFExtract/SHA2-256", 2, HKDFExtract<EVP_sha256>},
2541 {"HKDFExtract/SHA2-384", 2, HKDFExtract<EVP_sha384>},
2542 {"HMAC-SHA-1", 2, HMAC<EVP_sha1>},
2543 {"HMAC-SHA2-224", 2, HMAC<EVP_sha224>},
2544 {"HMAC-SHA2-256", 2, HMAC<EVP_sha256>},
2545 {"HMAC-SHA2-384", 2, HMAC<EVP_sha384>},
2546 {"HMAC-SHA2-512", 2, HMAC<EVP_sha512>},
2547 {"HMAC-SHA2-512/256", 2, HMAC<EVP_sha512_256>},
2548 {"ctrDRBG/AES-256", 6, DRBG<false>},
2549 {"ctrDRBG-reseed/AES-256", 8, DRBG<true>},
2550 {"ECDSA/keyGen", 1, ECDSAKeyGen},
2551 {"ECDSA/keyVer", 3, ECDSAKeyVer},
2552 {"ECDSA/sigGen", 4, ECDSASigGen},
2553 {"ECDSA/sigVer", 7, ECDSASigVer},
2554 {"CMAC-AES", 3, CMAC_AES},
2555 {"CMAC-AES/verify", 3, CMAC_AESVerify},
2556 {"RSA/keyGen", 1, RSAKeyGen},
2557 {"RSA/sigGen/SHA2-224/pkcs1v1.5", 2, RSASigGen<EVP_sha224, false>},
2558 {"RSA/sigGen/SHA2-256/pkcs1v1.5", 2, RSASigGen<EVP_sha256, false>},
2559 {"RSA/sigGen/SHA2-384/pkcs1v1.5", 2, RSASigGen<EVP_sha384, false>},
2560 {"RSA/sigGen/SHA2-512/pkcs1v1.5", 2, RSASigGen<EVP_sha512, false>},
2561 {"RSA/sigGen/SHA-1/pkcs1v1.5", 2, RSASigGen<EVP_sha1, false>},
2562 {"RSA/sigGen/SHA2-224/pss", 2, RSASigGen<EVP_sha224, true>},
2563 {"RSA/sigGen/SHA2-256/pss", 2, RSASigGen<EVP_sha256, true>},
2564 {"RSA/sigGen/SHA2-384/pss", 2, RSASigGen<EVP_sha384, true>},
2565 {"RSA/sigGen/SHA2-512/pss", 2, RSASigGen<EVP_sha512, true>},
2566 {"RSA/sigGen/SHA2-512/256/pss", 2, RSASigGen<EVP_sha512_256, true>},
2567 {"RSA/sigGen/SHA-1/pss", 2, RSASigGen<EVP_sha1, true>},
2568 {"RSA/sigVer/SHA2-224/pkcs1v1.5", 4, RSASigVer<EVP_sha224, false>},
2569 {"RSA/sigVer/SHA2-256/pkcs1v1.5", 4, RSASigVer<EVP_sha256, false>},
2570 {"RSA/sigVer/SHA2-384/pkcs1v1.5", 4, RSASigVer<EVP_sha384, false>},
2571 {"RSA/sigVer/SHA2-512/pkcs1v1.5", 4, RSASigVer<EVP_sha512, false>},
2572 {"RSA/sigVer/SHA-1/pkcs1v1.5", 4, RSASigVer<EVP_sha1, false>},
2573 {"RSA/sigVer/SHA2-224/pss", 4, RSASigVer<EVP_sha224, true>},
2574 {"RSA/sigVer/SHA2-256/pss", 4, RSASigVer<EVP_sha256, true>},
2575 {"RSA/sigVer/SHA2-384/pss", 4, RSASigVer<EVP_sha384, true>},
2576 {"RSA/sigVer/SHA2-512/pss", 4, RSASigVer<EVP_sha512, true>},
2577 {"RSA/sigVer/SHA2-512/256/pss", 4, RSASigVer<EVP_sha512_256, true>},
2578 {"RSA/sigVer/SHA-1/pss", 4, RSASigVer<EVP_sha1, true>},
2579 {"TLSKDF/1.2/SHA2-256", 5, TLSKDF<EVP_sha256>},
2580 {"TLSKDF/1.2/SHA2-384", 5, TLSKDF<EVP_sha384>},
2581 {"TLSKDF/1.2/SHA2-512", 5, TLSKDF<EVP_sha512>},
2582 {"ECDH/P-224", 3, ECDH<NID_secp224r1>},
2583 {"ECDH/P-256", 3, ECDH<NID_X9_62_prime256v1>},
2584 {"ECDH/P-384", 3, ECDH<NID_secp384r1>},
2585 {"ECDH/P-521", 3, ECDH<NID_secp521r1>},
2586 {"FFDH", 6, FFDH},
2587 {"ML-DSA-44/keyGen", 1,
2588 MLDSAKeyGen<BCM_mldsa44_private_key, BCM_MLDSA44_PUBLIC_KEY_BYTES,
2589 BCM_mldsa44_generate_key_external_entropy_fips,
2590 BCM_mldsa44_marshal_private_key>},
2591 {"ML-DSA-65/keyGen", 1,
2592 MLDSAKeyGen<BCM_mldsa65_private_key, BCM_MLDSA65_PUBLIC_KEY_BYTES,
2593 BCM_mldsa65_generate_key_external_entropy_fips,
2594 BCM_mldsa65_marshal_private_key>},
2595 {"ML-DSA-87/keyGen", 1,
2596 MLDSAKeyGen<BCM_mldsa87_private_key, BCM_MLDSA87_PUBLIC_KEY_BYTES,
2597 BCM_mldsa87_generate_key_external_entropy_fips,
2598 BCM_mldsa87_marshal_private_key>},
2599 {"ML-DSA-44/sigGen", 3,
2600 MLDSASigGen<BCM_mldsa44_private_key, BCM_MLDSA44_SIGNATURE_BYTES,
2601 BCM_mldsa44_parse_private_key, BCM_mldsa44_sign_internal>},
2602 {"ML-DSA-65/sigGen", 3,
2603 MLDSASigGen<BCM_mldsa65_private_key, BCM_MLDSA65_SIGNATURE_BYTES,
2604 BCM_mldsa65_parse_private_key, BCM_mldsa65_sign_internal>},
2605 {"ML-DSA-87/sigGen", 3,
2606 MLDSASigGen<BCM_mldsa87_private_key, BCM_MLDSA87_SIGNATURE_BYTES,
2607 BCM_mldsa87_parse_private_key, BCM_mldsa87_sign_internal>},
2608 {"ML-DSA-44/sigVer", 3,
2609 MLDSASigVer<BCM_mldsa44_public_key, BCM_MLDSA44_SIGNATURE_BYTES,
2610 BCM_mldsa44_parse_public_key, BCM_mldsa44_verify_internal>},
2611 {"ML-DSA-65/sigVer", 3,
2612 MLDSASigVer<BCM_mldsa65_public_key, BCM_MLDSA65_SIGNATURE_BYTES,
2613 BCM_mldsa65_parse_public_key, BCM_mldsa65_verify_internal>},
2614 {"ML-DSA-87/sigVer", 3,
2615 MLDSASigVer<BCM_mldsa87_public_key, BCM_MLDSA87_SIGNATURE_BYTES,
2616 BCM_mldsa87_parse_public_key, BCM_mldsa87_verify_internal>},
2617 {"ML-KEM-768/keyGen", 1,
2618 MLKEMKeyGen<BCM_mlkem768_private_key, BCM_MLKEM768_PUBLIC_KEY_BYTES,
2619 BCM_mlkem768_generate_key_external_seed,
2620 BCM_mlkem768_marshal_private_key>},
2621 {"ML-KEM-1024/keyGen", 1,
2622 MLKEMKeyGen<BCM_mlkem1024_private_key, BCM_MLKEM1024_PUBLIC_KEY_BYTES,
2623 BCM_mlkem1024_generate_key_external_seed,
2624 BCM_mlkem1024_marshal_private_key>},
2625 {"ML-KEM-768/encap", 2,
2626 MLKEMEncap<BCM_mlkem768_public_key, BCM_mlkem768_parse_public_key,
2627 BCM_MLKEM768_CIPHERTEXT_BYTES,
2628 BCM_mlkem768_encap_external_entropy>},
2629 {"ML-KEM-1024/encap", 2,
2630 MLKEMEncap<BCM_mlkem1024_public_key, BCM_mlkem1024_parse_public_key,
2631 BCM_MLKEM1024_CIPHERTEXT_BYTES,
2632 BCM_mlkem1024_encap_external_entropy>},
2633 {"ML-KEM-768/decap", 2,
2634 MLKEMDecap<BCM_mlkem768_private_key, BCM_mlkem768_parse_private_key,
2635 BCM_mlkem768_decap>},
2636 {"ML-KEM-1024/decap", 2,
2637 MLKEMDecap<BCM_mlkem1024_private_key, BCM_mlkem1024_parse_private_key,
2638 BCM_mlkem1024_decap>},
2639 {"SLH-DSA-SHA2-128s/keyGen", 1, SLHDSAKeyGen},
2640 {"SLH-DSA-SHA2-128s/sigGen", 3, SLHDSASigGen},
2641 {"SLH-DSA-SHA2-128s/sigVer", 3, SLHDSASigVer},
2642 };
2643
FindHandler(Span<const Span<const uint8_t>> args)2644 Handler FindHandler(Span<const Span<const uint8_t>> args) {
2645 auto algorithm = bssl::BytesAsStringView(args[0]);
2646 for (const auto &func : kFunctions) {
2647 if (algorithm == func.name) {
2648 if (args.size() - 1 != func.num_expected_args) {
2649 LOG_ERROR("\'%s\' operation received %zu arguments but expected %u.\n",
2650 func.name, args.size() - 1, func.num_expected_args);
2651 return nullptr;
2652 }
2653
2654 return func.handler;
2655 }
2656 }
2657
2658 LOG_ERROR("Unknown operation: %s\n", std::string(algorithm).c_str());
2659 return nullptr;
2660 }
2661
2662 } // namespace acvp
2663 } // namespace bssl
2664