aboutsummaryrefslogtreecommitdiffstats
path: root/test/monniaux/BearSSL/tools/brssl.h
blob: a23ba00f710342a96ad609067bc3878406c5abb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
/*
 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef BRSSL_H__
#define BRSSL_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "bearssl.h"

/*
 * malloc() wrapper:
 * -- If len is 0, then NULL is returned.
 * -- If len is non-zero, and allocation fails, then an error message is
 *    printed and the process exits with an error code.
 */
void *xmalloc(size_t len);

/*
 * free() wrapper, meant to release blocks allocated with xmalloc().
 */
void xfree(void *buf);

/*
 * Duplicate a character string into a newly allocated block.
 */
char *xstrdup(const void *src);

/*
 * Allocate a new block with the provided length, filled with a copy
 * of exactly that many bytes starting at address 'src'.
 */
void *xblobdup(const void *src, size_t len);

/*
 * Duplicate a public key, into newly allocated blocks. The returned
 * key must be later on released with xfreepkey().
 */
br_x509_pkey *xpkeydup(const br_x509_pkey *pk);

/*
 * Release a public key that was allocated with xpkeydup(). If pk is NULL,
 * this function does nothing.
 */
void xfreepkey(br_x509_pkey *pk);

/*
 * Macros for growable arrays.
 */

/*
 * Make a structure type for a vector of 'type'.
 */
#define VECTOR(type)   struct { \
		type *buf; \
		size_t ptr, len; \
	}

/*
 * Constant initialiser for a vector.
 */
#define VEC_INIT   { 0, 0, 0 }

/*
 * Clear a vector.
 */
#define VEC_CLEAR(vec)   do { \
		xfree((vec).buf); \
		(vec).buf = NULL; \
		(vec).ptr = 0; \
		(vec).len = 0; \
	} while (0)

/*
 * Clear a vector, first calling the provided function on each vector
 * element.
 */
#define VEC_CLEAREXT(vec, fun)   do { \
		size_t vec_tmp; \
		for (vec_tmp = 0; vec_tmp < (vec).ptr; vec_tmp ++) { \
			(fun)(&(vec).buf[vec_tmp]); \
		} \
		VEC_CLEAR(vec); \
	} while (0)

/*
 * Add a value at the end of a vector.
 */
#define VEC_ADD(vec, x)   do { \
		(vec).buf = vector_expand((vec).buf, sizeof *((vec).buf), \
			&(vec).ptr, &(vec).len, 1); \
		(vec).buf[(vec).ptr ++] = (x); \
	} while (0)

/*
 * Add several values at the end of a vector.
 */
#define VEC_ADDMANY(vec, xp, num)   do { \
		size_t vec_num = (num); \
		(vec).buf = vector_expand((vec).buf, sizeof *((vec).buf), \
			&(vec).ptr, &(vec).len, vec_num); \
		memcpy((vec).buf + (vec).ptr, \
			(xp), vec_num * sizeof *((vec).buf)); \
		(vec).ptr += vec_num; \
	} while (0)

/*
 * Access a vector element by index. This is a lvalue, and can be modified.
 */
#define VEC_ELT(vec, idx)   ((vec).buf[idx])

/*
 * Get current vector length.
 */
#define VEC_LEN(vec)   ((vec).ptr)

/*
 * Copy all vector elements into a newly allocated block.
 */
#define VEC_TOARRAY(vec)    xblobdup((vec).buf, sizeof *((vec).buf) * (vec).ptr)

/*
 * Internal function used to handle memory allocations for vectors.
 */
void *vector_expand(void *buf,
	size_t esize, size_t *ptr, size_t *len, size_t extra);

/*
 * Type for a vector of bytes.
 */
typedef VECTOR(unsigned char) bvector;

/*
 * Compare two strings for equality; returned value is 1 if the strings
 * are to be considered equal, 0 otherwise. Comparison is case-insensitive
 * (ASCII letters only) and skips some characters (all whitespace, defined
 * as ASCII codes 0 to 32 inclusive, and also '-', '_', '.', '/', '+' and
 * ':').
 */
int eqstr(const char *s1, const char *s2);

/*
 * Convert a string to a positive integer (size_t). Returned value is
 * (size_t)-1 on error. On error, an explicit error message is printed.
 */
size_t parse_size(const char *s);

