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