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