1 /* Copyright (c) 2019, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <map>
16 #include <string>
17 #include <vector>
18
19 #include <assert.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <string.h>
23 #include <sys/uio.h>
24 #include <unistd.h>
25 #include <cstdarg>
26
27 #include <openssl/aead.h>
28 #include <openssl/aes.h>
29 #include <openssl/bn.h>
30 #include <openssl/cipher.h>
31 #include <openssl/cmac.h>
32 #include <openssl/dh.h>
33 #include <openssl/digest.h>
34 #include <openssl/ec.h>
35 #include <openssl/ec_key.h>
36 #include <openssl/ecdh.h>
37 #include <openssl/ecdsa.h>
38 #include <openssl/err.h>
39 #include <openssl/hmac.h>
40 #include <openssl/obj.h>
41 #include <openssl/rsa.h>
42 #include <openssl/sha.h>
43 #include <openssl/span.h>
44
45 #include "../../../../crypto/fipsmodule/ec/internal.h"
46 #include "../../../../crypto/fipsmodule/rand/internal.h"
47 #include "../../../../crypto/fipsmodule/tls/internal.h"
48
49 static constexpr size_t kMaxArgs = 8;
50 static constexpr size_t kMaxArgLength = (1 << 20);
51 static constexpr size_t kMaxNameLength = 30;
52
53 static_assert((kMaxArgs - 1 * kMaxArgLength) + kMaxNameLength > (1 << 30),
54 "Argument limits permit excessive messages");
55
56 using namespace bssl;
57
ReadAll(int fd,void * in_data,size_t data_len)58 static bool ReadAll(int fd, void *in_data, size_t data_len) {
59 uint8_t *data = reinterpret_cast<uint8_t *>(in_data);
60 size_t done = 0;
61
62 while (done < data_len) {
63 ssize_t r;
64 do {
65 r = read(fd, &data[done], data_len - done);
66 } while (r == -1 && errno == EINTR);
67
68 if (r <= 0) {
69 return false;
70 }
71
72 done += r;
73 }
74
75 return true;
76 }
77
78 template <typename... Args>
WriteReply(int fd,Args...args)79 static bool WriteReply(int fd, Args... args) {
80 std::vector<Span<const uint8_t>> spans = {args...};
81 if (spans.empty() || spans.size() > kMaxArgs) {
82 abort();
83 }
84
85 uint32_t nums[1 + kMaxArgs];
86 iovec iovs[kMaxArgs + 1];
87 nums[0] = spans.size();
88 iovs[0].iov_base = nums;
89 iovs[0].iov_len = sizeof(uint32_t) * (1 + spans.size());
90
91 size_t num_iov = 1;
92 for (size_t i = 0; i < spans.size(); i++) {
93 const auto &span = spans[i];
94 nums[i + 1] = span.size();
95 if (span.empty()) {
96 continue;
97 }
98
99 iovs[num_iov].iov_base = const_cast<uint8_t *>(span.data());
100 iovs[num_iov].iov_len = span.size();
101 num_iov++;
102 }
103
104 size_t iov_done = 0;
105 while (iov_done < num_iov) {
106 ssize_t r;
107 do {
108 r = writev(fd, &iovs[iov_done], num_iov - iov_done);
109 } while (r == -1 && errno == EINTR);
110
111 if (r <= 0) {
112 return false;
113 }
114
115 size_t written = r;
116 for (size_t i = iov_done; i < num_iov && written > 0; i++) {
117 iovec &iov = iovs[i];
118
119 size_t done = written;
120 if (done > iov.iov_len) {
121 done = iov.iov_len;
122 }
123
124 iov.iov_base = reinterpret_cast<uint8_t *>(iov.iov_base) + done;
125 iov.iov_len -= done;
126 written -= done;
127
128 if (iov.iov_len == 0) {
129 iov_done++;
130 }
131 }
132
133 assert(written == 0);
134 }
135
136 return true;
137 }
138
GetConfig(const Span<const uint8_t> args[])139 static bool GetConfig(const Span<const uint8_t> args[]) {
140 static constexpr char kConfig[] =
141 R"([
142 {
143 "algorithm": "SHA2-224",
144 "revision": "1.0",
145 "messageLength": [{
146 "min": 0, "max": 65528, "increment": 8
147 }]
148 },
149 {
150 "algorithm": "SHA2-256",
151 "revision": "1.0",
152 "messageLength": [{
153 "min": 0, "max": 65528, "increment": 8
154 }]
155 },
156 {
157 "algorithm": "SHA2-384",
158 "revision": "1.0",
159 "messageLength": [{
160 "min": 0, "max": 65528, "increment": 8
161 }]
162 },
163 {
164 "algorithm": "SHA2-512",
165 "revision": "1.0",
166 "messageLength": [{
167 "min": 0, "max": 65528, "increment": 8
168 }]
169 },
170 {
171 "algorithm": "SHA2-512/256",
172 "revision": "1.0",
173 "messageLength": [{
174 "min": 0, "max": 65528, "increment": 8
175 }]
176 },
177 {
178 "algorithm": "SHA-1",
179 "revision": "1.0",
180 "messageLength": [{
181 "min": 0, "max": 65528, "increment": 8
182 }]
183 },
184 {
185 "algorithm": "ACVP-AES-ECB",
186 "revision": "1.0",
187 "direction": ["encrypt", "decrypt"],
188 "keyLen": [128, 192, 256]
189 },
190 {
191 "algorithm": "ACVP-AES-CTR",
192 "revision": "1.0",
193 "direction": ["encrypt", "decrypt"],
194 "keyLen": [128, 192, 256],
195 "payloadLen": [{
196 "min": 8, "max": 128, "increment": 8
197 }],
198 "incrementalCounter": true,
199 "overflowCounter": true,
200 "performCounterTests": true
201 },
202 {
203 "algorithm": "ACVP-AES-CBC",
204 "revision": "1.0",
205 "direction": ["encrypt", "decrypt"],
206 "keyLen": [128, 192, 256]
207 },
208 {
209 "algorithm": "ACVP-AES-GCM",
210 "revision": "1.0",
211 "direction": ["encrypt", "decrypt"],
212 "keyLen": [128, 192, 256],
213 "payloadLen": [{
214 "min": 0, "max": 256, "increment": 8
215 }],
216 "aadLen": [{
217 "min": 0, "max": 320, "increment": 8
218 }],
219 "tagLen": [32, 64, 96, 104, 112, 120, 128],
220 "ivLen": [96],
221 "ivGen": "external"
222 },
223 {
224 "algorithm": "ACVP-AES-KW",
225 "revision": "1.0",
226 "direction": [
227 "encrypt",
228 "decrypt"
229 ],
230 "kwCipher": [
231 "cipher"
232 ],
233 "keyLen": [
234 128, 192, 256
235 ],
236 "payloadLen": [{"min": 128, "max": 1024, "increment": 64}]
237 },
238 {
239 "algorithm": "ACVP-AES-KWP",
240 "revision": "1.0",
241 "direction": [
242 "encrypt",
243 "decrypt"
244 ],
245 "kwCipher": [
246 "cipher"
247 ],
248 "keyLen": [
249 128, 192, 256
250 ],
251 "payloadLen": [{"min": 8, "max": 4096, "increment": 8}]
252 },
253 {
254 "algorithm": "ACVP-AES-CCM",
255 "revision": "1.0",
256 "direction": [
257 "encrypt",
258 "decrypt"
259 ],
260 "keyLen": [
261 128
262 ],
263 "payloadLen": [{"min": 0, "max": 256, "increment": 8}],
264 "ivLen": [104],
265 "tagLen": [32],
266 "aadLen": [{"min": 0, "max": 1024, "increment": 8}]
267 },
268 {
269 "algorithm": "ACVP-TDES-ECB",
270 "revision": "1.0",
271 "direction": ["encrypt", "decrypt"],
272 "keyLen": [192],
273 "keyingOption": [1]
274 },
275 {
276 "algorithm": "ACVP-TDES-CBC",
277 "revision": "1.0",
278 "direction": ["encrypt", "decrypt"],
279 "keyLen": [192],
280 "keyingOption": [1]
281 },
282 {
283 "algorithm": "HMAC-SHA-1",
284 "revision": "1.0",
285 "keyLen": [{
286 "min": 8, "max": 2048, "increment": 8
287 }],
288 "macLen": [{
289 "min": 32, "max": 160, "increment": 8
290 }]
291 },
292 {
293 "algorithm": "HMAC-SHA2-224",
294 "revision": "1.0",
295 "keyLen": [{
296 "min": 8, "max": 2048, "increment": 8
297 }],
298 "macLen": [{
299 "min": 32, "max": 224, "increment": 8
300 }]
301 },
302 {
303 "algorithm": "HMAC-SHA2-256",
304 "revision": "1.0",
305 "keyLen": [{
306 "min": 8, "max": 2048, "increment": 8
307 }],
308 "macLen": [{
309 "min": 32, "max": 256, "increment": 8
310 }]
311 },
312 {
313 "algorithm": "HMAC-SHA2-384",
314 "revision": "1.0",
315 "keyLen": [{
316 "min": 8, "max": 2048, "increment": 8
317 }],
318 "macLen": [{
319 "min": 32, "max": 384, "increment": 8
320 }]
321 },
322 {
323 "algorithm": "HMAC-SHA2-512",
324 "revision": "1.0",
325 "keyLen": [{
326 "min": 8, "max": 2048, "increment": 8
327 }],
328 "macLen": [{
329 "min": 32, "max": 512, "increment": 8
330 }]
331 },
332 {
333 "algorithm": "ctrDRBG",
334 "revision": "1.0",
335 "predResistanceEnabled": [false],
336 "reseedImplemented": false,
337 "capabilities": [{
338 "mode": "AES-256",
339 "derFuncEnabled": false,
340 "entropyInputLen": [384],
341 "nonceLen": [0],
342 "persoStringLen": [{"min": 0, "max": 384, "increment": 16}],
343 "additionalInputLen": [
344 {"min": 0, "max": 384, "increment": 16}
345 ],
346 "returnedBitsLen": 2048
347 }]
348 },
349 {
350 "algorithm": "ECDSA",
351 "mode": "keyGen",
352 "revision": "1.0",
353 "curve": [
354 "P-224",
355 "P-256",
356 "P-384",
357 "P-521"
358 ],
359 "secretGenerationMode": [
360 "testing candidates"
361 ]
362 },
363 {
364 "algorithm": "ECDSA",
365 "mode": "keyVer",
366 "revision": "1.0",
367 "curve": [
368 "P-224",
369 "P-256",
370 "P-384",
371 "P-521"
372 ]
373 },
374 {
375 "algorithm": "ECDSA",
376 "mode": "sigGen",
377 "revision": "1.0",
378 "capabilities": [{
379 "curve": [
380 "P-224",
381 "P-256",
382 "P-384",
383 "P-521"
384 ],
385 "hashAlg": [
386 "SHA2-224",
387 "SHA2-256",
388 "SHA2-384",
389 "SHA2-512"
390 ]
391 }]
392 },
393 {
394 "algorithm": "ECDSA",
395 "mode": "sigVer",
396 "revision": "1.0",
397 "capabilities": [{
398 "curve": [
399 "P-224",
400 "P-256",
401 "P-384",
402 "P-521"
403 ],
404 "hashAlg": [
405 "SHA2-224",
406 "SHA2-256",
407 "SHA2-384",
408 "SHA2-512"
409 ]
410 }]
411 },
412 {
413 "algorithm": "RSA",
414 "mode": "keyGen",
415 "revision": "FIPS186-4",
416 "infoGeneratedByServer": true,
417 "pubExpMode": "fixed",
418 "fixedPubExp": "010001",
419 "keyFormat": "standard",
420 "capabilities": [{
421 "randPQ": "B.3.3",
422 "properties": [{
423 "modulo": 2048,
424 "primeTest": [
425 "tblC2"
426 ]
427 },{
428 "modulo": 3072,
429 "primeTest": [
430 "tblC2"
431 ]
432 },{
433 "modulo": 4096,
434 "primeTest": [
435 "tblC2"
436 ]
437 }]
438 }]
439 },
440 {
441 "algorithm": "RSA",
442 "mode": "sigGen",
443 "revision": "FIPS186-4",
444 "capabilities": [{
445 "sigType": "pkcs1v1.5",
446 "properties": [{
447 "modulo": 2048,
448 "hashPair": [{
449 "hashAlg": "SHA2-224"
450 }, {
451 "hashAlg": "SHA2-256"
452 }, {
453 "hashAlg": "SHA2-384"
454 }, {
455 "hashAlg": "SHA2-512"
456 }]
457 }]
458 },{
459 "sigType": "pkcs1v1.5",
460 "properties": [{
461 "modulo": 3072,
462 "hashPair": [{
463 "hashAlg": "SHA2-224"
464 }, {
465 "hashAlg": "SHA2-256"
466 }, {
467 "hashAlg": "SHA2-384"
468 }, {
469 "hashAlg": "SHA2-512"
470 }]
471 }]
472 },{
473 "sigType": "pkcs1v1.5",
474 "properties": [{
475 "modulo": 4096,
476 "hashPair": [{
477 "hashAlg": "SHA2-224"
478 }, {
479 "hashAlg": "SHA2-256"
480 }, {
481 "hashAlg": "SHA2-384"
482 }, {
483 "hashAlg": "SHA2-512"
484 }]
485 }]
486 },{
487 "sigType": "pss",
488 "properties": [{
489 "modulo": 2048,
490 "hashPair": [{
491 "hashAlg": "SHA2-224",
492 "saltLen": 28
493 }, {
494 "hashAlg": "SHA2-256",
495 "saltLen": 32
496 }, {
497 "hashAlg": "SHA2-384",
498 "saltLen": 48
499 }, {
500 "hashAlg": "SHA2-512",
501 "saltLen": 64
502 }]
503 }]
504 },{
505 "sigType": "pss",
506 "properties": [{
507 "modulo": 3072,
508 "hashPair": [{
509 "hashAlg": "SHA2-224",
510 "saltLen": 28
511 }, {
512 "hashAlg": "SHA2-256",
513 "saltLen": 32
514 }, {
515 "hashAlg": "SHA2-384",
516 "saltLen": 48
517 }, {
518 "hashAlg": "SHA2-512",
519 "saltLen": 64
520 }]
521 }]
522 },{
523 "sigType": "pss",
524 "properties": [{
525 "modulo": 4096,
526 "hashPair": [{
527 "hashAlg": "SHA2-224",
528 "saltLen": 28
529 }, {
530 "hashAlg": "SHA2-256",
531 "saltLen": 32
532 }, {
533 "hashAlg": "SHA2-384",
534 "saltLen": 48
535 }, {
536 "hashAlg": "SHA2-512",
537 "saltLen": 64
538 }]
539 }]
540 }]
541 },
542 {
543 "algorithm": "RSA",
544 "mode": "sigVer",
545 "revision": "FIPS186-4",
546 "pubExpMode": "fixed",
547 "fixedPubExp": "010001",
548 "capabilities": [{
549 "sigType": "pkcs1v1.5",
550 "properties": [{
551 "modulo": 1024,
552 "hashPair": [{
553 "hashAlg": "SHA2-224"
554 }, {
555 "hashAlg": "SHA2-256"
556 }, {
557 "hashAlg": "SHA2-384"
558 }, {
559 "hashAlg": "SHA2-512"
560 }, {
561 "hashAlg": "SHA-1"
562 }]
563 }]
564 },{
565 "sigType": "pkcs1v1.5",
566 "properties": [{
567 "modulo": 2048,
568 "hashPair": [{
569 "hashAlg": "SHA2-224"
570 }, {
571 "hashAlg": "SHA2-256"
572 }, {
573 "hashAlg": "SHA2-384"
574 }, {
575 "hashAlg": "SHA2-512"
576 }, {
577 "hashAlg": "SHA-1"
578 }]
579 }]
580 },{
581 "sigType": "pkcs1v1.5",
582 "properties": [{
583 "modulo": 3072,
584 "hashPair": [{
585 "hashAlg": "SHA2-224"
586 }, {
587 "hashAlg": "SHA2-256"
588 }, {
589 "hashAlg": "SHA2-384"
590 }, {
591 "hashAlg": "SHA2-512"
592 }, {
593 "hashAlg": "SHA-1"
594 }]
595 }]
596 },{
597 "sigType": "pkcs1v1.5",
598 "properties": [{
599 "modulo": 4096,
600 "hashPair": [{
601 "hashAlg": "SHA2-224"
602 }, {
603 "hashAlg": "SHA2-256"
604 }, {
605 "hashAlg": "SHA2-384"
606 }, {
607 "hashAlg": "SHA2-512"
608 }, {
609 "hashAlg": "SHA-1"
610 }]
611 }]
612 },{
613 "sigType": "pss",
614 "properties": [{
615 "modulo": 2048,
616 "hashPair": [{
617 "hashAlg": "SHA2-224",
618 "saltLen": 28
619 }, {
620 "hashAlg": "SHA2-256",
621 "saltLen": 32
622 }, {
623 "hashAlg": "SHA2-384",
624 "saltLen": 48
625 }, {
626 "hashAlg": "SHA2-512",
627 "saltLen": 64
628 }, {
629 "hashAlg": "SHA-1",
630 "saltLen": 20
631 }]
632 }]
633 },{
634 "sigType": "pss",
635 "properties": [{
636 "modulo": 3072,
637 "hashPair": [{
638 "hashAlg": "SHA2-224",
639 "saltLen": 28
640 }, {
641 "hashAlg": "SHA2-256",
642 "saltLen": 32
643 }, {
644 "hashAlg": "SHA2-384",
645 "saltLen": 48
646 }, {
647 "hashAlg": "SHA2-512",
648 "saltLen": 64
649 }, {
650 "hashAlg": "SHA-1",
651 "saltLen": 20
652 }]
653 }]
654 },{
655 "sigType": "pss",
656 "properties": [{
657 "modulo": 4096,
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": "SHA-1",
672 "saltLen": 20
673 }]
674 }]
675 }]
676 },
677 {
678 "algorithm": "CMAC-AES",
679 "revision": "1.0",
680 "capabilities": [{
681 "direction": ["gen"],
682 "msgLen": [{
683 "min": 0,
684 "max": 65536,
685 "increment": 8
686 }],
687 "keyLen": [128, 256],
688 "macLen": [{
689 "min": 32,
690 "max": 128,
691 "increment": 8
692 }]
693 }]
694 },
695 {
696 "algorithm": "kdf-components",
697 "revision": "1.0",
698 "mode": "tls",
699 "tlsVersion": [
700 "v1.0/1.1",
701 "v1.2"
702 ],
703 "hashAlg": [
704 "SHA2-256",
705 "SHA2-384",
706 "SHA2-512"
707 ]
708 },
709 {
710 "algorithm": "KAS-ECC-SSC",
711 "revision": "Sp800-56Ar3",
712 "scheme": {
713 "ephemeralUnified": {
714 "kasRole": [
715 "initiator",
716 "responder"
717 ]
718 }
719 },
720 "domainParameterGenerationMethods": [
721 "P-224",
722 "P-256",
723 "P-384",
724 "P-521"
725 ]
726 },
727 {
728 "algorithm": "KAS-FFC-SSC",
729 "revision": "Sp800-56Ar3",
730 "scheme": {
731 "dhEphem": {
732 "kasRole": [
733 "initiator"
734 ]
735 }
736 },
737 "domainParameterGenerationMethods": [
738 "FB",
739 "FC"
740 ]
741 }
742 ])";
743 return WriteReply(
744 STDOUT_FILENO,
745 Span<const uint8_t>(reinterpret_cast<const uint8_t *>(kConfig),
746 sizeof(kConfig) - 1));
747 }
748
749 template <uint8_t *(*OneShotHash)(const uint8_t *, size_t, uint8_t *),
750 size_t DigestLength>
Hash(const Span<const uint8_t> args[])751 static bool Hash(const Span<const uint8_t> args[]) {
752 uint8_t digest[DigestLength];
753 OneShotHash(args[0].data(), args[0].size(), digest);
754 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(digest));
755 }
756
GetIterations(const Span<const uint8_t> iterations_bytes)757 static uint32_t GetIterations(const Span<const uint8_t> iterations_bytes) {
758 uint32_t iterations;
759 if (iterations_bytes.size() != sizeof(iterations)) {
760 fprintf(stderr,
761 "Expected %u-byte input for number of iterations, but found %u "
762 "bytes.\n",
763 static_cast<unsigned>(sizeof(iterations)),
764 static_cast<unsigned>(iterations_bytes.size()));
765 abort();
766 }
767
768 memcpy(&iterations, iterations_bytes.data(), sizeof(iterations));
769 if (iterations == 0 || iterations == UINT32_MAX) {
770 fprintf(stderr, "Invalid number of iterations: %x.\n",
771 static_cast<unsigned>(iterations));
772 abort();
773 }
774
775 return iterations;
776 }
777
778 template <int (*SetKey)(const uint8_t *key, unsigned bits, AES_KEY *out),
779 void (*Block)(const uint8_t *in, uint8_t *out, const AES_KEY *key)>
AES(const Span<const uint8_t> args[])780 static bool AES(const Span<const uint8_t> args[]) {
781 AES_KEY key;
782 if (SetKey(args[0].data(), args[0].size() * 8, &key) != 0) {
783 return false;
784 }
785 if (args[1].size() % AES_BLOCK_SIZE != 0) {
786 return false;
787 }
788 std::vector<uint8_t> result(args[1].begin(), args[1].end());
789 const uint32_t iterations = GetIterations(args[2]);
790
791 std::vector<uint8_t> prev_result;
792 for (uint32_t j = 0; j < iterations; j++) {
793 if (j == iterations - 1) {
794 prev_result = result;
795 }
796
797 for (size_t i = 0; i < args[1].size(); i += AES_BLOCK_SIZE) {
798 Block(result.data() + i, result.data() + i, &key);
799 }
800 }
801
802 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(result),
803 Span<const uint8_t>(prev_result));
804 }
805
806 template <int (*SetKey)(const uint8_t *key, unsigned bits, AES_KEY *out),
807 int Direction>
AES_CBC(const Span<const uint8_t> args[])808 static bool AES_CBC(const Span<const uint8_t> args[]) {
809 AES_KEY key;
810 if (SetKey(args[0].data(), args[0].size() * 8, &key) != 0) {
811 return false;
812 }
813 if (args[1].size() % AES_BLOCK_SIZE != 0 || args[1].empty() ||
814 args[2].size() != AES_BLOCK_SIZE) {
815 return false;
816 }
817 std::vector<uint8_t> input(args[1].begin(), args[1].end());
818 std::vector<uint8_t> iv(args[2].begin(), args[2].end());
819 const uint32_t iterations = GetIterations(args[3]);
820
821 std::vector<uint8_t> result(input.size());
822 std::vector<uint8_t> prev_result, prev_input;
823
824 for (uint32_t j = 0; j < iterations; j++) {
825 prev_result = result;
826 if (j > 0) {
827 if (Direction == AES_ENCRYPT) {
828 iv = result;
829 } else {
830 iv = prev_input;
831 }
832 }
833
834 // AES_cbc_encrypt will mutate the given IV, but we need it later.
835 uint8_t iv_copy[AES_BLOCK_SIZE];
836 memcpy(iv_copy, iv.data(), sizeof(iv_copy));
837 AES_cbc_encrypt(input.data(), result.data(), input.size(), &key, iv_copy,
838 Direction);
839
840 if (Direction == AES_DECRYPT) {
841 prev_input = input;
842 }
843
844 if (j == 0) {
845 input = iv;
846 } else {
847 input = prev_result;
848 }
849 }
850
851 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(result),
852 Span<const uint8_t>(prev_result));
853 }
854
AES_CTR(const Span<const uint8_t> args[])855 static bool AES_CTR(const Span<const uint8_t> args[]) {
856 static const uint32_t kOneIteration = 1;
857 if (args[3].size() != sizeof(kOneIteration) ||
858 memcmp(args[3].data(), &kOneIteration, sizeof(kOneIteration))) {
859 fprintf(stderr, "Only a single iteration supported with AES-CTR\n");
860 return false;
861 }
862
863 AES_KEY key;
864 if (AES_set_encrypt_key(args[0].data(), args[0].size() * 8, &key) != 0) {
865 return false;
866 }
867 if (args[2].size() != AES_BLOCK_SIZE) {
868 return false;
869 }
870 uint8_t iv[AES_BLOCK_SIZE];
871 memcpy(iv, args[2].data(), AES_BLOCK_SIZE);
872 if (GetIterations(args[3]) != 1) {
873 fprintf(stderr, "Multiple iterations of AES-CTR is not supported.\n");
874 return false;
875 }
876
877 std::vector<uint8_t> out;
878 out.resize(args[1].size());
879 unsigned num = 0;
880 uint8_t ecount_buf[AES_BLOCK_SIZE];
881 AES_ctr128_encrypt(args[1].data(), out.data(), args[1].size(), &key, iv,
882 ecount_buf, &num);
883 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(out));
884 }
885
AESGCMSetup(EVP_AEAD_CTX * ctx,Span<const uint8_t> tag_len_span,Span<const uint8_t> key)886 static bool AESGCMSetup(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
887 Span<const uint8_t> key) {
888 uint32_t tag_len_32;
889 if (tag_len_span.size() != sizeof(tag_len_32)) {
890 fprintf(stderr, "Tag size value is %u bytes, not an uint32_t\n",
891 static_cast<unsigned>(tag_len_span.size()));
892 return false;
893 }
894 memcpy(&tag_len_32, tag_len_span.data(), sizeof(tag_len_32));
895
896 const EVP_AEAD *aead;
897 switch (key.size()) {
898 case 16:
899 aead = EVP_aead_aes_128_gcm();
900 break;
901 case 24:
902 aead = EVP_aead_aes_192_gcm();
903 break;
904 case 32:
905 aead = EVP_aead_aes_256_gcm();
906 break;
907 default:
908 fprintf(stderr, "Bad AES-GCM key length %u\n",
909 static_cast<unsigned>(key.size()));
910 return false;
911 }
912
913 if (!EVP_AEAD_CTX_init(ctx, aead, key.data(), key.size(), tag_len_32,
914 nullptr)) {
915 fprintf(stderr, "Failed to setup AES-GCM with tag length %u\n",
916 static_cast<unsigned>(tag_len_32));
917 return false;
918 }
919
920 return true;
921 }
922
AESCCMSetup(EVP_AEAD_CTX * ctx,Span<const uint8_t> tag_len_span,Span<const uint8_t> key)923 static bool AESCCMSetup(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
924 Span<const uint8_t> key) {
925 uint32_t tag_len_32;
926 if (tag_len_span.size() != sizeof(tag_len_32)) {
927 fprintf(stderr, "Tag size value is %u bytes, not an uint32_t\n",
928 static_cast<unsigned>(tag_len_span.size()));
929 return false;
930 }
931 memcpy(&tag_len_32, tag_len_span.data(), sizeof(tag_len_32));
932 if (tag_len_32 != 4) {
933 fprintf(stderr, "AES-CCM only supports 4-byte tags, but %u was requested\n",
934 static_cast<unsigned>(tag_len_32));
935 return false;
936 }
937
938 if (key.size() != 16) {
939 fprintf(stderr,
940 "AES-CCM only supports 128-bit keys, but %u bits were given\n",
941 static_cast<unsigned>(key.size() * 8));
942 return false;
943 }
944
945 if (!EVP_AEAD_CTX_init(ctx, EVP_aead_aes_128_ccm_bluetooth(), key.data(),
946 key.size(), tag_len_32, nullptr)) {
947 fprintf(stderr, "Failed to setup AES-CCM with tag length %u\n",
948 static_cast<unsigned>(tag_len_32));
949 return false;
950 }
951
952 return true;
953 }
954
955 template <bool (*SetupFunc)(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
956 Span<const uint8_t> key)>
AEADSeal(const Span<const uint8_t> args[])957 static bool AEADSeal(const Span<const uint8_t> args[]) {
958 Span<const uint8_t> tag_len_span = args[0];
959 Span<const uint8_t> key = args[1];
960 Span<const uint8_t> plaintext = args[2];
961 Span<const uint8_t> nonce = args[3];
962 Span<const uint8_t> ad = args[4];
963
964 bssl::ScopedEVP_AEAD_CTX ctx;
965 if (!SetupFunc(ctx.get(), tag_len_span, key)) {
966 return false;
967 }
968
969 if (EVP_AEAD_MAX_OVERHEAD + plaintext.size() < EVP_AEAD_MAX_OVERHEAD) {
970 return false;
971 }
972 std::vector<uint8_t> out(EVP_AEAD_MAX_OVERHEAD + plaintext.size());
973
974 size_t out_len;
975 if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
976 nonce.data(), nonce.size(), plaintext.data(),
977 plaintext.size(), ad.data(), ad.size())) {
978 return false;
979 }
980
981 out.resize(out_len);
982 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(out));
983 }
984
985 template <bool (*SetupFunc)(EVP_AEAD_CTX *ctx, Span<const uint8_t> tag_len_span,
986 Span<const uint8_t> key)>
AEADOpen(const Span<const uint8_t> args[])987 static bool AEADOpen(const Span<const uint8_t> args[]) {
988 Span<const uint8_t> tag_len_span = args[0];
989 Span<const uint8_t> key = args[1];
990 Span<const uint8_t> ciphertext = args[2];
991 Span<const uint8_t> nonce = args[3];
992 Span<const uint8_t> ad = args[4];
993
994 bssl::ScopedEVP_AEAD_CTX ctx;
995 if (!SetupFunc(ctx.get(), tag_len_span, key)) {
996 return false;
997 }
998
999 std::vector<uint8_t> out(ciphertext.size());
1000 size_t out_len;
1001 uint8_t success_flag[1] = {0};
1002
1003 if (!EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
1004 nonce.data(), nonce.size(), ciphertext.data(),
1005 ciphertext.size(), ad.data(), ad.size())) {
1006 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(success_flag),
1007 Span<const uint8_t>());
1008 }
1009
1010 out.resize(out_len);
1011 success_flag[0] = 1;
1012 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(success_flag),
1013 Span<const uint8_t>(out));
1014 }
1015
AESPaddedKeyWrapSetup(AES_KEY * out,bool decrypt,Span<const uint8_t> key)1016 static bool AESPaddedKeyWrapSetup(AES_KEY *out, bool decrypt,
1017 Span<const uint8_t> key) {
1018 if ((decrypt ? AES_set_decrypt_key : AES_set_encrypt_key)(
1019 key.data(), key.size() * 8, out) != 0) {
1020 fprintf(stderr, "Invalid AES key length for AES-KW(P): %u\n",
1021 static_cast<unsigned>(key.size()));
1022 return false;
1023 }
1024 return true;
1025 }
1026
AESKeyWrapSetup(AES_KEY * out,bool decrypt,Span<const uint8_t> key,Span<const uint8_t> input)1027 static bool AESKeyWrapSetup(AES_KEY *out, bool decrypt, Span<const uint8_t> key,
1028 Span<const uint8_t> input) {
1029 if (!AESPaddedKeyWrapSetup(out, decrypt, key)) {
1030 return false;
1031 }
1032
1033 if (input.size() % 8) {
1034 fprintf(stderr, "Invalid AES-KW input length: %u\n",
1035 static_cast<unsigned>(input.size()));
1036 return false;
1037 }
1038
1039 return true;
1040 }
1041
AESKeyWrapSeal(const Span<const uint8_t> args[])1042 static bool AESKeyWrapSeal(const Span<const uint8_t> args[]) {
1043 Span<const uint8_t> key = args[1];
1044 Span<const uint8_t> plaintext = args[2];
1045
1046 AES_KEY aes;
1047 if (!AESKeyWrapSetup(&aes, /*decrypt=*/false, key, plaintext) ||
1048 plaintext.size() > INT_MAX - 8) {
1049 return false;
1050 }
1051
1052 std::vector<uint8_t> out(plaintext.size() + 8);
1053 if (AES_wrap_key(&aes, /*iv=*/nullptr, out.data(), plaintext.data(),
1054 plaintext.size()) != static_cast<int>(out.size())) {
1055 fprintf(stderr, "AES-KW failed\n");
1056 return false;
1057 }
1058
1059 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(out));
1060 }
1061
AESKeyWrapOpen(const Span<const uint8_t> args[])1062 static bool AESKeyWrapOpen(const Span<const uint8_t> args[]) {
1063 Span<const uint8_t> key = args[1];
1064 Span<const uint8_t> ciphertext = args[2];
1065
1066 AES_KEY aes;
1067 if (!AESKeyWrapSetup(&aes, /*decrypt=*/true, key, ciphertext) ||
1068 ciphertext.size() < 8 ||
1069 ciphertext.size() > INT_MAX) {
1070 return false;
1071 }
1072
1073 std::vector<uint8_t> out(ciphertext.size() - 8);
1074 uint8_t success_flag[1] = {0};
1075 if (AES_unwrap_key(&aes, /*iv=*/nullptr, out.data(), ciphertext.data(),
1076 ciphertext.size()) != static_cast<int>(out.size())) {
1077 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(success_flag),
1078 Span<const uint8_t>());
1079 }
1080
1081 success_flag[0] = 1;
1082 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(success_flag),
1083 Span<const uint8_t>(out));
1084 }
1085
AESPaddedKeyWrapSeal(const Span<const uint8_t> args[])1086 static bool AESPaddedKeyWrapSeal(const Span<const uint8_t> args[]) {
1087 Span<const uint8_t> key = args[1];
1088 Span<const uint8_t> plaintext = args[2];
1089
1090 AES_KEY aes;
1091 if (!AESPaddedKeyWrapSetup(&aes, /*decrypt=*/false, key) ||
1092 plaintext.size() + 15 < 15) {
1093 return false;
1094 }
1095
1096 std::vector<uint8_t> out(plaintext.size() + 15);
1097 size_t out_len;
1098 if (!AES_wrap_key_padded(&aes, out.data(), &out_len, out.size(),
1099 plaintext.data(), plaintext.size())) {
1100 fprintf(stderr, "AES-KWP failed\n");
1101 return false;
1102 }
1103
1104 out.resize(out_len);
1105 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(out));
1106 }
1107
AESPaddedKeyWrapOpen(const Span<const uint8_t> args[])1108 static bool AESPaddedKeyWrapOpen(const Span<const uint8_t> args[]) {
1109 Span<const uint8_t> key = args[1];
1110 Span<const uint8_t> ciphertext = args[2];
1111
1112 AES_KEY aes;
1113 if (!AESPaddedKeyWrapSetup(&aes, /*decrypt=*/true, key) ||
1114 ciphertext.size() % 8) {
1115 return false;
1116 }
1117
1118 std::vector<uint8_t> out(ciphertext.size());
1119 size_t out_len;
1120 uint8_t success_flag[1] = {0};
1121 if (!AES_unwrap_key_padded(&aes, out.data(), &out_len, out.size(),
1122 ciphertext.data(), ciphertext.size())) {
1123 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(success_flag),
1124 Span<const uint8_t>());
1125 }
1126
1127 success_flag[0] = 1;
1128 out.resize(out_len);
1129 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(success_flag),
1130 Span<const uint8_t>(out));
1131 }
1132
1133 template <bool Encrypt>
TDES(const Span<const uint8_t> args[])1134 static bool TDES(const Span<const uint8_t> args[]) {
1135 const EVP_CIPHER *cipher = EVP_des_ede3();
1136
1137 if (args[0].size() != 24) {
1138 fprintf(stderr, "Bad key length %u for 3DES.\n",
1139 static_cast<unsigned>(args[0].size()));
1140 return false;
1141 }
1142 bssl::ScopedEVP_CIPHER_CTX ctx;
1143 if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, args[0].data(), nullptr,
1144 Encrypt ? 1 : 0) ||
1145 !EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) {
1146 return false;
1147 }
1148
1149 if (args[1].size() % 8) {
1150 fprintf(stderr, "Bad input length %u for 3DES.\n",
1151 static_cast<unsigned>(args[1].size()));
1152 return false;
1153 }
1154 std::vector<uint8_t> result(args[1].begin(), args[1].end());
1155
1156 const uint32_t iterations = GetIterations(args[2]);
1157 std::vector<uint8_t> prev_result, prev_prev_result;
1158
1159 for (uint32_t j = 0; j < iterations; j++) {
1160 if (j == iterations - 1) {
1161 prev_result = result;
1162 } else if (iterations >= 2 && j == iterations - 2) {
1163 prev_prev_result = result;
1164 }
1165
1166 int out_len;
1167 if (!EVP_CipherUpdate(ctx.get(), result.data(), &out_len, result.data(),
1168 result.size()) ||
1169 out_len != static_cast<int>(result.size())) {
1170 return false;
1171 }
1172 }
1173
1174 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(result),
1175 Span<const uint8_t>(prev_result),
1176 Span<const uint8_t>(prev_prev_result));
1177 }
1178
1179 template <bool Encrypt>
TDES_CBC(const Span<const uint8_t> args[])1180 static bool TDES_CBC(const Span<const uint8_t> args[]) {
1181 const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
1182
1183 if (args[0].size() != 24) {
1184 fprintf(stderr, "Bad key length %u for 3DES.\n",
1185 static_cast<unsigned>(args[0].size()));
1186 return false;
1187 }
1188
1189 if (args[1].size() % 8 || args[1].size() == 0) {
1190 fprintf(stderr, "Bad input length %u for 3DES.\n",
1191 static_cast<unsigned>(args[1].size()));
1192 return false;
1193 }
1194 std::vector<uint8_t> input(args[1].begin(), args[1].end());
1195
1196 if (args[2].size() != EVP_CIPHER_iv_length(cipher)) {
1197 fprintf(stderr, "Bad IV length %u for 3DES.\n",
1198 static_cast<unsigned>(args[2].size()));
1199 return false;
1200 }
1201 std::vector<uint8_t> iv(args[2].begin(), args[2].end());
1202 const uint32_t iterations = GetIterations(args[3]);
1203
1204 std::vector<uint8_t> result(input.size());
1205 std::vector<uint8_t> prev_result, prev_prev_result;
1206 bssl::ScopedEVP_CIPHER_CTX ctx;
1207 if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, args[0].data(), iv.data(),
1208 Encrypt ? 1 : 0) ||
1209 !EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) {
1210 return false;
1211 }
1212
1213 for (uint32_t j = 0; j < iterations; j++) {
1214 prev_prev_result = prev_result;
1215 prev_result = result;
1216
1217 int out_len, out_len2;
1218 if (!EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, nullptr, iv.data(),
1219 -1) ||
1220 !EVP_CipherUpdate(ctx.get(), result.data(), &out_len, input.data(),
1221 input.size()) ||
1222 !EVP_CipherFinal_ex(ctx.get(), result.data() + out_len, &out_len2) ||
1223 (out_len + out_len2) != static_cast<int>(result.size())) {
1224 return false;
1225 }
1226
1227 if (Encrypt) {
1228 if (j == 0) {
1229 input = iv;
1230 } else {
1231 input = prev_result;
1232 }
1233 iv = result;
1234 } else {
1235 iv = input;
1236 input = result;
1237 }
1238 }
1239
1240 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(result),
1241 Span<const uint8_t>(prev_result),
1242 Span<const uint8_t>(prev_prev_result));
1243 }
1244
1245 template <const EVP_MD *HashFunc()>
HMAC(const Span<const uint8_t> args[])1246 static bool HMAC(const Span<const uint8_t> args[]) {
1247 const EVP_MD *const md = HashFunc();
1248 uint8_t digest[EVP_MAX_MD_SIZE];
1249 unsigned digest_len;
1250 if (::HMAC(md, args[1].data(), args[1].size(), args[0].data(), args[0].size(),
1251 digest, &digest_len) == nullptr) {
1252 return false;
1253 }
1254 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(digest, digest_len));
1255 }
1256
DRBG(const Span<const uint8_t> args[])1257 static bool DRBG(const Span<const uint8_t> args[]) {
1258 const auto out_len_bytes = args[0];
1259 const auto entropy = args[1];
1260 const auto personalisation = args[2];
1261 const auto additional_data1 = args[3];
1262 const auto additional_data2 = args[4];
1263 const auto nonce = args[5];
1264
1265 uint32_t out_len;
1266 if (out_len_bytes.size() != sizeof(out_len) ||
1267 entropy.size() != CTR_DRBG_ENTROPY_LEN ||
1268 // nonces are not supported
1269 nonce.size() != 0) {
1270 return false;
1271 }
1272 memcpy(&out_len, out_len_bytes.data(), sizeof(out_len));
1273 if (out_len > (1 << 24)) {
1274 return false;
1275 }
1276 std::vector<uint8_t> out(out_len);
1277
1278 CTR_DRBG_STATE drbg;
1279 if (!CTR_DRBG_init(&drbg, entropy.data(), personalisation.data(),
1280 personalisation.size()) ||
1281 !CTR_DRBG_generate(&drbg, out.data(), out_len, additional_data1.data(),
1282 additional_data1.size()) ||
1283 !CTR_DRBG_generate(&drbg, out.data(), out_len, additional_data2.data(),
1284 additional_data2.size())) {
1285 return false;
1286 }
1287
1288 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(out));
1289 }
1290
StringEq(Span<const uint8_t> a,const char * b)1291 static bool StringEq(Span<const uint8_t> a, const char *b) {
1292 const size_t len = strlen(b);
1293 return a.size() == len && memcmp(a.data(), b, len) == 0;
1294 }
1295
ECKeyFromName(Span<const uint8_t> name)1296 static bssl::UniquePtr<EC_KEY> ECKeyFromName(Span<const uint8_t> name) {
1297 int nid;
1298 if (StringEq(name, "P-224")) {
1299 nid = NID_secp224r1;
1300 } else if (StringEq(name, "P-256")) {
1301 nid = NID_X9_62_prime256v1;
1302 } else if (StringEq(name, "P-384")) {
1303 nid = NID_secp384r1;
1304 } else if (StringEq(name, "P-521")) {
1305 nid = NID_secp521r1;
1306 } else {
1307 return nullptr;
1308 }
1309
1310 return bssl::UniquePtr<EC_KEY>(EC_KEY_new_by_curve_name(nid));
1311 }
1312
BIGNUMBytes(const BIGNUM * bn)1313 static std::vector<uint8_t> BIGNUMBytes(const BIGNUM *bn) {
1314 const size_t len = BN_num_bytes(bn);
1315 std::vector<uint8_t> ret(len);
1316 BN_bn2bin(bn, ret.data());
1317 return ret;
1318 }
1319
GetPublicKeyBytes(const EC_KEY * key)1320 static std::pair<std::vector<uint8_t>, std::vector<uint8_t>> GetPublicKeyBytes(
1321 const EC_KEY *key) {
1322 bssl::UniquePtr<BIGNUM> x(BN_new());
1323 bssl::UniquePtr<BIGNUM> y(BN_new());
1324 if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key),
1325 EC_KEY_get0_public_key(key), x.get(),
1326 y.get(), /*ctx=*/nullptr)) {
1327 abort();
1328 }
1329
1330 std::vector<uint8_t> x_bytes = BIGNUMBytes(x.get());
1331 std::vector<uint8_t> y_bytes = BIGNUMBytes(y.get());
1332
1333 return std::make_pair(std::move(x_bytes), std::move(y_bytes));
1334 }
1335
ECDSAKeyGen(const Span<const uint8_t> args[])1336 static bool ECDSAKeyGen(const Span<const uint8_t> args[]) {
1337 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1338 if (!key || !EC_KEY_generate_key_fips(key.get())) {
1339 return false;
1340 }
1341
1342 const auto pub_key = GetPublicKeyBytes(key.get());
1343 std::vector<uint8_t> d_bytes =
1344 BIGNUMBytes(EC_KEY_get0_private_key(key.get()));
1345
1346 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(d_bytes),
1347 Span<const uint8_t>(pub_key.first),
1348 Span<const uint8_t>(pub_key.second));
1349 }
1350
BytesToBIGNUM(Span<const uint8_t> bytes)1351 static bssl::UniquePtr<BIGNUM> BytesToBIGNUM(Span<const uint8_t> bytes) {
1352 bssl::UniquePtr<BIGNUM> bn(BN_new());
1353 BN_bin2bn(bytes.data(), bytes.size(), bn.get());
1354 return bn;
1355 }
1356
ECDSAKeyVer(const Span<const uint8_t> args[])1357 static bool ECDSAKeyVer(const Span<const uint8_t> args[]) {
1358 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1359 if (!key) {
1360 return false;
1361 }
1362
1363 bssl::UniquePtr<BIGNUM> x(BytesToBIGNUM(args[1]));
1364 bssl::UniquePtr<BIGNUM> y(BytesToBIGNUM(args[2]));
1365
1366 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(EC_KEY_get0_group(key.get())));
1367 uint8_t reply[1];
1368 if (!EC_POINT_set_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
1369 point.get(), x.get(), y.get(),
1370 /*ctx=*/nullptr) ||
1371 !EC_KEY_set_public_key(key.get(), point.get()) ||
1372 !EC_KEY_check_fips(key.get())) {
1373 reply[0] = 0;
1374 } else {
1375 reply[0] = 1;
1376 }
1377
1378 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(reply));
1379 }
1380
HashFromName(Span<const uint8_t> name)1381 static const EVP_MD *HashFromName(Span<const uint8_t> name) {
1382 if (StringEq(name, "SHA2-224")) {
1383 return EVP_sha224();
1384 } else if (StringEq(name, "SHA2-256")) {
1385 return EVP_sha256();
1386 } else if (StringEq(name, "SHA2-384")) {
1387 return EVP_sha384();
1388 } else if (StringEq(name, "SHA2-512")) {
1389 return EVP_sha512();
1390 } else {
1391 return nullptr;
1392 }
1393 }
1394
ECDSASigGen(const Span<const uint8_t> args[])1395 static bool ECDSASigGen(const Span<const uint8_t> args[]) {
1396 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1397 bssl::UniquePtr<BIGNUM> d = BytesToBIGNUM(args[1]);
1398 const EVP_MD *hash = HashFromName(args[2]);
1399 uint8_t digest[EVP_MAX_MD_SIZE];
1400 unsigned digest_len;
1401 if (!key || !hash ||
1402 !EVP_Digest(args[3].data(), args[3].size(), digest, &digest_len, hash,
1403 /*impl=*/nullptr) ||
1404 !EC_KEY_set_private_key(key.get(), d.get())) {
1405 return false;
1406 }
1407
1408 bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, key.get()));
1409 if (!sig) {
1410 return false;
1411 }
1412
1413 std::vector<uint8_t> r_bytes(BIGNUMBytes(sig->r));
1414 std::vector<uint8_t> s_bytes(BIGNUMBytes(sig->s));
1415
1416 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(r_bytes),
1417 Span<const uint8_t>(s_bytes));
1418 }
1419
ECDSASigVer(const Span<const uint8_t> args[])1420 static bool ECDSASigVer(const Span<const uint8_t> args[]) {
1421 bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
1422 const EVP_MD *hash = HashFromName(args[1]);
1423 auto msg = args[2];
1424 bssl::UniquePtr<BIGNUM> x(BytesToBIGNUM(args[3]));
1425 bssl::UniquePtr<BIGNUM> y(BytesToBIGNUM(args[4]));
1426 bssl::UniquePtr<BIGNUM> r(BytesToBIGNUM(args[5]));
1427 bssl::UniquePtr<BIGNUM> s(BytesToBIGNUM(args[6]));
1428 ECDSA_SIG sig;
1429 sig.r = r.get();
1430 sig.s = s.get();
1431
1432 uint8_t digest[EVP_MAX_MD_SIZE];
1433 unsigned digest_len;
1434 if (!key || !hash ||
1435 !EVP_Digest(msg.data(), msg.size(), digest, &digest_len, hash,
1436 /*impl=*/nullptr)) {
1437 return false;
1438 }
1439
1440 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(EC_KEY_get0_group(key.get())));
1441 uint8_t reply[1];
1442 if (!EC_POINT_set_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
1443 point.get(), x.get(), y.get(),
1444 /*ctx=*/nullptr) ||
1445 !EC_KEY_set_public_key(key.get(), point.get()) ||
1446 !EC_KEY_check_fips(key.get()) ||
1447 !ECDSA_do_verify(digest, digest_len, &sig, key.get())) {
1448 reply[0] = 0;
1449 } else {
1450 reply[0] = 1;
1451 }
1452
1453 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(reply));
1454 }
1455
CMAC_AES(const Span<const uint8_t> args[])1456 static bool CMAC_AES(const Span<const uint8_t> args[]) {
1457 uint8_t mac[16];
1458 if (!AES_CMAC(mac, args[1].data(), args[1].size(), args[2].data(),
1459 args[2].size())) {
1460 return false;
1461 }
1462
1463 uint32_t mac_len;
1464 if (args[0].size() != sizeof(mac_len)) {
1465 return false;
1466 }
1467 memcpy(&mac_len, args[0].data(), sizeof(mac_len));
1468 if (mac_len > sizeof(mac)) {
1469 return false;
1470 }
1471
1472 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(mac, mac_len));
1473 }
1474
CMAC_AESVerify(const Span<const uint8_t> args[])1475 static bool CMAC_AESVerify(const Span<const uint8_t> args[]) {
1476 // This function is just for testing since libcrypto doesn't do the
1477 // verification itself. The regcap doesn't advertise "ver" support.
1478 uint8_t mac[16];
1479 if (!AES_CMAC(mac, args[0].data(), args[0].size(), args[1].data(),
1480 args[1].size()) ||
1481 args[2].size() > sizeof(mac)) {
1482 return false;
1483 }
1484
1485 const uint8_t ok = OPENSSL_memcmp(mac, args[2].data(), args[2].size());
1486 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(&ok, sizeof(ok)));
1487 }
1488
CachedRSAKeys()1489 static std::map<unsigned, bssl::UniquePtr<RSA>>& CachedRSAKeys() {
1490 static std::map<unsigned, bssl::UniquePtr<RSA>> keys;
1491 return keys;
1492 }
1493
GetRSAKey(unsigned bits)1494 static RSA* GetRSAKey(unsigned bits) {
1495 auto it = CachedRSAKeys().find(bits);
1496 if (it != CachedRSAKeys().end()) {
1497 return it->second.get();
1498 }
1499
1500 bssl::UniquePtr<RSA> key(RSA_new());
1501 if (!RSA_generate_key_fips(key.get(), bits, nullptr)) {
1502 abort();
1503 }
1504
1505 RSA *const ret = key.get();
1506 CachedRSAKeys().emplace(static_cast<unsigned>(bits), std::move(key));
1507
1508 return ret;
1509 }
1510
RSAKeyGen(const Span<const uint8_t> args[])1511 static bool RSAKeyGen(const Span<const uint8_t> args[]) {
1512 uint32_t bits;
1513 if (args[0].size() != sizeof(bits)) {
1514 return false;
1515 }
1516 memcpy(&bits, args[0].data(), sizeof(bits));
1517
1518 bssl::UniquePtr<RSA> key(RSA_new());
1519 if (!RSA_generate_key_fips(key.get(), bits, nullptr)) {
1520 fprintf(stderr, "RSA_generate_key_fips failed for modulus length %u.\n",
1521 bits);
1522 return false;
1523 }
1524
1525 const BIGNUM *n, *e, *d, *p, *q;
1526 RSA_get0_key(key.get(), &n, &e, &d);
1527 RSA_get0_factors(key.get(), &p, &q);
1528
1529 if (!WriteReply(STDOUT_FILENO, BIGNUMBytes(e), BIGNUMBytes(p), BIGNUMBytes(q),
1530 BIGNUMBytes(n), BIGNUMBytes(d))) {
1531 return false;
1532 }
1533
1534 CachedRSAKeys().emplace(static_cast<unsigned>(bits), std::move(key));
1535 return true;
1536 }
1537
1538 template<const EVP_MD *(MDFunc)(), bool UsePSS>
RSASigGen(const Span<const uint8_t> args[])1539 static bool RSASigGen(const Span<const uint8_t> args[]) {
1540 uint32_t bits;
1541 if (args[0].size() != sizeof(bits)) {
1542 return false;
1543 }
1544 memcpy(&bits, args[0].data(), sizeof(bits));
1545 const Span<const uint8_t> msg = args[1];
1546
1547 RSA *const key = GetRSAKey(bits);
1548 const EVP_MD *const md = MDFunc();
1549 uint8_t digest_buf[EVP_MAX_MD_SIZE];
1550 unsigned digest_len;
1551 if (!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
1552 return false;
1553 }
1554
1555 std::vector<uint8_t> sig(RSA_size(key));
1556 size_t sig_len;
1557 if (UsePSS) {
1558 if (!RSA_sign_pss_mgf1(key, &sig_len, sig.data(), sig.size(), digest_buf,
1559 digest_len, md, md, -1)) {
1560 return false;
1561 }
1562 } else {
1563 unsigned sig_len_u;
1564 if (!RSA_sign(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
1565 &sig_len_u, key)) {
1566 return false;
1567 }
1568 sig_len = sig_len_u;
1569 }
1570
1571 sig.resize(sig_len);
1572
1573 return WriteReply(STDOUT_FILENO, BIGNUMBytes(RSA_get0_n(key)),
1574 BIGNUMBytes(RSA_get0_e(key)), sig);
1575 }
1576
1577 template<const EVP_MD *(MDFunc)(), bool UsePSS>
RSASigVer(const Span<const uint8_t> args[])1578 static bool RSASigVer(const Span<const uint8_t> args[]) {
1579 const Span<const uint8_t> n_bytes = args[0];
1580 const Span<const uint8_t> e_bytes = args[1];
1581 const Span<const uint8_t> msg = args[2];
1582 const Span<const uint8_t> sig = args[3];
1583
1584 BIGNUM *n = BN_new();
1585 BIGNUM *e = BN_new();
1586 bssl::UniquePtr<RSA> key(RSA_new());
1587 if (!BN_bin2bn(n_bytes.data(), n_bytes.size(), n) ||
1588 !BN_bin2bn(e_bytes.data(), e_bytes.size(), e) ||
1589 !RSA_set0_key(key.get(), n, e, /*d=*/nullptr)) {
1590 return false;
1591 }
1592
1593 const EVP_MD *const md = MDFunc();
1594 uint8_t digest_buf[EVP_MAX_MD_SIZE];
1595 unsigned digest_len;
1596 if (!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
1597 return false;
1598 }
1599
1600 uint8_t ok;
1601 if (UsePSS) {
1602 ok = RSA_verify_pss_mgf1(key.get(), digest_buf, digest_len, md, md, -1,
1603 sig.data(), sig.size());
1604 } else {
1605 ok = RSA_verify(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
1606 sig.size(), key.get());
1607 }
1608 ERR_clear_error();
1609
1610 return WriteReply(STDOUT_FILENO, Span<const uint8_t>(&ok, 1));
1611 }
1612
1613 template<const EVP_MD *(MDFunc)()>
TLSKDF(const Span<const uint8_t> args[])1614 static bool TLSKDF(const Span<const uint8_t> args[]) {
1615 const Span<const uint8_t> out_len_bytes = args[0];
1616 const Span<const uint8_t> secret = args[1];
1617 const Span<const uint8_t> label = args[2];
1618 const Span<const uint8_t> seed1 = args[3];
1619 const Span<const uint8_t> seed2 = args[4];
1620 const EVP_MD *md = MDFunc();
1621
1622 uint32_t out_len;
1623 if (out_len_bytes.size() != sizeof(out_len)) {
1624 return 0;
1625 }
1626 memcpy(&out_len, out_len_bytes.data(), sizeof(out_len));
1627
1628 std::vector<uint8_t> out(static_cast<size_t>(out_len));
1629 if (!CRYPTO_tls1_prf(md, out.data(), out.size(), secret.data(), secret.size(),
1630 reinterpret_cast<const char *>(label.data()),
1631 label.size(), seed1.data(), seed1.size(), seed2.data(),
1632 seed2.size())) {
1633 return 0;
1634 }
1635
1636 return WriteReply(STDOUT_FILENO, out);
1637 }
1638
1639 template <int Nid>
ECDH(const Span<const uint8_t> args[])1640 static bool ECDH(const Span<const uint8_t> args[]) {
1641 bssl::UniquePtr<BIGNUM> their_x(BytesToBIGNUM(args[0]));
1642 bssl::UniquePtr<BIGNUM> their_y(BytesToBIGNUM(args[1]));
1643 const Span<const uint8_t> private_key = args[2];
1644
1645 bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(Nid));
1646 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
1647
1648 const EC_GROUP *const group = EC_KEY_get0_group(ec_key.get());
1649 bssl::UniquePtr<EC_POINT> their_point(EC_POINT_new(group));
1650 if (!EC_POINT_set_affine_coordinates_GFp(
1651 group, their_point.get(), their_x.get(), their_y.get(), ctx.get())) {
1652 fprintf(stderr, "Invalid peer point for ECDH.\n");
1653 return false;
1654 }
1655
1656 if (!private_key.empty()) {
1657 bssl::UniquePtr<BIGNUM> our_k(BytesToBIGNUM(private_key));
1658 if (!EC_KEY_set_private_key(ec_key.get(), our_k.get())) {
1659 fprintf(stderr, "EC_KEY_set_private_key failed.\n");
1660 return false;
1661 }
1662
1663 bssl::UniquePtr<EC_POINT> our_pub(EC_POINT_new(group));
1664 if (!EC_POINT_mul(group, our_pub.get(), our_k.get(), nullptr, nullptr,
1665 ctx.get()) ||
1666 !EC_KEY_set_public_key(ec_key.get(), our_pub.get())) {
1667 fprintf(stderr, "Calculating public key failed.\n");
1668 return false;
1669 }
1670 } else if (!EC_KEY_generate_key_fips(ec_key.get())) {
1671 fprintf(stderr, "EC_KEY_generate_key_fips failed.\n");
1672 return false;
1673 }
1674
1675 // The output buffer is one larger than |EC_MAX_BYTES| so that truncation
1676 // can be detected.
1677 std::vector<uint8_t> output(EC_MAX_BYTES + 1);
1678 const int out_len =
1679 ECDH_compute_key(output.data(), output.size(), their_point.get(),
1680 ec_key.get(), /*kdf=*/nullptr);
1681 if (out_len < 0) {
1682 fprintf(stderr, "ECDH_compute_key failed.\n");
1683 return false;
1684 } else if (static_cast<size_t>(out_len) == output.size()) {
1685 fprintf(stderr, "ECDH_compute_key output may have been truncated.\n");
1686 return false;
1687 }
1688 output.resize(static_cast<size_t>(out_len));
1689
1690 const EC_POINT *pub = EC_KEY_get0_public_key(ec_key.get());
1691 bssl::UniquePtr<BIGNUM> x(BN_new());
1692 bssl::UniquePtr<BIGNUM> y(BN_new());
1693 if (!EC_POINT_get_affine_coordinates_GFp(group, pub, x.get(), y.get(),
1694 ctx.get())) {
1695 fprintf(stderr, "EC_POINT_get_affine_coordinates_GFp failed.\n");
1696 return false;
1697 }
1698
1699 return WriteReply(STDOUT_FILENO, BIGNUMBytes(x.get()), BIGNUMBytes(y.get()),
1700 output);
1701 }
1702
FFDH(const Span<const uint8_t> args[])1703 static bool FFDH(const Span<const uint8_t> args[]) {
1704 bssl::UniquePtr<BIGNUM> p(BytesToBIGNUM(args[0]));
1705 bssl::UniquePtr<BIGNUM> q(BytesToBIGNUM(args[1]));
1706 bssl::UniquePtr<BIGNUM> g(BytesToBIGNUM(args[2]));
1707 bssl::UniquePtr<BIGNUM> their_pub(BytesToBIGNUM(args[3]));
1708 const Span<const uint8_t> private_key_span = args[4];
1709 const Span<const uint8_t> public_key_span = args[5];
1710
1711 bssl::UniquePtr<DH> dh(DH_new());
1712 if (!DH_set0_pqg(dh.get(), p.get(), q.get(), g.get())) {
1713 fprintf(stderr, "DH_set0_pqg failed.\n");
1714 return 0;
1715 }
1716
1717 // DH_set0_pqg took ownership of these values.
1718 p.release();
1719 q.release();
1720 g.release();
1721
1722 if (!private_key_span.empty()) {
1723 bssl::UniquePtr<BIGNUM> private_key(BytesToBIGNUM(private_key_span));
1724 bssl::UniquePtr<BIGNUM> public_key(BytesToBIGNUM(public_key_span));
1725
1726 if (!DH_set0_key(dh.get(), public_key.get(), private_key.get())) {
1727 fprintf(stderr, "DH_set0_key failed.\n");
1728 return 0;
1729 }
1730
1731 // DH_set0_key took ownership of these values.
1732 public_key.release();
1733 private_key.release();
1734 } else if (!DH_generate_key(dh.get())) {
1735 fprintf(stderr, "DH_generate_key failed.\n");
1736 return false;
1737 }
1738
1739 std::vector<uint8_t> z(DH_size(dh.get()));
1740 if (DH_compute_key_padded(z.data(), their_pub.get(), dh.get()) !=
1741 static_cast<int>(z.size())) {
1742 fprintf(stderr, "DH_compute_key_hashed failed.\n");
1743 return false;
1744 }
1745
1746 return WriteReply(STDOUT_FILENO, BIGNUMBytes(DH_get0_pub_key(dh.get())), z);
1747 }
1748
1749 static constexpr struct {
1750 const char name[kMaxNameLength + 1];
1751 uint8_t expected_args;
1752 bool (*handler)(const Span<const uint8_t>[]);
1753 } kFunctions[] = {
1754 {"getConfig", 0, GetConfig},
1755 {"SHA-1", 1, Hash<SHA1, SHA_DIGEST_LENGTH>},
1756 {"SHA2-224", 1, Hash<SHA224, SHA224_DIGEST_LENGTH>},
1757 {"SHA2-256", 1, Hash<SHA256, SHA256_DIGEST_LENGTH>},
1758 {"SHA2-384", 1, Hash<SHA384, SHA384_DIGEST_LENGTH>},
1759 {"SHA2-512", 1, Hash<SHA512, SHA512_DIGEST_LENGTH>},
1760 {"SHA2-512/256", 1, Hash<SHA512_256, SHA512_256_DIGEST_LENGTH>},
1761 {"AES/encrypt", 3, AES<AES_set_encrypt_key, AES_encrypt>},
1762 {"AES/decrypt", 3, AES<AES_set_decrypt_key, AES_decrypt>},
1763 {"AES-CBC/encrypt", 4, AES_CBC<AES_set_encrypt_key, AES_ENCRYPT>},
1764 {"AES-CBC/decrypt", 4, AES_CBC<AES_set_decrypt_key, AES_DECRYPT>},
1765 {"AES-CTR/encrypt", 4, AES_CTR},
1766 {"AES-CTR/decrypt", 4, AES_CTR},
1767 {"AES-GCM/seal", 5, AEADSeal<AESGCMSetup>},
1768 {"AES-GCM/open", 5, AEADOpen<AESGCMSetup>},
1769 {"AES-KW/seal", 5, AESKeyWrapSeal},
1770 {"AES-KW/open", 5, AESKeyWrapOpen},
1771 {"AES-KWP/seal", 5, AESPaddedKeyWrapSeal},
1772 {"AES-KWP/open", 5, AESPaddedKeyWrapOpen},
1773 {"AES-CCM/seal", 5, AEADSeal<AESCCMSetup>},
1774 {"AES-CCM/open", 5, AEADOpen<AESCCMSetup>},
1775 {"3DES-ECB/encrypt", 3, TDES<true>},
1776 {"3DES-ECB/decrypt", 3, TDES<false>},
1777 {"3DES-CBC/encrypt", 4, TDES_CBC<true>},
1778 {"3DES-CBC/decrypt", 4, TDES_CBC<false>},
1779 {"HMAC-SHA-1", 2, HMAC<EVP_sha1>},
1780 {"HMAC-SHA2-224", 2, HMAC<EVP_sha224>},
1781 {"HMAC-SHA2-256", 2, HMAC<EVP_sha256>},
1782 {"HMAC-SHA2-384", 2, HMAC<EVP_sha384>},
1783 {"HMAC-SHA2-512", 2, HMAC<EVP_sha512>},
1784 {"ctrDRBG/AES-256", 6, DRBG},
1785 {"ECDSA/keyGen", 1, ECDSAKeyGen},
1786 {"ECDSA/keyVer", 3, ECDSAKeyVer},
1787 {"ECDSA/sigGen", 4, ECDSASigGen},
1788 {"ECDSA/sigVer", 7, ECDSASigVer},
1789 {"CMAC-AES", 3, CMAC_AES},
1790 {"CMAC-AES/verify", 3, CMAC_AESVerify},
1791 {"RSA/keyGen", 1, RSAKeyGen},
1792 {"RSA/sigGen/SHA2-224/pkcs1v1.5", 2, RSASigGen<EVP_sha224, false>},
1793 {"RSA/sigGen/SHA2-256/pkcs1v1.5", 2, RSASigGen<EVP_sha256, false>},
1794 {"RSA/sigGen/SHA2-384/pkcs1v1.5", 2, RSASigGen<EVP_sha384, false>},
1795 {"RSA/sigGen/SHA2-512/pkcs1v1.5", 2, RSASigGen<EVP_sha512, false>},
1796 {"RSA/sigGen/SHA-1/pkcs1v1.5", 2, RSASigGen<EVP_sha1, false>},
1797 {"RSA/sigGen/SHA2-224/pss", 2, RSASigGen<EVP_sha224, true>},
1798 {"RSA/sigGen/SHA2-256/pss", 2, RSASigGen<EVP_sha256, true>},
1799 {"RSA/sigGen/SHA2-384/pss", 2, RSASigGen<EVP_sha384, true>},
1800 {"RSA/sigGen/SHA2-512/pss", 2, RSASigGen<EVP_sha512, true>},
1801 {"RSA/sigGen/SHA-1/pss", 2, RSASigGen<EVP_sha1, true>},
1802 {"RSA/sigVer/SHA2-224/pkcs1v1.5", 4, RSASigVer<EVP_sha224, false>},
1803 {"RSA/sigVer/SHA2-256/pkcs1v1.5", 4, RSASigVer<EVP_sha256, false>},
1804 {"RSA/sigVer/SHA2-384/pkcs1v1.5", 4, RSASigVer<EVP_sha384, false>},
1805 {"RSA/sigVer/SHA2-512/pkcs1v1.5", 4, RSASigVer<EVP_sha512, false>},
1806 {"RSA/sigVer/SHA-1/pkcs1v1.5", 4, RSASigVer<EVP_sha1, false>},
1807 {"RSA/sigVer/SHA2-224/pss", 4, RSASigVer<EVP_sha224, true>},
1808 {"RSA/sigVer/SHA2-256/pss", 4, RSASigVer<EVP_sha256, true>},
1809 {"RSA/sigVer/SHA2-384/pss", 4, RSASigVer<EVP_sha384, true>},
1810 {"RSA/sigVer/SHA2-512/pss", 4, RSASigVer<EVP_sha512, true>},
1811 {"RSA/sigVer/SHA-1/pss", 4, RSASigVer<EVP_sha1, true>},
1812 {"TLSKDF/1.0/SHA-1", 5, TLSKDF<EVP_md5_sha1>},
1813 {"TLSKDF/1.2/SHA2-256", 5, TLSKDF<EVP_sha256>},
1814 {"TLSKDF/1.2/SHA2-384", 5, TLSKDF<EVP_sha384>},
1815 {"TLSKDF/1.2/SHA2-512", 5, TLSKDF<EVP_sha512>},
1816 {"ECDH/P-224", 3, ECDH<NID_secp224r1>},
1817 {"ECDH/P-256", 3, ECDH<NID_X9_62_prime256v1>},
1818 {"ECDH/P-384", 3, ECDH<NID_secp384r1>},
1819 {"ECDH/P-521", 3, ECDH<NID_secp521r1>},
1820 {"FFDH", 6, FFDH},
1821 };
1822
main()1823 int main() {
1824 uint32_t nums[1 + kMaxArgs];
1825 std::unique_ptr<uint8_t[]> buf;
1826 size_t buf_len = 0;
1827 Span<const uint8_t> args[kMaxArgs];
1828
1829 for (;;) {
1830 if (!ReadAll(STDIN_FILENO, nums, sizeof(uint32_t) * 2)) {
1831 return 1;
1832 }
1833
1834 const size_t num_args = nums[0];
1835 if (num_args == 0) {
1836 fprintf(stderr, "Invalid, zero-argument operation requested.\n");
1837 return 2;
1838 } else if (num_args > kMaxArgs) {
1839 fprintf(stderr,
1840 "Operation requested with %zu args, but %zu is the limit.\n",
1841 num_args, kMaxArgs);
1842 return 2;
1843 }
1844
1845 if (num_args > 1 &&
1846 !ReadAll(STDIN_FILENO, &nums[2], sizeof(uint32_t) * (num_args - 1))) {
1847 return 1;
1848 }
1849
1850 size_t need = 0;
1851 for (size_t i = 0; i < num_args; i++) {
1852 const size_t arg_length = nums[i + 1];
1853 if (i == 0 && arg_length > kMaxNameLength) {
1854 fprintf(stderr,
1855 "Operation with name of length %zu exceeded limit of %zu.\n",
1856 arg_length, kMaxNameLength);
1857 return 2;
1858 } else if (arg_length > kMaxArgLength) {
1859 fprintf(
1860 stderr,
1861 "Operation with argument of length %zu exceeded limit of %zu.\n",
1862 arg_length, kMaxArgLength);
1863 return 2;
1864 }
1865
1866 // static_assert around kMaxArgs etc enforces that this doesn't overflow.
1867 need += arg_length;
1868 }
1869
1870 if (need > buf_len) {
1871 size_t alloced = need + (need >> 1);
1872 if (alloced < need) {
1873 abort();
1874 }
1875 buf.reset(new uint8_t[alloced]);
1876 buf_len = alloced;
1877 }
1878
1879 if (!ReadAll(STDIN_FILENO, buf.get(), need)) {
1880 return 1;
1881 }
1882
1883 size_t offset = 0;
1884 for (size_t i = 0; i < num_args; i++) {
1885 args[i] = Span<const uint8_t>(&buf[offset], nums[i + 1]);
1886 offset += nums[i + 1];
1887 }
1888
1889 bool found = false;
1890 for (const auto &func : kFunctions) {
1891 if (args[0].size() == strlen(func.name) &&
1892 memcmp(args[0].data(), func.name, args[0].size()) == 0) {
1893 if (num_args - 1 != func.expected_args) {
1894 fprintf(stderr,
1895 "\'%s\' operation received %zu arguments but expected %u.\n",
1896 func.name, num_args - 1, func.expected_args);
1897 return 2;
1898 }
1899
1900 if (!func.handler(&args[1])) {
1901 fprintf(stderr, "\'%s\' operation failed.\n", func.name);
1902 return 4;
1903 }
1904
1905 found = true;
1906 break;
1907 }
1908 }
1909
1910 if (!found) {
1911 const std::string name(reinterpret_cast<const char *>(args[0].data()),
1912 args[0].size());
1913 fprintf(stderr, "Unknown operation: %s\n", name.c_str());
1914 return 3;
1915 }
1916 }
1917 }
1918