1 /*
2  * Copyright 2017 Donald Stufft and individual contributors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * Test vector generator/checker for libsodium's box_seal APIs
17  * to build in a unix-like environment, use a command line like
18  * $ cc sealbox_test_vectors.c -I${IPATH} -L${LPATH} -lsodium -o sealbox_test_vectors
19  * with IPATH and LPATH defined to respectively point to libsodium's include path
20  * and to the directory containing the link library libsodium.a or libsodium.o
21  *
22  */
23 #include <stdio.h>
24 #include <string.h>
25 #include <sodium.h>
26 
27 int checkone (char *hxsecret, char *hxpub, size_t ptlen, char *hxplaintext,
28 	      size_t crlen, char *hxencrypted) {
29 
30     int pklen = crypto_box_PUBLICKEYBYTES;
31     int sklen = crypto_box_SECRETKEYBYTES;
32 
33     char *skr = sodium_malloc (sklen);
34     char *pub = sodium_malloc (pklen);
35     char *txt = sodium_malloc (ptlen);
36     char *crpt = sodium_malloc (crlen);
37     char *outp = sodium_malloc (ptlen);
38 
39     int rs = sodium_hex2bin (skr, sklen, hxsecret, 2 * sklen,
40                              NULL, NULL, NULL);
41     rs |= sodium_hex2bin (pub, pklen, hxpub, 2 * pklen, NULL, NULL, NULL);
42     rs |= sodium_hex2bin (txt, ptlen, hxplaintext, strlen (hxplaintext),
43                           NULL, NULL, NULL);
44     rs |= sodium_hex2bin (crpt, crlen, hxencrypted, strlen (hxencrypted),
45                           NULL, NULL, NULL);
46 
47     if (rs == 0)
48         rs = crypto_box_seal_open (outp, crpt, crlen, pub, skr);
49     if (rs == 0)
50         rs = sodium_memcmp (outp, txt, ptlen);
51 
52     sodium_free (crpt);
53     sodium_free (txt);
54     sodium_free (skr);
55     sodium_free (pub);
56 
57     return rs;
58 }
59 
60 void gentestline (int minmsglen, int maxmsglen) {
61 
62     int pklen = crypto_box_PUBLICKEYBYTES;
63     int sklen = crypto_box_SECRETKEYBYTES;
64     size_t txtlen = minmsglen + randombytes_uniform (maxmsglen - minmsglen + 1);
65     size_t encrlen = txtlen + crypto_box_SEALBYTES;
66 
67     char *skr = sodium_malloc (sklen);
68     char *pub = sodium_malloc (pklen);
69     char *txt = sodium_malloc (txtlen);
70     char *crpt = sodium_malloc (encrlen);
71 
72     crypto_box_keypair (pub, skr);
73     randombytes_buf (txt, txtlen);
74 
75     crypto_box_seal (crpt, txt, txtlen, pub);
76 
77     char *hskr = sodium_malloc (sklen * 2 + 1);
78     char *hpub = sodium_malloc (pklen * 2 + 1);
79     char *htxt = sodium_malloc (txtlen * 2 + 1);
80     char *hkrp = sodium_malloc (encrlen * 2 + 1);
81 
82     sodium_bin2hex (hskr, sklen * 2 + 1, skr, sklen);
83     sodium_bin2hex (hpub, pklen * 2 + 1, pub, pklen);
84     sodium_bin2hex (htxt, txtlen * 2 + 1, txt, txtlen);
85     sodium_bin2hex (hkrp, encrlen * 2 + 1, crpt, encrlen);
86 
87     printf ("%s\t%s\t%zu:%s\t%zu:%s\n", hskr, hpub, txtlen, htxt, encrlen, hkrp);
88 }
89 
90 int main (int argc, char **argv) {
91 /*
92  * If called without any argument, the resulting executable will
93  * read and hex decode the secret and public part of the receiver key,
94  * the original plaintext and the ciphertext, and then
95  * check if the message resulting from decrypting ciphertext with
96  * the secret key is equal to the given plaintext
97  *
98  * If called with a sequence of integer arguments, sealbox_test_vectors
99  * will generate the requested number of reference lines, encrypting
100  * random messages.
101  *
102  */
103     if (sodium_init () == -1) {
104         exit (1);
105     }
106 
107     if (argc == 1) {
108         size_t lsz = 0;
109         char *line = NULL;
110         ssize_t lln = 0;
111         int res;
112         char hxsecret[2 * crypto_box_SECRETKEYBYTES + 1];
113         char hxpub[2 * crypto_box_PUBLICKEYBYTES + 1];
114         char hxplaintext[2048 + 1];
115         char hxencrypted[2048 + 2 * crypto_box_SEALBYTES + 1];
116         char cmpplaintext[5 + 2048 + 1];
117         char cmpencrypted[5 + 2048 + 2 * crypto_box_SEALBYTES + 1];
118         size_t ptlen = 0;
119         size_t crlen = 0;
120 
121         while (lln = getline (&line, &lsz, stdin) > 0) {
122             if (lln > 0) {
123                 if (strncmp (line, "#", 1) == 0 ||
124                         strncmp (line, "\n", 1) == 0 ||
125                         strncmp (line, "\r", 1) == 0)
126                     continue;
127 
128                 sscanf (line, "%s%s%s%s",
129                         hxsecret, hxpub, cmpplaintext, cmpencrypted);
130                 sscanf (cmpplaintext, "%zu:%s",
131                         &ptlen, hxplaintext);
132                 sscanf (cmpencrypted, "%zu:%s",
133                         &crlen, hxencrypted);
134                 if (ptlen == 0)
135                         memset(hxplaintext, 0, sizeof(hxplaintext));
136                 if (crlen == 0)
137                         memset(hxencrypted, 0, sizeof(hxencrypted));
138                 res = checkone (hxsecret, hxpub, ptlen, hxplaintext, crlen, hxencrypted);
139                 char *rsstr = (res == 0) ? "OK" : "FAIL";
140                 printf ("%s\t%s\t%zu:%s\t%zu:%s\t%s\n",
141                         hxsecret, hxpub, ptlen, hxplaintext, crlen, hxencrypted, rsstr);
142             }
143             free (line);
144             line = NULL;
145         }
146     } else {
147         int nlines = atoi (argv[1]);
148         int minmsgl = 128;
149         int maxmsgl = 128;
150         if (argc == 3) {
151             minmsgl = atoi (argv[2]);
152             maxmsgl = atoi (argv[2]) * 2;
153         } else if (argc == 4) {
154             minmsgl = atoi (argv[2]);
155             maxmsgl = atoi (argv[3]);
156         }
157         for (int i = 0; i < nlines; i++) {
158             gentestline (minmsgl, maxmsgl);
159         }
160     }
161 }
162