/*
 * Structure for a known protocol version.
 */
typedef struct {
	const char *name;
	unsigned version;
	const char *comment;
} protocol_version;

/*
 * Known protocol versions. Last element has a NULL name.
 */
extern const protocol_version protocol_versions[];

/*
 * Parse a version name. If the name is not recognized, then an error
 * message is printed, and 0 is returned.
 */
unsigned parse_version(const char *name, size_t len);

/*
 * Type for a known hash function.
 */
typedef struct {
	const char *name;
	const br_hash_class *hclass;
	const char *comment;
} hash_function;

/*
 * Known hash functions. Last element has a NULL name.
 */
extern const hash_function hash_functions[];

/*
 * Parse hash function names. This function expects a comma-separated
 * list of names, and returns a bit mask corresponding to the matched
 * names. If one of the name does not match, or the list is empty, then
 * an error message is printed, and 0 is returned.
 */
unsigned parse_hash_functions(const char *arg);

/*
 * Get a curve name (by ID). If the curve ID is not known, this returns
 * NULL.
 */
const char *get_curve_name(int id);

/*
 * Get a curve name (by ID). The name is written in the provided buffer
 * (zero-terminated). If the curve ID is not known, the name is
 * "unknown (***)" where "***" is the decimal value of the identifier.
 * If the name does not fit in the provided buffer, then dst[0] is set
 * to 0 (unless len is 0, in which case nothing is written), and -1 is
 * returned. Otherwise, the name is written in dst[] (with a terminating
 * 0), and this function returns 0.
 */
int get_curve_name_ext(int id, char *dst, size_t len);

/*
 * Type for a known cipher suite.
 */
typedef struct {
	const char *name;
	uint16_t suite;
	unsigned req;
	const char *comment;
} cipher_suite;

/*
 * Known cipher suites. Last element has a NULL name.
 */
extern const cipher_suite cipher_suites[];

/*
 * Flags for cipher suite requirements.
 */
#define REQ_TLS12          0x0001   /* suite needs TLS 1.2 */
#define REQ_SHA1           0x0002   /* suite needs SHA-1 */
#define REQ_SHA256         0x0004   /* suite needs SHA-256 */
#define REQ_SHA384         0x0008   /* suite needs SHA-384 */
#define REQ_AESCBC         0x0010   /* suite needs AES/CBC encryption */
#define REQ_AESGCM         0x0020   /* suite needs AES/GCM encryption */
#define REQ_AESCCM         0x0040   /* suite needs AES/CCM encryption */
#define REQ_CHAPOL         0x0080   /* suite needs ChaCha20+Poly1305 */
#define REQ_3DESCBC        0x0100   /* suite needs 3DES/CBC encryption */
#define REQ_RSAKEYX        0x0200   /* suite uses RSA key exchange */
#define REQ_ECDHE_RSA      0x0400   /* suite uses ECDHE_RSA key exchange */
#define REQ_ECDHE_ECDSA    0x0800   /* suite uses ECDHE_ECDSA key exchange */
#define REQ_ECDH           0x1000   /* suite uses static ECDH key exchange */

/*
 * Parse a list of cipher suite names. The names are comma-separated. If
 * one of the name is not recognised, or the list is empty, then an
 * appropriate error message is printed, and NULL is returned.
 * The returned array is allocated with xmalloc() and must be released
 * by the caller. That array is terminated with a dummy entry whose 'name'
 * field is NULL. The number of entries (not counting the dummy entry)
 * is also written into '*num'.
 */
cipher_suite *parse_suites(const char *arg, size_t *num);

/*
 * Get the name of a cipher suite. Returned value is NULL if the suite is
 * not recognized.
 */
const char *get_suite_name(unsigned suite);

/*
 * Get the name of a cipher suite. The name is written in the provided
 * buffer; if the suite is not recognised, then the name is
 * "unknown (0x****)" where "****" is the hexadecimal value of the suite.
 * If the name does not fit in the provided buffer, then dst[0] is set
 * to 0 (unless len is 0, in which case nothing is written), and -1 is
 * returned. Otherwise, the name is written in dst[] (with a terminating
 * 0), and this function returns 0.
 */
int get_suite_name_ext(unsigned suite, char *dst, size_t len);

/*
 * Tell whether a cipher suite uses ECDHE key exchange.
 */
int uses_ecdhe(unsigned suite);

/*
 * Print out all known names (for protocol versions, cipher suites...).
 */
void list_names(void);

/*
 * Print out all known elliptic curve names.
 */
void list_curves(void);

/*
 * Get the symbolic name for an elliptic curve (by ID).
 */
const char *ec_curve_name(int curve);

/*
 * Get a curve by symbolic name. If the name is not recognized, -1 is
 * returned.
 */
int get_curve_by_name(const char *str);

/*
 * Get the symbolic name for a hash function name (by ID).
 */
const char *hash_function_name(int id);

/*
 * Read a file completely. The returned block is allocated with xmalloc()
 * and must be released by the caller.
 * If the file cannot be found or read completely, or is empty, then an
 * appropriate error message is written, and NULL is returned.
 */
unsigned char *read_file(const char *fname, size_t *len);

/*
 * Write a file completely. This returns 0 on success, -1 on error. On
 * error, an appropriate error message is printed.
 */
int write_file(const char *fname, const void *data, size_t len);

/*
 * This function returns non-zero if the provided buffer "looks like"
 * a DER-encoded ASN.1 object (criteria: it has the tag for a SEQUENCE
 * with a definite length that matches the total object length).
 */
int looks_like_DER(const unsigned char *buf, size_t len);

/*
 * Type for a named blob (the 'name' is a normalised PEM header name).
 */
typedef struct {
	char *name;
	unsigned char *data;
	size_t data_len;
} pem_object;

/*
 * Release the contents of a named blob (buffer and name).
 */
void free_pem_object_contents(pem_object *po);

/*
 * Decode a buffer as a PEM file, and return all objects. On error, NULL
 * is returned and an error message is printed. Absence of any object
 * is an error.
 *
 * The returned array is terminated by a dummy object whose 'name' is
 * NULL. The number of objects (not counting the dummy terminator) is
 * written in '*num'.
 */
pem_object *decode_pem(const void *src, size_t len, size_t *num);

/*
 * Get the certificate(s) from a file. This accepts both a single
 * DER-encoded certificate, and a text file that contains
 * PEM-encoded certificates (and possibly other objects, which are
 * then ignored).
 *
 * On decoding error, or if the file turns out to contain no certificate
 * at all, then an error message is printed and NULL is returned.
 *
 * The returned array, and all referenced buffers, are allocated with
 * xmalloc() and must be released by the caller. The returned array
 * ends with a dummy entry whose 'data' field is NULL.
 * The number of decoded certificates (not counting the dummy entry)
 * is written into '*num'.
 */
br_x509_certificate *read_certificates(const char *fname, size_t *num);

/*
 * Release certificates. This releases all certificate data arrays,
 * and the whole array as well.
 */
void free_certificates(br_x509_certificate *certs, size_t num);

/*
 * Interpret a certificate as a trust anchor. The trust anchor is
 * newly allocated with xmalloc() and the caller must release it.
 * On decoding error, an error message is printed, and this function
 * returns NULL.
 */
br_x509_trust_anchor *certificate_to_trust_anchor(br_x509_certificate *xc);

/*
 * Type for a vector of trust anchors.
 */
typedef VECTOR(br_x509_trust_anchor) anchor_list;

/*
 * Release contents for a trust anchor (assuming they were dynamically
 * allocated with xmalloc()). The structure itself is NOT released.
 */
void free_ta_contents(br_x509_trust_anchor *ta);

/*
 * Decode certificates from a file and interpret them as trust anchors.
 * The trust anchors are added to the provided list. The number of found
 * anchors is returned; on error, 0 is returned (finding no anchor at
 * all is considered an error). An appropriate error message is displayed.
 */
size_t read_trust_anchors(anchor_list *dst, const char *fname);

/*
 * Get the "signer key type" for the certificate (key type of the
 * issuing CA). On error, this prints a message on stderr, and returns 0.
 */
int get_cert_signer_algo(br_x509_certificate *xc);

/*
 * Special "no anchor" X.509 validator that wraps around another X.509
 * validator and turns "not trusted" error codes into success. This is
 * by definition insecure, but convenient for debug purposes.
 */
typedef struct {
	const br_x509_class *vtable;
	const br_x509_class **inner;
} x509_noanchor_context;
extern const br_x509_class x509_noanchor_vtable;

/*
 * Initialise a "no anchor" X.509 validator.
 */
void x509_noanchor_init(x509_noanchor_context *xwc,
	const br_x509_class **inner);

/*
 * Aggregate type for a private key.
 */
typedef struct {
	int key_type;  /* BR_KEYTYPE_RSA or BR_KEYTYPE_EC */
	union {
		br_rsa_private_key rsa;
		br_ec_private_key ec;
	} key;
} private_key;

/*
 * Decode a private key from a file. On error, this prints an error
 * message and returns NULL.
 */
private_key *read_private_key(const char *fname);

/*
 * Free a private key.
 */
void free_private_key(private_key *sk);

/*
 * Get the encoded OID for a given hash function (to use with PKCS#1
 * signatures). If the hash function ID is 0 (for MD5+SHA-1), or if
 * the ID is not one of the SHA-* functions (SHA-1, SHA-224, SHA-256,
 * SHA-384, SHA-512), then this function returns NULL.
 */
const unsigned char *get_hash_oid(int id);

/*
 * Get a hash implementation by ID. This returns NULL if the hash
 * implementation is not available.
 */
const br_hash_class *get_hash_impl(int id);

/*
 * Find the symbolic name and the description for an error. If 'err' is
 * recognised then the error symbolic name is returned; if 'comment' is
 * not NULL then '*comment' is then set to a descriptive human-readable
 * message. If the error code 'err' is not recognised, then '*comment' is
 * untouched and this function returns NULL.
 */
const char *find_error_name(int err, const char **comment);

/*
 * Find the symbolic name for an algorithm implementation. Provided
 * pointer should be a pointer to a vtable or to a function, where
 * appropriate. If not recognised, then the string "UNKNOWN" is returned.
 *
 * If 'long_name' is non-zero, then the returned name recalls the
 * algorithm type as well; otherwise, only the core implementation name
 * is returned (e.g. the long name could be 'aes_big_cbcenc' while the
 * short name is 'big').
 */
const char *get_algo_name(const void *algo, int long_name);

/*
 * Run a SSL engine, with a socket connected to the peer, and using
 * stdin/stdout to exchange application data. The socket must be a
 * non-blocking descriptor.
 *
 * To help with Win32 compatibility, the socket descriptor is provided
 * as an "unsigned long" value.
 *
 * Returned value:
 *    0        SSL connection closed successfully
 *    x > 0    SSL error "x"
 *   -1        early socket close
 *   -2        stdout was closed, or something failed badly
 */
int run_ssl_engine(br_ssl_engine_context *eng,
	unsigned long fd, unsigned flags);

#define RUN_ENGINE_VERBOSE     0x0001  /* enable verbose messages */
#define RUN_ENGINE_TRACE       0x0002  /* hex dump of records */

/*
 * Do the "client" command. Returned value is 0 on success, -1 on failure.
 * Command-line arguments start _after_ the command name.
 */
int do_client(int argc, char *argv[]);

/*
 * Do the "server" command. Returned value is 0 on success, -1 on failure.
 * Command-line arguments start _after_ the command name.
 */
int do_server(int argc, char *argv[]);

/*
 * Do the "verify" command. Returned value is 0 on success, -1 on failure.
 * Command-line arguments start _after_ the command name.
 */
int do_verify(int argc, char *argv[]);

/*
 * Do the "skey" command. Returned value is 0 on success, -1 on failure.
 * Command-line arguments start _after_ the command name.
 */
int do_skey(int argc, char *argv[]);

/*
 * Do the "ta" command. Returned value is 0 on success, -1 on failure.
 * Command-line arguments start _after_ the command name.
 */
int do_ta(int argc, char *argv[]);

/*
 * Do the "chain" command. Returned value is 0 on success, -1 on failure.
 * Command-line arguments start _after_ the command name.
 */
int do_chain(int argc, char *argv[]);

/*
 * Do the "twrch" command. Returned value is 0 on success, -1 on failure
 * (processing or arguments), or a non-zero exit code. Command-line
 * arguments start _after_ the command name.
 */
int do_twrch(int argc, char *argv[]);

/*
 * Do the "impl" command. Returned value is 0 on success, -1 on failure.
 * Command-line arguments start _after_ the command name.
 */
int do_impl(int argc, char *argv[]);

#endif