Merge ^/head r344549 through r344775.
This commit is contained in:
commit
844fc3e907
@ -106,7 +106,12 @@ usr.sbin/bsdconfig dteske Pre-commit phabricator review requested.
|
||||
usr.sbin/dpv dteske Pre-commit review requested. Keep in sync with libdpv.
|
||||
usr.sbin/pkg pkg@ Please coordinate behavior or flag changes with pkg team.
|
||||
usr.sbin/sysrc dteske Pre-commit phabricator review requested. Keep in sync with bsdconfig(8) sysrc.subr.
|
||||
vmm(4) tychon, jhb Pre-commit review requested.
|
||||
vmm(4) tychon, jhb Pre-commit review requested via #bhyve
|
||||
phabricator group.
|
||||
libvmmapi tychon, jhb Pre-commit review requested via #bhyve
|
||||
phabricator group.
|
||||
usr.sbin/bhyve* tychon, jhb Pre-commit review requested via #bhyve
|
||||
phabricator group.
|
||||
autofs(5) trasz Pre-commit review recommended.
|
||||
iscsi(4) trasz Pre-commit review recommended.
|
||||
rctl(8) trasz Pre-commit review recommended.
|
||||
|
@ -190,9 +190,11 @@ OLD_FILES+=usr/lib/clang/7.0.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_
|
||||
OLD_DIRS+=usr/lib/clang/7.0.1/lib/freebsd
|
||||
OLD_DIRS+=usr/lib/clang/7.0.1/lib
|
||||
OLD_DIRS+=usr/lib/clang/7.0.1
|
||||
# 20190227: rename seq.h to seqc.h
|
||||
OLD_FILES+=usr/include/sys/seq.h
|
||||
# 20190222: libifconfig made INTERNALLIB
|
||||
OLD_FILES+=/usr/lib/libprivateifconfig.a
|
||||
OLD_FILES+=/usr/lib/libprivateifconfig_p.a
|
||||
OLD_FILES+=usr/lib/libprivateifconfig.a
|
||||
OLD_FILES+=usr/lib/libprivateifconfig_p.a
|
||||
# 20190131: pfil(9) changed
|
||||
OLD_FILES+=usr/share/man/man9/pfil_hook_get.9
|
||||
OLD_FILES+=usr/share/man/man9/pfil_rlock.9
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 11, 2018
|
||||
.Dd February 15, 2018
|
||||
.Dt ZFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -184,7 +184,7 @@
|
||||
.Ar bookmark
|
||||
.Nm
|
||||
.Cm send
|
||||
.Op Fl DLPRcenpv
|
||||
.Op Fl DLPRVcenpv
|
||||
.Op Fl i Ar snapshot | Fl I Ar snapshot
|
||||
.Ar snapshot
|
||||
.Nm
|
||||
@ -194,7 +194,7 @@
|
||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
|
||||
.Nm
|
||||
.Cm send
|
||||
.Op Fl Penv
|
||||
.Op Fl PVenv
|
||||
.Fl t Ar receive_resume_token
|
||||
.Nm
|
||||
.Cm receive Ns | Ns Cm recv
|
||||
@ -2607,7 +2607,7 @@ feature.
|
||||
.It Xo
|
||||
.Nm
|
||||
.Cm send
|
||||
.Op Fl DLPRcenpv
|
||||
.Op Fl DLPRVcenpv
|
||||
.Op Fl i Ar snapshot | Fl I Ar snapshot
|
||||
.Ar snapshot
|
||||
.Xc
|
||||
@ -2753,6 +2753,8 @@ Print machine-parsable verbose information about the stream package generated.
|
||||
.It Fl v, -verbose
|
||||
Print verbose information about the stream package generated.
|
||||
This information includes a per-second report of how much data has been sent.
|
||||
.It Fl V
|
||||
Set the process title to a per-second report of how much data has been sent.
|
||||
.El
|
||||
.Pp
|
||||
The format of the stream is committed. You will be able to receive your streams
|
||||
|
@ -3813,7 +3813,7 @@ zfs_do_send(int argc, char **argv)
|
||||
};
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt_long(argc, argv, ":i:I:RbDpvnPLet:c", long_options,
|
||||
while ((c = getopt_long(argc, argv, ":i:I:RbDpVvnPLet:c", long_options,
|
||||
NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
@ -3837,6 +3837,10 @@ zfs_do_send(int argc, char **argv)
|
||||
flags.parsable = B_TRUE;
|
||||
flags.verbose = B_TRUE;
|
||||
break;
|
||||
case 'V':
|
||||
flags.progress = B_TRUE;
|
||||
flags.progressastitle = B_TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
if (flags.verbose)
|
||||
extraverbose = B_TRUE;
|
||||
@ -5812,7 +5816,12 @@ zfs_do_holds(int argc, char **argv)
|
||||
|
||||
#define CHECK_SPINNER 30
|
||||
#define SPINNER_TIME 3 /* seconds */
|
||||
#define MOUNT_TIME 5 /* seconds */
|
||||
#define MOUNT_TIME 1 /* seconds */
|
||||
|
||||
typedef struct get_all_state {
|
||||
boolean_t ga_verbose;
|
||||
get_all_cb_t *ga_cbp;
|
||||
} get_all_state_t;
|
||||
|
||||
static int
|
||||
get_one_dataset(zfs_handle_t *zhp, void *data)
|
||||
@ -5821,10 +5830,10 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
|
||||
static int spinval = 0;
|
||||
static int spincheck = 0;
|
||||
static time_t last_spin_time = (time_t)0;
|
||||
get_all_cb_t *cbp = data;
|
||||
get_all_state_t *state = data;
|
||||
zfs_type_t type = zfs_get_type(zhp);
|
||||
|
||||
if (cbp->cb_verbose) {
|
||||
if (state->ga_verbose) {
|
||||
if (--spincheck < 0) {
|
||||
time_t now = time(NULL);
|
||||
if (last_spin_time + SPINNER_TIME < now) {
|
||||
@ -5850,25 +5859,23 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
libzfs_add_handle(cbp, zhp);
|
||||
assert(cbp->cb_used <= cbp->cb_alloc);
|
||||
libzfs_add_handle(state->ga_cbp, zhp);
|
||||
assert(state->ga_cbp->cb_used <= state->ga_cbp->cb_alloc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
get_all_datasets(zfs_handle_t ***dslist, size_t *count, boolean_t verbose)
|
||||
get_all_datasets(get_all_cb_t *cbp, boolean_t verbose)
|
||||
{
|
||||
get_all_cb_t cb = { 0 };
|
||||
cb.cb_verbose = verbose;
|
||||
cb.cb_getone = get_one_dataset;
|
||||
get_all_state_t state = {
|
||||
.ga_verbose = verbose,
|
||||
.ga_cbp = cbp
|
||||
};
|
||||
|
||||
if (verbose)
|
||||
set_progress_header(gettext("Reading ZFS config"));
|
||||
(void) zfs_iter_root(g_zfs, get_one_dataset, &cb);
|
||||
|
||||
*dslist = cb.cb_handles;
|
||||
*count = cb.cb_used;
|
||||
(void) zfs_iter_root(g_zfs, get_one_dataset, &state);
|
||||
|
||||
if (verbose)
|
||||
finish_progress(gettext("done."));
|
||||
@ -5879,8 +5886,19 @@ get_all_datasets(zfs_handle_t ***dslist, size_t *count, boolean_t verbose)
|
||||
* similar, we have a common function with an extra parameter to determine which
|
||||
* mode we are using.
|
||||
*/
|
||||
#define OP_SHARE 0x1
|
||||
#define OP_MOUNT 0x2
|
||||
typedef enum { OP_SHARE, OP_MOUNT } share_mount_op_t;
|
||||
|
||||
typedef struct share_mount_state {
|
||||
share_mount_op_t sm_op;
|
||||
boolean_t sm_verbose;
|
||||
int sm_flags;
|
||||
char *sm_options;
|
||||
char *sm_proto; /* only valid for OP_SHARE */
|
||||
pthread_mutex_t sm_lock; /* protects the remaining fields */
|
||||
uint_t sm_total; /* number of filesystems to process */
|
||||
uint_t sm_done; /* number of filesystems processed */
|
||||
int sm_status; /* -1 if any of the share/mount operations failed */
|
||||
} share_mount_state_t;
|
||||
|
||||
/*
|
||||
* Share or mount a dataset.
|
||||
@ -6101,9 +6119,6 @@ report_mount_progress(int current, int total)
|
||||
time_t now = time(NULL);
|
||||
char info[32];
|
||||
|
||||
/* report 1..n instead of 0..n-1 */
|
||||
++current;
|
||||
|
||||
/* display header if we're here for the first time */
|
||||
if (current == 1) {
|
||||
set_progress_header(gettext("Mounting ZFS filesystems"));
|
||||
@ -6122,6 +6137,29 @@ report_mount_progress(int current, int total)
|
||||
update_progress(info);
|
||||
}
|
||||
|
||||
/*
|
||||
* zfs_foreach_mountpoint() callback that mounts or shares on filesystem and
|
||||
* updates the progress meter
|
||||
*/
|
||||
static int
|
||||
share_mount_one_cb(zfs_handle_t *zhp, void *arg)
|
||||
{
|
||||
share_mount_state_t *sms = arg;
|
||||
int ret;
|
||||
|
||||
ret = share_mount_one(zhp, sms->sm_op, sms->sm_flags, sms->sm_proto,
|
||||
B_FALSE, sms->sm_options);
|
||||
|
||||
pthread_mutex_lock(&sms->sm_lock);
|
||||
if (ret != 0)
|
||||
sms->sm_status = ret;
|
||||
sms->sm_done++;
|
||||
if (sms->sm_verbose)
|
||||
report_mount_progress(sms->sm_done, sms->sm_total);
|
||||
pthread_mutex_unlock(&sms->sm_lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
append_options(char *mntopts, char *newopts)
|
||||
{
|
||||
@ -6194,8 +6232,6 @@ share_mount(int op, int argc, char **argv)
|
||||
|
||||
/* check number of arguments */
|
||||
if (do_all) {
|
||||
zfs_handle_t **dslist = NULL;
|
||||
size_t i, count = 0;
|
||||
char *protocol = NULL;
|
||||
|
||||
if (op == OP_SHARE && argc > 0) {
|
||||
@ -6216,35 +6252,48 @@ share_mount(int op, int argc, char **argv)
|
||||
}
|
||||
|
||||
start_progress_timer();
|
||||
get_all_datasets(&dslist, &count, verbose);
|
||||
get_all_cb_t cb = { 0 };
|
||||
get_all_datasets(&cb, verbose);
|
||||
|
||||
if (count == 0)
|
||||
if (cb.cb_used == 0) {
|
||||
if (options != NULL)
|
||||
free(options);
|
||||
return (0);
|
||||
}
|
||||
|
||||
qsort(dslist, count, sizeof (void *), libzfs_dataset_cmp);
|
||||
#ifdef illumos
|
||||
if (op == OP_SHARE) {
|
||||
sa_init_selective_arg_t sharearg;
|
||||
sharearg.zhandle_arr = dslist;
|
||||
sharearg.zhandle_len = count;
|
||||
if ((ret = zfs_init_libshare_arg(zfs_get_handle(dslist[0]),
|
||||
sharearg.zhandle_arr = cb.cb_handles;
|
||||
sharearg.zhandle_len = cb.cb_used;
|
||||
if ((ret = zfs_init_libshare_arg(g_zfs,
|
||||
SA_INIT_SHARE_API_SELECTIVE, &sharearg)) != SA_OK) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("Could not initialize libshare, %d"), ret);
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Could not initialize libshare, %d"), ret);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (verbose)
|
||||
report_mount_progress(i, count);
|
||||
|
||||
if (share_mount_one(dslist[i], op, flags, protocol,
|
||||
B_FALSE, options) != 0)
|
||||
ret = 1;
|
||||
zfs_close(dslist[i]);
|
||||
}
|
||||
#endif
|
||||
share_mount_state_t share_mount_state = { 0 };
|
||||
share_mount_state.sm_op = op;
|
||||
share_mount_state.sm_verbose = verbose;
|
||||
share_mount_state.sm_flags = flags;
|
||||
share_mount_state.sm_options = options;
|
||||
share_mount_state.sm_proto = protocol;
|
||||
share_mount_state.sm_total = cb.cb_used;
|
||||
pthread_mutex_init(&share_mount_state.sm_lock, NULL);
|
||||
|
||||
free(dslist);
|
||||
/*
|
||||
* libshare isn't mt-safe, so only do the operation in parallel
|
||||
* if we're mounting.
|
||||
*/
|
||||
zfs_foreach_mountpoint(g_zfs, cb.cb_handles, cb.cb_used,
|
||||
share_mount_one_cb, &share_mount_state, op == OP_MOUNT);
|
||||
ret = share_mount_state.sm_status;
|
||||
|
||||
for (int i = 0; i < cb.cb_used; i++)
|
||||
zfs_close(cb.cb_handles[i]);
|
||||
free(cb.cb_handles);
|
||||
} else if (argc == 0) {
|
||||
struct mnttab entry;
|
||||
|
||||
|
@ -579,12 +579,12 @@ typedef struct get_all_cb {
|
||||
zfs_handle_t **cb_handles;
|
||||
size_t cb_alloc;
|
||||
size_t cb_used;
|
||||
boolean_t cb_verbose;
|
||||
int (*cb_getone)(zfs_handle_t *, void *);
|
||||
} get_all_cb_t;
|
||||
|
||||
void zfs_foreach_mountpoint(libzfs_handle_t *, zfs_handle_t **, size_t,
|
||||
zfs_iter_f, void*, boolean_t);
|
||||
|
||||
void libzfs_add_handle(get_all_cb_t *, zfs_handle_t *);
|
||||
int libzfs_dataset_cmp(const void *, const void *);
|
||||
|
||||
/*
|
||||
* Functions to create and destroy datasets.
|
||||
@ -651,6 +651,9 @@ typedef struct sendflags {
|
||||
|
||||
/* compressed WRITE records are permitted */
|
||||
boolean_t compress;
|
||||
|
||||
/* show progress as process title(ie. -V) */
|
||||
boolean_t progressastitle;
|
||||
} sendflags_t;
|
||||
|
||||
typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *);
|
||||
|
@ -799,6 +799,7 @@ libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
|
||||
void
|
||||
libzfs_mnttab_init(libzfs_handle_t *hdl)
|
||||
{
|
||||
pthread_mutex_init(&hdl->libzfs_mnttab_cache_lock, NULL);
|
||||
assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
|
||||
avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
|
||||
sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
|
||||
@ -839,6 +840,7 @@ libzfs_mnttab_fini(libzfs_handle_t *hdl)
|
||||
free(mtn);
|
||||
}
|
||||
avl_destroy(&hdl->libzfs_mnttab_cache);
|
||||
(void) pthread_mutex_destroy(&hdl->libzfs_mnttab_cache_lock);
|
||||
}
|
||||
|
||||
void
|
||||
@ -853,6 +855,7 @@ libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
|
||||
{
|
||||
mnttab_node_t find;
|
||||
mnttab_node_t *mtn;
|
||||
int ret = ENOENT;
|
||||
|
||||
if (!hdl->libzfs_mnttab_enable) {
|
||||
struct mnttab srch = { 0 };
|
||||
@ -868,6 +871,7 @@ libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
|
||||
if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
|
||||
libzfs_mnttab_update(hdl);
|
||||
|
||||
@ -875,9 +879,10 @@ libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
|
||||
mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
|
||||
if (mtn) {
|
||||
*entry = mtn->mtn_mt;
|
||||
return (0);
|
||||
ret = 0;
|
||||
}
|
||||
return (ENOENT);
|
||||
pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
@ -886,8 +891,8 @@ libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
|
||||
{
|
||||
mnttab_node_t *mtn;
|
||||
|
||||
if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
|
||||
return;
|
||||
pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
|
||||
if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0) {
|
||||
mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
|
||||
mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
|
||||
mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
|
||||
@ -895,6 +900,8 @@ libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
|
||||
mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
|
||||
avl_add(&hdl->libzfs_mnttab_cache, mtn);
|
||||
}
|
||||
pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
|
||||
}
|
||||
|
||||
void
|
||||
libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
|
||||
@ -902,6 +909,7 @@ libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
|
||||
mnttab_node_t find;
|
||||
mnttab_node_t *ret;
|
||||
|
||||
pthread_mutex_lock(&hdl->libzfs_mnttab_cache_lock);
|
||||
find.mtn_mt.mnt_special = (char *)fsname;
|
||||
if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))
|
||||
!= NULL) {
|
||||
@ -912,6 +920,7 @@ libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
|
||||
free(ret->mtn_mt.mnt_mntopts);
|
||||
free(ret);
|
||||
}
|
||||
pthread_mutex_unlock(&hdl->libzfs_mnttab_cache_lock);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -22,7 +22,7 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011 Pawel Jakub Dawidek. All rights reserved.
|
||||
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2017 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
*/
|
||||
|
||||
@ -73,6 +73,13 @@ struct libzfs_handle {
|
||||
int libzfs_storeerr; /* stuff error messages into buffer */
|
||||
void *libzfs_sharehdl; /* libshare handle */
|
||||
boolean_t libzfs_mnttab_enable;
|
||||
/*
|
||||
* We need a lock to handle the case where parallel mount
|
||||
* threads are populating the mnttab cache simultaneously. The
|
||||
* lock only protects the integrity of the avl tree, and does
|
||||
* not protect the contents of the mnttab entries themselves.
|
||||
*/
|
||||
pthread_mutex_t libzfs_mnttab_cache_lock;
|
||||
avl_tree_t libzfs_mnttab_cache;
|
||||
int libzfs_pool_iter;
|
||||
libzfs_fru_t **libzfs_fru_hash;
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
|
||||
* Copyright 2017 Joyent, Inc.
|
||||
* Copyright 2017 RackTop Systems.
|
||||
* Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -83,10 +84,14 @@
|
||||
#include <libzfs.h>
|
||||
|
||||
#include "libzfs_impl.h"
|
||||
#include <thread_pool.h>
|
||||
|
||||
#include <libshare.h>
|
||||
#define MAXISALEN 257 /* based on sysinfo(2) man page */
|
||||
|
||||
static int mount_tp_nthr = 512; /* tpool threads for multi-threaded mounting */
|
||||
|
||||
static void zfs_mount_task(void *);
|
||||
static int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *);
|
||||
zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **,
|
||||
zfs_share_proto_t);
|
||||
@ -1134,25 +1139,32 @@ remove_mountpoint(zfs_handle_t *zhp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the given zfs handle to the cb_handles array, dynamically reallocating
|
||||
* the array if it is out of space
|
||||
*/
|
||||
void
|
||||
libzfs_add_handle(get_all_cb_t *cbp, zfs_handle_t *zhp)
|
||||
{
|
||||
if (cbp->cb_alloc == cbp->cb_used) {
|
||||
size_t newsz;
|
||||
void *ptr;
|
||||
zfs_handle_t **newhandles;
|
||||
|
||||
newsz = cbp->cb_alloc ? cbp->cb_alloc * 2 : 64;
|
||||
ptr = zfs_realloc(zhp->zfs_hdl,
|
||||
cbp->cb_handles, cbp->cb_alloc * sizeof (void *),
|
||||
newsz * sizeof (void *));
|
||||
cbp->cb_handles = ptr;
|
||||
newsz = cbp->cb_alloc != 0 ? cbp->cb_alloc * 2 : 64;
|
||||
newhandles = zfs_realloc(zhp->zfs_hdl,
|
||||
cbp->cb_handles, cbp->cb_alloc * sizeof (zfs_handle_t *),
|
||||
newsz * sizeof (zfs_handle_t *));
|
||||
cbp->cb_handles = newhandles;
|
||||
cbp->cb_alloc = newsz;
|
||||
}
|
||||
cbp->cb_handles[cbp->cb_used++] = zhp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursive helper function used during file system enumeration
|
||||
*/
|
||||
static int
|
||||
mount_cb(zfs_handle_t *zhp, void *data)
|
||||
zfs_iter_cb(zfs_handle_t *zhp, void *data)
|
||||
{
|
||||
get_all_cb_t *cbp = data;
|
||||
|
||||
@ -1178,104 +1190,362 @@ mount_cb(zfs_handle_t *zhp, void *data)
|
||||
}
|
||||
|
||||
libzfs_add_handle(cbp, zhp);
|
||||
if (zfs_iter_filesystems(zhp, mount_cb, cbp) != 0) {
|
||||
if (zfs_iter_filesystems(zhp, zfs_iter_cb, cbp) != 0) {
|
||||
zfs_close(zhp);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
libzfs_dataset_cmp(const void *a, const void *b)
|
||||
/*
|
||||
* Sort comparator that compares two mountpoint paths. We sort these paths so
|
||||
* that subdirectories immediately follow their parents. This means that we
|
||||
* effectively treat the '/' character as the lowest value non-nul char.
|
||||
* Since filesystems from non-global zones can have the same mountpoint
|
||||
* as other filesystems, the comparator sorts global zone filesystems to
|
||||
* the top of the list. This means that the global zone will traverse the
|
||||
* filesystem list in the correct order and can stop when it sees the
|
||||
* first zoned filesystem. In a non-global zone, only the delegated
|
||||
* filesystems are seen.
|
||||
*
|
||||
* An example sorted list using this comparator would look like:
|
||||
*
|
||||
* /foo
|
||||
* /foo/bar
|
||||
* /foo/bar/baz
|
||||
* /foo/baz
|
||||
* /foo.bar
|
||||
* /foo (NGZ1)
|
||||
* /foo (NGZ2)
|
||||
*
|
||||
* The mount code depend on this ordering to deterministically iterate
|
||||
* over filesystems in order to spawn parallel mount tasks.
|
||||
*/
|
||||
static int
|
||||
mountpoint_cmp(const void *arga, const void *argb)
|
||||
{
|
||||
zfs_handle_t **za = (zfs_handle_t **)a;
|
||||
zfs_handle_t **zb = (zfs_handle_t **)b;
|
||||
zfs_handle_t *const *zap = arga;
|
||||
zfs_handle_t *za = *zap;
|
||||
zfs_handle_t *const *zbp = argb;
|
||||
zfs_handle_t *zb = *zbp;
|
||||
char mounta[MAXPATHLEN];
|
||||
char mountb[MAXPATHLEN];
|
||||
const char *a = mounta;
|
||||
const char *b = mountb;
|
||||
boolean_t gota, gotb;
|
||||
uint64_t zoneda, zonedb;
|
||||
|
||||
if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0)
|
||||
verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
|
||||
zoneda = zfs_prop_get_int(za, ZFS_PROP_ZONED);
|
||||
zonedb = zfs_prop_get_int(zb, ZFS_PROP_ZONED);
|
||||
if (zoneda && !zonedb)
|
||||
return (1);
|
||||
if (!zoneda && zonedb)
|
||||
return (-1);
|
||||
gota = (zfs_get_type(za) == ZFS_TYPE_FILESYSTEM);
|
||||
if (gota)
|
||||
verify(zfs_prop_get(za, ZFS_PROP_MOUNTPOINT, mounta,
|
||||
sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
|
||||
if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0)
|
||||
verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
|
||||
gotb = (zfs_get_type(zb) == ZFS_TYPE_FILESYSTEM);
|
||||
if (gotb)
|
||||
verify(zfs_prop_get(zb, ZFS_PROP_MOUNTPOINT, mountb,
|
||||
sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
|
||||
|
||||
if (gota && gotb)
|
||||
return (strcmp(mounta, mountb));
|
||||
if (gota && gotb) {
|
||||
while (*a != '\0' && (*a == *b)) {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
if (*a == *b)
|
||||
return (0);
|
||||
if (*a == '\0')
|
||||
return (-1);
|
||||
if (*b == '\0')
|
||||
return (1);
|
||||
if (*a == '/')
|
||||
return (-1);
|
||||
if (*b == '/')
|
||||
return (1);
|
||||
return (*a < *b ? -1 : *a > *b);
|
||||
}
|
||||
|
||||
if (gota)
|
||||
return (-1);
|
||||
if (gotb)
|
||||
return (1);
|
||||
|
||||
return (strcmp(zfs_get_name(a), zfs_get_name(b)));
|
||||
/*
|
||||
* If neither filesystem has a mountpoint, revert to sorting by
|
||||
* datset name.
|
||||
*/
|
||||
return (strcmp(zfs_get_name(za), zfs_get_name(zb)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reutrn true if path2 is a child of path1
|
||||
*/
|
||||
static boolean_t
|
||||
libzfs_path_contains(const char *path1, const char *path2)
|
||||
{
|
||||
return (strstr(path2, path1) == path2 && path2[strlen(path1)] == '/');
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
non_descendant_idx(zfs_handle_t **handles, size_t num_handles, int idx)
|
||||
{
|
||||
char parent[ZFS_MAXPROPLEN];
|
||||
char child[ZFS_MAXPROPLEN];
|
||||
int i;
|
||||
|
||||
verify(zfs_prop_get(handles[idx], ZFS_PROP_MOUNTPOINT, parent,
|
||||
sizeof (parent), NULL, NULL, 0, B_FALSE) == 0);
|
||||
|
||||
for (i = idx + 1; i < num_handles; i++) {
|
||||
verify(zfs_prop_get(handles[i], ZFS_PROP_MOUNTPOINT, child,
|
||||
sizeof (child), NULL, NULL, 0, B_FALSE) == 0);
|
||||
if (!libzfs_path_contains(parent, child))
|
||||
break;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
typedef struct mnt_param {
|
||||
libzfs_handle_t *mnt_hdl;
|
||||
tpool_t *mnt_tp;
|
||||
zfs_handle_t **mnt_zhps; /* filesystems to mount */
|
||||
size_t mnt_num_handles;
|
||||
int mnt_idx; /* Index of selected entry to mount */
|
||||
zfs_iter_f mnt_func;
|
||||
void *mnt_data;
|
||||
} mnt_param_t;
|
||||
|
||||
/*
|
||||
* Allocate and populate the parameter struct for mount function, and
|
||||
* schedule mounting of the entry selected by idx.
|
||||
*/
|
||||
static void
|
||||
zfs_dispatch_mount(libzfs_handle_t *hdl, zfs_handle_t **handles,
|
||||
size_t num_handles, int idx, zfs_iter_f func, void *data, tpool_t *tp)
|
||||
{
|
||||
mnt_param_t *mnt_param = zfs_alloc(hdl, sizeof (mnt_param_t));
|
||||
|
||||
mnt_param->mnt_hdl = hdl;
|
||||
mnt_param->mnt_tp = tp;
|
||||
mnt_param->mnt_zhps = handles;
|
||||
mnt_param->mnt_num_handles = num_handles;
|
||||
mnt_param->mnt_idx = idx;
|
||||
mnt_param->mnt_func = func;
|
||||
mnt_param->mnt_data = data;
|
||||
|
||||
(void) tpool_dispatch(tp, zfs_mount_task, (void*)mnt_param);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the structure used to keep state of mounting or sharing operations
|
||||
* during a call to zpool_enable_datasets().
|
||||
*/
|
||||
typedef struct mount_state {
|
||||
/*
|
||||
* ms_mntstatus is set to -1 if any mount fails. While multiple threads
|
||||
* could update this variable concurrently, no synchronization is
|
||||
* needed as it's only ever set to -1.
|
||||
*/
|
||||
int ms_mntstatus;
|
||||
int ms_mntflags;
|
||||
const char *ms_mntopts;
|
||||
} mount_state_t;
|
||||
|
||||
static int
|
||||
zfs_mount_one(zfs_handle_t *zhp, void *arg)
|
||||
{
|
||||
mount_state_t *ms = arg;
|
||||
int ret = 0;
|
||||
|
||||
if (zfs_mount(zhp, ms->ms_mntopts, ms->ms_mntflags) != 0)
|
||||
ret = ms->ms_mntstatus = -1;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_share_one(zfs_handle_t *zhp, void *arg)
|
||||
{
|
||||
mount_state_t *ms = arg;
|
||||
int ret = 0;
|
||||
|
||||
if (zfs_share(zhp) != 0)
|
||||
ret = ms->ms_mntstatus = -1;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Thread pool function to mount one file system. On completion, it finds and
|
||||
* schedules its children to be mounted. This depends on the sorting done in
|
||||
* zfs_foreach_mountpoint(). Note that the degenerate case (chain of entries
|
||||
* each descending from the previous) will have no parallelism since we always
|
||||
* have to wait for the parent to finish mounting before we can schedule
|
||||
* its children.
|
||||
*/
|
||||
static void
|
||||
zfs_mount_task(void *arg)
|
||||
{
|
||||
mnt_param_t *mp = arg;
|
||||
int idx = mp->mnt_idx;
|
||||
zfs_handle_t **handles = mp->mnt_zhps;
|
||||
size_t num_handles = mp->mnt_num_handles;
|
||||
char mountpoint[ZFS_MAXPROPLEN];
|
||||
|
||||
verify(zfs_prop_get(handles[idx], ZFS_PROP_MOUNTPOINT, mountpoint,
|
||||
sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
|
||||
|
||||
if (mp->mnt_func(handles[idx], mp->mnt_data) != 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We dispatch tasks to mount filesystems with mountpoints underneath
|
||||
* this one. We do this by dispatching the next filesystem with a
|
||||
* descendant mountpoint of the one we just mounted, then skip all of
|
||||
* its descendants, dispatch the next descendant mountpoint, and so on.
|
||||
* The non_descendant_idx() function skips over filesystems that are
|
||||
* descendants of the filesystem we just dispatched.
|
||||
*/
|
||||
for (int i = idx + 1; i < num_handles;
|
||||
i = non_descendant_idx(handles, num_handles, i)) {
|
||||
char child[ZFS_MAXPROPLEN];
|
||||
verify(zfs_prop_get(handles[i], ZFS_PROP_MOUNTPOINT,
|
||||
child, sizeof (child), NULL, NULL, 0, B_FALSE) == 0);
|
||||
|
||||
if (!libzfs_path_contains(mountpoint, child))
|
||||
break; /* not a descendant, return */
|
||||
zfs_dispatch_mount(mp->mnt_hdl, handles, num_handles, i,
|
||||
mp->mnt_func, mp->mnt_data, mp->mnt_tp);
|
||||
}
|
||||
free(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue the func callback for each ZFS handle contained in the handles
|
||||
* array. This function is used to mount all datasets, and so this function
|
||||
* guarantees that filesystems for parent mountpoints are called before their
|
||||
* children. As such, before issuing any callbacks, we first sort the array
|
||||
* of handles by mountpoint.
|
||||
*
|
||||
* Callbacks are issued in one of two ways:
|
||||
*
|
||||
* 1. Sequentially: If the parallel argument is B_FALSE or the ZFS_SERIAL_MOUNT
|
||||
* environment variable is set, then we issue callbacks sequentially.
|
||||
*
|
||||
* 2. In parallel: If the parallel argument is B_TRUE and the ZFS_SERIAL_MOUNT
|
||||
* environment variable is not set, then we use a tpool to dispatch threads
|
||||
* to mount filesystems in parallel. This function dispatches tasks to mount
|
||||
* the filesystems at the top-level mountpoints, and these tasks in turn
|
||||
* are responsible for recursively mounting filesystems in their children
|
||||
* mountpoints.
|
||||
*/
|
||||
void
|
||||
zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles,
|
||||
size_t num_handles, zfs_iter_f func, void *data, boolean_t parallel)
|
||||
{
|
||||
zoneid_t zoneid = getzoneid();
|
||||
|
||||
/*
|
||||
* The ZFS_SERIAL_MOUNT environment variable is an undocumented
|
||||
* variable that can be used as a convenience to do a/b comparison
|
||||
* of serial vs. parallel mounting.
|
||||
*/
|
||||
boolean_t serial_mount = !parallel ||
|
||||
(getenv("ZFS_SERIAL_MOUNT") != NULL);
|
||||
|
||||
/*
|
||||
* Sort the datasets by mountpoint. See mountpoint_cmp for details
|
||||
* of how these are sorted.
|
||||
*/
|
||||
qsort(handles, num_handles, sizeof (zfs_handle_t *), mountpoint_cmp);
|
||||
|
||||
if (serial_mount) {
|
||||
for (int i = 0; i < num_handles; i++) {
|
||||
func(handles[i], data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue the callback function for each dataset using a parallel
|
||||
* algorithm that uses a thread pool to manage threads.
|
||||
*/
|
||||
tpool_t *tp = tpool_create(1, mount_tp_nthr, 0, NULL);
|
||||
|
||||
/*
|
||||
* There may be multiple "top level" mountpoints outside of the pool's
|
||||
* root mountpoint, e.g.: /foo /bar. Dispatch a mount task for each of
|
||||
* these.
|
||||
*/
|
||||
for (int i = 0; i < num_handles;
|
||||
i = non_descendant_idx(handles, num_handles, i)) {
|
||||
/*
|
||||
* Since the mountpoints have been sorted so that the zoned
|
||||
* filesystems are at the end, a zoned filesystem seen from
|
||||
* the global zone means that we're done.
|
||||
*/
|
||||
if (zoneid == GLOBAL_ZONEID &&
|
||||
zfs_prop_get_int(handles[i], ZFS_PROP_ZONED))
|
||||
break;
|
||||
zfs_dispatch_mount(hdl, handles, num_handles, i, func, data,
|
||||
tp);
|
||||
}
|
||||
|
||||
tpool_wait(tp); /* wait for all scheduled mounts to complete */
|
||||
tpool_destroy(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount and share all datasets within the given pool. This assumes that no
|
||||
* datasets within the pool are currently mounted. Because users can create
|
||||
* complicated nested hierarchies of mountpoints, we first gather all the
|
||||
* datasets and mountpoints within the pool, and sort them by mountpoint. Once
|
||||
* we have the list of all filesystems, we iterate over them in order and mount
|
||||
* and/or share each one.
|
||||
* datasets within the pool are currently mounted.
|
||||
*/
|
||||
#pragma weak zpool_mount_datasets = zpool_enable_datasets
|
||||
int
|
||||
zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
|
||||
{
|
||||
get_all_cb_t cb = { 0 };
|
||||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
mount_state_t ms = { 0 };
|
||||
zfs_handle_t *zfsp;
|
||||
int i, ret = -1;
|
||||
int *good;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Gather all non-snap datasets within the pool.
|
||||
*/
|
||||
if ((zfsp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_DATASET)) == NULL)
|
||||
if ((zfsp = zfs_open(zhp->zpool_hdl, zhp->zpool_name,
|
||||
ZFS_TYPE_DATASET)) == NULL)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Gather all non-snapshot datasets within the pool. Start by adding
|
||||
* the root filesystem for this pool to the list, and then iterate
|
||||
* over all child filesystems.
|
||||
*/
|
||||
libzfs_add_handle(&cb, zfsp);
|
||||
if (zfs_iter_filesystems(zfsp, mount_cb, &cb) != 0)
|
||||
goto out;
|
||||
/*
|
||||
* Sort the datasets by mountpoint.
|
||||
*/
|
||||
qsort(cb.cb_handles, cb.cb_used, sizeof (void *),
|
||||
libzfs_dataset_cmp);
|
||||
|
||||
/*
|
||||
* And mount all the datasets, keeping track of which ones
|
||||
* succeeded or failed.
|
||||
*/
|
||||
if ((good = zfs_alloc(zhp->zpool_hdl,
|
||||
cb.cb_used * sizeof (int))) == NULL)
|
||||
if (zfs_iter_filesystems(zfsp, zfs_iter_cb, &cb) != 0)
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; i < cb.cb_used; i++) {
|
||||
if (zfs_mount(cb.cb_handles[i], mntopts, flags) != 0)
|
||||
ret = -1;
|
||||
else
|
||||
good[i] = 1;
|
||||
}
|
||||
/*
|
||||
* Mount all filesystems
|
||||
*/
|
||||
ms.ms_mntopts = mntopts;
|
||||
ms.ms_mntflags = flags;
|
||||
zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
|
||||
zfs_mount_one, &ms, B_TRUE);
|
||||
if (ms.ms_mntstatus != 0)
|
||||
ret = ms.ms_mntstatus;
|
||||
|
||||
/*
|
||||
* Then share all the ones that need to be shared. This needs
|
||||
* to be a separate pass in order to avoid excessive reloading
|
||||
* of the configuration. Good should never be NULL since
|
||||
* zfs_alloc is supposed to exit if memory isn't available.
|
||||
* Share all filesystems that need to be shared. This needs to be
|
||||
* a separate pass because libshare is not mt-safe, and so we need
|
||||
* to share serially.
|
||||
*/
|
||||
for (i = 0; i < cb.cb_used; i++) {
|
||||
if (good[i] && zfs_share(cb.cb_handles[i]) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(good);
|
||||
ms.ms_mntstatus = 0;
|
||||
zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
|
||||
zfs_share_one, &ms, B_FALSE);
|
||||
if (ms.ms_mntstatus != 0)
|
||||
ret = ms.ms_mntstatus;
|
||||
|
||||
out:
|
||||
for (i = 0; i < cb.cb_used; i++)
|
||||
for (int i = 0; i < cb.cb_used; i++)
|
||||
zfs_close(cb.cb_handles[i]);
|
||||
free(cb.cb_handles);
|
||||
|
||||
|
@ -85,6 +85,8 @@ typedef struct progress_arg {
|
||||
zfs_handle_t *pa_zhp;
|
||||
int pa_fd;
|
||||
boolean_t pa_parsable;
|
||||
boolean_t pa_astitle;
|
||||
uint64_t pa_size;
|
||||
} progress_arg_t;
|
||||
|
||||
typedef struct dataref {
|
||||
@ -930,6 +932,7 @@ typedef struct send_dump_data {
|
||||
uint64_t prevsnap_obj;
|
||||
boolean_t seenfrom, seento, replicate, doall, fromorigin;
|
||||
boolean_t verbose, dryrun, parsable, progress, embed_data, std_out;
|
||||
boolean_t progressastitle;
|
||||
boolean_t large_block, compress;
|
||||
int outfd;
|
||||
boolean_t err;
|
||||
@ -1110,14 +1113,14 @@ send_progress_thread(void *arg)
|
||||
zfs_cmd_t zc = { 0 };
|
||||
zfs_handle_t *zhp = pa->pa_zhp;
|
||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||
unsigned long long bytes;
|
||||
unsigned long long bytes, total;
|
||||
char buf[16];
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
|
||||
|
||||
if (!pa->pa_parsable)
|
||||
if (!pa->pa_parsable && !pa->pa_astitle)
|
||||
(void) fprintf(stderr, "TIME SENT SNAPSHOT\n");
|
||||
|
||||
/*
|
||||
@ -1134,7 +1137,16 @@ send_progress_thread(void *arg)
|
||||
tm = localtime(&t);
|
||||
bytes = zc.zc_cookie;
|
||||
|
||||
if (pa->pa_parsable) {
|
||||
if (pa->pa_astitle) {
|
||||
int pct;
|
||||
if (pa->pa_size > bytes)
|
||||
pct = 100 * bytes / pa->pa_size;
|
||||
else
|
||||
pct = 100;
|
||||
|
||||
setproctitle("sending %s (%d%%: %llu/%llu)",
|
||||
zhp->zfs_name, pct, bytes, pa->pa_size);
|
||||
} else if (pa->pa_parsable) {
|
||||
(void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n",
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
bytes, zhp->zfs_name);
|
||||
@ -1204,6 +1216,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
|
||||
boolean_t isfromsnap, istosnap, fromorigin;
|
||||
boolean_t exclude = B_FALSE;
|
||||
FILE *fout = sdd->std_out ? stdout : stderr;
|
||||
uint64_t size = 0;
|
||||
|
||||
err = 0;
|
||||
thissnap = strchr(zhp->zfs_name, '@') + 1;
|
||||
@ -1278,15 +1291,16 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
|
||||
fromorigin = sdd->prevsnap[0] == '\0' &&
|
||||
(sdd->fromorigin || sdd->replicate);
|
||||
|
||||
if (sdd->verbose) {
|
||||
uint64_t size = 0;
|
||||
if (sdd->progress && sdd->dryrun) {
|
||||
(void) estimate_ioctl(zhp, sdd->prevsnap_obj,
|
||||
fromorigin, flags, &size);
|
||||
sdd->size += size;
|
||||
}
|
||||
|
||||
if (sdd->verbose) {
|
||||
send_print_verbose(fout, zhp->zfs_name,
|
||||
sdd->prevsnap[0] ? sdd->prevsnap : NULL,
|
||||
size, sdd->parsable);
|
||||
sdd->size += size;
|
||||
}
|
||||
|
||||
if (!sdd->dryrun) {
|
||||
@ -1298,6 +1312,8 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
|
||||
pa.pa_zhp = zhp;
|
||||
pa.pa_fd = sdd->outfd;
|
||||
pa.pa_parsable = sdd->parsable;
|
||||
pa.pa_size = sdd->size;
|
||||
pa.pa_astitle = sdd->progressastitle;
|
||||
|
||||
if ((err = pthread_create(&tid, NULL,
|
||||
send_progress_thread, &pa)) != 0) {
|
||||
@ -1580,6 +1596,7 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
int error = 0;
|
||||
char name[ZFS_MAX_DATASET_NAME_LEN];
|
||||
enum lzc_send_flags lzc_flags = 0;
|
||||
uint64_t size = 0;
|
||||
FILE *fout = (flags->verbose && flags->dryrun) ? stdout : stderr;
|
||||
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
@ -1648,12 +1665,13 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
fromname = name;
|
||||
}
|
||||
|
||||
if (flags->verbose) {
|
||||
uint64_t size = 0;
|
||||
if (flags->progress) {
|
||||
error = lzc_send_space(zhp->zfs_name, fromname,
|
||||
lzc_flags, &size);
|
||||
if (error == 0)
|
||||
size = MAX(0, (int64_t)(size - bytes));
|
||||
}
|
||||
if (flags->verbose) {
|
||||
send_print_verbose(fout, zhp->zfs_name, fromname,
|
||||
size, flags->parsable);
|
||||
}
|
||||
@ -1669,6 +1687,8 @@ zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
|
||||
pa.pa_zhp = zhp;
|
||||
pa.pa_fd = outfd;
|
||||
pa.pa_parsable = flags->parsable;
|
||||
pa.pa_size = size;
|
||||
pa.pa_astitle = flags->progressastitle;
|
||||
|
||||
error = pthread_create(&tid, NULL,
|
||||
send_progress_thread, &pa);
|
||||
@ -1878,6 +1898,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||
sdd.verbose = flags->verbose;
|
||||
sdd.parsable = flags->parsable;
|
||||
sdd.progress = flags->progress;
|
||||
sdd.progressastitle = flags->progressastitle;
|
||||
sdd.dryrun = flags->dryrun;
|
||||
sdd.large_block = flags->largeblock;
|
||||
sdd.embed_data = flags->embed_data;
|
||||
@ -1914,7 +1935,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||
sdd.cleanup_fd = -1;
|
||||
sdd.snapholds = NULL;
|
||||
}
|
||||
if (flags->verbose || sdd.snapholds != NULL) {
|
||||
if (flags->progress || sdd.snapholds != NULL) {
|
||||
/*
|
||||
* Do a verbose no-op dry run to get all the verbose output
|
||||
* or to gather snapshot hold's before generating any data,
|
||||
|
2427
contrib/bearssl/Doxyfile
Normal file
2427
contrib/bearssl/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
21
contrib/bearssl/LICENSE.txt
Normal file
21
contrib/bearssl/LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
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.
|
45
contrib/bearssl/Makefile
Normal file
45
contrib/bearssl/Makefile
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2017 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.
|
||||
|
||||
# ======================================================================
|
||||
|
||||
# The lines below are a horrible hack that nonetheless works. On a
|
||||
# "make" utility compatible with Single Unix v4 (this includes GNU and
|
||||
# BSD make), the '\' at the end of a command line counts as an escape
|
||||
# for the newline character, so the next line is still a comment.
|
||||
# However, Microsoft's nmake.exe (that comes with Visual Studio) does
|
||||
# not interpret the final '\' that way in a comment. The end result is
|
||||
# that when using nmake.exe, this will include "mk/Win.mk", whereas
|
||||
# GNU/BSD make will include "mk/Unix.mk".
|
||||
|
||||
# \
|
||||
!ifndef 0 # \
|
||||
!include mk/NMake.mk # \
|
||||
!else
|
||||
.POSIX:
|
||||
include mk/SingleUnix.mk
|
||||
# Extra hack for OpenBSD make.
|
||||
ifndef: all
|
||||
0: all
|
||||
endif: all
|
||||
# \
|
||||
!endif
|
136
contrib/bearssl/README.txt
Normal file
136
contrib/bearssl/README.txt
Normal file
@ -0,0 +1,136 @@
|
||||
# Documentation
|
||||
|
||||
The most up-to-date documentation is supposed to be available on the
|
||||
[BearSSL Web site](https://www.bearssl.org/).
|
||||
|
||||
# Disclaimer
|
||||
|
||||
BearSSL is considered beta-level software. Most planned functionalities
|
||||
are implemented; new evolution may still break both source and binary
|
||||
compatibility.
|
||||
|
||||
Using BearSSL for production purposes would be a relatively bold but not
|
||||
utterly crazy move. BearSSL is free, open-source software, provided
|
||||
without any guarantee of fitness or reliability. That being said, it
|
||||
appears to behave properly, and only minor issues have been found (and
|
||||
fixed) so far. You are encourage to inspect its API and code for
|
||||
learning, testing and possibly contributing.
|
||||
|
||||
The usage license is explicited in the `LICENSE.txt` file. This is the
|
||||
"MIT license". It can be summarised in the following way:
|
||||
|
||||
- You can use and reuse the library as you wish, and modify it, and
|
||||
integrate it in your own code, and distribute it as is or in any
|
||||
modified form, and so on.
|
||||
|
||||
- The only obligation that the license terms put upon you is that you
|
||||
acknowledge and make it clear that if anything breaks, it is not my
|
||||
fault, and I am not liable for anything, regardless of the type and
|
||||
amount of collateral damage. The license terms say that the copyright
|
||||
notice "shall be included in all copies or substantial portions of
|
||||
the Software": this is how the disclaimer is "made explicit".
|
||||
Basically, I have put it in every source file, so just keep it there.
|
||||
|
||||
# Installation
|
||||
|
||||
Right now, BearSSL is a simple library, along with a few test and debug
|
||||
command-line tools. There is no installer yet. The library _can_ be
|
||||
compiled as a shared library on some systems, but since the binary API
|
||||
is not fully stabilised, this is not a very good idea to do that right
|
||||
now.
|
||||
|
||||
To compile the code, just type `make`. This will try to use sane
|
||||
"default" values. On a Windows system with Visual Studio, run a console
|
||||
with the environment initialised for a specific version of the C compiler,
|
||||
and type `nmake`.
|
||||
|
||||
To override the default settings, create a custom configuration file in
|
||||
the `conf` directory, and invoke `make` (or `nmake`) with an explicit
|
||||
`CONF=` parameter. For instance, to use the provided `samd20.mk`
|
||||
configuration file (that targets cross-compilation for an Atmel board
|
||||
that features a Cortex-M0+ CPU), type:
|
||||
|
||||
make CONF=samd20
|
||||
|
||||
The `conf/samd20.mk` file includes the `Unix.mk` file and then overrides
|
||||
some of the parameters, including the destination directory. Any custom
|
||||
configuration can be made the same way.
|
||||
|
||||
Some compile-time options can be set through macros, either on the
|
||||
compiler command-line, or in the `src/config.h` file. See the comments
|
||||
in that file. Some settings are autodetected but they can still be
|
||||
explicitly overridden.
|
||||
|
||||
When compilation is done, the library (static and DLL, when appropriate)
|
||||
and the command-line tools can be found in the designated build
|
||||
directory (by default named `build`). The public headers (to be used
|
||||
by applications linked against BearSSL) are in the `inc/` directory.
|
||||
|
||||
To run the tests:
|
||||
|
||||
- `testcrypto all` runs the cryptographic tests (test vectors on all
|
||||
implemented cryptogaphic functions). It can be slow. You can also
|
||||
run a selection of the tests by providing their names (run
|
||||
`testcrypto` without any parameter to see the available names).
|
||||
|
||||
- `testspeed all` runs a number of performance benchmarks, there again
|
||||
on cryptographic functions. It gives a taste of how things go on the
|
||||
current platform. As for `testcrypto`, specific named benchmarks can
|
||||
be executed.
|
||||
|
||||
- `testx509` runs X.509 validation tests. The test certificates are
|
||||
all in `test/x509/`.
|
||||
|
||||
The `brssl` command-line tool produced in the build directory is a
|
||||
stand-alone binary. It can exercise some of the functionalities of
|
||||
BearSSL, in particular running a test SSL client or server. It is not
|
||||
meant for production purposes (e.g. the SSL client has a mode where it
|
||||
disregards the inability to validate the server's certificate, which is
|
||||
inherently unsafe, but convenient for debug).
|
||||
|
||||
**Using the library** means writing some application code that invokes
|
||||
it, and linking with the static library. The header files are all in the
|
||||
`inc` directory; copy them wherever makes sense (e.g. in the
|
||||
`/usr/local/include` directory). The library itself (`libbearssl.a`) is
|
||||
what you link against.
|
||||
|
||||
Alternatively, you may want to copy the source files directly into your
|
||||
own application code. This will make integrating ulterior versions of
|
||||
BearSSL more difficult. If you still want to go down that road, then
|
||||
simply copy all the `*.h` and `*.c` files from the `src` and `inc`
|
||||
directories into your application source code. In the BearSSL source
|
||||
archive, the source files are segregated into various sub-directories,
|
||||
but this is for my convenience only. There is no technical requirement
|
||||
for that, and all files can be dumped together in a simple directory.
|
||||
|
||||
Dependencies are simple and systematic:
|
||||
|
||||
- Each `*.c` file includes `inner.h`
|
||||
- `inner.h` includes `config.h` and `bearssl.h`
|
||||
- `bearssl.h` includes the other `bearssl_*.h`
|
||||
|
||||
# Versioning
|
||||
|
||||
I follow this simple version numbering scheme:
|
||||
|
||||
- Version numbers are `x.y` or `x.y.z` where `x`, `y` and `z` are
|
||||
decimal integers (possibly greater than 10). When the `.z` part is
|
||||
missing, it is equivalent to `.0`.
|
||||
|
||||
- Backward compatibility is maintained, at both source and binary levels,
|
||||
for each major version: this means that if some application code was
|
||||
designed for version `x.y`, then it should compile, link and run
|
||||
properly with any version `x.y'` for any `y'` greater than `y`.
|
||||
|
||||
The major version `0` is an exception. You shall not expect that any
|
||||
version that starts with `0.` offers any kind of compatibility,
|
||||
either source or binary, with any other `0.` version. (Of course I
|
||||
will try to maintain some decent level of source compatibility, but I
|
||||
make no promise in that respect. Since the API uses caller-allocated
|
||||
context structures, I already know that binary compatibility _will_
|
||||
be broken.)
|
||||
|
||||
- Sub-versions (the `y` part) are about added functionality. That is,
|
||||
it can be expected that `1.3` will contain some extra functions when
|
||||
compared to `1.2`. The next version level (the `z` part) is for
|
||||
bugfixes that do not add any functionality.
|
112
contrib/bearssl/T0/BlobWriter.cs
Normal file
112
contrib/bearssl/T0/BlobWriter.cs
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
/*
|
||||
* A simple class for writing out bytes as hexadecimal constants or
|
||||
* explicit expressions for the initializer of a C array of 'unsigned
|
||||
* char'. It starts every line with a given number of tabs, and aims at
|
||||
* keeping lines below a given threshold (each indentation tab counts as
|
||||
* 8 characters). An explicit newline is inserted before the first
|
||||
* element, and commas are used as separators.
|
||||
*/
|
||||
|
||||
class BlobWriter {
|
||||
|
||||
TextWriter w;
|
||||
int maxLineLen;
|
||||
int indent;
|
||||
int lineLen;
|
||||
|
||||
/*
|
||||
* Create a new instance. 'maxLineLen' is in characters, and
|
||||
* 'indent' is the number of tab characters at the start of
|
||||
* each line.
|
||||
*/
|
||||
internal BlobWriter(TextWriter w, int maxLineLen, int indent)
|
||||
{
|
||||
this.w = w;
|
||||
this.maxLineLen = maxLineLen;
|
||||
this.indent = indent;
|
||||
lineLen = -1;
|
||||
}
|
||||
|
||||
void DoNL()
|
||||
{
|
||||
w.WriteLine();
|
||||
for (int i = 0; i < indent; i ++) {
|
||||
w.Write('\t');
|
||||
}
|
||||
lineLen = (indent << 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a new byte value; it will be converted to an hexadecimal
|
||||
* constant in the output.
|
||||
*/
|
||||
internal void Append(byte b)
|
||||
{
|
||||
if (lineLen < 0) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(',');
|
||||
lineLen ++;
|
||||
if ((lineLen + 5) > maxLineLen) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(' ');
|
||||
lineLen ++;
|
||||
}
|
||||
}
|
||||
w.Write("0x{0:X2}", b);
|
||||
lineLen += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a C expression, which will be used as is. The expression
|
||||
* may resolve to several bytes if it uses internal commas. The
|
||||
* writer will try to honour the expected line length, but it
|
||||
* won't insert a newline character inside the expression.
|
||||
*/
|
||||
internal void Append(string expr)
|
||||
{
|
||||
if (lineLen < 0) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(',');
|
||||
lineLen ++;
|
||||
if ((lineLen + 1 + expr.Length) > maxLineLen) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(' ');
|
||||
lineLen ++;
|
||||
}
|
||||
}
|
||||
w.Write("{0}", expr);
|
||||
lineLen += expr.Length;
|
||||
}
|
||||
}
|
181
contrib/bearssl/T0/CPU.cs
Normal file
181
contrib/bearssl/T0/CPU.cs
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Execution of code during compilation is done in a virtual CPU
|
||||
* incarnated by this class, that contains the relevant registers.
|
||||
*
|
||||
* Accesses to the data on the stack are mapped to accesses to an
|
||||
* internal array, with no explicit control on boundaries. Since the
|
||||
* internal array may be larger than the actual stack contents,
|
||||
* nonsensical accesses may still "work" to some extent. The whole
|
||||
* thing won't derail beyond the CLR VM, though.
|
||||
*/
|
||||
|
||||
class CPU {
|
||||
|
||||
/*
|
||||
* Next instruction to execute is in ipBuf[ipOff].
|
||||
*/
|
||||
internal Opcode[] ipBuf;
|
||||
internal int ipOff;
|
||||
|
||||
/*
|
||||
* stackBuf and stackPtr implement the data stack. The system
|
||||
* stack uses frames; 'rsp' points to the current top frame.
|
||||
*/
|
||||
TValue[] stackBuf;
|
||||
int stackPtr;
|
||||
Frame rsp;
|
||||
|
||||
internal CPU()
|
||||
{
|
||||
stackBuf = new TValue[16];
|
||||
stackPtr = -1;
|
||||
rsp = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter a function, reserving space for 'numLocals' local variables.
|
||||
*/
|
||||
internal void Enter(Opcode[] code, int numLocals)
|
||||
{
|
||||
Frame f = new Frame(rsp, numLocals);
|
||||
rsp = f;
|
||||
f.savedIpBuf = ipBuf;
|
||||
f.savedIpOff = ipOff;
|
||||
ipBuf = code;
|
||||
ipOff = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit the current function.
|
||||
*/
|
||||
internal void Exit()
|
||||
{
|
||||
ipBuf = rsp.savedIpBuf;
|
||||
ipOff = rsp.savedIpOff;
|
||||
rsp = rsp.upper;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current stack depth (number of elements).
|
||||
*/
|
||||
internal int Depth {
|
||||
get {
|
||||
return stackPtr + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a value from the stack.
|
||||
*/
|
||||
internal TValue Pop()
|
||||
{
|
||||
return stackBuf[stackPtr --];
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a value on the stack.
|
||||
*/
|
||||
internal void Push(TValue v)
|
||||
{
|
||||
int len = stackBuf.Length;
|
||||
if (++ stackPtr == len) {
|
||||
TValue[] nbuf = new TValue[len << 1];
|
||||
Array.Copy(stackBuf, 0, nbuf, 0, len);
|
||||
stackBuf = nbuf;
|
||||
}
|
||||
stackBuf[stackPtr] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look at the value at depth 'depth' (0 is top of stack). The
|
||||
* stack is unchanged.
|
||||
*/
|
||||
internal TValue Peek(int depth)
|
||||
{
|
||||
return stackBuf[stackPtr - depth];
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate the stack at depth 'depth': the value at that depth
|
||||
* is moved to the top of stack.
|
||||
*/
|
||||
internal void Rot(int depth)
|
||||
{
|
||||
TValue v = stackBuf[stackPtr - depth];
|
||||
Array.Copy(stackBuf, stackPtr - (depth - 1),
|
||||
stackBuf, stackPtr - depth, depth);
|
||||
stackBuf[stackPtr] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inverse-rotate the stack at depth 'depth': the value at the
|
||||
* top of stack is moved to that depth.
|
||||
*/
|
||||
internal void NRot(int depth)
|
||||
{
|
||||
TValue v = stackBuf[stackPtr];
|
||||
Array.Copy(stackBuf, stackPtr - depth,
|
||||
stackBuf, stackPtr - (depth - 1), depth);
|
||||
stackBuf[stackPtr - depth] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current contents of the local variable 'num'.
|
||||
*/
|
||||
internal TValue GetLocal(int num)
|
||||
{
|
||||
return rsp.locals[num];
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the contents of the local variable 'num'.
|
||||
*/
|
||||
internal void PutLocal(int num, TValue v)
|
||||
{
|
||||
rsp.locals[num] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* The system stack really is a linked list of Frame instances.
|
||||
*/
|
||||
class Frame {
|
||||
|
||||
internal Frame upper;
|
||||
internal Opcode[] savedIpBuf;
|
||||
internal int savedIpOff;
|
||||
internal TValue[] locals;
|
||||
|
||||
internal Frame(Frame upper, int numLocals)
|
||||
{
|
||||
this.upper = upper;
|
||||
locals = new TValue[numLocals];
|
||||
}
|
||||
}
|
||||
}
|
100
contrib/bearssl/T0/CodeElement.cs
Normal file
100
contrib/bearssl/T0/CodeElement.cs
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
abstract class CodeElement {
|
||||
|
||||
internal int Address { get; set; }
|
||||
|
||||
internal int LastLength { get; set; }
|
||||
|
||||
// internal abstract int Length { get; }
|
||||
|
||||
internal CodeElement()
|
||||
{
|
||||
Address = -1;
|
||||
}
|
||||
|
||||
internal virtual void SetJumpTarget(CodeElement target)
|
||||
{
|
||||
throw new Exception("Code element accepts no target");
|
||||
}
|
||||
|
||||
internal abstract int GetLength(bool oneByteCode);
|
||||
|
||||
internal abstract int Encode(BlobWriter bw, bool oneByteCode);
|
||||
|
||||
internal static int EncodeOneByte(uint val, BlobWriter bw)
|
||||
{
|
||||
if (val > 255) {
|
||||
throw new Exception(string.Format(
|
||||
"Cannot encode '{0}' over one byte", val));
|
||||
}
|
||||
bw.Append((byte)val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
internal static int Encode7EUnsigned(uint val, BlobWriter bw)
|
||||
{
|
||||
int len = 1;
|
||||
for (uint w = val; w >= 0x80; w >>= 7) {
|
||||
len ++;
|
||||
}
|
||||
if (bw != null) {
|
||||
for (int k = (len - 1) * 7; k >= 0; k -= 7) {
|
||||
int x = (int)(val >> k) & 0x7F;
|
||||
if (k > 0) {
|
||||
x |= 0x80;
|
||||
}
|
||||
bw.Append((byte)x);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
internal static int Encode7ESigned(int val, BlobWriter bw)
|
||||
{
|
||||
int len = 1;
|
||||
if (val < 0) {
|
||||
for (int w = val; w < -0x40; w >>= 7) {
|
||||
len ++;
|
||||
}
|
||||
} else {
|
||||
for (int w = val; w >= 0x40; w >>= 7) {
|
||||
len ++;
|
||||
}
|
||||
}
|
||||
if (bw != null) {
|
||||
for (int k = (len - 1) * 7; k >= 0; k -= 7) {
|
||||
int x = (int)(val >> k) & 0x7F;
|
||||
if (k > 0) {
|
||||
x |= 0x80;
|
||||
}
|
||||
bw.Append((byte)x);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
97
contrib/bearssl/T0/CodeElementJump.cs
Normal file
97
contrib/bearssl/T0/CodeElementJump.cs
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementJump : CodeElement {
|
||||
|
||||
uint jumpType;
|
||||
CodeElement target;
|
||||
|
||||
internal CodeElementJump(uint jumpType)
|
||||
{
|
||||
this.jumpType = jumpType;
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override int Length {
|
||||
get {
|
||||
int len = Encode7EUnsigned(jumpType, null);
|
||||
int joff = JumpOff;
|
||||
if (joff == Int32.MinValue) {
|
||||
len ++;
|
||||
} else {
|
||||
len += Encode7ESigned(joff, null);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
internal override int GetLength(bool oneByteCode)
|
||||
{
|
||||
int len = oneByteCode ? 1 : Encode7EUnsigned(jumpType, null);
|
||||
int joff = JumpOff;
|
||||
if (joff == Int32.MinValue) {
|
||||
len ++;
|
||||
} else {
|
||||
len += Encode7ESigned(joff, null);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
internal override void SetJumpTarget(CodeElement target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
int JumpOff {
|
||||
get {
|
||||
if (target == null || Address < 0 || target.Address < 0)
|
||||
{
|
||||
return Int32.MinValue;
|
||||
} else {
|
||||
return target.Address - (Address + LastLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw, bool oneByteCode)
|
||||
{
|
||||
if (bw == null) {
|
||||
return GetLength(oneByteCode);
|
||||
}
|
||||
int len;
|
||||
if (oneByteCode) {
|
||||
len = EncodeOneByte(jumpType, bw);
|
||||
} else {
|
||||
len = Encode7EUnsigned(jumpType, bw);
|
||||
}
|
||||
int joff = JumpOff;
|
||||
if (joff == Int32.MinValue) {
|
||||
throw new Exception("Unresolved addresses");
|
||||
}
|
||||
return len + Encode7ESigned(joff, bw);
|
||||
}
|
||||
}
|
55
contrib/bearssl/T0/CodeElementUInt.cs
Normal file
55
contrib/bearssl/T0/CodeElementUInt.cs
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUInt : CodeElement {
|
||||
|
||||
uint val;
|
||||
|
||||
internal CodeElementUInt(uint val) : base()
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val, null);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
internal override int GetLength(bool oneByteCode)
|
||||
{
|
||||
return oneByteCode ? 1 : Encode7EUnsigned(val, null);
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw, bool oneByteCode)
|
||||
{
|
||||
return oneByteCode
|
||||
? EncodeOneByte(val, bw)
|
||||
: Encode7EUnsigned(val, bw);
|
||||
}
|
||||
}
|
66
contrib/bearssl/T0/CodeElementUIntExpr.cs
Normal file
66
contrib/bearssl/T0/CodeElementUIntExpr.cs
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntExpr : CodeElement {
|
||||
|
||||
uint val;
|
||||
TPointerExpr cx;
|
||||
int off;
|
||||
|
||||
internal CodeElementUIntExpr(uint val,
|
||||
TPointerExpr cx, int off) : base()
|
||||
{
|
||||
this.val = val;
|
||||
this.cx = cx;
|
||||
this.off = off;
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val, null)
|
||||
+ (cx.GetMaxBitLength(off) + 6) / 7;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
internal override int GetLength(bool oneByteCode)
|
||||
{
|
||||
int len = oneByteCode ? 1 : Encode7EUnsigned(val, null);
|
||||
return len + (cx.GetMaxBitLength(off) + 6) / 7;
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw, bool oneByteCode)
|
||||
{
|
||||
int len1 = oneByteCode
|
||||
? EncodeOneByte(val, bw)
|
||||
: Encode7EUnsigned(val, bw);
|
||||
int len2 = (cx.GetMaxBitLength(off) + 6) / 7;
|
||||
bw.Append(String.Format("T0_INT{0}({1})",
|
||||
len2, cx.ToCExpr(off)));
|
||||
return len1 + len2;
|
||||
}
|
||||
}
|
61
contrib/bearssl/T0/CodeElementUIntInt.cs
Normal file
61
contrib/bearssl/T0/CodeElementUIntInt.cs
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntInt : CodeElement {
|
||||
|
||||
uint val1;
|
||||
int val2;
|
||||
|
||||
internal CodeElementUIntInt(uint val1, int val2) : base()
|
||||
{
|
||||
this.val1 = val1;
|
||||
this.val2 = val2;
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val1, null)
|
||||
+ Encode7ESigned(val2, null);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
internal override int GetLength(bool oneByteCode)
|
||||
{
|
||||
return (oneByteCode ? 1 : Encode7EUnsigned(val1, null))
|
||||
+ Encode7ESigned(val2, null);
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw, bool oneByteCode)
|
||||
{
|
||||
int len = oneByteCode
|
||||
? EncodeOneByte(val1, bw)
|
||||
: Encode7EUnsigned(val1, bw);
|
||||
len += Encode7ESigned(val2, bw);
|
||||
return len;
|
||||
}
|
||||
}
|
60
contrib/bearssl/T0/CodeElementUIntUInt.cs
Normal file
60
contrib/bearssl/T0/CodeElementUIntUInt.cs
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntUInt : CodeElement {
|
||||
|
||||
uint val1, val2;
|
||||
|
||||
internal CodeElementUIntUInt(uint val1, uint val2) : base()
|
||||
{
|
||||
this.val1 = val1;
|
||||
this.val2 = val2;
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val1, null)
|
||||
+ Encode7EUnsigned(val2, null);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
internal override int GetLength(bool oneByteCode)
|
||||
{
|
||||
return (oneByteCode ? 1 : Encode7EUnsigned(val1, null))
|
||||
+ Encode7EUnsigned(val2, null);
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw, bool oneByteCode)
|
||||
{
|
||||
int len = oneByteCode
|
||||
? EncodeOneByte(val1, bw)
|
||||
: Encode7EUnsigned(val1, bw);
|
||||
len += Encode7EUnsigned(val2, bw);
|
||||
return len;
|
||||
}
|
||||
}
|
198
contrib/bearssl/T0/ConstData.cs
Normal file
198
contrib/bearssl/T0/ConstData.cs
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
class ConstData {
|
||||
|
||||
internal long ID { get; private set; }
|
||||
internal int Address { get; set; }
|
||||
internal int Length {
|
||||
get {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] buf;
|
||||
int len;
|
||||
|
||||
internal ConstData(T0Comp ctx)
|
||||
{
|
||||
ID = ctx.NextBlobID();
|
||||
buf = new byte[4];
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void Expand(int elen)
|
||||
{
|
||||
int tlen = len + elen;
|
||||
if (tlen > buf.Length) {
|
||||
int nlen = Math.Max(buf.Length << 1, tlen);
|
||||
byte[] nbuf = new byte[nlen];
|
||||
Array.Copy(buf, 0, nbuf, 0, len);
|
||||
buf = nbuf;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Add8(byte b)
|
||||
{
|
||||
Expand(1);
|
||||
buf[len ++] = b;
|
||||
}
|
||||
|
||||
internal void Add16(int x)
|
||||
{
|
||||
Expand(2);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void Add24(int x)
|
||||
{
|
||||
Expand(3);
|
||||
buf[len ++] = (byte)(x >> 16);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void Add32(int x)
|
||||
{
|
||||
Expand(4);
|
||||
buf[len ++] = (byte)(x >> 24);
|
||||
buf[len ++] = (byte)(x >> 16);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void AddString(string s)
|
||||
{
|
||||
byte[] sd = Encoding.UTF8.GetBytes(s);
|
||||
Expand(sd.Length + 1);
|
||||
Array.Copy(sd, 0, buf, len, sd.Length);
|
||||
buf[len + sd.Length] = 0;
|
||||
len += sd.Length + 1;
|
||||
}
|
||||
|
||||
void CheckIndex(int off, int dlen)
|
||||
{
|
||||
if (off < 0 || off > (len - dlen)) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Set8(int off, byte v)
|
||||
{
|
||||
CheckIndex(off, 1);
|
||||
buf[off] = v;
|
||||
}
|
||||
|
||||
internal byte Read8(int off)
|
||||
{
|
||||
CheckIndex(off, 1);
|
||||
return buf[off];
|
||||
}
|
||||
|
||||
internal int Read16(int off)
|
||||
{
|
||||
CheckIndex(off, 2);
|
||||
return (buf[off] << 8) | buf[off + 1];
|
||||
}
|
||||
|
||||
internal int Read24(int off)
|
||||
{
|
||||
CheckIndex(off, 3);
|
||||
return (buf[off] << 16) | (buf[off + 1] << 8) | buf[off + 2];
|
||||
}
|
||||
|
||||
internal int Read32(int off)
|
||||
{
|
||||
CheckIndex(off, 4);
|
||||
return (buf[off] << 24) | (buf[off + 1] << 16)
|
||||
| (buf[off + 2] << 8) | buf[off + 3];
|
||||
}
|
||||
|
||||
internal string ToString(int off)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
int x = DecodeUTF8(ref off);
|
||||
if (x == 0) {
|
||||
return sb.ToString();
|
||||
}
|
||||
if (x < 0x10000) {
|
||||
sb.Append((char)x);
|
||||
} else {
|
||||
x -= 0x10000;
|
||||
sb.Append((char)(0xD800 + (x >> 10)));
|
||||
sb.Append((char)(0xDC00 + (x & 0x3FF)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DecodeUTF8(ref int off)
|
||||
{
|
||||
if (off >= len) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
int x = buf[off ++];
|
||||
if (x < 0xC0 || x > 0xF7) {
|
||||
return x;
|
||||
}
|
||||
int elen, acc;
|
||||
if (x >= 0xF0) {
|
||||
elen = 3;
|
||||
acc = x & 0x07;
|
||||
} else if (x >= 0xE0) {
|
||||
elen = 2;
|
||||
acc = x & 0x0F;
|
||||
} else {
|
||||
elen = 1;
|
||||
acc = x & 0x1F;
|
||||
}
|
||||
if (off + elen > len) {
|
||||
return x;
|
||||
}
|
||||
for (int i = 0; i < elen; i ++) {
|
||||
int y = buf[off + i];
|
||||
if (y < 0x80 || y >= 0xC0) {
|
||||
return x;
|
||||
}
|
||||
acc = (acc << 6) + (y & 0x3F);
|
||||
}
|
||||
if (acc > 0x10FFFF) {
|
||||
return x;
|
||||
}
|
||||
off += elen;
|
||||
return acc;
|
||||
}
|
||||
|
||||
internal void Encode(BlobWriter bw)
|
||||
{
|
||||
for (int i = 0; i < len; i ++) {
|
||||
bw.Append(buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
117
contrib/bearssl/T0/Opcode.cs
Normal file
117
contrib/bearssl/T0/Opcode.cs
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
abstract class Opcode {
|
||||
|
||||
internal Opcode()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute this opcode.
|
||||
*/
|
||||
internal abstract void Run(CPU cpu);
|
||||
|
||||
/*
|
||||
* Resolve the target (word reference) for this opcode.
|
||||
*/
|
||||
internal virtual void ResolveTarget(Word target)
|
||||
{
|
||||
throw new Exception("Not a call opcode");
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the jump offset for this opcode. Displacement is
|
||||
* relative to the address of the opcode that immediately follows
|
||||
* the jump code; thus, 0 implies no jump at all.
|
||||
*/
|
||||
internal virtual void ResolveJump(int disp)
|
||||
{
|
||||
throw new Exception("Not a jump opcode");
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Word that this opcode references; this can happen
|
||||
* only with "call" and "const" opcodes. For all other opcodes,
|
||||
* this method returns null.
|
||||
*/
|
||||
internal virtual Word GetReference(T0Comp ctx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the data block that this opcode references; this can happen
|
||||
* only with "const" opcodes. For all other opcodes, this method
|
||||
* returns null.
|
||||
*/
|
||||
internal virtual ConstData GetDataBlock(T0Comp ctx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether this opcode may "fall through", i.e. execution
|
||||
* may at least potentially proceed to the next opcode.
|
||||
*/
|
||||
internal virtual bool MayFallThrough {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get jump displacement. For non-jump opcodes, this returns 0.
|
||||
*/
|
||||
internal virtual int JumpDisp {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get stack effect for this opcode (number of elements added to
|
||||
* the stack, could be negative). For OpcodeCall, this returns
|
||||
* 0.
|
||||
*/
|
||||
internal virtual int StackAction {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract CodeElement ToCodeElement();
|
||||
|
||||
/*
|
||||
* This method is called for the CodeElement corresponding to
|
||||
* this opcode, at gcode[off]; it is used to compute actual
|
||||
* byte jump offsets when converting code to C.
|
||||
*/
|
||||
internal virtual void FixUp(CodeElement[] gcode, int off)
|
||||
{
|
||||
}
|
||||
}
|
71
contrib/bearssl/T0/OpcodeCall.cs
Normal file
71
contrib/bearssl/T0/OpcodeCall.cs
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeCall : Opcode {
|
||||
|
||||
Word target;
|
||||
|
||||
internal OpcodeCall() : this(null)
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeCall(Word target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
internal override void ResolveTarget(Word target)
|
||||
{
|
||||
if (this.target != null) {
|
||||
throw new Exception("Opcode already resolved");
|
||||
}
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
target.Run(cpu);
|
||||
}
|
||||
|
||||
internal override Word GetReference(T0Comp ctx)
|
||||
{
|
||||
if (target == null) {
|
||||
throw new Exception("Unresolved call target");
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUInt((uint)target.Slot);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "call " + (target == null ? "UNRESOLVED" : target.Name);
|
||||
}
|
||||
}
|
95
contrib/bearssl/T0/OpcodeConst.cs
Normal file
95
contrib/bearssl/T0/OpcodeConst.cs
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeConst : Opcode {
|
||||
|
||||
TValue val;
|
||||
|
||||
internal OpcodeConst(TValue val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Push(val);
|
||||
}
|
||||
|
||||
internal override Word GetReference(T0Comp ctx)
|
||||
{
|
||||
TPointerXT xt = val.ptr as TPointerXT;
|
||||
if (xt == null) {
|
||||
return null;
|
||||
}
|
||||
xt.Resolve(ctx);
|
||||
return xt.Target;
|
||||
}
|
||||
|
||||
internal override ConstData GetDataBlock(T0Comp ctx)
|
||||
{
|
||||
TPointerBlob bp = val.ptr as TPointerBlob;
|
||||
return bp == null ? null : bp.Blob;
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
if (val.ptr == null) {
|
||||
return new CodeElementUIntInt(1, val.Int);
|
||||
}
|
||||
TPointerXT xt = val.ptr as TPointerXT;
|
||||
if (xt != null) {
|
||||
if (val.x != 0) {
|
||||
throw new Exception(
|
||||
"Cannot compile XT: non-zero offset");
|
||||
}
|
||||
return new CodeElementUIntInt(1, xt.Target.Slot);
|
||||
}
|
||||
TPointerBlob bp = val.ptr as TPointerBlob;
|
||||
if (bp != null) {
|
||||
return new CodeElementUIntInt(1,
|
||||
val.x + bp.Blob.Address);
|
||||
}
|
||||
TPointerExpr cx = val.ptr as TPointerExpr;
|
||||
if (cx != null) {
|
||||
return new CodeElementUIntExpr(1, cx, val.x);
|
||||
}
|
||||
throw new Exception(String.Format(
|
||||
"Cannot embed constant (type = {0})",
|
||||
val.ptr.GetType().FullName));
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "const " + val.ToString();
|
||||
}
|
||||
}
|
57
contrib/bearssl/T0/OpcodeGetLocal.cs
Normal file
57
contrib/bearssl/T0/OpcodeGetLocal.cs
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeGetLocal : Opcode {
|
||||
|
||||
int num;
|
||||
|
||||
internal OpcodeGetLocal(int num)
|
||||
{
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Push(cpu.GetLocal(num));
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUIntUInt(2, (uint)num);
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "getlocal " + num;
|
||||
}
|
||||
}
|
64
contrib/bearssl/T0/OpcodeJump.cs
Normal file
64
contrib/bearssl/T0/OpcodeJump.cs
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
abstract class OpcodeJump : Opcode {
|
||||
|
||||
int disp;
|
||||
|
||||
internal OpcodeJump() : this(Int32.MinValue)
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJump(int disp)
|
||||
{
|
||||
this.disp = disp;
|
||||
}
|
||||
|
||||
internal override int JumpDisp {
|
||||
get {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.ipOff += disp;
|
||||
}
|
||||
|
||||
internal override void ResolveJump(int disp)
|
||||
{
|
||||
if (this.disp != Int32.MinValue) {
|
||||
throw new Exception("Jump already resolved");
|
||||
}
|
||||
this.disp = disp;
|
||||
}
|
||||
|
||||
internal override void FixUp(CodeElement[] gcode, int off)
|
||||
{
|
||||
gcode[off].SetJumpTarget(gcode[off + 1 + disp]);
|
||||
}
|
||||
}
|
65
contrib/bearssl/T0/OpcodeJumpIf.cs
Normal file
65
contrib/bearssl/T0/OpcodeJumpIf.cs
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpIf : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpIf() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpIf(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
TValue v = cpu.Pop();
|
||||
if (v.Bool) {
|
||||
base.Run(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(5);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jumpif UNRESOLVED";
|
||||
} else {
|
||||
return "jumpif disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
65
contrib/bearssl/T0/OpcodeJumpIfNot.cs
Normal file
65
contrib/bearssl/T0/OpcodeJumpIfNot.cs
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpIfNot : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpIfNot() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpIfNot(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
TValue v = cpu.Pop();
|
||||
if (!v.Bool) {
|
||||
base.Run(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(6);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jumpifnot UNRESOLVED";
|
||||
} else {
|
||||
return "jumpifnot disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
61
contrib/bearssl/T0/OpcodeJumpUncond.cs
Normal file
61
contrib/bearssl/T0/OpcodeJumpUncond.cs
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpUncond : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpUncond() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpUncond(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Unconditional jumps do not "fall through" unless they
|
||||
* happen to be a jump to the next instruction...
|
||||
*/
|
||||
internal override bool MayFallThrough {
|
||||
get {
|
||||
return JumpDisp == 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(4);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jump UNRESOLVED";
|
||||
} else {
|
||||
return "jump disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
57
contrib/bearssl/T0/OpcodePutLocal.cs
Normal file
57
contrib/bearssl/T0/OpcodePutLocal.cs
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodePutLocal : Opcode {
|
||||
|
||||
int num;
|
||||
|
||||
internal OpcodePutLocal(int num)
|
||||
{
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.PutLocal(num, cpu.Pop());
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUIntUInt(3, (uint)num);
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "putlocal " + num;
|
||||
}
|
||||
}
|
50
contrib/bearssl/T0/OpcodeRet.cs
Normal file
50
contrib/bearssl/T0/OpcodeRet.cs
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeRet : Opcode {
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Exit();
|
||||
}
|
||||
|
||||
internal override bool MayFallThrough {
|
||||
get {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUInt(0);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "ret";
|
||||
}
|
||||
}
|
129
contrib/bearssl/T0/SType.cs
Normal file
129
contrib/bearssl/T0/SType.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
|
||||
/*
|
||||
* This structure contains the stack effect of a word: number of stack
|
||||
* element consumed on input, and number of stack element produced on
|
||||
* output.
|
||||
*/
|
||||
|
||||
struct SType {
|
||||
|
||||
/*
|
||||
* Get number of stack elements consumed on input; this is -1 if
|
||||
* the stack effect is not known.
|
||||
*/
|
||||
internal int DataIn {
|
||||
get {
|
||||
return din;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get number of stack elements produced on output; this is -1 if
|
||||
* either the stack effect is not known, or if the word never
|
||||
* exits.
|
||||
*/
|
||||
internal int DataOut {
|
||||
get {
|
||||
return dout;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell whether the stack effect is known.
|
||||
*/
|
||||
internal bool IsKnown {
|
||||
get {
|
||||
return din >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell whether the stack effect is known and the word never exits.
|
||||
*/
|
||||
internal bool NoExit {
|
||||
get {
|
||||
return din >= 0 && dout < 0;
|
||||
}
|
||||
}
|
||||
|
||||
int din, dout;
|
||||
|
||||
internal SType(int din, int dout)
|
||||
{
|
||||
if (din < 0) {
|
||||
din = -1;
|
||||
}
|
||||
if (dout < 0) {
|
||||
dout = -1;
|
||||
}
|
||||
this.din = din;
|
||||
this.dout = dout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special value for the unknown stack effect.
|
||||
*/
|
||||
internal static SType UNKNOWN = new SType(-1, -1);
|
||||
|
||||
/*
|
||||
* Constant for the "blank stack effect".
|
||||
*/
|
||||
internal static SType BLANK = new SType(0, 0);
|
||||
|
||||
public static bool operator ==(SType s1, SType s2)
|
||||
{
|
||||
return s1.din == s2.din && s1.dout == s2.dout;
|
||||
}
|
||||
|
||||
public static bool operator !=(SType s1, SType s2)
|
||||
{
|
||||
return s1.din != s2.din || s1.dout != s2.dout;
|
||||
}
|
||||
|
||||
public override bool Equals(Object obj)
|
||||
{
|
||||
return (obj is SType) && ((SType)obj == this);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return din * 31 + dout * 17;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (!IsKnown) {
|
||||
return "UNKNOWN";
|
||||
} else if (NoExit) {
|
||||
return string.Format("in:{0},noexit", din);
|
||||
} else {
|
||||
return string.Format("in:{0},out:{1}", din, dout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether this stack effect is a sub-effect of the provided
|
||||
* stack effect s. Stack effect s1 is a sub-effect of stack-effect
|
||||
* s2 if any of the following holds:
|
||||
* -- s1 and s2 are known, s1.din <= s2.din and s1 does not exit.
|
||||
* -- s1 and s2 are known, s1.din <= s2.din, s1 and s2 exit,
|
||||
* and s1.din - s1.dout == s2.din - s2.dout.
|
||||
*/
|
||||
internal bool IsSubOf(SType s)
|
||||
{
|
||||
if (!IsKnown || !s.IsKnown) {
|
||||
return false;
|
||||
}
|
||||
if (din > s.din) {
|
||||
return false;
|
||||
}
|
||||
if (NoExit) {
|
||||
return true;
|
||||
}
|
||||
if (s.NoExit) {
|
||||
return false;
|
||||
}
|
||||
return (din - dout) == (s.din - s.dout);
|
||||
}
|
||||
}
|
2123
contrib/bearssl/T0/T0Comp.cs
Normal file
2123
contrib/bearssl/T0/T0Comp.cs
Normal file
File diff suppressed because it is too large
Load Diff
64
contrib/bearssl/T0/TPointerBase.cs
Normal file
64
contrib/bearssl/T0/TPointerBase.cs
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerBase {
|
||||
|
||||
/* obsolete
|
||||
internal virtual TValue Get(TValue vp)
|
||||
{
|
||||
throw new Exception(
|
||||
"cannot get values from this pointer");
|
||||
}
|
||||
|
||||
internal virtual void Set(TValue vp, TValue nval)
|
||||
{
|
||||
throw new Exception(
|
||||
"cannot set values to this pointer");
|
||||
}
|
||||
*/
|
||||
|
||||
internal virtual bool ToBool(TValue vp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
internal virtual void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
throw new Exception("value is not an xt: " + ToString());
|
||||
}
|
||||
|
||||
internal virtual string ToString(TValue vp)
|
||||
{
|
||||
return String.Format("{0}+{1}",
|
||||
GetType().Name, vp.x);
|
||||
}
|
||||
|
||||
internal virtual bool Equals(TPointerBase tp)
|
||||
{
|
||||
return this == tp;
|
||||
}
|
||||
}
|
75
contrib/bearssl/T0/TPointerBlob.cs
Normal file
75
contrib/bearssl/T0/TPointerBlob.cs
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerBlob : TPointerBase {
|
||||
|
||||
internal ConstData Blob { get; private set; }
|
||||
|
||||
internal TPointerBlob(ConstData cd)
|
||||
{
|
||||
this.Blob = cd;
|
||||
}
|
||||
|
||||
internal TPointerBlob(T0Comp owner, string s)
|
||||
{
|
||||
Blob = new ConstData(owner);
|
||||
Blob.AddString(s);
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override TValue Get8(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read8(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get16(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read16(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get24(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read24(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get32(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read32(vp.x));
|
||||
}
|
||||
*/
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return Blob.ToString(vp.x);
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
TPointerBlob tb = tp as TPointerBlob;
|
||||
return tb != null && Blob == tb.Blob;
|
||||
}
|
||||
}
|
97
contrib/bearssl/T0/TPointerExpr.cs
Normal file
97
contrib/bearssl/T0/TPointerExpr.cs
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class TPointerExpr : TPointerBase {
|
||||
|
||||
string expr;
|
||||
int min, max;
|
||||
|
||||
internal TPointerExpr(string expr, int min, int max)
|
||||
{
|
||||
this.expr = expr;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
internal override bool ToBool(TValue vp)
|
||||
{
|
||||
throw new Exception("Cannot evaluate C-expr at compile time");
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return ToCExpr(vp.x);
|
||||
}
|
||||
|
||||
internal string ToCExpr(int off)
|
||||
{
|
||||
if (off == 0) {
|
||||
return expr;
|
||||
} else if (off > 0) {
|
||||
return String.Format(
|
||||
"(uint32_t)({0}) + {1}", expr, off);
|
||||
} else {
|
||||
return String.Format(
|
||||
"(uint32_t)({0}) - {1}", expr, -(long)off);
|
||||
}
|
||||
}
|
||||
|
||||
internal int GetMaxBitLength(int off)
|
||||
{
|
||||
long rmin = (long)min + off;
|
||||
long rmax = (long)max + off;
|
||||
int numBits = 1;
|
||||
if (rmin < 0) {
|
||||
numBits = Math.Max(numBits, BitLength(rmin));
|
||||
}
|
||||
if (rmax > 0) {
|
||||
numBits = Math.Max(numBits, BitLength(rmax));
|
||||
}
|
||||
return Math.Min(numBits, 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the minimal bit length of a value. This is for a signed
|
||||
* representation: the length includes a sign bit. Thus, the
|
||||
* returned value will be at least 1.
|
||||
*/
|
||||
static int BitLength(long v)
|
||||
{
|
||||
int num = 1;
|
||||
if (v < 0) {
|
||||
while (v != -1) {
|
||||
num ++;
|
||||
v >>= 1;
|
||||
}
|
||||
} else {
|
||||
while (v != 0) {
|
||||
num ++;
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
44
contrib/bearssl/T0/TPointerNull.cs
Normal file
44
contrib/bearssl/T0/TPointerNull.cs
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerNull : TPointerBase {
|
||||
|
||||
internal override bool ToBool(TValue vp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
return tp is TPointerNull;
|
||||
}
|
||||
}
|
73
contrib/bearssl/T0/TPointerXT.cs
Normal file
73
contrib/bearssl/T0/TPointerXT.cs
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerXT : TPointerBase {
|
||||
|
||||
internal string Name {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
internal Word Target {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
internal TPointerXT(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Target = null;
|
||||
}
|
||||
|
||||
internal TPointerXT(Word target)
|
||||
{
|
||||
this.Name = target.Name;
|
||||
this.Target = target;
|
||||
}
|
||||
|
||||
internal void Resolve(T0Comp ctx)
|
||||
{
|
||||
if (Target == null) {
|
||||
Target = ctx.Lookup(Name);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
Resolve(ctx);
|
||||
Target.Run(cpu);
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return String.Format("<'{0}>", Name);
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
TPointerXT tx = tp as TPointerXT;
|
||||
return tx != null && Name == tx.Name;
|
||||
}
|
||||
}
|
231
contrib/bearssl/T0/TValue.cs
Normal file
231
contrib/bearssl/T0/TValue.cs
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Each value is represented with a TValue structure. Integers use the 'x'
|
||||
* field, and 'ptr' is null; for pointers, the 'ptr' field is used, and the
|
||||
* 'x' is then an offset in the object represented by 'ptr'.
|
||||
*/
|
||||
|
||||
struct TValue {
|
||||
|
||||
internal int x;
|
||||
internal TPointerBase ptr;
|
||||
|
||||
internal TValue(int x)
|
||||
{
|
||||
this.x = x;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(uint x)
|
||||
{
|
||||
this.x = (int)x;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(bool b)
|
||||
{
|
||||
this.x = b ? -1 : 0;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(int x, TPointerBase ptr)
|
||||
{
|
||||
this.x = x;
|
||||
this.ptr = ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert this value to a boolean; integer 0 and null pointer are
|
||||
* 'false', other values are 'true'.
|
||||
*/
|
||||
internal bool Bool {
|
||||
get {
|
||||
if (ptr == null) {
|
||||
return x != 0;
|
||||
} else {
|
||||
return ptr.ToBool(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get this value as an integer. Pointers cannot be converted to
|
||||
* integers.
|
||||
*/
|
||||
internal int Int {
|
||||
get {
|
||||
if (ptr == null) {
|
||||
return x;
|
||||
}
|
||||
throw new Exception("not an integer: " + ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get this value as an unsigned integer. This is the integer
|
||||
* value, reduced modulo 2^32 in the 0..2^32-1 range.
|
||||
*/
|
||||
internal uint UInt {
|
||||
get {
|
||||
return (uint)Int;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* String format of integers uses decimal representation. For
|
||||
* pointers, this depends on the pointed-to value.
|
||||
*/
|
||||
public override string ToString()
|
||||
{
|
||||
if (ptr == null) {
|
||||
return String.Format("{0}", x);
|
||||
} else {
|
||||
return ptr.ToString(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this value is an XT, then execute it. Otherwise, an exception
|
||||
* is thrown.
|
||||
*/
|
||||
internal void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
ToXT().Execute(ctx, cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert this value to an XT. On failure, an exception is thrown.
|
||||
*/
|
||||
internal TPointerXT ToXT()
|
||||
{
|
||||
TPointerXT xt = ptr as TPointerXT;
|
||||
if (xt == null) {
|
||||
throw new Exception(
|
||||
"value is not an xt: " + ToString());
|
||||
}
|
||||
return xt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare this value to another.
|
||||
*/
|
||||
internal bool Equals(TValue v)
|
||||
{
|
||||
if (x != v.x) {
|
||||
return false;
|
||||
}
|
||||
if (ptr == v.ptr) {
|
||||
return true;
|
||||
}
|
||||
if (ptr == null || v.ptr == null) {
|
||||
return false;
|
||||
}
|
||||
return ptr.Equals(v.ptr);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(bool val)
|
||||
{
|
||||
return new TValue(val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(sbyte val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(byte val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(short val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(ushort val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(char val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(int val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(uint val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator bool(TValue v)
|
||||
{
|
||||
return v.Bool;
|
||||
}
|
||||
|
||||
public static implicit operator sbyte(TValue v)
|
||||
{
|
||||
return (sbyte)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator byte(TValue v)
|
||||
{
|
||||
return (byte)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator short(TValue v)
|
||||
{
|
||||
return (short)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator ushort(TValue v)
|
||||
{
|
||||
return (ushort)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator char(TValue v)
|
||||
{
|
||||
return (char)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator int(TValue v)
|
||||
{
|
||||
return (int)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator uint(TValue v)
|
||||
{
|
||||
return (uint)v.Int;
|
||||
}
|
||||
}
|
172
contrib/bearssl/T0/Word.cs
Normal file
172
contrib/bearssl/T0/Word.cs
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* A "word" is a function with a name. Words can be either native or
|
||||
* interpreted; native words are implemented as some in-compiler special
|
||||
* code.
|
||||
*
|
||||
* Some native words (not all of them) have a C implementation and can
|
||||
* thus be part of the generated C code. Native words with no C
|
||||
* implementation can be used only during compilation; this is typically
|
||||
* the case for words that support the syntax (e.g. 'if').
|
||||
*/
|
||||
|
||||
abstract class Word {
|
||||
|
||||
/*
|
||||
* The compiler context for this word.
|
||||
*/
|
||||
internal T0Comp TC {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Immediate words are executed immediately when encountered in the
|
||||
* source code, even while compiling another word.
|
||||
*/
|
||||
internal bool Immediate {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each word has a unique name. Names are case-sensitive.
|
||||
*/
|
||||
internal string Name {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Words are allocated slot numbers when output code is generated.
|
||||
*/
|
||||
internal int Slot {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each word may have a known stack effect.
|
||||
*/
|
||||
internal SType StackEffect {
|
||||
get; set;
|
||||
}
|
||||
|
||||
internal Word(T0Comp owner, string name)
|
||||
{
|
||||
TC = owner;
|
||||
Name = name;
|
||||
StackEffect = SType.UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolving a word means looking up all references to external
|
||||
* words.
|
||||
*/
|
||||
internal virtual void Resolve()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute this word. If the word is native, then its code is
|
||||
* run right away; if the word is interpreted, then the entry
|
||||
* sequence is executed.
|
||||
*/
|
||||
internal virtual void Run(CPU cpu)
|
||||
{
|
||||
throw new Exception(String.Format(
|
||||
"cannot run '{0}' at compile-time", Name));
|
||||
}
|
||||
|
||||
/*
|
||||
* All words may have an explicit C implementations. To be part
|
||||
* of the generated C code, a word must either be interpreted,
|
||||
* or have an explicit C implementation, or both.
|
||||
*/
|
||||
internal string CCode {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all words referenced from this one. This implies
|
||||
* resolving the word.
|
||||
*/
|
||||
internal virtual List<Word> GetReferences()
|
||||
{
|
||||
return new List<Word>();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all data blocks directly referenced from this one. This
|
||||
* implies resolving the word.
|
||||
*/
|
||||
internal virtual List<ConstData> GetDataBlocks()
|
||||
{
|
||||
return new List<ConstData>();
|
||||
}
|
||||
|
||||
/*
|
||||
* Produce the code elements for this word.
|
||||
*/
|
||||
internal virtual void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
throw new Exception("Word does not yield code elements");
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute/verify stack effect for this word.
|
||||
*/
|
||||
internal virtual void AnalyseFlow()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Get maximum data stack usage for this word. This is the number
|
||||
* of extra slots that this word may need on the data stack. If
|
||||
* the stack effect is not known, this returns -1.
|
||||
*/
|
||||
internal virtual int MaxDataStack {
|
||||
get {
|
||||
SType se = StackEffect;
|
||||
if (!se.IsKnown) {
|
||||
return -1;
|
||||
}
|
||||
if (se.NoExit) {
|
||||
return 0;
|
||||
} else {
|
||||
return Math.Min(0, se.DataOut - se.DataIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get maximum return stack usage for this word.
|
||||
*/
|
||||
internal virtual int MaxReturnStack {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
385
contrib/bearssl/T0/WordBuilder.cs
Normal file
385
contrib/bearssl/T0/WordBuilder.cs
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* A WordBuilder instance organizes construction of a new interpreted word.
|
||||
*
|
||||
* Opcodes are accumulated with specific methods. A control-flow stack
|
||||
* is maintained to resolve jumps.
|
||||
*
|
||||
* Each instance shall be used for only one word.
|
||||
*/
|
||||
|
||||
class WordBuilder {
|
||||
|
||||
T0Comp TC;
|
||||
string name;
|
||||
int[] cfStack;
|
||||
int cfPtr;
|
||||
List<Opcode> code;
|
||||
List<string> toResolve;
|
||||
Dictionary<string, int> locals;
|
||||
bool jumpToLast;
|
||||
|
||||
internal SType StackEffect {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new instance, with the specified word name.
|
||||
*/
|
||||
internal WordBuilder(T0Comp TC, string name)
|
||||
{
|
||||
this.TC = TC;
|
||||
this.name = name;
|
||||
cfStack = new int[16];
|
||||
cfPtr = -1;
|
||||
code = new List<Opcode>();
|
||||
toResolve = new List<string>();
|
||||
locals = new Dictionary<string, int>();
|
||||
jumpToLast = true;
|
||||
StackEffect = SType.UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the word. The control-flow stack must be empty. A 'ret'
|
||||
* opcode is automatically appended if required.
|
||||
*/
|
||||
internal Word Build()
|
||||
{
|
||||
if (cfPtr != -1) {
|
||||
throw new Exception("control-flow stack is not empty");
|
||||
}
|
||||
if (jumpToLast || code[code.Count - 1].MayFallThrough) {
|
||||
Ret();
|
||||
}
|
||||
Word w = new WordInterpreted(TC, name, locals.Count,
|
||||
code.ToArray(), toResolve.ToArray());
|
||||
w.StackEffect = StackEffect;
|
||||
return w;
|
||||
}
|
||||
|
||||
void Add(Opcode op)
|
||||
{
|
||||
Add(op, null);
|
||||
}
|
||||
|
||||
void Add(Opcode op, string refName)
|
||||
{
|
||||
code.Add(op);
|
||||
toResolve.Add(refName);
|
||||
jumpToLast = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate the control-flow stack at depth 'depth'.
|
||||
*/
|
||||
internal void CSRoll(int depth)
|
||||
{
|
||||
int x = cfStack[cfPtr - depth];
|
||||
Array.Copy(cfStack, cfPtr - (depth - 1),
|
||||
cfStack, cfPtr - depth, depth);
|
||||
cfStack[cfPtr] = x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a copy of the control-flow element at depth 'depth', and
|
||||
* push it on top of the control-flow stack.
|
||||
*/
|
||||
internal void CSPick(int depth)
|
||||
{
|
||||
int x = cfStack[cfPtr - depth];
|
||||
CSPush(x);
|
||||
}
|
||||
|
||||
void CSPush(int x)
|
||||
{
|
||||
int len = cfStack.Length;
|
||||
if (++ cfPtr == len) {
|
||||
int[] ncf = new int[len << 1];
|
||||
Array.Copy(cfStack, 0, ncf, 0, len);
|
||||
cfStack = ncf;
|
||||
}
|
||||
cfStack[cfPtr] = x;
|
||||
}
|
||||
|
||||
int CSPop()
|
||||
{
|
||||
return cfStack[cfPtr --];
|
||||
}
|
||||
|
||||
/*
|
||||
* Push an origin on the control-flow stack, corresponding to the
|
||||
* next opcode to add.
|
||||
*/
|
||||
internal void CSPushOrig()
|
||||
{
|
||||
CSPush(code.Count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a destination on the control-flow stack, corresponding to
|
||||
* the next opcode to add.
|
||||
*/
|
||||
internal void CSPushDest()
|
||||
{
|
||||
CSPush(-code.Count - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop an origin from the control-flow stack. An exception is
|
||||
* thrown if the value is not an origin.
|
||||
*/
|
||||
internal int CSPopOrig()
|
||||
{
|
||||
int x = CSPop();
|
||||
if (x < 0) {
|
||||
throw new Exception("not an origin");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a destination from the control-flow stack. An exception is
|
||||
* thrown if the value is not a destination.
|
||||
*/
|
||||
internal int CSPopDest()
|
||||
{
|
||||
int x = CSPop();
|
||||
if (x >= 0) {
|
||||
throw new Exception("not a destination");
|
||||
}
|
||||
return -x - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "push literal" opcode.
|
||||
*/
|
||||
internal void Literal(TValue v)
|
||||
{
|
||||
Add(new OpcodeConst(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile a "call" by name. This method implements the support
|
||||
* for local variables:
|
||||
*
|
||||
* - If the target is '>' followed by a local variable name, then
|
||||
* a "put local" opcode is added.
|
||||
*
|
||||
* - Otherwise, if the target is a local variable name, then a
|
||||
* "get local" opcode is added.
|
||||
*
|
||||
* - Otherwise, a call to the named word is added. The target name
|
||||
* will be resolved later on (typically, when the word containing
|
||||
* the call opcode is first invoked, or when C code is generated).
|
||||
*/
|
||||
internal void Call(string target)
|
||||
{
|
||||
string lname;
|
||||
bool write;
|
||||
if (target.StartsWith(">")) {
|
||||
lname = target.Substring(1);
|
||||
write = true;
|
||||
} else {
|
||||
lname = target;
|
||||
write = false;
|
||||
}
|
||||
int lnum;
|
||||
if (locals.TryGetValue(lname, out lnum)) {
|
||||
if (write) {
|
||||
Add(new OpcodePutLocal(lnum));
|
||||
} else {
|
||||
Add(new OpcodeGetLocal(lnum));
|
||||
}
|
||||
} else {
|
||||
Add(new OpcodeCall(), target);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode to the designated word.
|
||||
*/
|
||||
internal void CallExt(Word wtarget)
|
||||
{
|
||||
Add(new OpcodeCall(wtarget), null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode to a word which is not currently resolved.
|
||||
* This method ignores local variables.
|
||||
*/
|
||||
internal void CallExt(string target)
|
||||
{
|
||||
Add(new OpcodeCall(), target);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "get local" opcode; the provided local name must already
|
||||
* be defined.
|
||||
*/
|
||||
internal void GetLocal(string name)
|
||||
{
|
||||
int lnum;
|
||||
if (locals.TryGetValue(name, out lnum)) {
|
||||
Add(new OpcodeGetLocal(lnum));
|
||||
} else {
|
||||
throw new Exception("no such local: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "put local" opcode; the provided local name must already
|
||||
* be defined.
|
||||
*/
|
||||
internal void PutLocal(string name)
|
||||
{
|
||||
int lnum;
|
||||
if (locals.TryGetValue(name, out lnum)) {
|
||||
Add(new OpcodePutLocal(lnum));
|
||||
} else {
|
||||
throw new Exception("no such local: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a new local name.
|
||||
*/
|
||||
internal void DefLocal(string lname)
|
||||
{
|
||||
if (locals.ContainsKey(lname)) {
|
||||
throw new Exception(String.Format(
|
||||
"local already defined: {0}", lname));
|
||||
}
|
||||
locals[lname] = locals.Count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode whose target is an XT value (which may be
|
||||
* resolved or as yet unresolved).
|
||||
*/
|
||||
internal void Call(TPointerXT xt)
|
||||
{
|
||||
if (xt.Target == null) {
|
||||
Add(new OpcodeCall(), xt.Name);
|
||||
} else {
|
||||
Add(new OpcodeCall(xt.Target));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "ret" opcode.
|
||||
*/
|
||||
internal void Ret()
|
||||
{
|
||||
Add(new OpcodeRet());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward unconditional jump. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void Ahead()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpUncond());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'true'. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void AheadIf()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpIf());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'false'. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void AheadIfNot()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpIfNot());
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve a previous forward jump to the current code address.
|
||||
* The top of control-flow stack is popped and must be an origin.
|
||||
*/
|
||||
internal void Then()
|
||||
{
|
||||
int x = CSPopOrig();
|
||||
code[x].ResolveJump(code.Count - x - 1);
|
||||
jumpToLast = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push the current code address on the control-flow stack as a
|
||||
* destination, to be used by an ulterior backward jump.
|
||||
*/
|
||||
internal void Begin()
|
||||
{
|
||||
CSPushDest();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward unconditional jump. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void Again()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpUncond(x - code.Count - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'true'. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void AgainIf()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpIf(x - code.Count - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'false'. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void AgainIfNot()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpIfNot(x - code.Count - 1));
|
||||
}
|
||||
}
|
96
contrib/bearssl/T0/WordData.cs
Normal file
96
contrib/bearssl/T0/WordData.cs
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class WordData : Word {
|
||||
|
||||
ConstData blob;
|
||||
string baseBlobName;
|
||||
int offset;
|
||||
bool ongoingResolution;
|
||||
|
||||
internal WordData(T0Comp owner, string name,
|
||||
ConstData blob, int offset)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.blob = blob;
|
||||
this.offset = offset;
|
||||
StackEffect = new SType(0, 1);
|
||||
}
|
||||
|
||||
internal WordData(T0Comp owner, string name,
|
||||
string baseBlobName, int offset)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.baseBlobName = baseBlobName;
|
||||
this.offset = offset;
|
||||
StackEffect = new SType(0, 1);
|
||||
}
|
||||
|
||||
internal override void Resolve()
|
||||
{
|
||||
if (blob != null) {
|
||||
return;
|
||||
}
|
||||
if (ongoingResolution) {
|
||||
throw new Exception(String.Format(
|
||||
"circular reference in blobs ({0})", Name));
|
||||
}
|
||||
ongoingResolution = true;
|
||||
WordData wd = TC.Lookup(baseBlobName) as WordData;
|
||||
if (wd == null) {
|
||||
throw new Exception(String.Format(
|
||||
"data word '{0}' based on non-data word '{1}'",
|
||||
Name, baseBlobName));
|
||||
}
|
||||
wd.Resolve();
|
||||
blob = wd.blob;
|
||||
offset += wd.offset;
|
||||
ongoingResolution = false;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
Resolve();
|
||||
cpu.Push(new TValue(offset, new TPointerBlob(blob)));
|
||||
}
|
||||
|
||||
internal override List<ConstData> GetDataBlocks()
|
||||
{
|
||||
Resolve();
|
||||
List<ConstData> r = new List<ConstData>();
|
||||
r.Add(blob);
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
Resolve();
|
||||
dst.Add(new CodeElementUInt(0));
|
||||
dst.Add(new CodeElementUIntInt(1, blob.Address + offset));
|
||||
dst.Add(new CodeElementUInt(0));
|
||||
}
|
||||
}
|
283
contrib/bearssl/T0/WordInterpreted.cs
Normal file
283
contrib/bearssl/T0/WordInterpreted.cs
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* The implementation for interpreted words.
|
||||
*/
|
||||
|
||||
class WordInterpreted : Word {
|
||||
|
||||
/*
|
||||
* Get the number of local variables for this word.
|
||||
*/
|
||||
internal int NumLocals {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the sequence of opcodes for this word.
|
||||
*/
|
||||
internal Opcode[] Code {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
string[] toResolve;
|
||||
|
||||
internal WordInterpreted(T0Comp owner, string name,
|
||||
int numLocals, Opcode[] code, string[] toResolve)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.Code = code;
|
||||
this.toResolve = toResolve;
|
||||
NumLocals = numLocals;
|
||||
}
|
||||
|
||||
internal override void Resolve()
|
||||
{
|
||||
if (toResolve == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < toResolve.Length; i ++) {
|
||||
string tt = toResolve[i];
|
||||
if (tt == null) {
|
||||
continue;
|
||||
}
|
||||
Code[i].ResolveTarget(TC.Lookup(tt));
|
||||
}
|
||||
toResolve = null;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
Resolve();
|
||||
cpu.Enter(Code, NumLocals);
|
||||
}
|
||||
|
||||
internal override List<Word> GetReferences()
|
||||
{
|
||||
Resolve();
|
||||
List<Word> r = new List<Word>();
|
||||
foreach (Opcode op in Code) {
|
||||
Word w = op.GetReference(TC);
|
||||
if (w != null) {
|
||||
r.Add(w);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override List<ConstData> GetDataBlocks()
|
||||
{
|
||||
Resolve();
|
||||
List<ConstData> r = new List<ConstData>();
|
||||
foreach (Opcode op in Code) {
|
||||
ConstData cd = op.GetDataBlock(TC);
|
||||
if (cd != null) {
|
||||
r.Add(cd);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
Resolve();
|
||||
int n = Code.Length;
|
||||
CodeElement[] gcode = new CodeElement[n];
|
||||
for (int i = 0; i < n; i ++) {
|
||||
gcode[i] = Code[i].ToCodeElement();
|
||||
}
|
||||
for (int i = 0; i < n; i ++) {
|
||||
Code[i].FixUp(gcode, i);
|
||||
}
|
||||
dst.Add(new CodeElementUInt((uint)NumLocals));
|
||||
for (int i = 0; i < n; i ++) {
|
||||
dst.Add(gcode[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int flowAnalysis;
|
||||
int maxDataStack;
|
||||
int maxReturnStack;
|
||||
|
||||
bool MergeSA(int[] sa, int j, int c)
|
||||
{
|
||||
if (sa[j] == Int32.MinValue) {
|
||||
sa[j] = c;
|
||||
return true;
|
||||
} else if (sa[j] != c) {
|
||||
throw new Exception(string.Format(
|
||||
"In word '{0}', offset {1}:"
|
||||
+ " stack action mismatch ({2} / {3})",
|
||||
Name, j, sa[j], c));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void AnalyseFlow()
|
||||
{
|
||||
switch (flowAnalysis) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
return;
|
||||
default:
|
||||
throw new Exception("recursive call detected in '"
|
||||
+ Name + "'");
|
||||
}
|
||||
flowAnalysis = 2;
|
||||
int n = Code.Length;
|
||||
int[] sa = new int[n];
|
||||
for (int i = 0; i < n; i ++) {
|
||||
sa[i] = Int32.MinValue;
|
||||
}
|
||||
sa[0] = 0;
|
||||
int[] toExplore = new int[n];
|
||||
int tX = 0, tY = 0;
|
||||
int off = 0;
|
||||
|
||||
int exitSA = Int32.MinValue;
|
||||
int mds = 0;
|
||||
int mrs = 0;
|
||||
|
||||
int maxDepth = 0;
|
||||
|
||||
for (;;) {
|
||||
Opcode op = Code[off];
|
||||
bool mft = op.MayFallThrough;
|
||||
int c = sa[off];
|
||||
int a;
|
||||
if (op is OpcodeCall) {
|
||||
Word w = op.GetReference(TC);
|
||||
w.AnalyseFlow();
|
||||
SType se = w.StackEffect;
|
||||
if (!se.IsKnown) {
|
||||
throw new Exception(string.Format(
|
||||
"call from '{0}' to '{1}'"
|
||||
+ " with unknown stack effect",
|
||||
Name, w.Name));
|
||||
}
|
||||
if (se.NoExit) {
|
||||
mft = false;
|
||||
a = 0;
|
||||
} else {
|
||||
a = se.DataOut - se.DataIn;
|
||||
}
|
||||
mds = Math.Max(mds, c + w.MaxDataStack);
|
||||
mrs = Math.Max(mrs, w.MaxReturnStack);
|
||||
maxDepth = Math.Min(maxDepth, c - se.DataIn);
|
||||
} else if (op is OpcodeRet) {
|
||||
if (exitSA == Int32.MinValue) {
|
||||
exitSA = c;
|
||||
} else if (exitSA != c) {
|
||||
throw new Exception(string.Format(
|
||||
"'{0}': exit stack action"
|
||||
+ " mismatch: {1} / {2}"
|
||||
+ " (offset {3})",
|
||||
Name, exitSA, c, off));
|
||||
}
|
||||
a = 0;
|
||||
} else {
|
||||
a = op.StackAction;
|
||||
mds = Math.Max(mds, c + a);
|
||||
}
|
||||
c += a;
|
||||
maxDepth = Math.Min(maxDepth, c);
|
||||
|
||||
int j = op.JumpDisp;
|
||||
if (j != 0) {
|
||||
j += off + 1;
|
||||
toExplore[tY ++] = j;
|
||||
MergeSA(sa, j, c);
|
||||
}
|
||||
off ++;
|
||||
if (!mft || !MergeSA(sa, off, c)) {
|
||||
if (tX < tY) {
|
||||
off = toExplore[tX ++];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxDataStack = mds;
|
||||
maxReturnStack = 1 + NumLocals + mrs;
|
||||
|
||||
/*
|
||||
* TODO: see about this warning. Usage of a 'fail'
|
||||
* word (that does not exit) within a 'case..endcase'
|
||||
* structure will make an unreachable opcode. In a future
|
||||
* version we might want to automatically remove dead
|
||||
* opcodes.
|
||||
for (int i = 0; i < n; i ++) {
|
||||
if (sa[i] == Int32.MinValue) {
|
||||
Console.WriteLine("warning: word '{0}',"
|
||||
+ " offset {1}: unreachable opcode",
|
||||
Name, i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
SType computed;
|
||||
if (exitSA == Int32.MinValue) {
|
||||
computed = new SType(-maxDepth, -1);
|
||||
} else {
|
||||
computed = new SType(-maxDepth, -maxDepth + exitSA);
|
||||
}
|
||||
|
||||
if (StackEffect.IsKnown) {
|
||||
if (!computed.IsSubOf(StackEffect)) {
|
||||
throw new Exception(string.Format(
|
||||
"word '{0}':"
|
||||
+ " computed stack effect {1}"
|
||||
+ " does not match declared {2}",
|
||||
Name, computed.ToString(),
|
||||
StackEffect.ToString()));
|
||||
}
|
||||
} else {
|
||||
StackEffect = computed;
|
||||
}
|
||||
|
||||
flowAnalysis = 1;
|
||||
}
|
||||
|
||||
internal override int MaxDataStack {
|
||||
get {
|
||||
AnalyseFlow();
|
||||
return maxDataStack;
|
||||
}
|
||||
}
|
||||
|
||||
internal override int MaxReturnStack {
|
||||
get {
|
||||
AnalyseFlow();
|
||||
return maxReturnStack;
|
||||
}
|
||||
}
|
||||
}
|
59
contrib/bearssl/T0/WordNative.cs
Normal file
59
contrib/bearssl/T0/WordNative.cs
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Class for native words.
|
||||
*/
|
||||
|
||||
class WordNative : Word {
|
||||
|
||||
/*
|
||||
* A type for the native implementation: a method that takes a
|
||||
* CPU as parameter, and returns nothing.
|
||||
*/
|
||||
internal delegate void NativeRun(CPU cpu);
|
||||
|
||||
NativeRun code;
|
||||
|
||||
internal WordNative(T0Comp owner, string name, NativeRun code)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
internal WordNative(T0Comp owner, string name,
|
||||
SType stackEffect, NativeRun code)
|
||||
: this(owner, name, code)
|
||||
{
|
||||
StackEffect = stackEffect;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
code(cpu);
|
||||
}
|
||||
}
|
309
contrib/bearssl/T0/kern.t0
Normal file
309
contrib/bearssl/T0/kern.t0
Normal file
@ -0,0 +1,309 @@
|
||||
: \ `\n parse drop ; immediate
|
||||
|
||||
\ This file defines the core non-native functions (mainly used for
|
||||
\ parsing words, i.e. not part of the generated output). The line above
|
||||
\ defines the syntax for comments.
|
||||
|
||||
\ Define parenthesis comments.
|
||||
\ : ( `) parse drop ; immediate
|
||||
|
||||
: else postpone ahead 1 cs-roll postpone then ; immediate
|
||||
: while postpone if 1 cs-roll ; immediate
|
||||
: repeat postpone again postpone then ; immediate
|
||||
|
||||
: ['] ' ; immediate
|
||||
: [compile] compile ; immediate
|
||||
|
||||
: 2drop drop drop ;
|
||||
: dup2 over over ;
|
||||
|
||||
\ Local variables are defined with the native word '(local)'. We define
|
||||
\ a helper construction that mimics what is found in Apple's Open Firmware
|
||||
\ implementation. The syntax is: { a b ... ; c d ... }
|
||||
\ I.e. there is an opening brace, then some names. Names appearing before
|
||||
\ the semicolon are locals that are both defined and then filled with the
|
||||
\ values on stack (in stack order: { a b } fills 'b' with the top-of-stack,
|
||||
\ and 'a' with the value immediately below). Names appearing after the
|
||||
\ semicolon are not initialized.
|
||||
: __deflocal ( from_stack name -- )
|
||||
dup (local) swap if
|
||||
compile-local-write
|
||||
else
|
||||
drop
|
||||
then ;
|
||||
: __deflocals ( from_stack -- )
|
||||
next-word
|
||||
dup "}" eqstr if
|
||||
2drop ret
|
||||
then
|
||||
dup ";" eqstr if
|
||||
2drop 0 __deflocals ret
|
||||
then
|
||||
over __deflocals
|
||||
__deflocal ;
|
||||
: {
|
||||
-1 __deflocals ; immediate
|
||||
|
||||
\ Data building words.
|
||||
: data:
|
||||
new-data-block next-word define-data-word ;
|
||||
: hexb|
|
||||
0 0 { acc z }
|
||||
begin
|
||||
char
|
||||
dup `| = if
|
||||
z if "Truncated hexadecimal byte" puts cr exitvm then
|
||||
ret
|
||||
then
|
||||
dup 0x20 > if
|
||||
hexval
|
||||
z if acc 4 << + data-add8 else >acc then
|
||||
z not >z
|
||||
then
|
||||
again ;
|
||||
|
||||
\ Convert hexadecimal character to number. Complain loudly if conversion
|
||||
\ is not possible.
|
||||
: hexval ( char -- x )
|
||||
hexval-nf dup 0 < if "Not an hex digit: " puts . cr exitvm then ;
|
||||
|
||||
\ Convert hexadecimal character to number. If not an hexadecimal digit,
|
||||
\ return -1.
|
||||
: hexval-nf ( char -- x )
|
||||
dup dup `0 >= swap `9 <= and if `0 - ret then
|
||||
dup dup `A >= swap `F <= and if `A - 10 + ret then
|
||||
dup dup `a >= swap `f <= and if `a - 10 + ret then
|
||||
drop -1 ;
|
||||
|
||||
\ Convert decimal character to number. Complain loudly if conversion
|
||||
\ is not possible.
|
||||
: decval ( char -- x )
|
||||
decval-nf dup 0 < if "Not a decimal digit: " puts . cr exitvm then ;
|
||||
|
||||
\ Convert decimal character to number. If not a decimal digit,
|
||||
\ return -1.
|
||||
: decval-nf ( char -- x )
|
||||
dup dup `0 >= swap `9 <= and if `0 - ret then
|
||||
drop -1 ;
|
||||
|
||||
\ Commonly used shorthands.
|
||||
: 1+ 1 + ;
|
||||
: 2+ 2 + ;
|
||||
: 1- 1 - ;
|
||||
: 2- 2 - ;
|
||||
: 0= 0 = ;
|
||||
: 0<> 0 <> ;
|
||||
: 0< 0 < ;
|
||||
: 0> 0 > ;
|
||||
|
||||
\ Get a 16-bit value from the constant data block. This uses big-endian
|
||||
\ encoding.
|
||||
: data-get16 ( addr -- x )
|
||||
dup data-get8 8 << swap 1+ data-get8 + ;
|
||||
|
||||
\ The case..endcase construction is the equivalent of 'switch' is C.
|
||||
\ Usage:
|
||||
\ case
|
||||
\ E1 of C1 endof
|
||||
\ E2 of C2 endof
|
||||
\ ...
|
||||
\ CN
|
||||
\ endcase
|
||||
\
|
||||
\ Upon entry, it considers the TOS (let's call it X). It will then evaluate
|
||||
\ E1, which should yield a single value Y1; at that point, the X value is
|
||||
\ still on the stack, just below Y1, and must remain untouched. The 'of'
|
||||
\ word compares X with Y1; if they are equal, C1 is executed, and then
|
||||
\ control jumps to after the 'endcase'. The X value is popped from the
|
||||
\ stack immediately before evaluating C1.
|
||||
\
|
||||
\ If X and Y1 are not equal, flow proceeds to E2, to obtain a value Y2 to
|
||||
\ compare with X. And so on.
|
||||
\
|
||||
\ If none of the 'of' clauses found a match, then CN is evaluated. When CN
|
||||
\ is evaluated, the X value is on the TOS, and CN must either leave it on
|
||||
\ the stack, or replace it with exactly one value; the 'endcase' word
|
||||
\ expects (and drops) one value.
|
||||
\
|
||||
\ Implementation: this is mostly copied from ANS Forth specification,
|
||||
\ although simplified a bit because we know that our control-flow stack
|
||||
\ is independent of the data stack. During compilation, the number of
|
||||
\ clauses is maintained on the stack; each of..endof clause really is
|
||||
\ an 'if..else' that must be terminated with a matching 'then' in 'endcase'.
|
||||
|
||||
: case 0 ; immediate
|
||||
: of 1+ postpone over postpone = postpone if postpone drop ; immediate
|
||||
: endof postpone else ; immediate
|
||||
: endcase
|
||||
postpone drop
|
||||
begin dup while 1- postpone then repeat drop ; immediate
|
||||
|
||||
\ A simpler and more generic "case": there is no management for a value
|
||||
\ on the stack, and each test is supposed to come up with its own boolean
|
||||
\ value.
|
||||
: choice 0 ; immediate
|
||||
: uf 1+ postpone if ; immediate
|
||||
: ufnot 1+ postpone ifnot ; immediate
|
||||
: enduf postpone else ; immediate
|
||||
: endchoice begin dup while 1- postpone then repeat drop ; immediate
|
||||
|
||||
\ C implementations for native words that can be used in generated code.
|
||||
add-cc: co { T0_CO(); }
|
||||
add-cc: execute { T0_ENTER(ip, rp, T0_POP()); }
|
||||
add-cc: drop { (void)T0_POP(); }
|
||||
add-cc: dup { T0_PUSH(T0_PEEK(0)); }
|
||||
add-cc: swap { T0_SWAP(); }
|
||||
add-cc: over { T0_PUSH(T0_PEEK(1)); }
|
||||
add-cc: rot { T0_ROT(); }
|
||||
add-cc: -rot { T0_NROT(); }
|
||||
add-cc: roll { T0_ROLL(T0_POP()); }
|
||||
add-cc: pick { T0_PICK(T0_POP()); }
|
||||
add-cc: + {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a + b);
|
||||
}
|
||||
add-cc: - {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a - b);
|
||||
}
|
||||
add-cc: neg {
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-a);
|
||||
}
|
||||
add-cc: * {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a * b);
|
||||
}
|
||||
add-cc: / {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSHi(a / b);
|
||||
}
|
||||
add-cc: u/ {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a / b);
|
||||
}
|
||||
add-cc: % {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSHi(a % b);
|
||||
}
|
||||
add-cc: u% {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a % b);
|
||||
}
|
||||
add-cc: < {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
}
|
||||
add-cc: <= {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
}
|
||||
add-cc: > {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a > b));
|
||||
}
|
||||
add-cc: >= {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
}
|
||||
add-cc: = {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a == b));
|
||||
}
|
||||
add-cc: <> {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a != b));
|
||||
}
|
||||
add-cc: u< {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
}
|
||||
add-cc: u<= {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
}
|
||||
add-cc: u> {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a > b));
|
||||
}
|
||||
add-cc: u>= {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
}
|
||||
add-cc: and {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a & b);
|
||||
}
|
||||
add-cc: or {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a | b);
|
||||
}
|
||||
add-cc: xor {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a ^ b);
|
||||
}
|
||||
add-cc: not {
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(~a);
|
||||
}
|
||||
add-cc: << {
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x << c);
|
||||
}
|
||||
add-cc: >> {
|
||||
int c = (int)T0_POPi();
|
||||
int32_t x = T0_POPi();
|
||||
T0_PUSHi(x >> c);
|
||||
}
|
||||
add-cc: u>> {
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x >> c);
|
||||
}
|
||||
add-cc: data-get8 {
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(t0_datablock[addr]);
|
||||
}
|
||||
|
||||
add-cc: . {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf(" %ld", (long)T0_POPi());
|
||||
}
|
||||
add-cc: putc {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("%c", (char)T0_POPi());
|
||||
}
|
||||
add-cc: puts {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("%s", &t0_datablock[T0_POPi()]);
|
||||
}
|
||||
add-cc: cr {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("\n");
|
||||
}
|
||||
add-cc: eqstr {
|
||||
const void *b = &t0_datablock[T0_POPi()];
|
||||
const void *a = &t0_datablock[T0_POPi()];
|
||||
T0_PUSH(-(int32_t)(strcmp(a, b) == 0));
|
||||
}
|
BIN
contrib/bearssl/T0Comp.exe
Executable file
BIN
contrib/bearssl/T0Comp.exe
Executable file
Binary file not shown.
0
contrib/bearssl/build/.do_not_remove
Normal file
0
contrib/bearssl/build/.do_not_remove
Normal file
69
contrib/bearssl/conf/Unix.mk
Normal file
69
contrib/bearssl/conf/Unix.mk
Normal file
@ -0,0 +1,69 @@
|
||||
# Configuration for a native build on a generic Unix-like system.
|
||||
|
||||
# Build directory.
|
||||
BUILD = build
|
||||
|
||||
# Extension for executable files.
|
||||
E =
|
||||
|
||||
# Extension for object files.
|
||||
O = .o
|
||||
|
||||
# Prefix for library file name.
|
||||
LP = lib
|
||||
|
||||
# Extension for library file name.
|
||||
L = .a
|
||||
|
||||
# Prefix for DLL file name.
|
||||
DP = lib
|
||||
|
||||
# Extension for DLL file name.
|
||||
D = .so
|
||||
|
||||
# Output file names can be overridden directly. By default, they are
|
||||
# assembled using the prefix/extension macros defined above.
|
||||
# BEARSSLLIB = libbearssl.a
|
||||
# BEARSSLDLL = libbearssl.so
|
||||
# BRSSL = brssl
|
||||
# TESTCRYPTO = testcrypto
|
||||
# TESTSPEED = testspeed
|
||||
# TESTX509 = testx509
|
||||
|
||||
# File deletion tool.
|
||||
RM = rm -f
|
||||
|
||||
# Directory creation tool.
|
||||
MKDIR = mkdir -p
|
||||
|
||||
# C compiler and flags.
|
||||
CC = cc
|
||||
CFLAGS = -W -Wall -Os -fPIC
|
||||
CCOUT = -c -o
|
||||
|
||||
# Static library building tool.
|
||||
AR = ar
|
||||
ARFLAGS = -rcs
|
||||
AROUT =
|
||||
|
||||
# DLL building tool.
|
||||
LDDLL = cc
|
||||
LDDLLFLAGS = -shared
|
||||
LDDLLOUT = -o
|
||||
|
||||
# Static linker.
|
||||
LD = cc
|
||||
LDFLAGS =
|
||||
LDOUT = -o
|
||||
|
||||
# C# compiler; we assume usage of Mono.
|
||||
MKT0COMP = mk$PmkT0.sh
|
||||
RUNT0COMP = mono T0Comp.exe
|
||||
|
||||
# Set the values to 'no' to disable building of the corresponding element
|
||||
# by default. Building can still be invoked with an explicit target call
|
||||
# (e.g. 'make dll' to force build the DLL).
|
||||
#STATICLIB = no
|
||||
#DLL = no
|
||||
#TOOLS = no
|
||||
#TESTS = no
|
12
contrib/bearssl/conf/Unix32.mk
Normal file
12
contrib/bearssl/conf/Unix32.mk
Normal file
@ -0,0 +1,12 @@
|
||||
# Example configuration file for compiling on a Unix-like system with
|
||||
# GCC, targeting a 32-bit output. Moreover, it enables the "LOMUL" setting
|
||||
# to make the code select the "small" integer implementations (i15, m15,
|
||||
# ctmul32...), which is not necessarily a good idea for performance, but
|
||||
# handy for tests.
|
||||
|
||||
include conf/Unix.mk
|
||||
|
||||
BUILD = build32
|
||||
CFLAGS = -W -Wall -Os -fPIC -m32 -DBR_LOMUL
|
||||
LDFLAGS = -m32
|
||||
LDDLLFLAGS = -shared -m32
|
11
contrib/bearssl/conf/UnixClang.mk
Normal file
11
contrib/bearssl/conf/UnixClang.mk
Normal file
@ -0,0 +1,11 @@
|
||||
# Example configuration file for compiling on a Unix-like system with
|
||||
# clang as compiler instead of gcc.
|
||||
|
||||
# We are on a Unix system so we assume a Single Unix compatible 'make'
|
||||
# utility, and Unix defaults.
|
||||
include conf/Unix.mk
|
||||
|
||||
BUILD = bclang
|
||||
CC = clang
|
||||
LD = clang
|
||||
LDDLL = clang
|
70
contrib/bearssl/conf/Win.mk
Normal file
70
contrib/bearssl/conf/Win.mk
Normal file
@ -0,0 +1,70 @@
|
||||
# Configuration for a native build on a Windows system with Visual Studio.
|
||||
|
||||
# Build directory.
|
||||
BUILD = build
|
||||
|
||||
# Extension for executable files.
|
||||
E = .exe
|
||||
|
||||
# Extension for object files.
|
||||
O = .obj
|
||||
|
||||
# Prefix for static library file name.
|
||||
LP =
|
||||
|
||||
# Extension for static library file name. We add an 's' so that the
|
||||
# name is distinct from the 'import library' generated along with the DLL.
|
||||
L = s.lib
|
||||
|
||||
# Prefix for DLL file name.
|
||||
DP =
|
||||
|
||||
# Extension for DLL file name.
|
||||
D = .dll
|
||||
|
||||
# Output file names can be overridden directly. By default, they are
|
||||
# assembled using the prefix/extension macros defined above.
|
||||
# BEARSSLLIB = bearssls.lib
|
||||
# BEARSSLDLL = bearssl.dll
|
||||
# BRSSL = brssl.exe
|
||||
# TESTCRYPTO = testcrypto.exe
|
||||
# TESTSPEED = testspeed.exe
|
||||
# TESTX509 = testx509.exe
|
||||
|
||||
# File deletion tool.
|
||||
RM = del /Q
|
||||
|
||||
# Directory creation tool.
|
||||
MKDIR = mkdir
|
||||
|
||||
# C compiler and flags.
|
||||
CC = cl
|
||||
CFLAGS = -nologo -W2 -O2
|
||||
CCOUT = -c -Fo
|
||||
|
||||
# Static library building tool.
|
||||
AR = lib
|
||||
ARFLAGS = -nologo
|
||||
AROUT = -out:
|
||||
|
||||
# DLL building tool.
|
||||
LDDLL = cl
|
||||
LDDLLFLAGS = -nologo -LD -MT
|
||||
LDDLLOUT = -Fe
|
||||
|
||||
# Static linker.
|
||||
LD = cl
|
||||
LDFLAGS = -nologo
|
||||
LDOUT = -Fe
|
||||
|
||||
# C# compiler.
|
||||
MKT0COMP = mk$PmkT0.cmd
|
||||
RUNT0COMP = T0Comp.exe
|
||||
|
||||
# Set the values to 'no' to disable building of the corresponding element
|
||||
# by default. Building can still be invoked with an explicit target call
|
||||
# (e.g. 'make dll' to force build the DLL).
|
||||
#STATICLIB = no
|
||||
#DLL = no
|
||||
#TOOLS = no
|
||||
#TESTS = no
|
20
contrib/bearssl/conf/samd20.mk
Normal file
20
contrib/bearssl/conf/samd20.mk
Normal file
@ -0,0 +1,20 @@
|
||||
# Example configuration file for compiling for an Atmel SAM D20 Xplained
|
||||
# Pro evaluation kit, on a Unix-like system, with a GNU toolchain.
|
||||
|
||||
# We are on a Unix system so we assume a Single Unix compatible 'make'
|
||||
# utility, and Unix defaults.
|
||||
include conf/Unix.mk
|
||||
|
||||
# We override the build directory.
|
||||
BUILD = samd20
|
||||
|
||||
# C compiler, linker, and static library builder.
|
||||
CC = arm-none-eabi-gcc
|
||||
CFLAGS = -W -Wall -Os -mthumb -ffunction-sections -fdata-sections -mcpu=cortex-m0plus -DBR_ARMEL_CORTEXM_GCC
|
||||
LD = arm-none-eabi-gcc
|
||||
AR = arm-none-eabi-ar
|
||||
|
||||
# We compile only the static library.
|
||||
DLL = no
|
||||
TOOLS = no
|
||||
TESTS = no
|
170
contrib/bearssl/inc/bearssl.h
Normal file
170
contrib/bearssl/inc/bearssl.h
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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 BR_BEARSSL_H__
|
||||
#define BR_BEARSSL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** \mainpage BearSSL API
|
||||
*
|
||||
* # API Layout
|
||||
*
|
||||
* The functions and structures defined by the BearSSL API are located
|
||||
* in various header files:
|
||||
*
|
||||
* | Header file | Elements |
|
||||
* | :-------------- | :------------------------------------------------ |
|
||||
* | bearssl_hash.h | Hash functions |
|
||||
* | bearssl_hmac.h | HMAC |
|
||||
* | bearssl_kdf.h | Key Derivation Functions |
|
||||
* | bearssl_rand.h | Pseudorandom byte generators |
|
||||
* | bearssl_prf.h | PRF implementations (for SSL/TLS) |
|
||||
* | bearssl_block.h | Symmetric encryption |
|
||||
* | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) |
|
||||
* | bearssl_rsa.h | RSA encryption and signatures |
|
||||
* | bearssl_ec.h | Elliptic curves support (including ECDSA) |
|
||||
* | bearssl_ssl.h | SSL/TLS engine interface |
|
||||
* | bearssl_x509.h | X.509 certificate decoding and validation |
|
||||
* | bearssl_pem.h | Base64/PEM decoding support functions |
|
||||
*
|
||||
* Applications using BearSSL are supposed to simply include `bearssl.h`
|
||||
* as follows:
|
||||
*
|
||||
* #include <bearssl.h>
|
||||
*
|
||||
* The `bearssl.h` file itself includes all the other header files. It is
|
||||
* possible to include specific header files, but it has no practical
|
||||
* advantage for the application. The API is separated into separate
|
||||
* header files only for documentation convenience.
|
||||
*
|
||||
*
|
||||
* # Conventions
|
||||
*
|
||||
* ## MUST and SHALL
|
||||
*
|
||||
* In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology
|
||||
* is used. Failure to meet requirements expressed with a "MUST" or
|
||||
* "SHALL" implies undefined behaviour, which means that segmentation
|
||||
* faults, buffer overflows, and other similar adverse events, may occur.
|
||||
*
|
||||
* In general, BearSSL is not very forgiving of programming errors, and
|
||||
* does not include much failsafes or error reporting when the problem
|
||||
* does not arise from external transient conditions, and can be fixed
|
||||
* only in the application code. This is done so in order to make the
|
||||
* total code footprint lighter.
|
||||
*
|
||||
*
|
||||
* ## `NULL` values
|
||||
*
|
||||
* Function parameters with a pointer type shall not be `NULL` unless
|
||||
* explicitly authorised by the documentation. As an exception, when
|
||||
* the pointer aims at a sequence of bytes and is accompanied with
|
||||
* a length parameter, and the length is zero (meaning that there is
|
||||
* no byte at all to retrieve), then the pointer may be `NULL` even if
|
||||
* not explicitly allowed.
|
||||
*
|
||||
*
|
||||
* ## Memory Allocation
|
||||
*
|
||||
* BearSSL does not perform dynamic memory allocation. This implies that
|
||||
* for any functionality that requires a non-transient state, the caller
|
||||
* is responsible for allocating the relevant context structure. Such
|
||||
* allocation can be done in any appropriate area, including static data
|
||||
* segments, the heap, and the stack, provided that proper alignment is
|
||||
* respected. The header files define these context structures
|
||||
* (including size and contents), so the C compiler should handle
|
||||
* alignment automatically.
|
||||
*
|
||||
* Since there is no dynamic resource allocation, there is also nothing to
|
||||
* release. When the calling code is done with a BearSSL feature, it
|
||||
* may simple release the context structures it allocated itself, with
|
||||
* no "close function" to call. If the context structures were allocated
|
||||
* on the stack (as local variables), then even that release operation is
|
||||
* implicit.
|
||||
*
|
||||
*
|
||||
* ## Structure Contents
|
||||
*
|
||||
* Except when explicitly indicated, structure contents are opaque: they
|
||||
* are included in the header files so that calling code may know the
|
||||
* structure sizes and alignment requirements, but callers SHALL NOT
|
||||
* access individual fields directly. For fields that are supposed to
|
||||
* be read from or written to, the API defines accessor functions (the
|
||||
* simplest of these accessor functions are defined as `static inline`
|
||||
* functions, and the C compiler will optimise them away).
|
||||
*
|
||||
*
|
||||
* # API Usage
|
||||
*
|
||||
* BearSSL usage for running a SSL/TLS client or server is described
|
||||
* on the [BearSSL Web site](https://www.bearssl.org/api1.html). The
|
||||
* BearSSL source archive also comes with sample code.
|
||||
*/
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
#include "bearssl_kdf.h"
|
||||
#include "bearssl_rand.h"
|
||||
#include "bearssl_prf.h"
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_aead.h"
|
||||
#include "bearssl_rsa.h"
|
||||
#include "bearssl_ec.h"
|
||||
#include "bearssl_ssl.h"
|
||||
#include "bearssl_x509.h"
|
||||
#include "bearssl_pem.h"
|
||||
|
||||
/** \brief Type for a configuration option.
|
||||
*
|
||||
* A "configuration option" is a value that is selected when the BearSSL
|
||||
* library itself is compiled. Most options are boolean; their value is
|
||||
* then either 1 (option is enabled) or 0 (option is disabled). Some
|
||||
* values have other integer values. Option names correspond to macro
|
||||
* names. Some of the options can be explicitly set in the internal
|
||||
* `"config.h"` file.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Configurable option name. */
|
||||
const char *name;
|
||||
/** \brief Configurable option value. */
|
||||
long value;
|
||||
} br_config_option;
|
||||
|
||||
/** \brief Get configuration report.
|
||||
*
|
||||
* This function returns compiled configuration options, each as a
|
||||
* 'long' value. Names match internal macro names, in particular those
|
||||
* that can be set in the `"config.h"` inner file. For boolean options,
|
||||
* the numerical value is 1 if enabled, 0 if disabled. For maximum
|
||||
* key sizes, values are expressed in bits.
|
||||
*
|
||||
* The returned array is terminated by an entry whose `name` is `NULL`.
|
||||
*
|
||||
* \return the configuration report.
|
||||
*/
|
||||
const br_config_option *br_get_config(void);
|
||||
|
||||
#endif
|
1059
contrib/bearssl/inc/bearssl_aead.h
Normal file
1059
contrib/bearssl/inc/bearssl_aead.h
Normal file
File diff suppressed because it is too large
Load Diff
2618
contrib/bearssl/inc/bearssl_block.h
Normal file
2618
contrib/bearssl/inc/bearssl_block.h
Normal file
File diff suppressed because it is too large
Load Diff
967
contrib/bearssl/inc/bearssl_ec.h
Normal file
967
contrib/bearssl/inc/bearssl_ec.h
Normal file
@ -0,0 +1,967 @@
|
||||
/*
|
||||
* 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 BR_BEARSSL_EC_H__
|
||||
#define BR_BEARSSL_EC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_rand.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_ec.h
|
||||
*
|
||||
* # Elliptic Curves
|
||||
*
|
||||
* This file documents the EC implementations provided with BearSSL, and
|
||||
* ECDSA.
|
||||
*
|
||||
* ## Elliptic Curve API
|
||||
*
|
||||
* Only "named curves" are supported. Each EC implementation supports
|
||||
* one or several named curves, identified by symbolic identifiers.
|
||||
* These identifiers are small integers, that correspond to the values
|
||||
* registered by the
|
||||
* [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
|
||||
*
|
||||
* Since all currently defined elliptic curve identifiers are in the 0..31
|
||||
* range, it is convenient to encode support of some curves in a 32-bit
|
||||
* word, such that bit x corresponds to curve of identifier x.
|
||||
*
|
||||
* An EC implementation is incarnated by a `br_ec_impl` instance, that
|
||||
* offers the following fields:
|
||||
*
|
||||
* - `supported_curves`
|
||||
*
|
||||
* A 32-bit word that documents the identifiers of the curves supported
|
||||
* by this implementation.
|
||||
*
|
||||
* - `generator()`
|
||||
*
|
||||
* Callback method that returns a pointer to the conventional generator
|
||||
* point for that curve.
|
||||
*
|
||||
* - `order()`
|
||||
*
|
||||
* Callback method that returns a pointer to the subgroup order for
|
||||
* that curve. That value uses unsigned big-endian encoding.
|
||||
*
|
||||
* - `xoff()`
|
||||
*
|
||||
* Callback method that returns the offset and length of the X
|
||||
* coordinate in an encoded point.
|
||||
*
|
||||
* - `mul()`
|
||||
*
|
||||
* Multiply a curve point with an integer.
|
||||
*
|
||||
* - `mulgen()`
|
||||
*
|
||||
* Multiply the curve generator with an integer. This may be faster
|
||||
* than the generic `mul()`.
|
||||
*
|
||||
* - `muladd()`
|
||||
*
|
||||
* Multiply two curve points by two integers, and return the sum of
|
||||
* the two products.
|
||||
*
|
||||
* All curve points are represented in uncompressed format. The `mul()`
|
||||
* and `muladd()` methods take care to validate that the provided points
|
||||
* are really part of the relevant curve subgroup.
|
||||
*
|
||||
* For all point multiplication functions, the following holds:
|
||||
*
|
||||
* - Functions validate that the provided points are valid members
|
||||
* of the relevant curve subgroup. An error is reported if that is
|
||||
* not the case.
|
||||
*
|
||||
* - Processing is constant-time, even if the point operands are not
|
||||
* valid. This holds for both the source and resulting points, and
|
||||
* the multipliers (integers). Only the byte length of the provided
|
||||
* multiplier arrays (not their actual value length in bits) may
|
||||
* leak through timing-based side channels.
|
||||
*
|
||||
* - The multipliers (integers) MUST be lower than the subgroup order.
|
||||
* If this property is not met, then the result is indeterminate,
|
||||
* but an error value is not ncessearily returned.
|
||||
*
|
||||
*
|
||||
* ## ECDSA
|
||||
*
|
||||
* ECDSA signatures have two standard formats, called "raw" and "asn1".
|
||||
* Internally, such a signature is a pair of modular integers `(r,s)`.
|
||||
* The "raw" format is the concatenation of the unsigned big-endian
|
||||
* encodings of these two integers, possibly left-padded with zeros so
|
||||
* that they have the same encoded length. The "asn1" format is the
|
||||
* DER encoding of an ASN.1 structure that contains the two integer
|
||||
* values:
|
||||
*
|
||||
* ECDSASignature ::= SEQUENCE {
|
||||
* r INTEGER,
|
||||
* s INTEGER
|
||||
* }
|
||||
*
|
||||
* In general, in all of X.509 and SSL/TLS, the "asn1" format is used.
|
||||
* BearSSL offers ECDSA implementations for both formats; conversion
|
||||
* functions between the two formats are also provided. Conversion of a
|
||||
* "raw" format signature into "asn1" may enlarge a signature by no more
|
||||
* than 9 bytes for all supported curves; conversely, conversion of an
|
||||
* "asn1" signature to "raw" may expand the signature but the "raw"
|
||||
* length will never be more than twice the length of the "asn1" length
|
||||
* (and usually it will be shorter).
|
||||
*
|
||||
* Note that for a given signature, the "raw" format is not fully
|
||||
* deterministic, in that it does not enforce a minimal common length.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standard curve ID. These ID are equal to the assigned numerical
|
||||
* identifiers assigned to these curves for TLS:
|
||||
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
|
||||
*/
|
||||
|
||||
/** \brief Identifier for named curve sect163k1. */
|
||||
#define BR_EC_sect163k1 1
|
||||
|
||||
/** \brief Identifier for named curve sect163r1. */
|
||||
#define BR_EC_sect163r1 2
|
||||
|
||||
/** \brief Identifier for named curve sect163r2. */
|
||||
#define BR_EC_sect163r2 3
|
||||
|
||||
/** \brief Identifier for named curve sect193r1. */
|
||||
#define BR_EC_sect193r1 4
|
||||
|
||||
/** \brief Identifier for named curve sect193r2. */
|
||||
#define BR_EC_sect193r2 5
|
||||
|
||||
/** \brief Identifier for named curve sect233k1. */
|
||||
#define BR_EC_sect233k1 6
|
||||
|
||||
/** \brief Identifier for named curve sect233r1. */
|
||||
#define BR_EC_sect233r1 7
|
||||
|
||||
/** \brief Identifier for named curve sect239k1. */
|
||||
#define BR_EC_sect239k1 8
|
||||
|
||||
/** \brief Identifier for named curve sect283k1. */
|
||||
#define BR_EC_sect283k1 9
|
||||
|
||||
/** \brief Identifier for named curve sect283r1. */
|
||||
#define BR_EC_sect283r1 10
|
||||
|
||||
/** \brief Identifier for named curve sect409k1. */
|
||||
#define BR_EC_sect409k1 11
|
||||
|
||||
/** \brief Identifier for named curve sect409r1. */
|
||||
#define BR_EC_sect409r1 12
|
||||
|
||||
/** \brief Identifier for named curve sect571k1. */
|
||||
#define BR_EC_sect571k1 13
|
||||
|
||||
/** \brief Identifier for named curve sect571r1. */
|
||||
#define BR_EC_sect571r1 14
|
||||
|
||||
/** \brief Identifier for named curve secp160k1. */
|
||||
#define BR_EC_secp160k1 15
|
||||
|
||||
/** \brief Identifier for named curve secp160r1. */
|
||||
#define BR_EC_secp160r1 16
|
||||
|
||||
/** \brief Identifier for named curve secp160r2. */
|
||||
#define BR_EC_secp160r2 17
|
||||
|
||||
/** \brief Identifier for named curve secp192k1. */
|
||||
#define BR_EC_secp192k1 18
|
||||
|
||||
/** \brief Identifier for named curve secp192r1. */
|
||||
#define BR_EC_secp192r1 19
|
||||
|
||||
/** \brief Identifier for named curve secp224k1. */
|
||||
#define BR_EC_secp224k1 20
|
||||
|
||||
/** \brief Identifier for named curve secp224r1. */
|
||||
#define BR_EC_secp224r1 21
|
||||
|
||||
/** \brief Identifier for named curve secp256k1. */
|
||||
#define BR_EC_secp256k1 22
|
||||
|
||||
/** \brief Identifier for named curve secp256r1. */
|
||||
#define BR_EC_secp256r1 23
|
||||
|
||||
/** \brief Identifier for named curve secp384r1. */
|
||||
#define BR_EC_secp384r1 24
|
||||
|
||||
/** \brief Identifier for named curve secp521r1. */
|
||||
#define BR_EC_secp521r1 25
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP256r1. */
|
||||
#define BR_EC_brainpoolP256r1 26
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP384r1. */
|
||||
#define BR_EC_brainpoolP384r1 27
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP512r1. */
|
||||
#define BR_EC_brainpoolP512r1 28
|
||||
|
||||
/** \brief Identifier for named curve Curve25519. */
|
||||
#define BR_EC_curve25519 29
|
||||
|
||||
/** \brief Identifier for named curve Curve448. */
|
||||
#define BR_EC_curve448 30
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC public key.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Public curve point (uncompressed format). */
|
||||
unsigned char *q;
|
||||
/** \brief Length of public curve point (in bytes). */
|
||||
size_t qlen;
|
||||
} br_ec_public_key;
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC private key.
|
||||
*
|
||||
* The private key is an integer modulo the curve subgroup order. The
|
||||
* encoding below tolerates extra leading zeros. In general, it is
|
||||
* recommended that the private key has the same length as the curve
|
||||
* subgroup order.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Private key (integer, unsigned big-endian encoding). */
|
||||
unsigned char *x;
|
||||
/** \brief Private key length (in bytes). */
|
||||
size_t xlen;
|
||||
} br_ec_private_key;
|
||||
|
||||
/**
|
||||
* \brief Type for an EC implementation.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Supported curves.
|
||||
*
|
||||
* This word is a bitfield: bit `x` is set if the curve of ID `x`
|
||||
* is supported. E.g. an implementation supporting both NIST P-256
|
||||
* (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have
|
||||
* value `0x01800000` in this field.
|
||||
*/
|
||||
uint32_t supported_curves;
|
||||
|
||||
/**
|
||||
* \brief Get the conventional generator.
|
||||
*
|
||||
* This function returns the conventional generator (encoded
|
||||
* curve point) for the specified curve. This function MUST NOT
|
||||
* be called if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded generator length (in bytes).
|
||||
* \return the encoded generator.
|
||||
*/
|
||||
const unsigned char *(*generator)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the subgroup order.
|
||||
*
|
||||
* This function returns the order of the subgroup generated by
|
||||
* the conventional generator, for the specified curve. Unsigned
|
||||
* big-endian encoding is used. This function MUST NOT be called
|
||||
* if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded order length (in bytes).
|
||||
* \return the encoded order.
|
||||
*/
|
||||
const unsigned char *(*order)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the offset and length for the X coordinate.
|
||||
*
|
||||
* This function returns the offset and length (in bytes) of
|
||||
* the X coordinate in an encoded non-zero point.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the X coordinate length (in bytes).
|
||||
* \return the offset for the X coordinate (in bytes).
|
||||
*/
|
||||
size_t (*xoff)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Multiply a curve point by an integer.
|
||||
*
|
||||
* The source point is provided in array `G` (of size `Glen` bytes);
|
||||
* the multiplication result is written over it. The multiplier
|
||||
* `x` (of size `xlen` bytes) uses unsigned big-endian encoding.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source point must be a valid point on the relevant curve
|
||||
* subgroup (and not the "point at infinity" either). If this is
|
||||
* not the case, then this function returns an error (0).
|
||||
*
|
||||
* - The multiplier integer MUST be non-zero and less than the
|
||||
* curve subgroup order. If this property does not hold, then
|
||||
* the result is indeterminate and an error code is not
|
||||
* guaranteed.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `G` are indeterminate.
|
||||
*
|
||||
* \param G point to multiply.
|
||||
* \param Glen length of the encoded point (in bytes).
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*mul)(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply the generator by an integer.
|
||||
*
|
||||
* The multiplier MUST be non-zero and less than the curve
|
||||
* subgroup order. Results are indeterminate if this property
|
||||
* does not hold.
|
||||
*
|
||||
* \param R output buffer for the point.
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return encoded result point length (in bytes).
|
||||
*/
|
||||
size_t (*mulgen)(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply two points by two integers and add the
|
||||
* results.
|
||||
*
|
||||
* The point `x*A + y*B` is computed and written back in the `A`
|
||||
* array.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source points (`A` and `B`) must be valid points on
|
||||
* the relevant curve subgroup (and not the "point at
|
||||
* infinity" either). If this is not the case, then this
|
||||
* function returns an error (0).
|
||||
*
|
||||
* - If the `B` pointer is `NULL`, then the conventional
|
||||
* subgroup generator is used. With some implementations,
|
||||
* this may be faster than providing a pointer to the
|
||||
* generator.
|
||||
*
|
||||
* - The multiplier integers (`x` and `y`) MUST be non-zero
|
||||
* and less than the curve subgroup order. If either integer
|
||||
* is zero, then an error is reported, but if one of them is
|
||||
* not lower than the subgroup order, then the result is
|
||||
* indeterminate and an error code is not guaranteed.
|
||||
*
|
||||
* - If the final result is the point at infinity, then an
|
||||
* error is returned.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `A` are indeterminate.
|
||||
*
|
||||
* \param A first point to multiply.
|
||||
* \param B second point to multiply (`NULL` for the generator).
|
||||
* \param len common length of the encoded points (in bytes).
|
||||
* \param x multiplier for `A` (unsigned big-endian).
|
||||
* \param xlen length of multiplier for `A` (in bytes).
|
||||
* \param y multiplier for `A` (unsigned big-endian).
|
||||
* \param ylen length of multiplier for `A` (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve);
|
||||
} br_ec_impl;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 31-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 15-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), with optional Karatsuba decomposition, and fast
|
||||
* modular reduction thanks to the field modulus special format. Only
|
||||
* 32-bit multiplications are used (with 32-bit results, not 64-bit).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), relying on multiplications of 31-bit values
|
||||
* (MUL31).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m62" (specialised code) for P-256.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer
|
||||
* to that implementation.
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m62;
|
||||
|
||||
/**
|
||||
* \brief Get the "m62" implementation of P-256, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_p256_m62_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m64" (specialised code) for P-256.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer
|
||||
* to that implementation.
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m64;
|
||||
|
||||
/**
|
||||
* \brief Get the "m64" implementation of P-256, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_p256_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 15-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 31-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 15 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 31 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m62" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 62 bits, with a 124-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer
|
||||
* to that implementation. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m62;
|
||||
|
||||
/**
|
||||
* \brief Get the "m62" implementation of Curve25519, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_c25519_m62_get(void);
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m64" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 64 bits, with a 128-bit result. This implementation is
|
||||
* defined only on platforms that offer the 64x64->128 multiplication
|
||||
* support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer
|
||||
* to that implementation. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m64;
|
||||
|
||||
/**
|
||||
* \brief Get the "m64" implementation of Curve25519, if available.
|
||||
*
|
||||
* \return the implementation, or 0.
|
||||
*/
|
||||
const br_ec_impl *br_ec_c25519_m64_get(void);
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m15".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m15` for Curve25519
|
||||
* - `br_ec_p256_m15` for NIST P-256
|
||||
* - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m15;
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m31".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m31` for Curve25519
|
||||
* - `br_ec_p256_m31` for NIST P-256
|
||||
* - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m31;
|
||||
|
||||
/**
|
||||
* \brief Get the "default" EC implementation for the current system.
|
||||
*
|
||||
* This returns a pointer to the preferred implementation on the
|
||||
* current system.
|
||||
*
|
||||
* \return the default EC implementation.
|
||||
*/
|
||||
const br_ec_impl *br_ec_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "raw" to "asn1".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but by no more than 9 bytes at
|
||||
* most. On error, 0 is returned (error conditions include an odd raw
|
||||
* signature length, or an oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "asn1" to "raw".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but the new signature length
|
||||
* will be less than twice the source length at most. On error, 0 is
|
||||
* returned (error conditions include an invalid ASN.1 structure or an
|
||||
* oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signer function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hash value is
|
||||
* assumed to have the length inferred from the designated hash function
|
||||
* class.
|
||||
*
|
||||
* Signature is written in the buffer pointed to by `sig`, and the length
|
||||
* (in bytes) is returned. On error, nothing is written in the buffer,
|
||||
* and 0 is returned. This function returns 0 if the specified curve is
|
||||
* not supported by the provided EC implementation.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation; maximum length is predictable from the implemented
|
||||
* curve:
|
||||
*
|
||||
* | curve | raw | asn1 |
|
||||
* | :--------- | --: | ---: |
|
||||
* | NIST P-256 | 64 | 72 |
|
||||
* | NIST P-384 | 96 | 104 |
|
||||
* | NIST P-521 | 132 | 139 |
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signature verification function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hashed value,
|
||||
* computed over the purportedly signed data, is also provided with
|
||||
* its length.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation.
|
||||
*
|
||||
* Returned value is 1 on success (valid signature), 0 on error. This
|
||||
* function returns 0 if the specified curve is not supported by the
|
||||
* provided EC implementation.
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC private key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_keygen()` may need or
|
||||
* ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PRIV_MAX_SIZE 72
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC public key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_compute_public()` may
|
||||
* need or ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PUB_MAX_SIZE 145
|
||||
|
||||
/**
|
||||
* \brief Generate a new EC private key.
|
||||
*
|
||||
* If the specified `curve` is not supported by the elliptic curve
|
||||
* implementation (`impl`), then this function returns zero.
|
||||
*
|
||||
* The `sk` structure fields are set to the new private key data. In
|
||||
* particular, `sk.x` is made to point to the provided key buffer (`kbuf`),
|
||||
* in which the actual private key data is written. That buffer is assumed
|
||||
* to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum
|
||||
* size for all supported curves.
|
||||
*
|
||||
* The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then
|
||||
* the private key is not actually generated, and `sk` may also be `NULL`;
|
||||
* the minimum length for `kbuf` is still computed and returned.
|
||||
*
|
||||
* If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is
|
||||
* still generated and stored in `kbuf`.
|
||||
*
|
||||
* \param rng_ctx source PRNG context (already initialized).
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param sk the private key structure to fill, or `NULL`.
|
||||
* \param kbuf the key element buffer, or `NULL`.
|
||||
* \param curve the curve identifier.
|
||||
* \return the key data length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_keygen(const br_prng_class **rng_ctx,
|
||||
const br_ec_impl *impl, br_ec_private_key *sk,
|
||||
void *kbuf, int curve);
|
||||
|
||||
/**
|
||||
* \brief Compute EC public key from EC private key.
|
||||
*
|
||||
* This function uses the provided elliptic curve implementation (`impl`)
|
||||
* to compute the public key corresponding to the private key held in `sk`.
|
||||
* The public key point is written into `kbuf`, which is then linked from
|
||||
* the `*pk` structure. The size of the public key point, i.e. the number
|
||||
* of bytes used in `kbuf`, is returned.
|
||||
*
|
||||
* If `kbuf` is `NULL`, then the public key point is NOT computed, and
|
||||
* the public key structure `*pk` is unmodified (`pk` may be `NULL` in
|
||||
* that case). The size of the public key point is still returned.
|
||||
*
|
||||
* If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key
|
||||
* point is computed and stored in `kbuf`, and its size is returned.
|
||||
*
|
||||
* If the curve used by the private key is not supported by the curve
|
||||
* implementation, then this function returns zero.
|
||||
*
|
||||
* The private key MUST be valid. An off-range private key value is not
|
||||
* necessarily detected, and leads to unpredictable results.
|
||||
*
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param pk the public key structure to fill (or `NULL`).
|
||||
* \param kbuf the public key point buffer (or `NULL`).
|
||||
* \param sk the source private key.
|
||||
* \return the public key point length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
|
||||
void *kbuf, const br_ec_private_key *sk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1346
contrib/bearssl/inc/bearssl_hash.h
Normal file
1346
contrib/bearssl/inc/bearssl_hash.h
Normal file
File diff suppressed because it is too large
Load Diff
241
contrib/bearssl/inc/bearssl_hmac.h
Normal file
241
contrib/bearssl/inc/bearssl_hmac.h
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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 BR_BEARSSL_HMAC_H__
|
||||
#define BR_BEARSSL_HMAC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_hmac.h
|
||||
*
|
||||
* # HMAC
|
||||
*
|
||||
* HMAC is initialized with a key and an underlying hash function; it
|
||||
* then fills a "key context". That context contains the processed
|
||||
* key.
|
||||
*
|
||||
* With the key context, a HMAC context can be initialized to process
|
||||
* the input bytes and obtain the MAC output. The key context is not
|
||||
* modified during that process, and can be reused.
|
||||
*
|
||||
* IMPORTANT: HMAC shall be used only with functions that have the
|
||||
* following properties:
|
||||
*
|
||||
* - hash output size does not exceed 64 bytes;
|
||||
* - hash internal state size does not exceed 64 bytes;
|
||||
* - internal block length is a power of 2 between 16 and 256 bytes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HMAC key context.
|
||||
*
|
||||
* The HMAC key context is initialised with a hash function implementation
|
||||
* and a secret key. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
const br_hash_class *dig_vtable;
|
||||
unsigned char ksi[64], kso[64];
|
||||
#endif
|
||||
} br_hmac_key_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC key context initialisation.
|
||||
*
|
||||
* Initialise the key context with the provided key, using the hash function
|
||||
* identified by `digest_vtable`. This supports arbitrary key lengths.
|
||||
*
|
||||
* \param kc HMAC key context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param key pointer to the HMAC secret key.
|
||||
* \param key_len HMAC secret key length (in bytes).
|
||||
*/
|
||||
void br_hmac_key_init(br_hmac_key_context *kc,
|
||||
const br_hash_class *digest_vtable, const void *key, size_t key_len);
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC key context.
|
||||
*
|
||||
* \param kc HMAC key context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_key_get_digest(
|
||||
const br_hmac_key_context *kc)
|
||||
{
|
||||
return kc->dig_vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief HMAC computation context.
|
||||
*
|
||||
* The HMAC computation context maintains the state for a single HMAC
|
||||
* computation. It is modified as input bytes are injected. The context
|
||||
* is caller-allocated and has no release function since it does not
|
||||
* dynamically allocate external resources. Its contents are opaque.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_hash_compat_context dig;
|
||||
unsigned char kso[64];
|
||||
size_t out_len;
|
||||
#endif
|
||||
} br_hmac_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC computation initialisation.
|
||||
*
|
||||
* Initialise a HMAC context with a key context. The key context is
|
||||
* unmodified. Relevant data from the key context is immediately copied;
|
||||
* the key context can thus be independently reused, modified or released
|
||||
* without impacting this HMAC computation.
|
||||
*
|
||||
* An explicit output length can be specified; the actual output length
|
||||
* will be the minimum of that value and the natural HMAC output length.
|
||||
* If `out_len` is 0, then the natural HMAC output length is selected. The
|
||||
* "natural output length" is the output length of the underlying hash
|
||||
* function.
|
||||
*
|
||||
* \param ctx HMAC context to initialise.
|
||||
* \param kc HMAC key context (already initialised with the key).
|
||||
* \param out_len HMAC output length (0 to select "natural length").
|
||||
*/
|
||||
void br_hmac_init(br_hmac_context *ctx,
|
||||
const br_hmac_key_context *kc, size_t out_len);
|
||||
|
||||
/**
|
||||
* \brief Get the HMAC output size.
|
||||
*
|
||||
* The HMAC output size is the number of bytes that will actually be
|
||||
* produced with `br_hmac_out()` with the provided context. This function
|
||||
* MUST NOT be called on a non-initialised HMAC computation context.
|
||||
* The returned value is the minimum of the HMAC natural length (output
|
||||
* size of the underlying hash function) and the `out_len` parameter which
|
||||
* was used with the last `br_hmac_init()` call on that context (if the
|
||||
* initialisation `out_len` parameter was 0, then this function will
|
||||
* return the HMAC natural length).
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \return the HMAC actual output size.
|
||||
*/
|
||||
static inline size_t
|
||||
br_hmac_size(br_hmac_context *ctx)
|
||||
{
|
||||
return ctx->out_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC context.
|
||||
*
|
||||
* \param hc HMAC context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_get_digest(
|
||||
const br_hmac_context *hc)
|
||||
{
|
||||
return hc->dig.vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Inject some bytes in HMAC.
|
||||
*
|
||||
* The provided `len` bytes are injected as extra input in the HMAC
|
||||
* computation incarnated by the `ctx` HMAC context. It is acceptable
|
||||
* that `len` is zero, in which case `data` is ignored (and may be
|
||||
* `NULL`) and this function does nothing.
|
||||
*/
|
||||
void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Compute the HMAC output.
|
||||
*
|
||||
* The destination buffer MUST be large enough to accommodate the result;
|
||||
* its length is at most the "natural length" of HMAC (i.e. the output
|
||||
* length of the underlying hash function). The context is NOT modified;
|
||||
* further bytes may be processed. Thus, "partial HMAC" values can be
|
||||
* efficiently obtained.
|
||||
*
|
||||
* Returned value is the output length (in bytes).
|
||||
*
|
||||
* \param ctx HMAC computation context.
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_out(const br_hmac_context *ctx, void *out);
|
||||
|
||||
/**
|
||||
* \brief Constant-time HMAC computation.
|
||||
*
|
||||
* This function compute the HMAC output in constant time. Some extra
|
||||
* input bytes are processed, then the output is computed. The extra
|
||||
* input consists in the `len` bytes pointed to by `data`. The `len`
|
||||
* parameter must lie between `min_len` and `max_len` (inclusive);
|
||||
* `max_len` bytes are actually read from `data`. Computing time (and
|
||||
* memory access pattern) will not depend upon the data byte contents or
|
||||
* the value of `len`.
|
||||
*
|
||||
* The output is written in the `out` buffer, that MUST be large enough
|
||||
* to receive it.
|
||||
*
|
||||
* The difference `max_len - min_len` MUST be less than 2<sup>30</sup>
|
||||
* (i.e. about one gigabyte).
|
||||
*
|
||||
* This function computes the output properly only if the underlying
|
||||
* hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256,
|
||||
* SHA-384 or SHA-512).
|
||||
*
|
||||
* The provided context is NOT modified.
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \param data the extra input bytes.
|
||||
* \param len the extra input length (in bytes).
|
||||
* \param min_len minimum extra input length (in bytes).
|
||||
* \param max_len maximum extra input length (in bytes).
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_outCT(const br_hmac_context *ctx,
|
||||
const void *data, size_t len, size_t min_len, size_t max_len,
|
||||
void *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
284
contrib/bearssl/inc/bearssl_kdf.h
Normal file
284
contrib/bearssl/inc/bearssl_kdf.h
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 BR_BEARSSL_KDF_H__
|
||||
#define BR_BEARSSL_KDF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_kdf.h
|
||||
*
|
||||
* # Key Derivation Functions
|
||||
*
|
||||
* KDF are functions that takes a variable length input, and provide a
|
||||
* variable length output, meant to be used to derive subkeys from a
|
||||
* master key.
|
||||
*
|
||||
* ## HKDF
|
||||
*
|
||||
* HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869).
|
||||
* It is based on HMAC, itself using an underlying hash function. Any
|
||||
* hash function can be used, as long as it is compatible with the rules
|
||||
* for the HMAC implementation (i.e. output size is 64 bytes or less, hash
|
||||
* internal state size is 64 bytes or less, and the internal block length is
|
||||
* a power of 2 between 16 and 256 bytes). HKDF has two phases:
|
||||
*
|
||||
* - HKDF-Extract: the input data in ingested, along with a "salt" value.
|
||||
*
|
||||
* - HKDF-Expand: the output is produced, from the result of processing
|
||||
* the input and salt, and using an extra non-secret parameter called
|
||||
* "info".
|
||||
*
|
||||
* The "salt" and "info" strings are non-secret and can be empty. Their role
|
||||
* is normally to bind the input and output, respectively, to conventional
|
||||
* identifiers that qualifu them within the used protocol or application.
|
||||
*
|
||||
* The implementation defined in this file uses the following functions:
|
||||
*
|
||||
* - `br_hkdf_init()`: initialize an HKDF context, with a hash function,
|
||||
* and the salt. This starts the HKDF-Extract process.
|
||||
*
|
||||
* - `br_hkdf_inject()`: inject more input bytes. This function may be
|
||||
* called repeatedly if the input data is provided by chunks.
|
||||
*
|
||||
* - `br_hkdf_flip()`: end the HKDF-Extract process, and start the
|
||||
* HKDF-Expand process.
|
||||
*
|
||||
* - `br_hkdf_produce()`: get the next bytes of output. This function
|
||||
* may be called several times to obtain the full output by chunks.
|
||||
* For correct HKDF processing, the same "info" string must be
|
||||
* provided for each call.
|
||||
*
|
||||
* Note that the HKDF total output size (the number of bytes that
|
||||
* HKDF-Expand is willing to produce) is limited: if the hash output size
|
||||
* is _n_ bytes, then the maximum output size is _255*n_.
|
||||
*
|
||||
* ## SHAKE
|
||||
*
|
||||
* SHAKE is defined in
|
||||
* [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final)
|
||||
* under two versions: SHAKE128 and SHAKE256, offering an alleged
|
||||
* "security level" of 128 and 256 bits, respectively (SHAKE128 is
|
||||
* about 20 to 25% faster than SHAKE256). SHAKE internally relies on
|
||||
* the Keccak family of sponge functions, not on any externally provided
|
||||
* hash function. Contrary to HKDF, SHAKE does not have a concept of
|
||||
* either a "salt" or an "info" string. The API consists in four
|
||||
* functions:
|
||||
*
|
||||
* - `br_shake_init()`: initialize a SHAKE context for a given
|
||||
* security level.
|
||||
*
|
||||
* - `br_shake_inject()`: inject more input bytes. This function may be
|
||||
* called repeatedly if the input data is provided by chunks.
|
||||
*
|
||||
* - `br_shake_flip()`: end the data injection process, and start the
|
||||
* data production process.
|
||||
*
|
||||
* - `br_shake_produce()`: get the next bytes of output. This function
|
||||
* may be called several times to obtain the full output by chunks.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HKDF context.
|
||||
*
|
||||
* The HKDF context is initialized with a hash function implementation
|
||||
* and a salt value. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
union {
|
||||
br_hmac_context hmac_ctx;
|
||||
br_hmac_key_context prk_ctx;
|
||||
} u;
|
||||
unsigned char buf[64];
|
||||
size_t ptr;
|
||||
size_t dig_len;
|
||||
unsigned chunk_num;
|
||||
#endif
|
||||
} br_hkdf_context;
|
||||
|
||||
/**
|
||||
* \brief HKDF context initialization.
|
||||
*
|
||||
* The underlying hash function and salt value are provided. Arbitrary
|
||||
* salt lengths can be used.
|
||||
*
|
||||
* HKDF makes a difference between a salt of length zero, and an
|
||||
* absent salt (the latter being equivalent to a salt consisting of
|
||||
* bytes of value zero, of the same length as the hash function output).
|
||||
* If `salt_len` is zero, then this function assumes that the salt is
|
||||
* present but of length zero. To specify an _absent_ salt, use
|
||||
* `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored).
|
||||
*
|
||||
* \param hc HKDF context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param salt HKDF-Extract salt.
|
||||
* \param salt_len HKDF-Extract salt length (in bytes).
|
||||
*/
|
||||
void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable,
|
||||
const void *salt, size_t salt_len);
|
||||
|
||||
/**
|
||||
* \brief The special "absent salt" value for HKDF.
|
||||
*/
|
||||
#define BR_HKDF_NO_SALT (&br_hkdf_no_salt)
|
||||
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
extern const unsigned char br_hkdf_no_salt;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief HKDF input injection (HKDF-Extract).
|
||||
*
|
||||
* This function injects some more input bytes ("key material") into
|
||||
* HKDF. This function may be called several times, after `br_hkdf_init()`
|
||||
* but before `br_hkdf_flip()`.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param ikm extra input bytes.
|
||||
* \param ikm_len number of extra input bytes.
|
||||
*/
|
||||
void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len);
|
||||
|
||||
/**
|
||||
* \brief HKDF switch to the HKDF-Expand phase.
|
||||
*
|
||||
* This call terminates the HKDF-Extract process (input injection), and
|
||||
* starts the HKDF-Expand process (output production).
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
*/
|
||||
void br_hkdf_flip(br_hkdf_context *hc);
|
||||
|
||||
/**
|
||||
* \brief HKDF output production (HKDF-Expand).
|
||||
*
|
||||
* Produce more output bytes from the current state. This function may be
|
||||
* called several times, but only after `br_hkdf_flip()`.
|
||||
*
|
||||
* Returned value is the number of actually produced bytes. The total
|
||||
* output length is limited to 255 times the output length of the
|
||||
* underlying hash function.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param info application specific information string.
|
||||
* \param info_len application specific information string length (in bytes).
|
||||
* \param out destination buffer for the HKDF output.
|
||||
* \param out_len the length of the requested output (in bytes).
|
||||
* \return the produced output length (in bytes).
|
||||
*/
|
||||
size_t br_hkdf_produce(br_hkdf_context *hc,
|
||||
const void *info, size_t info_len, void *out, size_t out_len);
|
||||
|
||||
/**
|
||||
* \brief SHAKE context.
|
||||
*
|
||||
* The HKDF context is initialized with a "security level". The internal
|
||||
* notion is called "capacity"; the capacity is twice the security level
|
||||
* (for instance, SHAKE128 has capacity 256).
|
||||
*
|
||||
* The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
unsigned char dbuf[200];
|
||||
size_t dptr;
|
||||
size_t rate;
|
||||
uint64_t A[25];
|
||||
#endif
|
||||
} br_shake_context;
|
||||
|
||||
/**
|
||||
* \brief SHAKE context initialization.
|
||||
*
|
||||
* The context is initialized for the provided "security level".
|
||||
* Internally, this sets the "capacity" to twice the security level;
|
||||
* thus, for SHAKE128, the `security_level` parameter should be 128,
|
||||
* which corresponds to a 256-bit capacity.
|
||||
*
|
||||
* Allowed security levels are all multiples of 32, from 32 to 768,
|
||||
* inclusive. Larger security levels imply lower performance; levels
|
||||
* beyond 256 bits don't make much sense. Standard levels are 128
|
||||
* and 256 bits (for SHAKE128 and SHAKE256, respectively).
|
||||
*
|
||||
* \param sc SHAKE context to initialise.
|
||||
* \param security_level security level (in bits).
|
||||
*/
|
||||
void br_shake_init(br_shake_context *sc, int security_level);
|
||||
|
||||
/**
|
||||
* \brief SHAKE input injection.
|
||||
*
|
||||
* This function injects some more input bytes ("key material") into
|
||||
* SHAKE. This function may be called several times, after `br_shake_init()`
|
||||
* but before `br_shake_flip()`.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
* \param data extra input bytes.
|
||||
* \param len number of extra input bytes.
|
||||
*/
|
||||
void br_shake_inject(br_shake_context *sc, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief SHAKE switch to production phase.
|
||||
*
|
||||
* This call terminates the input injection process, and starts the
|
||||
* output production process.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
*/
|
||||
void br_shake_flip(br_shake_context *hc);
|
||||
|
||||
/**
|
||||
* \brief SHAKE output production.
|
||||
*
|
||||
* Produce more output bytes from the current state. This function may be
|
||||
* called several times, but only after `br_shake_flip()`.
|
||||
*
|
||||
* There is no practical limit to the number of bytes that may be produced.
|
||||
*
|
||||
* \param sc SHAKE context.
|
||||
* \param out destination buffer for the SHAKE output.
|
||||
* \param len the length of the requested output (in bytes).
|
||||
*/
|
||||
void br_shake_produce(br_shake_context *sc, void *out, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
294
contrib/bearssl/inc/bearssl_pem.h
Normal file
294
contrib/bearssl/inc/bearssl_pem.h
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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 BR_BEARSSL_PEM_H__
|
||||
#define BR_BEARSSL_PEM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_pem.h
|
||||
*
|
||||
* # PEM Support
|
||||
*
|
||||
* PEM is a traditional encoding layer use to store binary objects (in
|
||||
* particular X.509 certificates, and private keys) in text files. While
|
||||
* the acronym comes from an old, defunct standard ("Privacy Enhanced
|
||||
* Mail"), the format has been reused, with some variations, by many
|
||||
* systems, and is a _de facto_ standard, even though it is not, actually,
|
||||
* specified in all clarity anywhere.
|
||||
*
|
||||
* ## Format Details
|
||||
*
|
||||
* BearSSL contains a generic, streamed PEM decoder, which handles the
|
||||
* following format:
|
||||
*
|
||||
* - The input source (a sequence of bytes) is assumed to be the
|
||||
* encoding of a text file in an ASCII-compatible charset. This
|
||||
* includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each
|
||||
* line ends on a newline character (U+000A LINE FEED). The
|
||||
* U+000D CARRIAGE RETURN characters are ignored, so the code
|
||||
* accepts both Windows-style and Unix-style line endings.
|
||||
*
|
||||
* - Each object begins with a banner that occurs at the start of
|
||||
* a line; the first banner characters are "`-----BEGIN `" (five
|
||||
* dashes, the word "BEGIN", and a space). The banner matching is
|
||||
* not case-sensitive.
|
||||
*
|
||||
* - The _object name_ consists in the characters that follow the
|
||||
* banner start sequence, up to the end of the line, but without
|
||||
* trailing dashes (in "normal" PEM, there are five trailing
|
||||
* dashes, but this implementation is not picky about these dashes).
|
||||
* The BearSSL decoder normalises the name characters to uppercase
|
||||
* (for ASCII letters only) and accepts names up to 127 characters.
|
||||
*
|
||||
* - The object ends with a banner that again occurs at the start of
|
||||
* a line, and starts with "`-----END `" (again case-insensitive).
|
||||
*
|
||||
* - Between that start and end banner, only Base64 data shall occur.
|
||||
* Base64 converts each sequence of three bytes into four
|
||||
* characters; the four characters are ASCII letters, digits, "`+`"
|
||||
* or "`-`" signs, and one or two "`=`" signs may occur in the last
|
||||
* quartet. Whitespace is ignored (whitespace is any ASCII character
|
||||
* of code 32 or less, so control characters are whitespace) and
|
||||
* lines may have arbitrary length; the only restriction is that the
|
||||
* four characters of a quartet must appear on the same line (no
|
||||
* line break inside a quartet).
|
||||
*
|
||||
* - A single file may contain more than one PEM object. Bytes that
|
||||
* occur between objects are ignored.
|
||||
*
|
||||
*
|
||||
* ## PEM Decoder API
|
||||
*
|
||||
* The PEM decoder offers a state-machine API. The caller allocates a
|
||||
* decoder context, then injects source bytes. Source bytes are pushed
|
||||
* with `br_pem_decoder_push()`. The decoder stops accepting bytes when
|
||||
* it reaches an "event", which is either the start of an object, the
|
||||
* end of an object, or a decoding error within an object.
|
||||
*
|
||||
* The `br_pem_decoder_event()` function is used to obtain the current
|
||||
* event; it also clears it, thus allowing the decoder to accept more
|
||||
* bytes. When a object start event is raised, the decoder context
|
||||
* offers the found object name (normalised to ASCII uppercase).
|
||||
*
|
||||
* When an object is reached, the caller must set an appropriate callback
|
||||
* function, which will receive (by chunks) the decoded object data.
|
||||
*
|
||||
* Since the decoder context makes no dynamic allocation, it requires
|
||||
* no explicit deallocation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief PEM decoder context.
|
||||
*
|
||||
* Contents are opaque (they should not be accessed directly).
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
/* CPU for the T0 virtual machine. */
|
||||
struct {
|
||||
uint32_t *dp;
|
||||
uint32_t *rp;
|
||||
const unsigned char *ip;
|
||||
} cpu;
|
||||
uint32_t dp_stack[32];
|
||||
uint32_t rp_stack[32];
|
||||
int err;
|
||||
|
||||
const unsigned char *hbuf;
|
||||
size_t hlen;
|
||||
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len);
|
||||
void *dest_ctx;
|
||||
|
||||
unsigned char event;
|
||||
char name[128];
|
||||
unsigned char buf[255];
|
||||
size_t ptr;
|
||||
#endif
|
||||
} br_pem_decoder_context;
|
||||
|
||||
/**
|
||||
* \brief Initialise a PEM decoder structure.
|
||||
*
|
||||
* \param ctx decoder context to initialise.
|
||||
*/
|
||||
void br_pem_decoder_init(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Push some bytes into the decoder.
|
||||
*
|
||||
* Returned value is the number of bytes actually consumed; this may be
|
||||
* less than the number of provided bytes if an event is raised. When an
|
||||
* event is raised, it must be read (with `br_pem_decoder_event()`);
|
||||
* until the event is read, this function will return 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param data new data bytes.
|
||||
* \param len number of new data bytes.
|
||||
* \return the number of bytes actually received (may be less than `len`).
|
||||
*/
|
||||
size_t br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Set the receiver for decoded data.
|
||||
*
|
||||
* When an object is entered, the provided function (with opaque context
|
||||
* pointer) will be called repeatedly with successive chunks of decoded
|
||||
* data for that object. If `dest` is set to 0, then decoded data is
|
||||
* simply ignored. The receiver can be set at any time, but, in practice,
|
||||
* it should be called immediately after receiving a "start of object"
|
||||
* event.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param dest callback for receiving decoded data.
|
||||
* \param dest_ctx opaque context pointer for the `dest` callback.
|
||||
*/
|
||||
static inline void
|
||||
br_pem_decoder_setdest(br_pem_decoder_context *ctx,
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len),
|
||||
void *dest_ctx)
|
||||
{
|
||||
ctx->dest = dest;
|
||||
ctx->dest_ctx = dest_ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the last event.
|
||||
*
|
||||
* If an event was raised, then this function returns the event value, and
|
||||
* also clears it, thereby allowing the decoder to proceed. If no event
|
||||
* was raised since the last call to `br_pem_decoder_event()`, then this
|
||||
* function returns 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the raised event, or 0.
|
||||
*/
|
||||
int br_pem_decoder_event(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Event: start of object.
|
||||
*
|
||||
* This event is raised when the start of a new object has been detected.
|
||||
* The object name (normalised to uppercase) can be accessed with
|
||||
* `br_pem_decoder_name()`.
|
||||
*/
|
||||
#define BR_PEM_BEGIN_OBJ 1
|
||||
|
||||
/**
|
||||
* \brief Event: end of object.
|
||||
*
|
||||
* This event is raised when the end of the current object is reached
|
||||
* (normally, i.e. with no decoding error).
|
||||
*/
|
||||
#define BR_PEM_END_OBJ 2
|
||||
|
||||
/**
|
||||
* \brief Event: decoding error.
|
||||
*
|
||||
* This event is raised when decoding fails within an object.
|
||||
* This formally closes the current object and brings the decoder back
|
||||
* to the "out of any object" state. The offending line in the source
|
||||
* is consumed.
|
||||
*/
|
||||
#define BR_PEM_ERROR 3
|
||||
|
||||
/**
|
||||
* \brief Get the name of the encountered object.
|
||||
*
|
||||
* The encountered object name is defined only when the "start of object"
|
||||
* event is raised. That name is normalised to uppercase (for ASCII letters
|
||||
* only) and does not include trailing dashes.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the current object name.
|
||||
*/
|
||||
static inline const char *
|
||||
br_pem_decoder_name(br_pem_decoder_context *ctx)
|
||||
{
|
||||
return ctx->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Encode an object in PEM.
|
||||
*
|
||||
* This function encodes the provided binary object (`data`, of length `len`
|
||||
* bytes) into PEM. The `banner` text will be included in the header and
|
||||
* footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header).
|
||||
*
|
||||
* The length (in characters) of the PEM output is returned; that length
|
||||
* does NOT include the terminating zero, that this function nevertheless
|
||||
* adds. If using the returned value for allocation purposes, the allocated
|
||||
* buffer size MUST be at least one byte larger than the returned size.
|
||||
*
|
||||
* If `dest` is `NULL`, then the encoding does not happen; however, the
|
||||
* length of the encoded object is still computed and returned.
|
||||
*
|
||||
* The `data` pointer may be `NULL` only if `len` is zero (when encoding
|
||||
* an object of length zero, which is not very useful), or when `dest`
|
||||
* is `NULL` (in that case, source data bytes are ignored).
|
||||
*
|
||||
* Some `flags` can be specified to alter the encoding behaviour:
|
||||
*
|
||||
* - If `BR_PEM_LINE64` is set, then line-breaking will occur after
|
||||
* every 64 characters of output, instead of the default of 76.
|
||||
*
|
||||
* - If `BR_PEM_CRLF` is set, then end-of-line sequence will use
|
||||
* CR+LF instead of a single LF.
|
||||
*
|
||||
* The `data` and `dest` buffers may overlap, in which case the source
|
||||
* binary data is destroyed in the process. Note that the PEM-encoded output
|
||||
* is always larger than the source binary.
|
||||
*
|
||||
* \param dest the destination buffer (or `NULL`).
|
||||
* \param data the source buffer (can be `NULL` in some cases).
|
||||
* \param len the source length (in bytes).
|
||||
* \param banner the PEM banner expression.
|
||||
* \param flags the behavioural flags.
|
||||
* \return the PEM object length (in characters), EXCLUDING the final zero.
|
||||
*/
|
||||
size_t br_pem_encode(void *dest, const void *data, size_t len,
|
||||
const char *banner, unsigned flags);
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: split lines at 64 characters.
|
||||
*/
|
||||
#define BR_PEM_LINE64 0x0001
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: use CR+LF line endings.
|
||||
*/
|
||||
#define BR_PEM_CRLF 0x0002
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
150
contrib/bearssl/inc/bearssl_prf.h
Normal file
150
contrib/bearssl/inc/bearssl_prf.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 BR_BEARSSL_PRF_H__
|
||||
#define BR_BEARSSL_PRF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_prf.h
|
||||
*
|
||||
* # The TLS PRF
|
||||
*
|
||||
* The "PRF" is the pseudorandom function used internally during the
|
||||
* SSL/TLS handshake, notably to expand negotiated shared secrets into
|
||||
* the symmetric encryption keys that will be used to process the
|
||||
* application data.
|
||||
*
|
||||
* TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This
|
||||
* is implemented by the `br_tls10_prf()` function.
|
||||
*
|
||||
* TLS 1.2 redefines the PRF, using an explicit hash function. The
|
||||
* `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that
|
||||
* PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites
|
||||
* rely on the SHA-256 based PRF, but some use SHA-384.
|
||||
*
|
||||
* The PRF always uses as input three parameters: a "secret" (some
|
||||
* bytes), a "label" (ASCII string), and a "seed" (again some bytes). An
|
||||
* arbitrary output length can be produced. The "seed" is provided as an
|
||||
* arbitrary number of binary chunks, that gets internally concatenated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Type for a seed chunk.
|
||||
*
|
||||
* Each chunk may have an arbitrary length, and may be empty (no byte at
|
||||
* all). If the chunk length is zero, then the pointer to the chunk data
|
||||
* may be `NULL`.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the chunk data.
|
||||
*/
|
||||
const void *data;
|
||||
|
||||
/**
|
||||
* \brief Chunk length (in bytes).
|
||||
*/
|
||||
size_t len;
|
||||
} br_tls_prf_seed_chunk;
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.0 and 1.1.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.0 and 1.1. It internally uses
|
||||
* MD5 and SHA-1.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls10_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-256.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-256.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha256_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-384.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-384.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha384_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* brief A convenient type name for a PRF implementation.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
typedef void (*br_tls_prf_impl)(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
397
contrib/bearssl/inc/bearssl_rand.h
Normal file
397
contrib/bearssl/inc/bearssl_rand.h
Normal file
@ -0,0 +1,397 @@
|
||||
/*
|
||||
* 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 BR_BEARSSL_RAND_H__
|
||||
#define BR_BEARSSL_RAND_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_rand.h
|
||||
*
|
||||
* # Pseudo-Random Generators
|
||||
*
|
||||
* A PRNG is a state-based engine that outputs pseudo-random bytes on
|
||||
* demand. It is initialized with an initial seed, and additional seed
|
||||
* bytes can be added afterwards. Bytes produced depend on the seeds and
|
||||
* also on the exact sequence of calls (including sizes requested for
|
||||
* each call).
|
||||
*
|
||||
*
|
||||
* ## Procedural and OOP API
|
||||
*
|
||||
* For the PRNG of name "`xxx`", two API are provided. The _procedural_
|
||||
* API defined a context structure `br_xxx_context` and three functions:
|
||||
*
|
||||
* - `br_xxx_init()`
|
||||
*
|
||||
* Initialise the context with an initial seed.
|
||||
*
|
||||
* - `br_xxx_generate()`
|
||||
*
|
||||
* Produce some pseudo-random bytes.
|
||||
*
|
||||
* - `br_xxx_update()`
|
||||
*
|
||||
* Inject some additional seed.
|
||||
*
|
||||
* The initialisation function sets the first context field (`vtable`)
|
||||
* to a pointer to the vtable that supports the OOP API. The OOP API
|
||||
* provides access to the same functions through function pointers,
|
||||
* named `init()`, `generate()` and `update()`.
|
||||
*
|
||||
* Note that the context initialisation method may accept additional
|
||||
* parameters, provided as a 'const void *' pointer at API level. These
|
||||
* additional parameters depend on the implemented PRNG.
|
||||
*
|
||||
*
|
||||
* ## HMAC_DRBG
|
||||
*
|
||||
* HMAC_DRBG is defined in [NIST SP 800-90A Revision
|
||||
* 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
|
||||
* It uses HMAC repeatedly, over some configurable underlying hash
|
||||
* function. In BearSSL, it is implemented under the "`hmac_drbg`" name.
|
||||
* The "extra parameters" pointer for context initialisation should be
|
||||
* set to a pointer to the vtable for the underlying hash function (e.g.
|
||||
* pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256).
|
||||
*
|
||||
* According to the NIST standard, each request shall produce up to
|
||||
* 2<sup>19</sup> bits (i.e. 64 kB of data); moreover, the context shall
|
||||
* be reseeded at least once every 2<sup>48</sup> requests. This
|
||||
* implementation does not maintain the reseed counter (the threshold is
|
||||
* too high to be reached in practice) and does not object to producing
|
||||
* more than 64 kB in a single request; thus, the code cannot fail,
|
||||
* which corresponds to the fact that the API has no room for error
|
||||
* codes. However, this implies that requesting more than 64 kB in one
|
||||
* `generate()` request, or making more than 2<sup>48</sup> requests
|
||||
* without reseeding, is formally out of NIST specification. There is
|
||||
* no currently known security penalty for exceeding the NIST limits,
|
||||
* and, in any case, HMAC_DRBG usage in implementing SSL/TLS always
|
||||
* stays much below these thresholds.
|
||||
*
|
||||
*
|
||||
* ## AESCTR_DRBG
|
||||
*
|
||||
* AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is
|
||||
* meant to be used only in situations where you are desperate for
|
||||
* speed, and have an hardware-optimized AES/CTR implementation. Whether
|
||||
* this will yield perceptible improvements depends on what you use the
|
||||
* pseudorandom bytes for, and how many you want; for instance, RSA key
|
||||
* pair generation uses a substantial amount of randomness, and using
|
||||
* AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key
|
||||
* generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz).
|
||||
*
|
||||
* Internally, it uses CTR mode with successive counter values, starting
|
||||
* at zero (counter value expressed over 128 bits, big-endian convention).
|
||||
* The counter is not allowed to reach 32768; thus, every 32768*16 bytes
|
||||
* at most, the `update()` function is run (on an empty seed, if none is
|
||||
* provided). The `update()` function computes the new AES-128 key by
|
||||
* applying a custom hash function to the concatenation of a state-dependent
|
||||
* word (encryption of an all-one block with the current key) and the new
|
||||
* seed. The custom hash function uses Hirose's construction over AES-256;
|
||||
* see the comments in `aesctr_drbg.c` for details.
|
||||
*
|
||||
* This DRBG does not follow an existing standard, and thus should be
|
||||
* considered as inadequate for production use until it has been properly
|
||||
* analysed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Class type for PRNG implementations.
|
||||
*
|
||||
* A `br_prng_class` instance references the methods implementing a PRNG.
|
||||
* Constant instances of this structure are defined for each implemented
|
||||
* PRNG. Such instances are also called "vtables".
|
||||
*/
|
||||
typedef struct br_prng_class_ br_prng_class;
|
||||
struct br_prng_class_ {
|
||||
/**
|
||||
* \brief Size (in bytes) of the context structure appropriate for
|
||||
* running this PRNG.
|
||||
*/
|
||||
size_t context_size;
|
||||
|
||||
/**
|
||||
* \brief Initialisation method.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its
|
||||
* first field (the vtable pointer); this function sets that
|
||||
* first field to a pointer to the vtable.
|
||||
*
|
||||
* The extra parameters depend on the implementation; each
|
||||
* implementation defines what kind of extra parameters it
|
||||
* expects (if any).
|
||||
*
|
||||
* Requirements on the initial seed depend on the implemented
|
||||
* PRNG.
|
||||
*
|
||||
* \param ctx PRNG context to initialise.
|
||||
* \param params extra parameters for the PRNG.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void (*init)(const br_prng_class **ctx, const void *params,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void (*generate)(const br_prng_class **ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes.
|
||||
*
|
||||
* The provided seed bytes are added into the PRNG internal
|
||||
* entropy pool.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void (*update)(const br_prng_class **ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Context for HMAC_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
unsigned char K[64];
|
||||
unsigned char V[64];
|
||||
const br_hash_class *digest_class;
|
||||
#endif
|
||||
} br_hmac_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for HMAC_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_hmac_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief HMAC_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The `seed` value is what is called, in NIST terminology, the
|
||||
* concatenation of the "seed", "nonce" and "personalization string", in
|
||||
* that order.
|
||||
*
|
||||
* The `digest_class` parameter defines the underlying hash function.
|
||||
* Formally, the NIST standard specifies that the hash function shall
|
||||
* be only SHA-1 or one of the SHA-2 functions. This implementation also
|
||||
* works with any other implemented hash function (such as MD5), but
|
||||
* this is non-standard and therefore not recommended.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context to initialise.
|
||||
* \param digest_class vtable for the underlying hash function.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_init(br_hmac_drbg_context *ctx,
|
||||
const br_hash_class *digest_class, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with HMAC_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly. Formally, requesting
|
||||
* more than 65536 bytes in one request falls out of specification
|
||||
* limits (but it won't fail).
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in HMAC_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the HMAC_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_update(br_hmac_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Get the hash function implementation used by a given instance of
|
||||
* HMAC_DRBG.
|
||||
*
|
||||
* This calls MUST NOT be performed on a context which was not
|
||||
* previously initialised.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \return the hash function vtable.
|
||||
*/
|
||||
static inline const br_hash_class *
|
||||
br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)
|
||||
{
|
||||
return ctx->digest_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Type for a provider of entropy seeds.
|
||||
*
|
||||
* A "seeder" is a function that is able to obtain random values from
|
||||
* some source and inject them as entropy seed in a PRNG. A seeder
|
||||
* shall guarantee that the total entropy of the injected seed is large
|
||||
* enough to seed a PRNG for purposes of cryptographic key generation
|
||||
* (i.e. at least 128 bits).
|
||||
*
|
||||
* A seeder may report a failure to obtain adequate entropy. Seeders
|
||||
* shall endeavour to fix themselves transient errors by trying again;
|
||||
* thus, callers may consider reported errors as permanent.
|
||||
*
|
||||
* \param ctx PRNG context to seed.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef int (*br_prng_seeder)(const br_prng_class **ctx);
|
||||
|
||||
/**
|
||||
* \brief Get a seeder backed by the operating system or hardware.
|
||||
*
|
||||
* Get a seeder that feeds on RNG facilities provided by the current
|
||||
* operating system or hardware. If no such facility is known, then 0
|
||||
* is returned.
|
||||
*
|
||||
* If `name` is not `NULL`, then `*name` is set to a symbolic string
|
||||
* that identifies the seeder implementation. If no seeder is returned
|
||||
* and `name` is not `NULL`, then `*name` is set to a pointer to the
|
||||
* constant string `"none"`.
|
||||
*
|
||||
* \param name receiver for seeder name, or `NULL`.
|
||||
* \return the system seeder, if available, or 0.
|
||||
*/
|
||||
br_prng_seeder br_prng_seeder_system(const char **name);
|
||||
|
||||
/**
|
||||
* \brief Context for AESCTR_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_aes_gen_ctr_keys sk;
|
||||
uint32_t cc;
|
||||
#endif
|
||||
} br_aesctr_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for AESCTR_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_aesctr_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief AESCTR_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The internal AES key is first set to the all-zero key; then, the
|
||||
* `br_aesctr_drbg_update()` function is called with the provided `seed`.
|
||||
* The call is performed even if the seed length (`seed_len`) is zero.
|
||||
*
|
||||
* The `aesctr` parameter defines the underlying AES/CTR implementation.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context to initialise.
|
||||
* \param aesctr vtable for the AES/CTR implementation.
|
||||
* \param seed initial seed (can be `NULL` if `seed_len` is zero).
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
|
||||
const br_block_ctr_class *aesctr, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with AESCTR_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx,
|
||||
void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in AESCTR_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the AESCTR_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1655
contrib/bearssl/inc/bearssl_rsa.h
Normal file
1655
contrib/bearssl/inc/bearssl_rsa.h
Normal file
File diff suppressed because it is too large
Load Diff
4296
contrib/bearssl/inc/bearssl_ssl.h
Normal file
4296
contrib/bearssl/inc/bearssl_ssl.h
Normal file
File diff suppressed because it is too large
Load Diff
1397
contrib/bearssl/inc/bearssl_x509.h
Normal file
1397
contrib/bearssl/inc/bearssl_x509.h
Normal file
File diff suppressed because it is too large
Load Diff
41
contrib/bearssl/mk/Defaults.mk
Normal file
41
contrib/bearssl/mk/Defaults.mk
Normal file
@ -0,0 +1,41 @@
|
||||
# Copyright (c) 2017 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.
|
||||
|
||||
# ======================================================================
|
||||
|
||||
# This file sets variables with generic default values, which can be
|
||||
# overridden in the selected configuration file.
|
||||
|
||||
BUILD = build
|
||||
OBJDIR = $(BUILD)$Pobj
|
||||
BEARSSLLIB = $(BUILD)$P$(LP)bearssl$L
|
||||
BEARSSLDLL = $(BUILD)$P$(DP)bearssl$D
|
||||
BRSSL = $(BUILD)$Pbrssl$E
|
||||
TESTCRYPTO = $(BUILD)$Ptestcrypto$E
|
||||
TESTSPEED = $(BUILD)$Ptestspeed$E
|
||||
TESTX509 = $(BUILD)$Ptestx509$E
|
||||
INCFLAGS = -Isrc -Iinc
|
||||
T0COMP = T0Comp.exe
|
||||
STATICLIB = lib
|
||||
DLL = dll
|
||||
TOOLS = tools
|
||||
TESTS = tests
|
38
contrib/bearssl/mk/NMake.mk
Normal file
38
contrib/bearssl/mk/NMake.mk
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2017 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.
|
||||
|
||||
# ======================================================================
|
||||
|
||||
# This file sets variables for use with NMake.exe, as distributed with
|
||||
# Visual Studio.
|
||||
|
||||
# Load generic defaults.
|
||||
!include mk/Defaults.mk
|
||||
|
||||
# Default configuration is 'Win' (native build with Visual Studio).
|
||||
CONF = Win
|
||||
|
||||
# Path separator.
|
||||
P = ^\
|
||||
|
||||
!include conf/$(CONF).mk
|
||||
!include mk/Rules.mk
|
1318
contrib/bearssl/mk/Rules.mk
Normal file
1318
contrib/bearssl/mk/Rules.mk
Normal file
File diff suppressed because it is too large
Load Diff
38
contrib/bearssl/mk/SingleUnix.mk
Normal file
38
contrib/bearssl/mk/SingleUnix.mk
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2017 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.
|
||||
|
||||
# ======================================================================
|
||||
|
||||
# This file sets variables for use with a SingleUnix-compatible 'make'
|
||||
# utility.
|
||||
|
||||
# Load generic default.
|
||||
include mk/Defaults.mk
|
||||
|
||||
# Path separator.
|
||||
P = /
|
||||
|
||||
# Default configuration is 'Unix' (native build on a Unix-like system).
|
||||
CONF = Unix
|
||||
|
||||
include conf/$(CONF).mk
|
||||
include mk/Rules.mk
|
32
contrib/bearssl/mk/mkT0.cmd
Normal file
32
contrib/bearssl/mk/mkT0.cmd
Normal file
@ -0,0 +1,32 @@
|
||||
@echo off
|
||||
|
||||
rem =====================================================================
|
||||
rem This script uses the command-line C# compiler csc.exe, which is
|
||||
rem provided with the .NET framework. We need framework 3.5 or later
|
||||
rem (some of the code uses features not available in the language version
|
||||
rem implemented in the compiler provided with framework 2.0.50727).
|
||||
rem =====================================================================
|
||||
|
||||
if exist "%SystemRoot%\Microsoft.NET\Framework\v3.5\csc.exe" (
|
||||
set CSC="%SystemRoot%\Microsoft.NET\Framework\v3.5\csc.exe"
|
||||
goto do_compile
|
||||
)
|
||||
if exist "%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\csc.exe" (
|
||||
set CSC="%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\csc.exe"
|
||||
goto do_compile
|
||||
)
|
||||
if exist "%SystemRoot%\Microsoft.NET\Framework64\v3.5\csc.exe" (
|
||||
set CSC="%SystemRoot%\Microsoft.NET\Framework64\v3.5\csc.exe"
|
||||
goto do_compile
|
||||
)
|
||||
if exist "%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\csc.exe" (
|
||||
set CSC="%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
|
||||
goto do_compile
|
||||
)
|
||||
|
||||
echo C# compiler not found
|
||||
exit 1
|
||||
|
||||
:do_compile
|
||||
%CSC% /nologo /out:T0Comp.exe /main:T0Comp /res:T0\kern.t0,t0-kernel T0\*.cs
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
11
contrib/bearssl/mk/mkT0.sh
Executable file
11
contrib/bearssl/mk/mkT0.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#! /bin/sh
|
||||
|
||||
CSC=$(which mono-csc || which dmcs || echo "none")
|
||||
|
||||
if [ $CSC = "none" ]; then
|
||||
echo "Error: Please install mono-devel."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
$CSC /out:T0Comp.exe /main:T0Comp /res:T0/kern.t0,t0-kernel T0/*.cs
|
570
contrib/bearssl/mk/mkrules.sh
Executable file
570
contrib/bearssl/mk/mkrules.sh
Executable file
@ -0,0 +1,570 @@
|
||||
#! /bin/sh
|
||||
|
||||
# ========================================================================
|
||||
#
|
||||
# Copyright (c) 2017 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.
|
||||
#
|
||||
# ========================================================================
|
||||
#
|
||||
# This script is used to generate the 'Rules.mk' file from the list
|
||||
# of source file included below. If the list changes (e.g. to add a
|
||||
# new source file), then add it here and rerun this script.
|
||||
#
|
||||
# ========================================================================
|
||||
|
||||
# Solaris compatibility: switch to a more POSIX-compliant /bin/sh.
|
||||
if [ -z "$BR_SCRIPT_LOOP" ] ; then
|
||||
BR_SCRIPT_LOOP=yes
|
||||
export BR_SCRIPT_LOOP
|
||||
if [ -x /usr/xpg6/bin/sh ] ; then
|
||||
exec /usr/xpg6/bin/sh "$0" "$@"
|
||||
fi
|
||||
if [ -x /usr/xpg4/bin/sh ] ; then
|
||||
exec /usr/xpg4/bin/sh "$0" "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Exit on first error.
|
||||
set -e
|
||||
|
||||
# Source files. Please keep in alphabetical order.
|
||||
coresrc=" \
|
||||
src/settings.c \
|
||||
src/aead/ccm.c \
|
||||
src/aead/eax.c \
|
||||
src/aead/gcm.c \
|
||||
src/codec/ccopy.c \
|
||||
src/codec/dec16be.c \
|
||||
src/codec/dec16le.c \
|
||||
src/codec/dec32be.c \
|
||||
src/codec/dec32le.c \
|
||||
src/codec/dec64be.c \
|
||||
src/codec/dec64le.c \
|
||||
src/codec/enc16be.c \
|
||||
src/codec/enc16le.c \
|
||||
src/codec/enc32be.c \
|
||||
src/codec/enc32le.c \
|
||||
src/codec/enc64be.c \
|
||||
src/codec/enc64le.c \
|
||||
src/codec/pemdec.c \
|
||||
src/codec/pemenc.c \
|
||||
src/ec/ec_all_m15.c \
|
||||
src/ec/ec_all_m31.c \
|
||||
src/ec/ec_c25519_i15.c \
|
||||
src/ec/ec_c25519_i31.c \
|
||||
src/ec/ec_c25519_m15.c \
|
||||
src/ec/ec_c25519_m31.c \
|
||||
src/ec/ec_c25519_m62.c \
|
||||
src/ec/ec_c25519_m64.c \
|
||||
src/ec/ec_curve25519.c \
|
||||
src/ec/ec_default.c \
|
||||
src/ec/ec_keygen.c \
|
||||
src/ec/ec_p256_m15.c \
|
||||
src/ec/ec_p256_m31.c \
|
||||
src/ec/ec_p256_m62.c \
|
||||
src/ec/ec_p256_m64.c \
|
||||
src/ec/ec_prime_i15.c \
|
||||
src/ec/ec_prime_i31.c \
|
||||
src/ec/ec_pubkey.c \
|
||||
src/ec/ec_secp256r1.c \
|
||||
src/ec/ec_secp384r1.c \
|
||||
src/ec/ec_secp521r1.c \
|
||||
src/ec/ecdsa_atr.c \
|
||||
src/ec/ecdsa_default_sign_asn1.c \
|
||||
src/ec/ecdsa_default_sign_raw.c \
|
||||
src/ec/ecdsa_default_vrfy_asn1.c \
|
||||
src/ec/ecdsa_default_vrfy_raw.c \
|
||||
src/ec/ecdsa_i15_bits.c \
|
||||
src/ec/ecdsa_i15_sign_asn1.c \
|
||||
src/ec/ecdsa_i15_sign_raw.c \
|
||||
src/ec/ecdsa_i15_vrfy_asn1.c \
|
||||
src/ec/ecdsa_i15_vrfy_raw.c \
|
||||
src/ec/ecdsa_i31_bits.c \
|
||||
src/ec/ecdsa_i31_sign_asn1.c \
|
||||
src/ec/ecdsa_i31_sign_raw.c \
|
||||
src/ec/ecdsa_i31_vrfy_asn1.c \
|
||||
src/ec/ecdsa_i31_vrfy_raw.c \
|
||||
src/ec/ecdsa_rta.c \
|
||||
src/hash/dig_oid.c \
|
||||
src/hash/dig_size.c \
|
||||
src/hash/ghash_ctmul.c \
|
||||
src/hash/ghash_ctmul32.c \
|
||||
src/hash/ghash_ctmul64.c \
|
||||
src/hash/ghash_pclmul.c \
|
||||
src/hash/ghash_pwr8.c \
|
||||
src/hash/md5.c \
|
||||
src/hash/md5sha1.c \
|
||||
src/hash/mgf1.c \
|
||||
src/hash/multihash.c \
|
||||
src/hash/sha1.c \
|
||||
src/hash/sha2big.c \
|
||||
src/hash/sha2small.c \
|
||||
src/int/i15_add.c \
|
||||
src/int/i15_bitlen.c \
|
||||
src/int/i15_decmod.c \
|
||||
src/int/i15_decode.c \
|
||||
src/int/i15_decred.c \
|
||||
src/int/i15_encode.c \
|
||||
src/int/i15_fmont.c \
|
||||
src/int/i15_iszero.c \
|
||||
src/int/i15_moddiv.c \
|
||||
src/int/i15_modpow.c \
|
||||
src/int/i15_modpow2.c \
|
||||
src/int/i15_montmul.c \
|
||||
src/int/i15_mulacc.c \
|
||||
src/int/i15_muladd.c \
|
||||
src/int/i15_ninv15.c \
|
||||
src/int/i15_reduce.c \
|
||||
src/int/i15_rshift.c \
|
||||
src/int/i15_sub.c \
|
||||
src/int/i15_tmont.c \
|
||||
src/int/i31_add.c \
|
||||
src/int/i31_bitlen.c \
|
||||
src/int/i31_decmod.c \
|
||||
src/int/i31_decode.c \
|
||||
src/int/i31_decred.c \
|
||||
src/int/i31_encode.c \
|
||||
src/int/i31_fmont.c \
|
||||
src/int/i31_iszero.c \
|
||||
src/int/i31_moddiv.c \
|
||||
src/int/i31_modpow.c \
|
||||
src/int/i31_modpow2.c \
|
||||
src/int/i31_montmul.c \
|
||||
src/int/i31_mulacc.c \
|
||||
src/int/i31_muladd.c \
|
||||
src/int/i31_ninv31.c \
|
||||
src/int/i31_reduce.c \
|
||||
src/int/i31_rshift.c \
|
||||
src/int/i31_sub.c \
|
||||
src/int/i31_tmont.c \
|
||||
src/int/i32_add.c \
|
||||
src/int/i32_bitlen.c \
|
||||
src/int/i32_decmod.c \
|
||||
src/int/i32_decode.c \
|
||||
src/int/i32_decred.c \
|
||||
src/int/i32_div32.c \
|
||||
src/int/i32_encode.c \
|
||||
src/int/i32_fmont.c \
|
||||
src/int/i32_iszero.c \
|
||||
src/int/i32_modpow.c \
|
||||
src/int/i32_montmul.c \
|
||||
src/int/i32_mulacc.c \
|
||||
src/int/i32_muladd.c \
|
||||
src/int/i32_ninv32.c \
|
||||
src/int/i32_reduce.c \
|
||||
src/int/i32_sub.c \
|
||||
src/int/i32_tmont.c \
|
||||
src/int/i62_modpow2.c \
|
||||
src/kdf/hkdf.c \
|
||||
src/kdf/shake.c \
|
||||
src/mac/hmac.c \
|
||||
src/mac/hmac_ct.c \
|
||||
src/rand/aesctr_drbg.c \
|
||||
src/rand/hmac_drbg.c \
|
||||
src/rand/sysrng.c \
|
||||
src/rsa/rsa_default_keygen.c \
|
||||
src/rsa/rsa_default_modulus.c \
|
||||
src/rsa/rsa_default_oaep_decrypt.c \
|
||||
src/rsa/rsa_default_oaep_encrypt.c \
|
||||
src/rsa/rsa_default_pkcs1_sign.c \
|
||||
src/rsa/rsa_default_pkcs1_vrfy.c \
|
||||
src/rsa/rsa_default_priv.c \
|
||||
src/rsa/rsa_default_privexp.c \
|
||||
src/rsa/rsa_default_pss_sign.c \
|
||||
src/rsa/rsa_default_pss_vrfy.c \
|
||||
src/rsa/rsa_default_pub.c \
|
||||
src/rsa/rsa_default_pubexp.c \
|
||||
src/rsa/rsa_i15_keygen.c \
|
||||
src/rsa/rsa_i15_modulus.c \
|
||||
src/rsa/rsa_i15_oaep_decrypt.c \
|
||||
src/rsa/rsa_i15_oaep_encrypt.c \
|
||||
src/rsa/rsa_i15_pkcs1_sign.c \
|
||||
src/rsa/rsa_i15_pkcs1_vrfy.c \
|
||||
src/rsa/rsa_i15_priv.c \
|
||||
src/rsa/rsa_i15_privexp.c \
|
||||
src/rsa/rsa_i15_pss_sign.c \
|
||||
src/rsa/rsa_i15_pss_vrfy.c \
|
||||
src/rsa/rsa_i15_pub.c \
|
||||
src/rsa/rsa_i15_pubexp.c \
|
||||
src/rsa/rsa_i31_keygen.c \
|
||||
src/rsa/rsa_i31_keygen_inner.c \
|
||||
src/rsa/rsa_i31_modulus.c \
|
||||
src/rsa/rsa_i31_oaep_decrypt.c \
|
||||
src/rsa/rsa_i31_oaep_encrypt.c \
|
||||
src/rsa/rsa_i31_pkcs1_sign.c \
|
||||
src/rsa/rsa_i31_pkcs1_vrfy.c \
|
||||
src/rsa/rsa_i31_priv.c \
|
||||
src/rsa/rsa_i31_privexp.c \
|
||||
src/rsa/rsa_i31_pss_sign.c \
|
||||
src/rsa/rsa_i31_pss_vrfy.c \
|
||||
src/rsa/rsa_i31_pub.c \
|
||||
src/rsa/rsa_i31_pubexp.c \
|
||||
src/rsa/rsa_i32_oaep_decrypt.c \
|
||||
src/rsa/rsa_i32_oaep_encrypt.c \
|
||||
src/rsa/rsa_i32_pkcs1_sign.c \
|
||||
src/rsa/rsa_i32_pkcs1_vrfy.c \
|
||||
src/rsa/rsa_i32_priv.c \
|
||||
src/rsa/rsa_i32_pss_sign.c \
|
||||
src/rsa/rsa_i32_pss_vrfy.c \
|
||||
src/rsa/rsa_i32_pub.c \
|
||||
src/rsa/rsa_i62_keygen.c \
|
||||
src/rsa/rsa_i62_oaep_decrypt.c \
|
||||
src/rsa/rsa_i62_oaep_encrypt.c \
|
||||
src/rsa/rsa_i62_pkcs1_sign.c \
|
||||
src/rsa/rsa_i62_pkcs1_vrfy.c \
|
||||
src/rsa/rsa_i62_priv.c \
|
||||
src/rsa/rsa_i62_pss_sign.c \
|
||||
src/rsa/rsa_i62_pss_vrfy.c \
|
||||
src/rsa/rsa_i62_pub.c \
|
||||
src/rsa/rsa_oaep_pad.c \
|
||||
src/rsa/rsa_oaep_unpad.c \
|
||||
src/rsa/rsa_pkcs1_sig_pad.c \
|
||||
src/rsa/rsa_pkcs1_sig_unpad.c \
|
||||
src/rsa/rsa_pss_sig_pad.c \
|
||||
src/rsa/rsa_pss_sig_unpad.c \
|
||||
src/rsa/rsa_ssl_decrypt.c \
|
||||
src/ssl/prf.c \
|
||||
src/ssl/prf_md5sha1.c \
|
||||
src/ssl/prf_sha256.c \
|
||||
src/ssl/prf_sha384.c \
|
||||
src/ssl/ssl_ccert_single_ec.c \
|
||||
src/ssl/ssl_ccert_single_rsa.c \
|
||||
src/ssl/ssl_client.c \
|
||||
src/ssl/ssl_client_default_rsapub.c \
|
||||
src/ssl/ssl_client_full.c \
|
||||
src/ssl/ssl_engine.c \
|
||||
src/ssl/ssl_engine_default_aescbc.c \
|
||||
src/ssl/ssl_engine_default_aesccm.c \
|
||||
src/ssl/ssl_engine_default_aesgcm.c \
|
||||
src/ssl/ssl_engine_default_chapol.c \
|
||||
src/ssl/ssl_engine_default_descbc.c \
|
||||
src/ssl/ssl_engine_default_ec.c \
|
||||
src/ssl/ssl_engine_default_ecdsa.c \
|
||||
src/ssl/ssl_engine_default_rsavrfy.c \
|
||||
src/ssl/ssl_hashes.c \
|
||||
src/ssl/ssl_hs_client.c \
|
||||
src/ssl/ssl_hs_server.c \
|
||||
src/ssl/ssl_io.c \
|
||||
src/ssl/ssl_keyexport.c \
|
||||
src/ssl/ssl_lru.c \
|
||||
src/ssl/ssl_rec_cbc.c \
|
||||
src/ssl/ssl_rec_ccm.c \
|
||||
src/ssl/ssl_rec_chapol.c \
|
||||
src/ssl/ssl_rec_gcm.c \
|
||||
src/ssl/ssl_scert_single_ec.c \
|
||||
src/ssl/ssl_scert_single_rsa.c \
|
||||
src/ssl/ssl_server.c \
|
||||
src/ssl/ssl_server_full_ec.c \
|
||||
src/ssl/ssl_server_full_rsa.c \
|
||||
src/ssl/ssl_server_mine2c.c \
|
||||
src/ssl/ssl_server_mine2g.c \
|
||||
src/ssl/ssl_server_minf2c.c \
|
||||
src/ssl/ssl_server_minf2g.c \
|
||||
src/ssl/ssl_server_minr2g.c \
|
||||
src/ssl/ssl_server_minu2g.c \
|
||||
src/ssl/ssl_server_minv2g.c \
|
||||
src/symcipher/aes_big_cbcdec.c \
|
||||
src/symcipher/aes_big_cbcenc.c \
|
||||
src/symcipher/aes_big_ctr.c \
|
||||
src/symcipher/aes_big_ctrcbc.c \
|
||||
src/symcipher/aes_big_dec.c \
|
||||
src/symcipher/aes_big_enc.c \
|
||||
src/symcipher/aes_common.c \
|
||||
src/symcipher/aes_ct.c \
|
||||
src/symcipher/aes_ct64.c \
|
||||
src/symcipher/aes_ct64_cbcdec.c \
|
||||
src/symcipher/aes_ct64_cbcenc.c \
|
||||
src/symcipher/aes_ct64_ctr.c \
|
||||
src/symcipher/aes_ct64_ctrcbc.c \
|
||||
src/symcipher/aes_ct64_dec.c \
|
||||
src/symcipher/aes_ct64_enc.c \
|
||||
src/symcipher/aes_ct_cbcdec.c \
|
||||
src/symcipher/aes_ct_cbcenc.c \
|
||||
src/symcipher/aes_ct_ctr.c \
|
||||
src/symcipher/aes_ct_ctrcbc.c \
|
||||
src/symcipher/aes_ct_dec.c \
|
||||
src/symcipher/aes_ct_enc.c \
|
||||
src/symcipher/aes_pwr8.c \
|
||||
src/symcipher/aes_pwr8_cbcdec.c \
|
||||
src/symcipher/aes_pwr8_cbcenc.c \
|
||||
src/symcipher/aes_pwr8_ctr.c \
|
||||
src/symcipher/aes_pwr8_ctrcbc.c \
|
||||
src/symcipher/aes_small_cbcdec.c \
|
||||
src/symcipher/aes_small_cbcenc.c \
|
||||
src/symcipher/aes_small_ctr.c \
|
||||
src/symcipher/aes_small_ctrcbc.c \
|
||||
src/symcipher/aes_small_dec.c \
|
||||
src/symcipher/aes_small_enc.c \
|
||||
src/symcipher/aes_x86ni.c \
|
||||
src/symcipher/aes_x86ni_cbcdec.c \
|
||||
src/symcipher/aes_x86ni_cbcenc.c \
|
||||
src/symcipher/aes_x86ni_ctr.c \
|
||||
src/symcipher/aes_x86ni_ctrcbc.c \
|
||||
src/symcipher/chacha20_ct.c \
|
||||
src/symcipher/chacha20_sse2.c \
|
||||
src/symcipher/des_ct.c \
|
||||
src/symcipher/des_ct_cbcdec.c \
|
||||
src/symcipher/des_ct_cbcenc.c \
|
||||
src/symcipher/des_support.c \
|
||||
src/symcipher/des_tab.c \
|
||||
src/symcipher/des_tab_cbcdec.c \
|
||||
src/symcipher/des_tab_cbcenc.c \
|
||||
src/symcipher/poly1305_ctmul.c \
|
||||
src/symcipher/poly1305_ctmul32.c \
|
||||
src/symcipher/poly1305_ctmulq.c \
|
||||
src/symcipher/poly1305_i15.c \
|
||||
src/x509/asn1enc.c \
|
||||
src/x509/encode_ec_pk8der.c \
|
||||
src/x509/encode_ec_rawder.c \
|
||||
src/x509/encode_rsa_pk8der.c \
|
||||
src/x509/encode_rsa_rawder.c \
|
||||
src/x509/skey_decoder.c \
|
||||
src/x509/x509_decoder.c \
|
||||
src/x509/x509_knownkey.c \
|
||||
src/x509/x509_minimal.c \
|
||||
src/x509/x509_minimal_full.c"
|
||||
|
||||
# Source files for the 'brssl' command-line tool.
|
||||
toolssrc=" \
|
||||
tools/brssl.c \
|
||||
tools/certs.c \
|
||||
tools/chain.c \
|
||||
tools/client.c \
|
||||
tools/errors.c \
|
||||
tools/files.c \
|
||||
tools/impl.c \
|
||||
tools/keys.c \
|
||||
tools/names.c \
|
||||
tools/server.c \
|
||||
tools/skey.c \
|
||||
tools/sslio.c \
|
||||
tools/ta.c \
|
||||
tools/twrch.c \
|
||||
tools/vector.c \
|
||||
tools/verify.c \
|
||||
tools/xmem.c"
|
||||
|
||||
# Source files the the 'testcrypto' command-line tool.
|
||||
testcryptosrc=" \
|
||||
test/test_crypto.c"
|
||||
|
||||
# Source files the the 'testspeed' command-line tool.
|
||||
testspeedsrc=" \
|
||||
test/test_speed.c"
|
||||
|
||||
# Source files the the 'testx509' command-line tool.
|
||||
testx509src=" \
|
||||
test/test_x509.c"
|
||||
|
||||
# Public header files.
|
||||
headerspub=" \
|
||||
inc/bearssl.h \
|
||||
inc/bearssl_aead.h \
|
||||
inc/bearssl_block.h \
|
||||
inc/bearssl_ec.h \
|
||||
inc/bearssl_hash.h \
|
||||
inc/bearssl_hmac.h \
|
||||
inc/bearssl_kdf.h \
|
||||
inc/bearssl_pem.h \
|
||||
inc/bearssl_prf.h \
|
||||
inc/bearssl_rand.h \
|
||||
inc/bearssl_rsa.h \
|
||||
inc/bearssl_ssl.h \
|
||||
inc/bearssl_x509.h"
|
||||
|
||||
# Private header files.
|
||||
headerspriv=" \
|
||||
src/config.h \
|
||||
src/inner.h"
|
||||
|
||||
# Header files for the 'brssl' command-line tool.
|
||||
headerstools=" \
|
||||
tools/brssl.h"
|
||||
|
||||
# T0 compiler source code.
|
||||
t0compsrc=" \
|
||||
T0/BlobWriter.cs \
|
||||
T0/CPU.cs \
|
||||
T0/CodeElement.cs \
|
||||
T0/CodeElementJump.cs \
|
||||
T0/CodeElementUInt.cs \
|
||||
T0/CodeElementUIntExpr.cs \
|
||||
T0/CodeElementUIntInt.cs \
|
||||
T0/CodeElementUIntUInt.cs \
|
||||
T0/ConstData.cs \
|
||||
T0/Opcode.cs \
|
||||
T0/OpcodeCall.cs \
|
||||
T0/OpcodeConst.cs \
|
||||
T0/OpcodeGetLocal.cs \
|
||||
T0/OpcodeJump.cs \
|
||||
T0/OpcodeJumpIf.cs \
|
||||
T0/OpcodeJumpIfNot.cs \
|
||||
T0/OpcodeJumpUncond.cs \
|
||||
T0/OpcodePutLocal.cs \
|
||||
T0/OpcodeRet.cs \
|
||||
T0/SType.cs \
|
||||
T0/T0Comp.cs \
|
||||
T0/TPointerBase.cs \
|
||||
T0/TPointerBlob.cs \
|
||||
T0/TPointerExpr.cs \
|
||||
T0/TPointerNull.cs \
|
||||
T0/TPointerXT.cs \
|
||||
T0/TValue.cs \
|
||||
T0/Word.cs \
|
||||
T0/WordBuilder.cs \
|
||||
T0/WordData.cs \
|
||||
T0/WordInterpreted.cs \
|
||||
T0/WordNative.cs"
|
||||
|
||||
t0compkern=" \
|
||||
T0/kern.t0"
|
||||
|
||||
# Function to turn slashes into $P (macro for path separator).
|
||||
escsep() {
|
||||
printf '%s' "$1" | sed 's/\//$P/g'
|
||||
}
|
||||
|
||||
# Create rules file.
|
||||
rm -f Rules.mk
|
||||
cat > Rules.mk <<EOF
|
||||
# Automatically generated rules. Use 'mkrules.sh' to modify/regenerate.
|
||||
EOF
|
||||
|
||||
(printf "\nOBJ ="
|
||||
for f in $coresrc ; do
|
||||
printf ' \\\n $(OBJDIR)$P%s' "$(basename "$f" .c)\$O"
|
||||
done
|
||||
printf "\nOBJBRSSL ="
|
||||
for f in $toolssrc ; do
|
||||
printf ' \\\n $(OBJDIR)$P%s' "$(basename "$f" .c)\$O"
|
||||
done
|
||||
printf "\nOBJTESTCRYPTO ="
|
||||
for f in $testcryptosrc ; do
|
||||
printf ' \\\n $(OBJDIR)$P%s' "$(basename "$f" .c)\$O"
|
||||
done
|
||||
printf "\nOBJTESTSPEED ="
|
||||
for f in $testspeedsrc ; do
|
||||
printf ' \\\n $(OBJDIR)$P%s' "$(basename "$f" .c)\$O"
|
||||
done
|
||||
printf "\nOBJTESTX509 ="
|
||||
for f in $testx509src ; do
|
||||
printf ' \\\n $(OBJDIR)$P%s' "$(basename "$f" .c)\$O"
|
||||
done
|
||||
printf "\nHEADERSPUB ="
|
||||
for f in $headerspub ; do
|
||||
printf " %s" "$(escsep "$f")"
|
||||
done
|
||||
printf "\nHEADERSPRIV = %s" '$(HEADERSPUB)'
|
||||
for f in $headerspriv ; do
|
||||
printf " %s" "$(escsep "$f")"
|
||||
done
|
||||
printf "\nHEADERSTOOLS = %s" '$(HEADERSPUB)'
|
||||
for f in $headerstools ; do
|
||||
printf " %s" "$(escsep "$f")"
|
||||
done
|
||||
printf "\nT0SRC ="
|
||||
for f in $t0compsrc ; do
|
||||
printf " %s" "$(escsep "$f")"
|
||||
done
|
||||
printf "\nT0KERN ="
|
||||
for f in $t0kernsrc ; do
|
||||
printf " %s" "$(escsep "$f")"
|
||||
done
|
||||
printf "\n") >> Rules.mk
|
||||
|
||||
cat >> Rules.mk <<EOF
|
||||
|
||||
all: \$(STATICLIB) \$(DLL) \$(TOOLS) \$(TESTS)
|
||||
|
||||
no:
|
||||
|
||||
lib: \$(BEARSSLLIB)
|
||||
|
||||
dll: \$(BEARSSLDLL)
|
||||
|
||||
tools: \$(BRSSL)
|
||||
|
||||
tests: \$(TESTCRYPTO) \$(TESTSPEED) \$(TESTX509)
|
||||
|
||||
T0: kT0
|
||||
|
||||
kT0: \$(T0COMP) src\$Pssl\$Pssl_hs_common.t0 src\$Pssl\$Pssl_hs_client.t0 src\$Pssl\$Pssl_hs_server.t0 src\$Px509\$Pasn1.t0 src\$Px509\$Pskey_decoder.t0 src\$Px509\$Px509_decoder.t0 src\$Px509\$Px509_minimal.t0
|
||||
\$(RUNT0COMP) -o src\$Pcodec\$Ppemdec -r br_pem_decoder src\$Pcodec\$Ppemdec.t0
|
||||
\$(RUNT0COMP) -o src\$Pssl\$Pssl_hs_client -r br_ssl_hs_client src\$Pssl\$Pssl_hs_common.t0 src\$Pssl\$Pssl_hs_client.t0
|
||||
\$(RUNT0COMP) -o src\$Pssl\$Pssl_hs_server -r br_ssl_hs_server src\$Pssl\$Pssl_hs_common.t0 src\$Pssl\$Pssl_hs_server.t0
|
||||
\$(RUNT0COMP) -o src\$Px509\$Pskey_decoder -r br_skey_decoder src\$Px509\$Pasn1.t0 src\$Px509\$Pskey_decoder.t0
|
||||
\$(RUNT0COMP) -o src\$Px509\$Px509_decoder -r br_x509_decoder src\$Px509\$Pasn1.t0 src\$Px509\$Px509_decoder.t0
|
||||
\$(RUNT0COMP) -o src\$Px509\$Px509_minimal -r br_x509_minimal src\$Px509\$Pasn1.t0 src\$Px509\$Px509_minimal.t0
|
||||
|
||||
\$(T0COMP): \$(T0SRC) \$(T0KERN)
|
||||
\$(MKT0COMP)
|
||||
|
||||
clean:
|
||||
-\$(RM) \$(OBJDIR)\$P*\$O
|
||||
-\$(RM) \$(BEARSSLLIB) \$(BEARSSLDLL) \$(BRSSL) \$(TESTCRYPTO) \$(TESTSPEED) \$(TESTX509)
|
||||
|
||||
\$(OBJDIR):
|
||||
-\$(MKDIR) \$(OBJDIR)
|
||||
|
||||
\$(BEARSSLLIB): \$(OBJDIR) \$(OBJ)
|
||||
\$(AR) \$(ARFLAGS) \$(AROUT)\$(BEARSSLLIB) \$(OBJ)
|
||||
|
||||
\$(BEARSSLDLL): \$(OBJDIR) \$(OBJ)
|
||||
\$(LDDLL) \$(LDDLLFLAGS) \$(LDDLLOUT)\$(BEARSSLDLL) \$(OBJ)
|
||||
|
||||
\$(BRSSL): \$(BEARSSLLIB) \$(OBJBRSSL)
|
||||
\$(LD) \$(LDFLAGS) \$(LDOUT)\$(BRSSL) \$(OBJBRSSL) \$(BEARSSLLIB)
|
||||
|
||||
\$(TESTCRYPTO): \$(BEARSSLLIB) \$(OBJTESTCRYPTO)
|
||||
\$(LD) \$(LDFLAGS) \$(LDOUT)\$(TESTCRYPTO) \$(OBJTESTCRYPTO) \$(BEARSSLLIB)
|
||||
|
||||
\$(TESTSPEED): \$(BEARSSLLIB) \$(OBJTESTSPEED)
|
||||
\$(LD) \$(LDFLAGS) \$(LDOUT)\$(TESTSPEED) \$(OBJTESTSPEED) \$(BEARSSLLIB)
|
||||
|
||||
\$(TESTX509): \$(BEARSSLLIB) \$(OBJTESTX509)
|
||||
\$(LD) \$(LDFLAGS) \$(LDOUT)\$(TESTX509) \$(OBJTESTX509) \$(BEARSSLLIB)
|
||||
EOF
|
||||
|
||||
(for f in $coresrc ; do
|
||||
b="$(basename "$f" .c)\$O"
|
||||
g="$(escsep "$f")"
|
||||
printf '\n$(OBJDIR)$P%s: %s $(HEADERSPRIV)\n\t$(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$P%s %s\n' "$b" "$g" "$b" "$g"
|
||||
done
|
||||
|
||||
for f in $toolssrc ; do
|
||||
b="$(basename "$f" .c)\$O"
|
||||
g="$(escsep "$f")"
|
||||
printf '\n$(OBJDIR)$P%s: %s $(HEADERSTOOLS)\n\t$(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$P%s %s\n' "$b" "$g" "$b" "$g"
|
||||
done
|
||||
|
||||
for f in $testcryptosrc $testspeedsrc ; do
|
||||
b="$(basename "$f" .c)\$O"
|
||||
g="$(escsep "$f")"
|
||||
printf '\n$(OBJDIR)$P%s: %s $(HEADERSPRIV)\n\t$(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$P%s %s\n' "$b" "$g" "$b" "$g"
|
||||
done
|
||||
|
||||
for f in $testx509src ; do
|
||||
b="$(basename "$f" .c)\$O"
|
||||
g="$(escsep "$f")"
|
||||
printf '\n$(OBJDIR)$P%s: %s $(HEADERSPRIV)\n\t$(CC) $(CFLAGS) $(INCFLAGS) -DSRCDIRNAME=".." $(CCOUT)$(OBJDIR)$P%s %s\n' "$b" "$g" "$b" "$g"
|
||||
done) >> Rules.mk
|
36
contrib/bearssl/samples/README.txt
Normal file
36
contrib/bearssl/samples/README.txt
Normal file
@ -0,0 +1,36 @@
|
||||
This directory contains sample code for using BearSSL.
|
||||
|
||||
client_basic.c
|
||||
|
||||
A sample client code, that connects to a server, performs a SSL
|
||||
handshake, sends a basic HTTP GET request, and dumps the complete
|
||||
answer on stdout.
|
||||
|
||||
Compile it against BearSSL headers (in the ../inc directory) and
|
||||
library (libbearssl.a). This code will validate the server
|
||||
certificate against two hardcoded trust anchors.
|
||||
|
||||
server_basic.c
|
||||
|
||||
A sample SSL server, that serves one client at a time. It reads a
|
||||
single HTTP request (that it does not really parse; it just waits for
|
||||
the two successive line endings that mark the end of the request),
|
||||
and pushes a basic response.
|
||||
|
||||
Compile it against BearSSL headers (in the ../inc directory) and
|
||||
library (libbearssl.a). Depending on compilation options (see the
|
||||
code), it will use one of several certificate chains, that exercise
|
||||
various combinations of RSA and EC keys and signatures. These
|
||||
certificate chains link to the trust anchors that are hardcoded
|
||||
in client_basic.c, so the sample client and the sample server can
|
||||
be tested against each other.
|
||||
|
||||
custom_profile.c
|
||||
|
||||
A sample C source file that shows how to write your own client or
|
||||
server profiles (selections of cipher suites and algorithms).
|
||||
|
||||
|
||||
The .pem files are certificate and keys corresponding to the chains
|
||||
and anchors used by the sample client and server. They are provided
|
||||
for reference only; these files are not used by the examples.
|
14
contrib/bearssl/samples/cert-ee-ec+rsa.pem
Normal file
14
contrib/bearssl/samples/cert-ee-ec+rsa.pem
Normal file
@ -0,0 +1,14 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICcTCCAVmgAwIBAgIUbmO7Sc5BfgOM9Ubyiq5hCDWwlLMwDQYJKoZIhvcNAQELBQAwJzELMAkG
|
||||
A1UEBhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEy
|
||||
MzEyMzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIB
|
||||
BggqhkjOPQMBBwNCAARfOJ2n/02Kr/Y0OUYa/Drf9COqqer7xQjeAI6+eaU3WExt3QHKq0ffibbH
|
||||
Fx84/B0gFN1FwOCPk044C/zpmaFJo2YwZDAfBgNVHSMEGDAWgBR8z6PGKffzxaoZ0MAW6+BAD85E
|
||||
pzAdBgNVHQ4EFgQUww6GqnW0FcDllQkyvl6SdankRJswDAYDVR0TAQH/BAIwADAUBgNVHREEDTAL
|
||||
gglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAI6JY6ebqBCOnhjQpHrdLIIWjwsO1cpXu19v
|
||||
/FcowCG6rZSoF0JF1zH3hFcZRiQ8x0k4P0h6CRrrUbrFdY5MsiWwxyI+5+VG27E2/BuFUbDtgxbw
|
||||
OnnaXShq7mogTLBwXrDtem0tGsm0ccLEox0lhjBUsZgmwVHg+DGtZ0id5qFSOyBHyXDagLWk9D9y
|
||||
azcwVzksRptE8dlOu6Zf45rFf2y2Zcu/QHKS0Gj2rnl+JMFbaDAoU3FhevQ2ezvCtuwf3DBABA3q
|
||||
swrPddO9nqtxcWh/pUFSAOmzruQe8btpxjvV3tLCJWkIPDfM94Jq5ah7agLavaQBMzPz3kYA7HXP
|
||||
4H0=
|
||||
-----END CERTIFICATE-----
|
10
contrib/bearssl/samples/cert-ee-ec.pem
Normal file
10
contrib/bearssl/samples/cert-ee-ec.pem
Normal file
@ -0,0 +1,10 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBsDCCAVagAwIBAgIUHE0AkWniRqyQfGRcU/H/t8HLbnowCgYIKoZIzj0EAwIwJzELMAkGA1UE
|
||||
BhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEy
|
||||
MzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggq
|
||||
hkjOPQMBBwNCAARfOJ2n/02Kr/Y0OUYa/Drf9COqqer7xQjeAI6+eaU3WExt3QHKq0ffibbHFx84
|
||||
/B0gFN1FwOCPk044C/zpmaFJo2YwZDAfBgNVHSMEGDAWgBTw0PEi+XpIFwZ7Pb249c1VnFw+cDAd
|
||||
BgNVHQ4EFgQUww6GqnW0FcDllQkyvl6SdankRJswDAYDVR0TAQH/BAIwADAUBgNVHREEDTALggls
|
||||
b2NhbGhvc3QwCgYIKoZIzj0EAwIDSAAwRQIhAJH79ATQ5S4B1IzwF2IP3MyAyhjEQHwnA8s0Aw2b
|
||||
yFlNAiAFVWni2KFAMzQOfkkyZB0/ax/QLbcvUgRWr9M3j4eZog==
|
||||
-----END CERTIFICATE-----
|
17
contrib/bearssl/samples/cert-ee-rsa.pem
Normal file
17
contrib/bearssl/samples/cert-ee-rsa.pem
Normal file
@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPDCCAiSgAwIBAgIUWNq6Ns3toNpcEDNzjgxkknmSrwMwDQYJKoZIhvcNAQELBQAwJzELMAkG
|
||||
A1UEBhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEy
|
||||
MzEyMzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQDUeh0nuis6Z7KRavvng0TK7Rx1rd1Ng2LWqmiVsiQhexWuKplo
|
||||
Fe1m8LhY59P1LsbZKl7nDi7n/GdZwMhhfUukb92f2ciFh2THuhoPKdSWqHiaa2IgqTLQ7qmMKGFH
|
||||
olAqY/Yh3trY1fB/xQCCcOajv1yJJ09RkncDw7DMLjvsI/IvU0GviZP/0oCxQ5fe1hmgkhJ6PWZ5
|
||||
4cG84Xdwoos9RoRTP+ROQkE3kh4f/Tiz9++HOYDTVs/04BPeZLBypAOExEHtb/o+4soEINLX3CyC
|
||||
K3ribaEcSNvPiU80lz0oqFPa58HhcxWjMHZ/jyNCFD1RNNJarTyby8j+f26OQPO9AgMBAAGjZjBk
|
||||
MB8GA1UdIwQYMBaAFMUBrXzmY8mcF1/FoqfhUF/o9ajGMB0GA1UdDgQWBBTFAa185mPJnBdfxaKn
|
||||
4VBf6PWoxjAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsF
|
||||
AAOCAQEAcbNdIcIO19DG+Epzh00iAifQx/j9Gm1iWIIIdiAHwEiS8+mYWusNTlaVY2hNq9QAduA3
|
||||
zwsRYVlc3valFFnZJZ9Z2dNehqwdpiwyQhkyE0ALVM1nJra9tJakyh9/N9aodes6gVEwuflKAW/R
|
||||
1u1P3z8wYAZnko5hhV8atYyzD2Gp+t9dxGQA6oexM199y6OFJG4sZTvqcz+G0/3o5ALGYWomF1IB
|
||||
JVx/qM5pH6xhLLcEr/2kepnLJhVM/3TUcwxXDCbr1yrcXMNBu8Lzzha9jnv76d+rIQ2Rs43Yz8j0
|
||||
SbnQ4xZwP7Pe1Acl+kZEUolNicjiyrUzf8chvSjv/mZ0Aw==
|
||||
-----END CERTIFICATE-----
|
10
contrib/bearssl/samples/cert-ica-ec.pem
Normal file
10
contrib/bearssl/samples/cert-ica-ec.pem
Normal file
@ -0,0 +1,10 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBqTCCAU6gAwIBAgIUINPr4oz+2uajLF478mY6KzZ7sMowCgYIKoZIzj0EAwIwHDELMAkGA1UE
|
||||
BhMCQ0ExDTALBgNVBAMTBFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMzcxMjMxMjM1OTU5WjAnMQsw
|
||||
CQYDVQQGEwJDQTEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0D
|
||||
AQcDQgAEcC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDN
|
||||
SZ4Hv9CunebQsycWoaNjMGEwHwYDVR0jBBgwFoAUlUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0O
|
||||
BBYEFPDQ8SL5ekgXBns9vbj1zVWcXD5wMA4GA1UdDwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/
|
||||
MAoGCCqGSM49BAMCA0kAMEYCIQCF40ZomdYCellmHLdPNS0INjhhfgVI2GlDH+tW6a0GDgIhAIJw
|
||||
tGIDSUbIVFkF2XjbUxzgbmb1DxQ7yS04EnCRVvmp
|
||||
-----END CERTIFICATE-----
|
17
contrib/bearssl/samples/cert-ica-rsa.pem
Normal file
17
contrib/bearssl/samples/cert-ica-rsa.pem
Normal file
@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDNDCCAhygAwIBAgIUcA9g7vAHmpxprJdiJk9dBbb5j0gwDQYJKoZIhvcNAQELBQAwHDELMAkG
|
||||
A1UEBhMCQ0ExDTALBgNVBAMTBFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMzcxMjMxMjM1OTU5WjAn
|
||||
MQswCQYDVQQGEwJDQTEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
||||
AAOCAQ8AMIIBCgKCAQEAs+hrr5wWUuOBDFCrJc7MDcfyH39Q3yxcNdZiLmMnQafkU6hLJ/oTkaP6
|
||||
CUovO17Pd7OKwc1JlZx1DWR07+TXS7mhm2jSMHFI6vdLFN8/R6nYu+yPKMz637QflHyW/AgFKPno
|
||||
9C8v7mKcijrghVhgtg8tMLTAQVSRTB9frfEZ8MAipn3YP3k0WUJ7W7VBxGR/Us88NyKhL3kllCRB
|
||||
wj/6x3X7SLUNGKf0VPMubthDWMSrUOgFrZG2HgF1s1Sc3qCZFfus8VyXSVHM71gSb3NrszQUAQ9a
|
||||
nfqq1pPT4urDq7xO7cxRobj4lLa0LKiGKx/2UUMpUl4TibNqeGBOTsAbpQIDAQABo2MwYTAfBgNV
|
||||
HSMEGDAWgBTDCry0kGOWkkW8J6DwWIkq1XgAEjAdBgNVHQ4EFgQUfM+jxin388WqGdDAFuvgQA/O
|
||||
RKcwDgYDVR0PAQH/BAQDAgCGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFQ7
|
||||
9OrG5OjAWxKyrfq9qfRiA61XTG8Hp0c1dT5IoltxEAGPk5mdp0fjjj6vLboG/tTkl7wQjaalOjzm
|
||||
Ics72hPjSiPrvLqlkJGtVW7V3YVLayfSOXYGLtQjW7tVtUk/fS8hy5Z1GZmpmfELuz7HEKeLelK5
|
||||
SeQUCHjnPdmYV9r/2rmNZnWAtV2532ll2xbnHsRA5EaKHnYyFueDZ9p4VqsPTFzxcNpmIPT4D/bc
|
||||
L3KXa3hAeZ1bbb4DznBCqCpxEd8ugQHqhhKRT9AY7YSkSDC5uXtWPu+N4R/9kLJEhVhvpzB0fPGu
|
||||
jJk/8U1XxZVowjay7MJoesCBqVUF58+vUKw=
|
||||
-----END CERTIFICATE-----
|
9
contrib/bearssl/samples/cert-root-ec.pem
Normal file
9
contrib/bearssl/samples/cert-root-ec.pem
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBijCCATCgAwIBAgIBCTAKBggqhkjOPQQDAjAcMQswCQYDVQQGEwJDQTENMAsGA1UEAxMEUm9v
|
||||
dDAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEyMzU5NTlaMBwxCzAJBgNVBAYTAkNBMQ0wCwYDVQQD
|
||||
EwRSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t
|
||||
6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eHwuXYxfN/jaNjMGEwHwYDVR0jBBgwFoAU
|
||||
lUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0OBBYEFJVBtOJnqvF/vI9582gUWmuSFqJAMA4GA1Ud
|
||||
DwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQCz1GCIAoRtqU2h
|
||||
x62hec7E+/XxnUGDORWnkliiGrcmxQIgNPq9NHD7ts0xYjTwZsd0bN62+iY93lM4LHbkNV9q/gA=
|
||||
-----END CERTIFICATE-----
|
16
contrib/bearssl/samples/cert-root-rsa.pem
Normal file
16
contrib/bearssl/samples/cert-root-rsa.pem
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFjCCAf6gAwIBAgIBCDANBgkqhkiG9w0BAQsFADAcMQswCQYDVQQGEwJDQTENMAsGA1UEAxME
|
||||
Um9vdDAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEyMzU5NTlaMBwxCzAJBgNVBAYTAkNBMQ0wCwYD
|
||||
VQQDEwRSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttk01FD9s696c/HOOL9d
|
||||
b0Xh/U6xmMZggybSF9HFt5qjwd5jOZec8F5cyBwXuYgZbfC2LjBQoVRuk8DbzzDLnx4nefHDmVI1
|
||||
qj2237CtfMtJzcDt52YQKunOKB8hUPp3TC3a7zxY606/zun7Gtqjg6PNo8qTgNza8xfMeqszgJyy
|
||||
1H9GP8U83GGUtycpbiq8Wwk21MY7Deu+ztsdHLwQanFxs/LKKJp38orsQu+xSo7i8hoyKs3ApkYs
|
||||
msKFN5F/RqGTgaF0Zt+6szkgkZP6HaGohefk+Qf2EPaoJwG2fxLDQMPJ4rCrSRg6ZLZZt5W1ljbf
|
||||
ImmqcmpUTicpow6XFQIDAQABo2MwYTAfBgNVHSMEGDAWgBTDCry0kGOWkkW8J6DwWIkq1XgAEjAd
|
||||
BgNVHQ4EFgQUwwq8tJBjlpJFvCeg8FiJKtV4ABIwDgYDVR0PAQH/BAQDAgCGMA8GA1UdEwEB/wQF
|
||||
MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA7SaR2V1Gx71RiL5Cdfr15jkU88snnm+v+0PvIfQrNP
|
||||
4RzKJkaD3j//oZf6Hr2yH6c7Bi3OhCxBFNbXjDXiAXVRoTjOSxNSwVq43utl9Z4IKAZzQlEYW5S5
|
||||
U0oskEq2q6jDEWoj8lUtQW4GAVuZhq7lNs0jJJu84IBsxHJFgZJ/7+LHFLXs+vQkz3hjzMZ7gIt+
|
||||
lwXI/gdY9ld1QB6WLLIzxs7zid+Z0LZTYi851vbmMwUqgL8V5Np0Q0EVHHy1c6LQ0hj1kVLay2ZN
|
||||
d2dsUMCQJI5EF2kWon+xFDpAtv0vUT2xuMkYFhjS/aBxzevWCsXuUQphBYaIGli8P68NNPo=
|
||||
-----END CERTIFICATE-----
|
166
contrib/bearssl/samples/chain-ec+rsa.h
Normal file
166
contrib/bearssl/samples/chain-ec+rsa.h
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* A sample server certificate chain with a single intermediate CA.
|
||||
* Certificate key type: EC
|
||||
* Signing algorithm for both certificates: RSA
|
||||
*/
|
||||
|
||||
static const unsigned char CERT0[] = {
|
||||
0x30, 0x82, 0x02, 0x71, 0x30, 0x82, 0x01, 0x59, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x6E, 0x63, 0xBB, 0x49, 0xCE, 0x41, 0x7E, 0x03, 0x8C,
|
||||
0xF5, 0x46, 0xF2, 0x8A, 0xAE, 0x61, 0x08, 0x35, 0xB0, 0x94, 0xB3, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64,
|
||||
0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31,
|
||||
0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A,
|
||||
0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39,
|
||||
0x35, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
|
||||
0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
|
||||
0x55, 0x04, 0x03, 0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F,
|
||||
0x73, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
|
||||
0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
|
||||
0x07, 0x03, 0x42, 0x00, 0x04, 0x5F, 0x38, 0x9D, 0xA7, 0xFF, 0x4D, 0x8A,
|
||||
0xAF, 0xF6, 0x34, 0x39, 0x46, 0x1A, 0xFC, 0x3A, 0xDF, 0xF4, 0x23, 0xAA,
|
||||
0xA9, 0xEA, 0xFB, 0xC5, 0x08, 0xDE, 0x00, 0x8E, 0xBE, 0x79, 0xA5, 0x37,
|
||||
0x58, 0x4C, 0x6D, 0xDD, 0x01, 0xCA, 0xAB, 0x47, 0xDF, 0x89, 0xB6, 0xC7,
|
||||
0x17, 0x1F, 0x38, 0xFC, 0x1D, 0x20, 0x14, 0xDD, 0x45, 0xC0, 0xE0, 0x8F,
|
||||
0x93, 0x4E, 0x38, 0x0B, 0xFC, 0xE9, 0x99, 0xA1, 0x49, 0xA3, 0x66, 0x30,
|
||||
0x64, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16,
|
||||
0x80, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA, 0x19,
|
||||
0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30, 0x1D,
|
||||
0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC3, 0x0E, 0x86,
|
||||
0xAA, 0x75, 0xB4, 0x15, 0xC0, 0xE5, 0x95, 0x09, 0x32, 0xBE, 0x5E, 0x92,
|
||||
0x75, 0xA9, 0xE4, 0x44, 0x9B, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13,
|
||||
0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x11, 0x04, 0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61,
|
||||
0x6C, 0x68, 0x6F, 0x73, 0x74, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48,
|
||||
0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01,
|
||||
0x00, 0x8E, 0x89, 0x63, 0xA7, 0x9B, 0xA8, 0x10, 0x8E, 0x9E, 0x18, 0xD0,
|
||||
0xA4, 0x7A, 0xDD, 0x2C, 0x82, 0x16, 0x8F, 0x0B, 0x0E, 0xD5, 0xCA, 0x57,
|
||||
0xBB, 0x5F, 0x6F, 0xFC, 0x57, 0x28, 0xC0, 0x21, 0xBA, 0xAD, 0x94, 0xA8,
|
||||
0x17, 0x42, 0x45, 0xD7, 0x31, 0xF7, 0x84, 0x57, 0x19, 0x46, 0x24, 0x3C,
|
||||
0xC7, 0x49, 0x38, 0x3F, 0x48, 0x7A, 0x09, 0x1A, 0xEB, 0x51, 0xBA, 0xC5,
|
||||
0x75, 0x8E, 0x4C, 0xB2, 0x25, 0xB0, 0xC7, 0x22, 0x3E, 0xE7, 0xE5, 0x46,
|
||||
0xDB, 0xB1, 0x36, 0xFC, 0x1B, 0x85, 0x51, 0xB0, 0xED, 0x83, 0x16, 0xF0,
|
||||
0x3A, 0x79, 0xDA, 0x5D, 0x28, 0x6A, 0xEE, 0x6A, 0x20, 0x4C, 0xB0, 0x70,
|
||||
0x5E, 0xB0, 0xED, 0x7A, 0x6D, 0x2D, 0x1A, 0xC9, 0xB4, 0x71, 0xC2, 0xC4,
|
||||
0xA3, 0x1D, 0x25, 0x86, 0x30, 0x54, 0xB1, 0x98, 0x26, 0xC1, 0x51, 0xE0,
|
||||
0xF8, 0x31, 0xAD, 0x67, 0x48, 0x9D, 0xE6, 0xA1, 0x52, 0x3B, 0x20, 0x47,
|
||||
0xC9, 0x70, 0xDA, 0x80, 0xB5, 0xA4, 0xF4, 0x3F, 0x72, 0x6B, 0x37, 0x30,
|
||||
0x57, 0x39, 0x2C, 0x46, 0x9B, 0x44, 0xF1, 0xD9, 0x4E, 0xBB, 0xA6, 0x5F,
|
||||
0xE3, 0x9A, 0xC5, 0x7F, 0x6C, 0xB6, 0x65, 0xCB, 0xBF, 0x40, 0x72, 0x92,
|
||||
0xD0, 0x68, 0xF6, 0xAE, 0x79, 0x7E, 0x24, 0xC1, 0x5B, 0x68, 0x30, 0x28,
|
||||
0x53, 0x71, 0x61, 0x7A, 0xF4, 0x36, 0x7B, 0x3B, 0xC2, 0xB6, 0xEC, 0x1F,
|
||||
0xDC, 0x30, 0x40, 0x04, 0x0D, 0xEA, 0xB3, 0x0A, 0xCF, 0x75, 0xD3, 0xBD,
|
||||
0x9E, 0xAB, 0x71, 0x71, 0x68, 0x7F, 0xA5, 0x41, 0x52, 0x00, 0xE9, 0xB3,
|
||||
0xAE, 0xE4, 0x1E, 0xF1, 0xBB, 0x69, 0xC6, 0x3B, 0xD5, 0xDE, 0xD2, 0xC2,
|
||||
0x25, 0x69, 0x08, 0x3C, 0x37, 0xCC, 0xF7, 0x82, 0x6A, 0xE5, 0xA8, 0x7B,
|
||||
0x6A, 0x02, 0xDA, 0xBD, 0xA4, 0x01, 0x33, 0x33, 0xF3, 0xDE, 0x46, 0x00,
|
||||
0xEC, 0x75, 0xCF, 0xE0, 0x7D
|
||||
};
|
||||
|
||||
static const unsigned char CERT1[] = {
|
||||
0x30, 0x82, 0x03, 0x34, 0x30, 0x82, 0x02, 0x1C, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x70, 0x0F, 0x60, 0xEE, 0xF0, 0x07, 0x9A, 0x9C, 0x69,
|
||||
0xAC, 0x97, 0x62, 0x26, 0x4F, 0x5D, 0x05, 0xB6, 0xF9, 0x8F, 0x48, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D,
|
||||
0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35,
|
||||
0x39, 0x35, 0x39, 0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
|
||||
0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D,
|
||||
0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01,
|
||||
0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01,
|
||||
0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB3, 0xE8, 0x6B, 0xAF, 0x9C, 0x16,
|
||||
0x52, 0xE3, 0x81, 0x0C, 0x50, 0xAB, 0x25, 0xCE, 0xCC, 0x0D, 0xC7, 0xF2,
|
||||
0x1F, 0x7F, 0x50, 0xDF, 0x2C, 0x5C, 0x35, 0xD6, 0x62, 0x2E, 0x63, 0x27,
|
||||
0x41, 0xA7, 0xE4, 0x53, 0xA8, 0x4B, 0x27, 0xFA, 0x13, 0x91, 0xA3, 0xFA,
|
||||
0x09, 0x4A, 0x2F, 0x3B, 0x5E, 0xCF, 0x77, 0xB3, 0x8A, 0xC1, 0xCD, 0x49,
|
||||
0x95, 0x9C, 0x75, 0x0D, 0x64, 0x74, 0xEF, 0xE4, 0xD7, 0x4B, 0xB9, 0xA1,
|
||||
0x9B, 0x68, 0xD2, 0x30, 0x71, 0x48, 0xEA, 0xF7, 0x4B, 0x14, 0xDF, 0x3F,
|
||||
0x47, 0xA9, 0xD8, 0xBB, 0xEC, 0x8F, 0x28, 0xCC, 0xFA, 0xDF, 0xB4, 0x1F,
|
||||
0x94, 0x7C, 0x96, 0xFC, 0x08, 0x05, 0x28, 0xF9, 0xE8, 0xF4, 0x2F, 0x2F,
|
||||
0xEE, 0x62, 0x9C, 0x8A, 0x3A, 0xE0, 0x85, 0x58, 0x60, 0xB6, 0x0F, 0x2D,
|
||||
0x30, 0xB4, 0xC0, 0x41, 0x54, 0x91, 0x4C, 0x1F, 0x5F, 0xAD, 0xF1, 0x19,
|
||||
0xF0, 0xC0, 0x22, 0xA6, 0x7D, 0xD8, 0x3F, 0x79, 0x34, 0x59, 0x42, 0x7B,
|
||||
0x5B, 0xB5, 0x41, 0xC4, 0x64, 0x7F, 0x52, 0xCF, 0x3C, 0x37, 0x22, 0xA1,
|
||||
0x2F, 0x79, 0x25, 0x94, 0x24, 0x41, 0xC2, 0x3F, 0xFA, 0xC7, 0x75, 0xFB,
|
||||
0x48, 0xB5, 0x0D, 0x18, 0xA7, 0xF4, 0x54, 0xF3, 0x2E, 0x6E, 0xD8, 0x43,
|
||||
0x58, 0xC4, 0xAB, 0x50, 0xE8, 0x05, 0xAD, 0x91, 0xB6, 0x1E, 0x01, 0x75,
|
||||
0xB3, 0x54, 0x9C, 0xDE, 0xA0, 0x99, 0x15, 0xFB, 0xAC, 0xF1, 0x5C, 0x97,
|
||||
0x49, 0x51, 0xCC, 0xEF, 0x58, 0x12, 0x6F, 0x73, 0x6B, 0xB3, 0x34, 0x14,
|
||||
0x01, 0x0F, 0x5A, 0x9D, 0xFA, 0xAA, 0xD6, 0x93, 0xD3, 0xE2, 0xEA, 0xC3,
|
||||
0xAB, 0xBC, 0x4E, 0xED, 0xCC, 0x51, 0xA1, 0xB8, 0xF8, 0x94, 0xB6, 0xB4,
|
||||
0x2C, 0xA8, 0x86, 0x2B, 0x1F, 0xF6, 0x51, 0x43, 0x29, 0x52, 0x5E, 0x13,
|
||||
0x89, 0xB3, 0x6A, 0x78, 0x60, 0x4E, 0x4E, 0xC0, 0x1B, 0xA5, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC3, 0x0A, 0xBC, 0xB4,
|
||||
0x90, 0x63, 0x96, 0x92, 0x45, 0xBC, 0x27, 0xA0, 0xF0, 0x58, 0x89, 0x2A,
|
||||
0xD5, 0x78, 0x00, 0x12, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04,
|
||||
0x16, 0x04, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA,
|
||||
0x19, 0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30,
|
||||
0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03,
|
||||
0x02, 0x00, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
|
||||
0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09,
|
||||
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03,
|
||||
0x82, 0x01, 0x01, 0x00, 0x54, 0x3B, 0xF4, 0xEA, 0xC6, 0xE4, 0xE8, 0xC0,
|
||||
0x5B, 0x12, 0xB2, 0xAD, 0xFA, 0xBD, 0xA9, 0xF4, 0x62, 0x03, 0xAD, 0x57,
|
||||
0x4C, 0x6F, 0x07, 0xA7, 0x47, 0x35, 0x75, 0x3E, 0x48, 0xA2, 0x5B, 0x71,
|
||||
0x10, 0x01, 0x8F, 0x93, 0x99, 0x9D, 0xA7, 0x47, 0xE3, 0x8E, 0x3E, 0xAF,
|
||||
0x2D, 0xBA, 0x06, 0xFE, 0xD4, 0xE4, 0x97, 0xBC, 0x10, 0x8D, 0xA6, 0xA5,
|
||||
0x3A, 0x3C, 0xE6, 0x21, 0xCB, 0x3B, 0xDA, 0x13, 0xE3, 0x4A, 0x23, 0xEB,
|
||||
0xBC, 0xBA, 0xA5, 0x90, 0x91, 0xAD, 0x55, 0x6E, 0xD5, 0xDD, 0x85, 0x4B,
|
||||
0x6B, 0x27, 0xD2, 0x39, 0x76, 0x06, 0x2E, 0xD4, 0x23, 0x5B, 0xBB, 0x55,
|
||||
0xB5, 0x49, 0x3F, 0x7D, 0x2F, 0x21, 0xCB, 0x96, 0x75, 0x19, 0x99, 0xA9,
|
||||
0x99, 0xF1, 0x0B, 0xBB, 0x3E, 0xC7, 0x10, 0xA7, 0x8B, 0x7A, 0x52, 0xB9,
|
||||
0x49, 0xE4, 0x14, 0x08, 0x78, 0xE7, 0x3D, 0xD9, 0x98, 0x57, 0xDA, 0xFF,
|
||||
0xDA, 0xB9, 0x8D, 0x66, 0x75, 0x80, 0xB5, 0x5D, 0xB9, 0xDF, 0x69, 0x65,
|
||||
0xDB, 0x16, 0xE7, 0x1E, 0xC4, 0x40, 0xE4, 0x46, 0x8A, 0x1E, 0x76, 0x32,
|
||||
0x16, 0xE7, 0x83, 0x67, 0xDA, 0x78, 0x56, 0xAB, 0x0F, 0x4C, 0x5C, 0xF1,
|
||||
0x70, 0xDA, 0x66, 0x20, 0xF4, 0xF8, 0x0F, 0xF6, 0xDC, 0x2F, 0x72, 0x97,
|
||||
0x6B, 0x78, 0x40, 0x79, 0x9D, 0x5B, 0x6D, 0xBE, 0x03, 0xCE, 0x70, 0x42,
|
||||
0xA8, 0x2A, 0x71, 0x11, 0xDF, 0x2E, 0x81, 0x01, 0xEA, 0x86, 0x12, 0x91,
|
||||
0x4F, 0xD0, 0x18, 0xED, 0x84, 0xA4, 0x48, 0x30, 0xB9, 0xB9, 0x7B, 0x56,
|
||||
0x3E, 0xEF, 0x8D, 0xE1, 0x1F, 0xFD, 0x90, 0xB2, 0x44, 0x85, 0x58, 0x6F,
|
||||
0xA7, 0x30, 0x74, 0x7C, 0xF1, 0xAE, 0x8C, 0x99, 0x3F, 0xF1, 0x4D, 0x57,
|
||||
0xC5, 0x95, 0x68, 0xC2, 0x36, 0xB2, 0xEC, 0xC2, 0x68, 0x7A, 0xC0, 0x81,
|
||||
0xA9, 0x55, 0x05, 0xE7, 0xCF, 0xAF, 0x50, 0xAC
|
||||
};
|
||||
|
||||
static const br_x509_certificate CHAIN[] = {
|
||||
{ (unsigned char *)CERT0, sizeof CERT0 },
|
||||
{ (unsigned char *)CERT1, sizeof CERT1 }
|
||||
};
|
||||
|
||||
#define CHAIN_LEN 2
|
117
contrib/bearssl/samples/chain-ec.h
Normal file
117
contrib/bearssl/samples/chain-ec.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* A sample server certificate chain with a single intermediate CA.
|
||||
* Certificate key type: EC
|
||||
* Signing algorithm for both certificates: ECDSA
|
||||
*/
|
||||
|
||||
static const unsigned char CERT0[] = {
|
||||
0x30, 0x82, 0x01, 0xB0, 0x30, 0x82, 0x01, 0x56, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x1C, 0x4D, 0x00, 0x91, 0x69, 0xE2, 0x46, 0xAC, 0x90,
|
||||
0x7C, 0x64, 0x5C, 0x53, 0xF1, 0xFF, 0xB7, 0xC1, 0xCB, 0x6E, 0x7A, 0x30,
|
||||
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30,
|
||||
0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
|
||||
0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74,
|
||||
0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x30, 0x30, 0x31,
|
||||
0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33,
|
||||
0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A,
|
||||
0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
|
||||
0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x30,
|
||||
0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
|
||||
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42,
|
||||
0x00, 0x04, 0x5F, 0x38, 0x9D, 0xA7, 0xFF, 0x4D, 0x8A, 0xAF, 0xF6, 0x34,
|
||||
0x39, 0x46, 0x1A, 0xFC, 0x3A, 0xDF, 0xF4, 0x23, 0xAA, 0xA9, 0xEA, 0xFB,
|
||||
0xC5, 0x08, 0xDE, 0x00, 0x8E, 0xBE, 0x79, 0xA5, 0x37, 0x58, 0x4C, 0x6D,
|
||||
0xDD, 0x01, 0xCA, 0xAB, 0x47, 0xDF, 0x89, 0xB6, 0xC7, 0x17, 0x1F, 0x38,
|
||||
0xFC, 0x1D, 0x20, 0x14, 0xDD, 0x45, 0xC0, 0xE0, 0x8F, 0x93, 0x4E, 0x38,
|
||||
0x0B, 0xFC, 0xE9, 0x99, 0xA1, 0x49, 0xA3, 0x66, 0x30, 0x64, 0x30, 0x1F,
|
||||
0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xF0,
|
||||
0xD0, 0xF1, 0x22, 0xF9, 0x7A, 0x48, 0x17, 0x06, 0x7B, 0x3D, 0xBD, 0xB8,
|
||||
0xF5, 0xCD, 0x55, 0x9C, 0x5C, 0x3E, 0x70, 0x30, 0x1D, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC3, 0x0E, 0x86, 0xAA, 0x75, 0xB4,
|
||||
0x15, 0xC0, 0xE5, 0x95, 0x09, 0x32, 0xBE, 0x5E, 0x92, 0x75, 0xA9, 0xE4,
|
||||
0x44, 0x9B, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF,
|
||||
0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04,
|
||||
0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F,
|
||||
0x73, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04,
|
||||
0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x91, 0xFB,
|
||||
0xF4, 0x04, 0xD0, 0xE5, 0x2E, 0x01, 0xD4, 0x8C, 0xF0, 0x17, 0x62, 0x0F,
|
||||
0xDC, 0xCC, 0x80, 0xCA, 0x18, 0xC4, 0x40, 0x7C, 0x27, 0x03, 0xCB, 0x34,
|
||||
0x03, 0x0D, 0x9B, 0xC8, 0x59, 0x4D, 0x02, 0x20, 0x05, 0x55, 0x69, 0xE2,
|
||||
0xD8, 0xA1, 0x40, 0x33, 0x34, 0x0E, 0x7E, 0x49, 0x32, 0x64, 0x1D, 0x3F,
|
||||
0x6B, 0x1F, 0xD0, 0x2D, 0xB7, 0x2F, 0x52, 0x04, 0x56, 0xAF, 0xD3, 0x37,
|
||||
0x8F, 0x87, 0x99, 0xA2
|
||||
};
|
||||
|
||||
static const unsigned char CERT1[] = {
|
||||
0x30, 0x82, 0x01, 0xA9, 0x30, 0x82, 0x01, 0x4E, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x20, 0xD3, 0xEB, 0xE2, 0x8C, 0xFE, 0xDA, 0xE6, 0xA3,
|
||||
0x2C, 0x5E, 0x3B, 0xF2, 0x66, 0x3A, 0x2B, 0x36, 0x7B, 0xB0, 0xCA, 0x30,
|
||||
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30,
|
||||
0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
|
||||
0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x30, 0x30,
|
||||
0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D,
|
||||
0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39,
|
||||
0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
|
||||
0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
|
||||
0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69,
|
||||
0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
|
||||
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48,
|
||||
0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x70, 0x2E, 0x92,
|
||||
0x82, 0x01, 0x17, 0x6C, 0x6D, 0xAB, 0xE1, 0xD1, 0x63, 0x09, 0x48, 0x49,
|
||||
0xD2, 0xA6, 0x35, 0x52, 0xD3, 0x3C, 0x73, 0xBB, 0xB2, 0x88, 0x37, 0x98,
|
||||
0x87, 0xF1, 0x8D, 0xE0, 0xEC, 0x65, 0x9A, 0x0E, 0x13, 0xF5, 0xED, 0x91,
|
||||
0x61, 0xC8, 0xB6, 0x6D, 0x33, 0x84, 0x6E, 0xAE, 0x8E, 0x55, 0x80, 0xCD,
|
||||
0x49, 0x9E, 0x07, 0xBF, 0xD0, 0xAE, 0x9D, 0xE6, 0xD0, 0xB3, 0x27, 0x16,
|
||||
0xA1, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23,
|
||||
0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x95, 0x41, 0xB4, 0xE2, 0x67, 0xAA,
|
||||
0xF1, 0x7F, 0xBC, 0x8F, 0x79, 0xF3, 0x68, 0x14, 0x5A, 0x6B, 0x92, 0x16,
|
||||
0xA2, 0x40, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04,
|
||||
0x14, 0xF0, 0xD0, 0xF1, 0x22, 0xF9, 0x7A, 0x48, 0x17, 0x06, 0x7B, 0x3D,
|
||||
0xBD, 0xB8, 0xF5, 0xCD, 0x55, 0x9C, 0x5C, 0x3E, 0x70, 0x30, 0x0E, 0x06,
|
||||
0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x00,
|
||||
0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04,
|
||||
0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86,
|
||||
0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02,
|
||||
0x21, 0x00, 0x85, 0xE3, 0x46, 0x68, 0x99, 0xD6, 0x02, 0x7A, 0x59, 0x66,
|
||||
0x1C, 0xB7, 0x4F, 0x35, 0x2D, 0x08, 0x36, 0x38, 0x61, 0x7E, 0x05, 0x48,
|
||||
0xD8, 0x69, 0x43, 0x1F, 0xEB, 0x56, 0xE9, 0xAD, 0x06, 0x0E, 0x02, 0x21,
|
||||
0x00, 0x82, 0x70, 0xB4, 0x62, 0x03, 0x49, 0x46, 0xC8, 0x54, 0x59, 0x05,
|
||||
0xD9, 0x78, 0xDB, 0x53, 0x1C, 0xE0, 0x6E, 0x66, 0xF5, 0x0F, 0x14, 0x3B,
|
||||
0xC9, 0x2D, 0x38, 0x12, 0x70, 0x91, 0x56, 0xF9, 0xA9
|
||||
};
|
||||
|
||||
static const br_x509_certificate CHAIN[] = {
|
||||
{ (unsigned char *)CERT0, sizeof CERT0 },
|
||||
{ (unsigned char *)CERT1, sizeof CERT1 }
|
||||
};
|
||||
|
||||
#define CHAIN_LEN 2
|
183
contrib/bearssl/samples/chain-rsa.h
Normal file
183
contrib/bearssl/samples/chain-rsa.h
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* A sample server certificate chain with a single intermediate CA.
|
||||
* Certificate key type: RSA
|
||||
* Signing algorithm for both certificates: RSA
|
||||
*/
|
||||
|
||||
static const unsigned char CERT0[] = {
|
||||
0x30, 0x82, 0x03, 0x3C, 0x30, 0x82, 0x02, 0x24, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x58, 0xDA, 0xBA, 0x36, 0xCD, 0xED, 0xA0, 0xDA, 0x5C,
|
||||
0x10, 0x33, 0x73, 0x8E, 0x0C, 0x64, 0x92, 0x79, 0x92, 0xAF, 0x03, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64,
|
||||
0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31,
|
||||
0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A,
|
||||
0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39,
|
||||
0x35, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
|
||||
0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
|
||||
0x55, 0x04, 0x03, 0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F,
|
||||
0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86,
|
||||
0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
|
||||
0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xD4,
|
||||
0x7A, 0x1D, 0x27, 0xBA, 0x2B, 0x3A, 0x67, 0xB2, 0x91, 0x6A, 0xFB, 0xE7,
|
||||
0x83, 0x44, 0xCA, 0xED, 0x1C, 0x75, 0xAD, 0xDD, 0x4D, 0x83, 0x62, 0xD6,
|
||||
0xAA, 0x68, 0x95, 0xB2, 0x24, 0x21, 0x7B, 0x15, 0xAE, 0x2A, 0x99, 0x68,
|
||||
0x15, 0xED, 0x66, 0xF0, 0xB8, 0x58, 0xE7, 0xD3, 0xF5, 0x2E, 0xC6, 0xD9,
|
||||
0x2A, 0x5E, 0xE7, 0x0E, 0x2E, 0xE7, 0xFC, 0x67, 0x59, 0xC0, 0xC8, 0x61,
|
||||
0x7D, 0x4B, 0xA4, 0x6F, 0xDD, 0x9F, 0xD9, 0xC8, 0x85, 0x87, 0x64, 0xC7,
|
||||
0xBA, 0x1A, 0x0F, 0x29, 0xD4, 0x96, 0xA8, 0x78, 0x9A, 0x6B, 0x62, 0x20,
|
||||
0xA9, 0x32, 0xD0, 0xEE, 0xA9, 0x8C, 0x28, 0x61, 0x47, 0xA2, 0x50, 0x2A,
|
||||
0x63, 0xF6, 0x21, 0xDE, 0xDA, 0xD8, 0xD5, 0xF0, 0x7F, 0xC5, 0x00, 0x82,
|
||||
0x70, 0xE6, 0xA3, 0xBF, 0x5C, 0x89, 0x27, 0x4F, 0x51, 0x92, 0x77, 0x03,
|
||||
0xC3, 0xB0, 0xCC, 0x2E, 0x3B, 0xEC, 0x23, 0xF2, 0x2F, 0x53, 0x41, 0xAF,
|
||||
0x89, 0x93, 0xFF, 0xD2, 0x80, 0xB1, 0x43, 0x97, 0xDE, 0xD6, 0x19, 0xA0,
|
||||
0x92, 0x12, 0x7A, 0x3D, 0x66, 0x79, 0xE1, 0xC1, 0xBC, 0xE1, 0x77, 0x70,
|
||||
0xA2, 0x8B, 0x3D, 0x46, 0x84, 0x53, 0x3F, 0xE4, 0x4E, 0x42, 0x41, 0x37,
|
||||
0x92, 0x1E, 0x1F, 0xFD, 0x38, 0xB3, 0xF7, 0xEF, 0x87, 0x39, 0x80, 0xD3,
|
||||
0x56, 0xCF, 0xF4, 0xE0, 0x13, 0xDE, 0x64, 0xB0, 0x72, 0xA4, 0x03, 0x84,
|
||||
0xC4, 0x41, 0xED, 0x6F, 0xFA, 0x3E, 0xE2, 0xCA, 0x04, 0x20, 0xD2, 0xD7,
|
||||
0xDC, 0x2C, 0x82, 0x2B, 0x7A, 0xE2, 0x6D, 0xA1, 0x1C, 0x48, 0xDB, 0xCF,
|
||||
0x89, 0x4F, 0x34, 0x97, 0x3D, 0x28, 0xA8, 0x53, 0xDA, 0xE7, 0xC1, 0xE1,
|
||||
0x73, 0x15, 0xA3, 0x30, 0x76, 0x7F, 0x8F, 0x23, 0x42, 0x14, 0x3D, 0x51,
|
||||
0x34, 0xD2, 0x5A, 0xAD, 0x3C, 0x9B, 0xCB, 0xC8, 0xFE, 0x7F, 0x6E, 0x8E,
|
||||
0x40, 0xF3, 0xBD, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x66, 0x30, 0x64,
|
||||
0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
|
||||
0x14, 0xC5, 0x01, 0xAD, 0x7C, 0xE6, 0x63, 0xC9, 0x9C, 0x17, 0x5F, 0xC5,
|
||||
0xA2, 0xA7, 0xE1, 0x50, 0x5F, 0xE8, 0xF5, 0xA8, 0xC6, 0x30, 0x1D, 0x06,
|
||||
0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC5, 0x01, 0xAD, 0x7C,
|
||||
0xE6, 0x63, 0xC9, 0x9C, 0x17, 0x5F, 0xC5, 0xA2, 0xA7, 0xE1, 0x50, 0x5F,
|
||||
0xE8, 0xF5, 0xA8, 0xC6, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01,
|
||||
0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55, 0x1D,
|
||||
0x11, 0x04, 0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C,
|
||||
0x68, 0x6F, 0x73, 0x74, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
|
||||
0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
|
||||
0x71, 0xB3, 0x5D, 0x21, 0xC2, 0x0E, 0xD7, 0xD0, 0xC6, 0xF8, 0x4A, 0x73,
|
||||
0x87, 0x4D, 0x22, 0x02, 0x27, 0xD0, 0xC7, 0xF8, 0xFD, 0x1A, 0x6D, 0x62,
|
||||
0x58, 0x82, 0x08, 0x76, 0x20, 0x07, 0xC0, 0x48, 0x92, 0xF3, 0xE9, 0x98,
|
||||
0x5A, 0xEB, 0x0D, 0x4E, 0x56, 0x95, 0x63, 0x68, 0x4D, 0xAB, 0xD4, 0x00,
|
||||
0x76, 0xE0, 0x37, 0xCF, 0x0B, 0x11, 0x61, 0x59, 0x5C, 0xDE, 0xF6, 0xA5,
|
||||
0x14, 0x59, 0xD9, 0x25, 0x9F, 0x59, 0xD9, 0xD3, 0x5E, 0x86, 0xAC, 0x1D,
|
||||
0xA6, 0x2C, 0x32, 0x42, 0x19, 0x32, 0x13, 0x40, 0x0B, 0x54, 0xCD, 0x67,
|
||||
0x26, 0xB6, 0xBD, 0xB4, 0x96, 0xA4, 0xCA, 0x1F, 0x7F, 0x37, 0xD6, 0xA8,
|
||||
0x75, 0xEB, 0x3A, 0x81, 0x51, 0x30, 0xB9, 0xF9, 0x4A, 0x01, 0x6F, 0xD1,
|
||||
0xD6, 0xED, 0x4F, 0xDF, 0x3F, 0x30, 0x60, 0x06, 0x67, 0x92, 0x8E, 0x61,
|
||||
0x85, 0x5F, 0x1A, 0xB5, 0x8C, 0xB3, 0x0F, 0x61, 0xA9, 0xFA, 0xDF, 0x5D,
|
||||
0xC4, 0x64, 0x00, 0xEA, 0x87, 0xB1, 0x33, 0x5F, 0x7D, 0xCB, 0xA3, 0x85,
|
||||
0x24, 0x6E, 0x2C, 0x65, 0x3B, 0xEA, 0x73, 0x3F, 0x86, 0xD3, 0xFD, 0xE8,
|
||||
0xE4, 0x02, 0xC6, 0x61, 0x6A, 0x26, 0x17, 0x52, 0x01, 0x25, 0x5C, 0x7F,
|
||||
0xA8, 0xCE, 0x69, 0x1F, 0xAC, 0x61, 0x2C, 0xB7, 0x04, 0xAF, 0xFD, 0xA4,
|
||||
0x7A, 0x99, 0xCB, 0x26, 0x15, 0x4C, 0xFF, 0x74, 0xD4, 0x73, 0x0C, 0x57,
|
||||
0x0C, 0x26, 0xEB, 0xD7, 0x2A, 0xDC, 0x5C, 0xC3, 0x41, 0xBB, 0xC2, 0xF3,
|
||||
0xCE, 0x16, 0xBD, 0x8E, 0x7B, 0xFB, 0xE9, 0xDF, 0xAB, 0x21, 0x0D, 0x91,
|
||||
0xB3, 0x8D, 0xD8, 0xCF, 0xC8, 0xF4, 0x49, 0xB9, 0xD0, 0xE3, 0x16, 0x70,
|
||||
0x3F, 0xB3, 0xDE, 0xD4, 0x07, 0x25, 0xFA, 0x46, 0x44, 0x52, 0x89, 0x4D,
|
||||
0x89, 0xC8, 0xE2, 0xCA, 0xB5, 0x33, 0x7F, 0xC7, 0x21, 0xBD, 0x28, 0xEF,
|
||||
0xFE, 0x66, 0x74, 0x03
|
||||
};
|
||||
|
||||
static const unsigned char CERT1[] = {
|
||||
0x30, 0x82, 0x03, 0x34, 0x30, 0x82, 0x02, 0x1C, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x70, 0x0F, 0x60, 0xEE, 0xF0, 0x07, 0x9A, 0x9C, 0x69,
|
||||
0xAC, 0x97, 0x62, 0x26, 0x4F, 0x5D, 0x05, 0xB6, 0xF9, 0x8F, 0x48, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D,
|
||||
0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35,
|
||||
0x39, 0x35, 0x39, 0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
|
||||
0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D,
|
||||
0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01,
|
||||
0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01,
|
||||
0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB3, 0xE8, 0x6B, 0xAF, 0x9C, 0x16,
|
||||
0x52, 0xE3, 0x81, 0x0C, 0x50, 0xAB, 0x25, 0xCE, 0xCC, 0x0D, 0xC7, 0xF2,
|
||||
0x1F, 0x7F, 0x50, 0xDF, 0x2C, 0x5C, 0x35, 0xD6, 0x62, 0x2E, 0x63, 0x27,
|
||||
0x41, 0xA7, 0xE4, 0x53, 0xA8, 0x4B, 0x27, 0xFA, 0x13, 0x91, 0xA3, 0xFA,
|
||||
0x09, 0x4A, 0x2F, 0x3B, 0x5E, 0xCF, 0x77, 0xB3, 0x8A, 0xC1, 0xCD, 0x49,
|
||||
0x95, 0x9C, 0x75, 0x0D, 0x64, 0x74, 0xEF, 0xE4, 0xD7, 0x4B, 0xB9, 0xA1,
|
||||
0x9B, 0x68, 0xD2, 0x30, 0x71, 0x48, 0xEA, 0xF7, 0x4B, 0x14, 0xDF, 0x3F,
|
||||
0x47, 0xA9, 0xD8, 0xBB, 0xEC, 0x8F, 0x28, 0xCC, 0xFA, 0xDF, 0xB4, 0x1F,
|
||||
0x94, 0x7C, 0x96, 0xFC, 0x08, 0x05, 0x28, 0xF9, 0xE8, 0xF4, 0x2F, 0x2F,
|
||||
0xEE, 0x62, 0x9C, 0x8A, 0x3A, 0xE0, 0x85, 0x58, 0x60, 0xB6, 0x0F, 0x2D,
|
||||
0x30, 0xB4, 0xC0, 0x41, 0x54, 0x91, 0x4C, 0x1F, 0x5F, 0xAD, 0xF1, 0x19,
|
||||
0xF0, 0xC0, 0x22, 0xA6, 0x7D, 0xD8, 0x3F, 0x79, 0x34, 0x59, 0x42, 0x7B,
|
||||
0x5B, 0xB5, 0x41, 0xC4, 0x64, 0x7F, 0x52, 0xCF, 0x3C, 0x37, 0x22, 0xA1,
|
||||
0x2F, 0x79, 0x25, 0x94, 0x24, 0x41, 0xC2, 0x3F, 0xFA, 0xC7, 0x75, 0xFB,
|
||||
0x48, 0xB5, 0x0D, 0x18, 0xA7, 0xF4, 0x54, 0xF3, 0x2E, 0x6E, 0xD8, 0x43,
|
||||
0x58, 0xC4, 0xAB, 0x50, 0xE8, 0x05, 0xAD, 0x91, 0xB6, 0x1E, 0x01, 0x75,
|
||||
0xB3, 0x54, 0x9C, 0xDE, 0xA0, 0x99, 0x15, 0xFB, 0xAC, 0xF1, 0x5C, 0x97,
|
||||
0x49, 0x51, 0xCC, 0xEF, 0x58, 0x12, 0x6F, 0x73, 0x6B, 0xB3, 0x34, 0x14,
|
||||
0x01, 0x0F, 0x5A, 0x9D, 0xFA, 0xAA, 0xD6, 0x93, 0xD3, 0xE2, 0xEA, 0xC3,
|
||||
0xAB, 0xBC, 0x4E, 0xED, 0xCC, 0x51, 0xA1, 0xB8, 0xF8, 0x94, 0xB6, 0xB4,
|
||||
0x2C, 0xA8, 0x86, 0x2B, 0x1F, 0xF6, 0x51, 0x43, 0x29, 0x52, 0x5E, 0x13,
|
||||
0x89, 0xB3, 0x6A, 0x78, 0x60, 0x4E, 0x4E, 0xC0, 0x1B, 0xA5, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC3, 0x0A, 0xBC, 0xB4,
|
||||
0x90, 0x63, 0x96, 0x92, 0x45, 0xBC, 0x27, 0xA0, 0xF0, 0x58, 0x89, 0x2A,
|
||||
0xD5, 0x78, 0x00, 0x12, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04,
|
||||
0x16, 0x04, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA,
|
||||
0x19, 0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30,
|
||||
0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03,
|
||||
0x02, 0x00, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
|
||||
0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09,
|
||||
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03,
|
||||
0x82, 0x01, 0x01, 0x00, 0x54, 0x3B, 0xF4, 0xEA, 0xC6, 0xE4, 0xE8, 0xC0,
|
||||
0x5B, 0x12, 0xB2, 0xAD, 0xFA, 0xBD, 0xA9, 0xF4, 0x62, 0x03, 0xAD, 0x57,
|
||||
0x4C, 0x6F, 0x07, 0xA7, 0x47, 0x35, 0x75, 0x3E, 0x48, 0xA2, 0x5B, 0x71,
|
||||
0x10, 0x01, 0x8F, 0x93, 0x99, 0x9D, 0xA7, 0x47, 0xE3, 0x8E, 0x3E, 0xAF,
|
||||
0x2D, 0xBA, 0x06, 0xFE, 0xD4, 0xE4, 0x97, 0xBC, 0x10, 0x8D, 0xA6, 0xA5,
|
||||
0x3A, 0x3C, 0xE6, 0x21, 0xCB, 0x3B, 0xDA, 0x13, 0xE3, 0x4A, 0x23, 0xEB,
|
||||
0xBC, 0xBA, 0xA5, 0x90, 0x91, 0xAD, 0x55, 0x6E, 0xD5, 0xDD, 0x85, 0x4B,
|
||||
0x6B, 0x27, 0xD2, 0x39, 0x76, 0x06, 0x2E, 0xD4, 0x23, 0x5B, 0xBB, 0x55,
|
||||
0xB5, 0x49, 0x3F, 0x7D, 0x2F, 0x21, 0xCB, 0x96, 0x75, 0x19, 0x99, 0xA9,
|
||||
0x99, 0xF1, 0x0B, 0xBB, 0x3E, 0xC7, 0x10, 0xA7, 0x8B, 0x7A, 0x52, 0xB9,
|
||||
0x49, 0xE4, 0x14, 0x08, 0x78, 0xE7, 0x3D, 0xD9, 0x98, 0x57, 0xDA, 0xFF,
|
||||
0xDA, 0xB9, 0x8D, 0x66, 0x75, 0x80, 0xB5, 0x5D, 0xB9, 0xDF, 0x69, 0x65,
|
||||
0xDB, 0x16, 0xE7, 0x1E, 0xC4, 0x40, 0xE4, 0x46, 0x8A, 0x1E, 0x76, 0x32,
|
||||
0x16, 0xE7, 0x83, 0x67, 0xDA, 0x78, 0x56, 0xAB, 0x0F, 0x4C, 0x5C, 0xF1,
|
||||
0x70, 0xDA, 0x66, 0x20, 0xF4, 0xF8, 0x0F, 0xF6, 0xDC, 0x2F, 0x72, 0x97,
|
||||
0x6B, 0x78, 0x40, 0x79, 0x9D, 0x5B, 0x6D, 0xBE, 0x03, 0xCE, 0x70, 0x42,
|
||||
0xA8, 0x2A, 0x71, 0x11, 0xDF, 0x2E, 0x81, 0x01, 0xEA, 0x86, 0x12, 0x91,
|
||||
0x4F, 0xD0, 0x18, 0xED, 0x84, 0xA4, 0x48, 0x30, 0xB9, 0xB9, 0x7B, 0x56,
|
||||
0x3E, 0xEF, 0x8D, 0xE1, 0x1F, 0xFD, 0x90, 0xB2, 0x44, 0x85, 0x58, 0x6F,
|
||||
0xA7, 0x30, 0x74, 0x7C, 0xF1, 0xAE, 0x8C, 0x99, 0x3F, 0xF1, 0x4D, 0x57,
|
||||
0xC5, 0x95, 0x68, 0xC2, 0x36, 0xB2, 0xEC, 0xC2, 0x68, 0x7A, 0xC0, 0x81,
|
||||
0xA9, 0x55, 0x05, 0xE7, 0xCF, 0xAF, 0x50, 0xAC
|
||||
};
|
||||
|
||||
static const br_x509_certificate CHAIN[] = {
|
||||
{ (unsigned char *)CERT0, sizeof CERT0 },
|
||||
{ (unsigned char *)CERT1, sizeof CERT1 }
|
||||
};
|
||||
|
||||
#define CHAIN_LEN 2
|
380
contrib/bearssl/samples/client_basic.c
Normal file
380
contrib/bearssl/samples/client_basic.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* Connect to the specified host and port. The connected socket is
|
||||
* returned, or -1 on error.
|
||||
*/
|
||||
static int
|
||||
host_connect(const char *host, const char *port)
|
||||
{
|
||||
struct addrinfo hints, *si, *p;
|
||||
int fd;
|
||||
int err;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
err = getaddrinfo(host, port, &hints, &si);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "ERROR: getaddrinfo(): %s\n",
|
||||
gai_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
fd = -1;
|
||||
for (p = si; p != NULL; p = p->ai_next) {
|
||||
struct sockaddr *sa;
|
||||
void *addr;
|
||||
char tmp[INET6_ADDRSTRLEN + 50];
|
||||
|
||||
sa = (struct sockaddr *)p->ai_addr;
|
||||
if (sa->sa_family == AF_INET) {
|
||||
addr = &((struct sockaddr_in *)sa)->sin_addr;
|
||||
} else if (sa->sa_family == AF_INET6) {
|
||||
addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
|
||||
} else {
|
||||
addr = NULL;
|
||||
}
|
||||
if (addr != NULL) {
|
||||
inet_ntop(p->ai_family, addr, tmp, sizeof tmp);
|
||||
} else {
|
||||
sprintf(tmp, "<unknown family: %d>",
|
||||
(int)sa->sa_family);
|
||||
}
|
||||
fprintf(stderr, "connecting to: %s\n", tmp);
|
||||
fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
if (fd < 0) {
|
||||
perror("socket()");
|
||||
continue;
|
||||
}
|
||||
if (connect(fd, p->ai_addr, p->ai_addrlen) < 0) {
|
||||
perror("connect()");
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (p == NULL) {
|
||||
freeaddrinfo(si);
|
||||
fprintf(stderr, "ERROR: failed to connect\n");
|
||||
return -1;
|
||||
}
|
||||
freeaddrinfo(si);
|
||||
fprintf(stderr, "connected.\n");
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level data read callback for the simplified SSL I/O API.
|
||||
*/
|
||||
static int
|
||||
sock_read(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t rlen;
|
||||
|
||||
rlen = read(*(int *)ctx, buf, len);
|
||||
if (rlen <= 0) {
|
||||
if (rlen < 0 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return (int)rlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level data write callback for the simplified SSL I/O API.
|
||||
*/
|
||||
static int
|
||||
sock_write(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t wlen;
|
||||
|
||||
wlen = write(*(int *)ctx, buf, len);
|
||||
if (wlen <= 0) {
|
||||
if (wlen < 0 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return (int)wlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The hardcoded trust anchors. These are the two DN + public key that
|
||||
* correspond to the self-signed certificates cert-root-rsa.pem and
|
||||
* cert-root-ec.pem.
|
||||
*
|
||||
* C code for hardcoded trust anchors can be generated with the "brssl"
|
||||
* command-line tool (with the "ta" command).
|
||||
*/
|
||||
|
||||
static const unsigned char TA0_DN[] = {
|
||||
0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
|
||||
0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74
|
||||
};
|
||||
|
||||
static const unsigned char TA0_RSA_N[] = {
|
||||
0xB6, 0xD9, 0x34, 0xD4, 0x50, 0xFD, 0xB3, 0xAF, 0x7A, 0x73, 0xF1, 0xCE,
|
||||
0x38, 0xBF, 0x5D, 0x6F, 0x45, 0xE1, 0xFD, 0x4E, 0xB1, 0x98, 0xC6, 0x60,
|
||||
0x83, 0x26, 0xD2, 0x17, 0xD1, 0xC5, 0xB7, 0x9A, 0xA3, 0xC1, 0xDE, 0x63,
|
||||
0x39, 0x97, 0x9C, 0xF0, 0x5E, 0x5C, 0xC8, 0x1C, 0x17, 0xB9, 0x88, 0x19,
|
||||
0x6D, 0xF0, 0xB6, 0x2E, 0x30, 0x50, 0xA1, 0x54, 0x6E, 0x93, 0xC0, 0xDB,
|
||||
0xCF, 0x30, 0xCB, 0x9F, 0x1E, 0x27, 0x79, 0xF1, 0xC3, 0x99, 0x52, 0x35,
|
||||
0xAA, 0x3D, 0xB6, 0xDF, 0xB0, 0xAD, 0x7C, 0xCB, 0x49, 0xCD, 0xC0, 0xED,
|
||||
0xE7, 0x66, 0x10, 0x2A, 0xE9, 0xCE, 0x28, 0x1F, 0x21, 0x50, 0xFA, 0x77,
|
||||
0x4C, 0x2D, 0xDA, 0xEF, 0x3C, 0x58, 0xEB, 0x4E, 0xBF, 0xCE, 0xE9, 0xFB,
|
||||
0x1A, 0xDA, 0xA3, 0x83, 0xA3, 0xCD, 0xA3, 0xCA, 0x93, 0x80, 0xDC, 0xDA,
|
||||
0xF3, 0x17, 0xCC, 0x7A, 0xAB, 0x33, 0x80, 0x9C, 0xB2, 0xD4, 0x7F, 0x46,
|
||||
0x3F, 0xC5, 0x3C, 0xDC, 0x61, 0x94, 0xB7, 0x27, 0x29, 0x6E, 0x2A, 0xBC,
|
||||
0x5B, 0x09, 0x36, 0xD4, 0xC6, 0x3B, 0x0D, 0xEB, 0xBE, 0xCE, 0xDB, 0x1D,
|
||||
0x1C, 0xBC, 0x10, 0x6A, 0x71, 0x71, 0xB3, 0xF2, 0xCA, 0x28, 0x9A, 0x77,
|
||||
0xF2, 0x8A, 0xEC, 0x42, 0xEF, 0xB1, 0x4A, 0x8E, 0xE2, 0xF2, 0x1A, 0x32,
|
||||
0x2A, 0xCD, 0xC0, 0xA6, 0x46, 0x2C, 0x9A, 0xC2, 0x85, 0x37, 0x91, 0x7F,
|
||||
0x46, 0xA1, 0x93, 0x81, 0xA1, 0x74, 0x66, 0xDF, 0xBA, 0xB3, 0x39, 0x20,
|
||||
0x91, 0x93, 0xFA, 0x1D, 0xA1, 0xA8, 0x85, 0xE7, 0xE4, 0xF9, 0x07, 0xF6,
|
||||
0x10, 0xF6, 0xA8, 0x27, 0x01, 0xB6, 0x7F, 0x12, 0xC3, 0x40, 0xC3, 0xC9,
|
||||
0xE2, 0xB0, 0xAB, 0x49, 0x18, 0x3A, 0x64, 0xB6, 0x59, 0xB7, 0x95, 0xB5,
|
||||
0x96, 0x36, 0xDF, 0x22, 0x69, 0xAA, 0x72, 0x6A, 0x54, 0x4E, 0x27, 0x29,
|
||||
0xA3, 0x0E, 0x97, 0x15
|
||||
};
|
||||
|
||||
static const unsigned char TA0_RSA_E[] = {
|
||||
0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
static const unsigned char TA1_DN[] = {
|
||||
0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
|
||||
0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74
|
||||
};
|
||||
|
||||
static const unsigned char TA1_EC_Q[] = {
|
||||
0x04, 0x71, 0x74, 0xBA, 0xAB, 0xB9, 0x30, 0x2E, 0x81, 0xD5, 0xE5, 0x57,
|
||||
0xF9, 0xF3, 0x20, 0x68, 0x0C, 0x9C, 0xF9, 0x64, 0xDB, 0xB4, 0x20, 0x0D,
|
||||
0x6D, 0xEA, 0x40, 0xD0, 0x4A, 0x6E, 0x42, 0xFD, 0xB6, 0x9A, 0x68, 0x25,
|
||||
0x44, 0xF6, 0xDF, 0x7B, 0xC4, 0xFC, 0xDE, 0xDD, 0x7B, 0xBB, 0xC5, 0xDB,
|
||||
0x7C, 0x76, 0x3F, 0x41, 0x66, 0x40, 0x6E, 0xDB, 0xA7, 0x87, 0xC2, 0xE5,
|
||||
0xD8, 0xC5, 0xF3, 0x7F, 0x8D
|
||||
};
|
||||
|
||||
static const br_x509_trust_anchor TAs[2] = {
|
||||
{
|
||||
{ (unsigned char *)TA0_DN, sizeof TA0_DN },
|
||||
BR_X509_TA_CA,
|
||||
{
|
||||
BR_KEYTYPE_RSA,
|
||||
{ .rsa = {
|
||||
(unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N,
|
||||
(unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E,
|
||||
} }
|
||||
}
|
||||
},
|
||||
{
|
||||
{ (unsigned char *)TA1_DN, sizeof TA1_DN },
|
||||
BR_X509_TA_CA,
|
||||
{
|
||||
BR_KEYTYPE_EC,
|
||||
{ .ec = {
|
||||
BR_EC_secp256r1,
|
||||
(unsigned char *)TA1_EC_Q, sizeof TA1_EC_Q,
|
||||
} }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define TAs_NUM 2
|
||||
|
||||
/*
|
||||
* Main program: this is a simple program that expects 2 or 3 arguments.
|
||||
* The first two arguments are a hostname and a port; the program will
|
||||
* open a SSL connection with that server and port. It will then send
|
||||
* a simple HTTP GET request, using the third argument as target path
|
||||
* ("/" is used as path if no third argument was provided). The HTTP
|
||||
* response, complete with header and contents, is received and written
|
||||
* on stdout.
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *host, *port, *path;
|
||||
int fd;
|
||||
br_ssl_client_context sc;
|
||||
br_x509_minimal_context xc;
|
||||
unsigned char iobuf[BR_SSL_BUFSIZE_BIDI];
|
||||
br_sslio_context ioc;
|
||||
|
||||
/*
|
||||
* Parse command-line argument: host, port, and path. The path
|
||||
* is optional; if absent, "/" is used.
|
||||
*/
|
||||
if (argc < 3 || argc > 4) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
host = argv[1];
|
||||
port = argv[2];
|
||||
if (argc == 4) {
|
||||
path = argv[3];
|
||||
} else {
|
||||
path = "/";
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore SIGPIPE to avoid crashing in case of abrupt socket close.
|
||||
*/
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/*
|
||||
* Open the socket to the target server.
|
||||
*/
|
||||
fd = host_connect(host, port);
|
||||
if (fd < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the client context:
|
||||
* -- Use the "full" profile (all supported algorithms).
|
||||
* -- The provided X.509 validation engine is initialised, with
|
||||
* the hardcoded trust anchor.
|
||||
*/
|
||||
br_ssl_client_init_full(&sc, &xc, TAs, TAs_NUM);
|
||||
|
||||
/*
|
||||
* Set the I/O buffer to the provided array. We allocated a
|
||||
* buffer large enough for full-duplex behaviour with all
|
||||
* allowed sizes of SSL records, hence we set the last argument
|
||||
* to 1 (which means "split the buffer into separate input and
|
||||
* output areas").
|
||||
*/
|
||||
br_ssl_engine_set_buffer(&sc.eng, iobuf, sizeof iobuf, 1);
|
||||
|
||||
/*
|
||||
* Reset the client context, for a new handshake. We provide the
|
||||
* target host name: it will be used for the SNI extension. The
|
||||
* last parameter is 0: we are not trying to resume a session.
|
||||
*/
|
||||
br_ssl_client_reset(&sc, host, 0);
|
||||
|
||||
/*
|
||||
* Initialise the simplified I/O wrapper context, to use our
|
||||
* SSL client context, and the two callbacks for socket I/O.
|
||||
*/
|
||||
br_sslio_init(&ioc, &sc.eng, sock_read, &fd, sock_write, &fd);
|
||||
|
||||
/*
|
||||
* Note that while the context has, at that point, already
|
||||
* assembled the ClientHello to send, nothing happened on the
|
||||
* network yet. Real I/O will occur only with the next call.
|
||||
*
|
||||
* We write our simple HTTP request. We could test each call
|
||||
* for an error (-1), but this is not strictly necessary, since
|
||||
* the error state "sticks": if the context fails for any reason
|
||||
* (e.g. bad server certificate), then it will remain in failed
|
||||
* state and all subsequent calls will return -1 as well.
|
||||
*/
|
||||
br_sslio_write_all(&ioc, "GET ", 4);
|
||||
br_sslio_write_all(&ioc, path, strlen(path));
|
||||
br_sslio_write_all(&ioc, " HTTP/1.0\r\nHost: ", 17);
|
||||
br_sslio_write_all(&ioc, host, strlen(host));
|
||||
br_sslio_write_all(&ioc, "\r\n\r\n", 4);
|
||||
|
||||
/*
|
||||
* SSL is a buffered protocol: we make sure that all our request
|
||||
* bytes are sent onto the wire.
|
||||
*/
|
||||
br_sslio_flush(&ioc);
|
||||
|
||||
/*
|
||||
* Read the server's response. We use here a small 512-byte buffer,
|
||||
* but most of the buffering occurs in the client context: the
|
||||
* server will send full records (up to 16384 bytes worth of data
|
||||
* each), and the client context buffers one full record at a time.
|
||||
*/
|
||||
for (;;) {
|
||||
int rlen;
|
||||
unsigned char tmp[512];
|
||||
|
||||
rlen = br_sslio_read(&ioc, tmp, sizeof tmp);
|
||||
if (rlen < 0) {
|
||||
break;
|
||||
}
|
||||
fwrite(tmp, 1, rlen, stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the socket.
|
||||
*/
|
||||
close(fd);
|
||||
|
||||
/*
|
||||
* Check whether we closed properly or not. If the engine is
|
||||
* closed, then its error status allows to distinguish between
|
||||
* a normal closure and a SSL error.
|
||||
*
|
||||
* If the engine is NOT closed, then this means that the
|
||||
* underlying network socket was closed or failed in some way.
|
||||
* Note that many Web servers out there do not properly close
|
||||
* their SSL connections (they don't send a close_notify alert),
|
||||
* which will be reported here as "socket closed without proper
|
||||
* SSL termination".
|
||||
*/
|
||||
if (br_ssl_engine_current_state(&sc.eng) == BR_SSL_CLOSED) {
|
||||
int err;
|
||||
|
||||
err = br_ssl_engine_last_error(&sc.eng);
|
||||
if (err == 0) {
|
||||
fprintf(stderr, "closed.\n");
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
fprintf(stderr, "SSL error %d\n", err);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"socket closed without proper SSL termination\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
601
contrib/bearssl/samples/custom_profile.c
Normal file
601
contrib/bearssl/samples/custom_profile.c
Normal file
@ -0,0 +1,601 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* A "profile" is an initialisation function for a SSL context, that
|
||||
* configures a list of cipher suites and algorithm implementations.
|
||||
* While BearSSL comes with a few predefined profiles, you might one
|
||||
* to define you own, using the example below as guidance.
|
||||
*
|
||||
* Each individual initialisation call sets a parameter or an algorithm
|
||||
* support. Setting a specific algorithm pulls in the implementation of
|
||||
* that algorithm in the compiled binary, as per static linking
|
||||
* behaviour. Removing some of this calls will then reduce total code
|
||||
* footprint, but also mechanically prevents some features to be
|
||||
* supported (protocol versions and cipher suites).
|
||||
*
|
||||
* The two below define profiles for the client and the server contexts,
|
||||
* respectively. Of course, in a typical size-constrained application,
|
||||
* you would use one or the other, not both, to avoid pulling in code
|
||||
* for both.
|
||||
*/
|
||||
|
||||
void
|
||||
example_client_profile(br_ssl_client_context *cc
|
||||
/* and possibly some other arguments */)
|
||||
{
|
||||
/*
|
||||
* A list of cipher suites, by preference (first is most
|
||||
* preferred). The list below contains all cipher suites supported
|
||||
* by BearSSL; trim it done to your needs.
|
||||
*/
|
||||
static const uint16_t suites[] = {
|
||||
BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||
};
|
||||
|
||||
/*
|
||||
* Client context must be cleared at some point. This sets
|
||||
* every value and pointer to 0 or NULL.
|
||||
*/
|
||||
br_ssl_client_zero(cc);
|
||||
|
||||
/*
|
||||
* Define minimum and maximum protocol versions. Supported
|
||||
* versions are:
|
||||
* BR_TLS10 TLS 1.0
|
||||
* BR_TLS11 TLS 1.1
|
||||
* BR_TLS12 TLS 1.2
|
||||
*/
|
||||
br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
|
||||
|
||||
/*
|
||||
* Set the PRF implementation(s).
|
||||
* For TLS 1.0 and 1.1, the "prf10" is needed.
|
||||
* For TLS 1.2, this depends on the cipher suite:
|
||||
* -- cipher suites with a name ending in "SHA384" need "prf_sha384";
|
||||
* -- all others need "prf_sha256".
|
||||
*
|
||||
* Note that a cipher suite like TLS_RSA_WITH_AES_128_CBC_SHA will
|
||||
* use SHA-1 for the per-record MAC (that's what the final "SHA"
|
||||
* means), but still SHA-256 for the PRF when selected along with
|
||||
* the TLS-1.2 protocol version.
|
||||
*/
|
||||
br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf);
|
||||
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
|
||||
br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf);
|
||||
|
||||
/*
|
||||
* Set hash functions for the engine. Required hash functions
|
||||
* depend on the protocol and cipher suite:
|
||||
*
|
||||
* -- TLS 1.0 and 1.1 require both MD5 and SHA-1.
|
||||
* -- With TLS 1.2, cipher suites with a name ending in "SHA384"
|
||||
* require SHA-384.
|
||||
* -- With TLS 1.2, cipher suites with a name ending in "SHA256"
|
||||
* require SHA-256.
|
||||
* -- With TLS 1.2, cipher suites with a name ending in "SHA"
|
||||
* require both SHA-256 and SHA-1.
|
||||
*
|
||||
* Moreover, these hash functions are also used to compute
|
||||
* hashes supporting signatures on the server side (for ECDHE_*
|
||||
* cipher suites), and on the client side (for client
|
||||
* certificates, except in the case of full static ECDH). In TLS
|
||||
* 1.0 and 1.1, SHA-1 (and also MD5) will be used, but with TLS
|
||||
* 1.2 these hash functions are negotiated between client and
|
||||
* server; SHA-256 and/or SHA-384 should be sufficient in
|
||||
* practice.
|
||||
*
|
||||
* Note that with current implementations, SHA-224 and SHA-256
|
||||
* share the same file, so if you use one, you may have the other
|
||||
* one with no additional overhead. Similarly, SHA-384 and SHA-512
|
||||
* share the same implementation code.
|
||||
*/
|
||||
br_ssl_engine_set_hash(&cc->eng, br_md5_ID, &br_md5_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha1_ID, &br_sha1_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha224_ID, &br_sha224_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha384_ID, &br_sha384_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha512_ID, &br_sha512_vtable);
|
||||
|
||||
/*
|
||||
* Set the cipher suites. All specified cipher suite MUST be
|
||||
* supported, and the relevant algorithms MUST have been
|
||||
* configured (failure to provide needed implementations may
|
||||
* trigger unwanted behaviours like segfaults or overflows).
|
||||
*/
|
||||
br_ssl_engine_set_suites(&cc->eng, suites,
|
||||
(sizeof suites) / (sizeof suites[0]));
|
||||
|
||||
/*
|
||||
* Public-key algorithm implementations.
|
||||
*
|
||||
* -- RSA public core ("rsapub") is needed for "RSA" key exchange
|
||||
* (cipher suites whose name starts with TLS_RSA).
|
||||
*
|
||||
* -- RSA signature verification ("rsavrfy") is needed for
|
||||
* "ECDHE_RSA" cipher suites (not ECDH_RSA).
|
||||
*
|
||||
* -- Elliptic curve implementation ("ec") is needed for cipher
|
||||
* suites that use elliptic curves (both "ECDH" and "ECDHE"
|
||||
* cipher suites).
|
||||
*
|
||||
* -- ECDSA signature verification is needed for "ECDHE_ECDSA"
|
||||
* cipher suites (but not for ECDHE_RSA, ECDH_ECDSA or ECDH_RSA).
|
||||
*
|
||||
* Normally, you use the "default" implementations, obtained
|
||||
* through relevant function calls. These functions return
|
||||
* implementations that are deemed "best" for the current
|
||||
* platform, where "best" means "fastest within constant-time
|
||||
* implementations". Selecting the default implementation is a
|
||||
* mixture of compile-time and runtime checks.
|
||||
*
|
||||
* Nevertheless, specific implementations may be selected
|
||||
* explicitly, e.g. to use code which is slower but with a
|
||||
* smaller footprint.
|
||||
*
|
||||
* The RSA code comes in three variants, called "i15", "i31" and
|
||||
* "i32". The "i31" code is somewhat faster than the "i32" code.
|
||||
* Usually, "i31" is faster than "i15", except on some specific
|
||||
* architectures (ARM Cortex M0, M0+, M1 and M3) where the "i15"
|
||||
* should be preferred (the "i15" code is constant-time, while
|
||||
* the "i31" is not, and the "i15" code is faster anyway).
|
||||
*
|
||||
* ECDSA code also comes in "i15" and "i31" variants. As in the
|
||||
* case of RSA, the "i31" code is faster, except on the small
|
||||
* ARM Cortex M, where the "i15" code is faster and safer.
|
||||
*
|
||||
* There are no less than 10 elliptic curve implementations:
|
||||
*
|
||||
* - ec_c25519_i15, ec_c25519_i31, ec_c25519_m15 and ec_c25519_m31
|
||||
* implement Curve25519.
|
||||
*
|
||||
* - ec_p256_m15 and ec_p256_m31 implement NIST curve P-256.
|
||||
*
|
||||
* - ec_prime_i15 and ec_prime_i31 implement NIST curves P-256,
|
||||
* P-384 and P-521.
|
||||
*
|
||||
* - ec_all_m15 is an aggregate implementation that uses
|
||||
* ec_c25519_m15, ec_p256_m15 and ec_prime_i15.
|
||||
*
|
||||
* - ec_all_m31 is an aggregate implementation that uses
|
||||
* ec_c25519_m31, ec_p256_m31 and ec_prime_i31.
|
||||
*
|
||||
* For a given curve, "m15" is faster than "i15" (but possibly
|
||||
* with a larger code footprint) and "m31" is faster than "i31"
|
||||
* (there again with a larger code footprint). For best
|
||||
* performance, use ec_all_m31, except on the small ARM Cortex M
|
||||
* where ec_all_m15 should be used. Referencing the other
|
||||
* implementations directly will result in smaller code, but
|
||||
* support for fewer curves and possibly lower performance.
|
||||
*/
|
||||
br_ssl_client_set_default_rsapub(cc);
|
||||
br_ssl_engine_set_default_rsavrfy(&cc->eng);
|
||||
br_ssl_engine_set_default_ecdsa(&cc->eng);
|
||||
/* Alternate: set implementations explicitly.
|
||||
br_ssl_client_set_rsapub(cc, &br_rsa_i31_public);
|
||||
br_ssl_client_set_rsavrfy(cc, &br_rsa_i31_pkcs1_vrfy);
|
||||
br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m31);
|
||||
br_ssl_engine_set_ecdsa(&cc->eng, &br_ecdsa_i31_vrfy_asn1);
|
||||
*/
|
||||
|
||||
/*
|
||||
* Record handler:
|
||||
* -- Cipher suites in AES_128_CBC, AES_256_CBC and 3DES_EDE_CBC
|
||||
* need the CBC record handler ("set_cbc").
|
||||
* -- Cipher suites in AES_128_GCM and AES_256_GCM need the GCM
|
||||
* record handler ("set_gcm").
|
||||
* -- Cipher suites in CHACHA20_POLY1305 need the ChaCha20+Poly1305
|
||||
* record handler ("set_chapol").
|
||||
*/
|
||||
br_ssl_engine_set_cbc(&cc->eng,
|
||||
&br_sslrec_in_cbc_vtable,
|
||||
&br_sslrec_out_cbc_vtable);
|
||||
br_ssl_engine_set_gcm(&cc->eng,
|
||||
&br_sslrec_in_gcm_vtable,
|
||||
&br_sslrec_out_gcm_vtable);
|
||||
br_ssl_engine_set_chapol(&cc->eng,
|
||||
&br_sslrec_in_chapol_vtable,
|
||||
&br_sslrec_out_chapol_vtable);
|
||||
|
||||
/*
|
||||
* Symmetric encryption:
|
||||
* -- AES_128_CBC and AES_256_CBC require an "aes_cbc" implementation
|
||||
* (actually two implementations, for encryption and decryption).
|
||||
* -- 3DES_EDE_CBC requires a "des_cbc" implementation
|
||||
* (actually two implementations, for encryption and decryption).
|
||||
* -- AES_128_GCM and AES_256_GCM require an "aes_ctr" imeplementation
|
||||
* and also a GHASH implementation.
|
||||
*
|
||||
* Two 3DES implementations are provided:
|
||||
*
|
||||
* des_tab Classical table-based implementation; it is
|
||||
* not constant-time.
|
||||
*
|
||||
* dest_ct Constant-time DES/3DES implementation. It is
|
||||
* slower than des_tab.
|
||||
*
|
||||
* Four AES implementations are provided:
|
||||
*
|
||||
* aes_ct Constant-time AES implementation, for 32-bit
|
||||
* systems.
|
||||
*
|
||||
* aes_ct64 Constant-time AES implementation, for 64-bit
|
||||
* systems. It actually also runs on 32-bit systems,
|
||||
* but, on such systems, it yields larger code and
|
||||
* slightly worse performance. On 64-bit systems,
|
||||
* aes_ct64 is about twice faster than aes_ct for
|
||||
* CTR processing (GCM encryption and decryption),
|
||||
* and for CBC (decryption only).
|
||||
*
|
||||
* aes_small Smallest implementation provided, but also the
|
||||
* slowest, and it is not constant-time. Use it
|
||||
* only if desperate for code size.
|
||||
*
|
||||
* aes_big Classical table-based AES implementation. This
|
||||
* is decently fast and still resonably compact,
|
||||
* but it is not constant-time.
|
||||
*
|
||||
* aes_x86ni Very fast implementation that uses the AES-NI
|
||||
* opcodes on recent x86 CPU. But it may not be
|
||||
* compiled in the library if the compiler or
|
||||
* architecture is not supported; and the CPU
|
||||
* may also not support the opcodes. Selection
|
||||
* functions are provided to test for availability
|
||||
* of the code and the opcodes.
|
||||
*
|
||||
* Whether having constant-time implementations is absolutely
|
||||
* required for security depends on the context (in particular
|
||||
* whether the target architecture actually has cache memory),
|
||||
* and while side-channel analysis for non-constant-time AES
|
||||
* code has been demonstrated in lab conditions, it certainly
|
||||
* does not apply to all actual usages, and it has never been
|
||||
* spotted in the wild. It is still considered cautious to use
|
||||
* constant-time code by default, and to consider the other
|
||||
* implementations only if duly measured performance issues make
|
||||
* it mandatory.
|
||||
*/
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct_cbcenc_vtable,
|
||||
&br_aes_ct_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct_ctr_vtable);
|
||||
/* Alternate: aes_ct64
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct64_cbcenc_vtable,
|
||||
&br_aes_ct64_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct64_ctr_vtable);
|
||||
*/
|
||||
/* Alternate: aes_small
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_small_cbcenc_vtable,
|
||||
&br_aes_small_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_small_ctr_vtable);
|
||||
*/
|
||||
/* Alternate: aes_big
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_big_cbcenc_vtable,
|
||||
&br_aes_big_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_big_ctr_vtable);
|
||||
*/
|
||||
br_ssl_engine_set_des_cbc(&cc->eng,
|
||||
&br_des_ct_cbcenc_vtable,
|
||||
&br_des_ct_cbcdec_vtable);
|
||||
/* Alternate: des_tab
|
||||
br_ssl_engine_set_des_cbc(&cc->eng,
|
||||
&br_des_tab_cbcenc_vtable,
|
||||
&br_des_tab_cbcdec_vtable);
|
||||
*/
|
||||
|
||||
/*
|
||||
* GHASH is needed for AES_128_GCM and AES_256_GCM. Three
|
||||
* implementations are provided:
|
||||
*
|
||||
* ctmul Uses 32-bit multiplications with a 64-bit result.
|
||||
*
|
||||
* ctmul32 Uses 32-bit multiplications with a 32-bit result.
|
||||
*
|
||||
* ctmul64 Uses 64-bit multiplications with a 64-bit result.
|
||||
*
|
||||
* On 64-bit platforms, ctmul64 is the smallest and fastest of
|
||||
* the three. On 32-bit systems, ctmul should be preferred. The
|
||||
* ctmul32 implementation is meant to be used for the specific
|
||||
* 32-bit systems that do not have a 32x32->64 multiplier (i.e.
|
||||
* the ARM Cortex-M0 and Cortex-M0+).
|
||||
*
|
||||
* These implementations are all constant-time as long as the
|
||||
* underlying multiplication opcode is constant-time (which is
|
||||
* true for all modern systems, but not for older architectures
|
||||
* such that ARM9 or 80486).
|
||||
*/
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul);
|
||||
/* Alternate: ghash_ctmul32
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul32);
|
||||
*/
|
||||
/* Alternate: ghash_ctmul64
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul64);
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* For a client, the normal case is to validate the server
|
||||
* certificate with regards to a set of trust anchors. This
|
||||
* entails using a br_x509_minimal_context structure, configured
|
||||
* with the relevant algorithms, as shown below.
|
||||
*
|
||||
* Alternatively, the client could "know" the intended server
|
||||
* public key through an out-of-band mechanism, in which case
|
||||
* a br_x509_knownkey_context is appropriate, for a much reduced
|
||||
* code footprint.
|
||||
*
|
||||
* We assume here that the following extra parameters have been
|
||||
* provided:
|
||||
*
|
||||
* xc engine context (br_x509_minimal_context *)
|
||||
* trust_anchors trust anchors (br_x509_trust_anchor *)
|
||||
* trust_anchors_num number of trust anchors (size_t)
|
||||
*/
|
||||
|
||||
/*
|
||||
* The X.509 engine needs a hash function for processing the
|
||||
* subject and issuer DN of certificates and trust anchors. Any
|
||||
* supported hash function is appropriate; here we use SHA-256.
|
||||
* The trust an
|
||||
*/
|
||||
br_x509_minimal_init(xc, &br_sha256_vtable,
|
||||
trust_anchors, trust_anchors_num);
|
||||
|
||||
/*
|
||||
* Set suites and asymmetric crypto implementations. We use the
|
||||
* "i31" code for RSA (it is somewhat faster than the "i32"
|
||||
* implementation). These implementations are used for
|
||||
* signature verification on certificates, but not for the
|
||||
* SSL-specific usage of the server's public key. For instance,
|
||||
* if the server has an EC public key but the rest of the chain
|
||||
* (intermediate CA, root...) use RSA, then you would need only
|
||||
* the RSA verification function below.
|
||||
*/
|
||||
br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy);
|
||||
br_x509_minimal_set_ecdsa(xc,
|
||||
&br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
|
||||
|
||||
/*
|
||||
* Set supported hash functions. These are for signatures on
|
||||
* certificates. There again, you only need the hash functions
|
||||
* that are actually used in certificates, but if a given
|
||||
* function was included for the SSL engine, you may as well
|
||||
* add it here.
|
||||
*
|
||||
* Note: the engine explicitly rejects signatures that use MD5.
|
||||
* Thus, there is no need for MD5 here.
|
||||
*/
|
||||
br_ssl_engine_set_hash(xc, br_sha1_ID, &br_sha1_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha224_ID, &br_sha224_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha256_ID, &br_sha256_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha384_ID, &br_sha384_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha512_ID, &br_sha512_vtable);
|
||||
|
||||
/*
|
||||
* Link the X.509 engine in the SSL engine.
|
||||
*/
|
||||
br_ssl_engine_set_x509(&cc->eng, &xc->vtable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Example server profile. Most of it is shared with the client
|
||||
* profile, so see the comments in the client function for details.
|
||||
*
|
||||
* This example function assumes a server with a (unique) RSA private
|
||||
* key, so the list of cipher suites is trimmed down for RSA.
|
||||
*/
|
||||
void
|
||||
example_server_profile(br_ssl_server_context *cc,
|
||||
const br_x509_certificate *chain, size_t chain_len,
|
||||
const br_rsa_private_key *sk)
|
||||
{
|
||||
static const uint16_t suites[] = {
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||
};
|
||||
|
||||
br_ssl_server_zero(cc);
|
||||
br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
|
||||
|
||||
br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf);
|
||||
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
|
||||
br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf);
|
||||
|
||||
/*
|
||||
* Apart from the requirements listed in the client side, these
|
||||
* hash functions are also used by the server to compute its
|
||||
* signature on ECDHE parameters. Which functions are needed
|
||||
* depends on what the client may support; furthermore, the
|
||||
* client may fail to send the relevant extension, in which
|
||||
* case the server will default to whatever it can (as per the
|
||||
* standard, it should be SHA-1 in that case).
|
||||
*/
|
||||
br_ssl_engine_set_hash(&cc->eng, br_md5_ID, &br_md5_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha1_ID, &br_sha1_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha224_ID, &br_sha224_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha384_ID, &br_sha384_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha512_ID, &br_sha512_vtable);
|
||||
|
||||
br_ssl_engine_set_suites(&cc->eng, suites,
|
||||
(sizeof suites) / (sizeof suites[0]));
|
||||
|
||||
/*
|
||||
* Elliptic curve implementation is used for ECDHE suites (but
|
||||
* not for ECDH).
|
||||
*/
|
||||
br_ssl_engine_set_ec(&cc->eng, &br_ec_prime_i31);
|
||||
|
||||
/*
|
||||
* Set the "server policy": handler for the certificate chain
|
||||
* and private key operations. Here, we indicate that the RSA
|
||||
* private key is fit for both signing and decrypting, and we
|
||||
* provide the two relevant implementations.
|
||||
|
||||
* BR_KEYTYPE_KEYX allows TLS_RSA_*, BR_KEYTYPE_SIGN allows
|
||||
* TLS_ECDHE_RSA_*.
|
||||
*/
|
||||
br_ssl_server_set_single_rsa(cc, chain, chain_len, sk,
|
||||
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||
br_rsa_i31_private, br_rsa_i31_pkcs1_sign);
|
||||
/*
|
||||
* If the server used an EC private key, this call would look
|
||||
* like this:
|
||||
|
||||
br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
|
||||
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||
cert_issuer_key_type,
|
||||
&br_ec_prime_i31, br_ecdsa_i31_sign_asn1);
|
||||
|
||||
* Note the tricky points:
|
||||
*
|
||||
* -- "ECDH" cipher suites use only the EC code (&br_ec_prime_i31);
|
||||
* the ECDHE_ECDSA cipher suites need both the EC code and
|
||||
* the ECDSA signature implementation.
|
||||
*
|
||||
* -- For "ECDH" (not "ECDHE") cipher suites, the engine must
|
||||
* know the key type (RSA or EC) for the intermediate CA that
|
||||
* issued the server's certificate; this is an artefact of
|
||||
* how the protocol is defined. BearSSL won't try to decode
|
||||
* the server's certificate to obtain that information (it
|
||||
* could do that, the code is there, but it would increase the
|
||||
* footprint). So this must be provided by the caller.
|
||||
*
|
||||
* -- BR_KEYTYPE_KEYX allows ECDH, BR_KEYTYPE_SIGN allows
|
||||
* ECDHE_ECDSA.
|
||||
*/
|
||||
|
||||
br_ssl_engine_set_cbc(&cc->eng,
|
||||
&br_sslrec_in_cbc_vtable,
|
||||
&br_sslrec_out_cbc_vtable);
|
||||
br_ssl_engine_set_gcm(&cc->eng,
|
||||
&br_sslrec_in_gcm_vtable,
|
||||
&br_sslrec_out_gcm_vtable);
|
||||
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct_cbcenc_vtable,
|
||||
&br_aes_ct_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct_ctr_vtable);
|
||||
/* Alternate: aes_ct64
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct64_cbcenc_vtable,
|
||||
&br_aes_ct64_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct64_ctr_vtable);
|
||||
*/
|
||||
/* Alternate: aes_small
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_small_cbcenc_vtable,
|
||||
&br_aes_small_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_small_ctr_vtable);
|
||||
*/
|
||||
/* Alternate: aes_big
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_big_cbcenc_vtable,
|
||||
&br_aes_big_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_big_ctr_vtable);
|
||||
*/
|
||||
br_ssl_engine_set_des_cbc(&cc->eng,
|
||||
&br_des_ct_cbcenc_vtable,
|
||||
&br_des_ct_cbcdec_vtable);
|
||||
/* Alternate: des_tab
|
||||
br_ssl_engine_set_des_cbc(&cc->eng,
|
||||
&br_des_tab_cbcenc_vtable,
|
||||
&br_des_tab_cbcdec_vtable);
|
||||
*/
|
||||
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul);
|
||||
/* Alternate: ghash_ctmul32
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul32);
|
||||
*/
|
||||
/* Alternate: ghash_ctmul64
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul64);
|
||||
*/
|
||||
}
|
40
contrib/bearssl/samples/key-ec.h
Normal file
40
contrib/bearssl/samples/key-ec.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* The private key for the server certificate (EC).
|
||||
*/
|
||||
|
||||
static const unsigned char EC_X[] = {
|
||||
0x03, 0x91, 0x5B, 0x42, 0x06, 0x90, 0x73, 0x91, 0x1B, 0x48, 0xEF, 0x08,
|
||||
0xFB, 0xB5, 0xAD, 0x75, 0x65, 0xF9, 0xE6, 0xF7, 0x21, 0x47, 0x62, 0x48,
|
||||
0xFA, 0x3F, 0x97, 0x7B, 0x70, 0x9D, 0x86, 0xA5
|
||||
};
|
||||
|
||||
static const br_ec_private_key EC = {
|
||||
23,
|
||||
(unsigned char *)EC_X, sizeof EC_X
|
||||
};
|
5
contrib/bearssl/samples/key-ee-ec.pem
Normal file
5
contrib/bearssl/samples/key-ee-ec.pem
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIAORW0IGkHORG0jvCPu1rXVl+eb3IUdiSPo/l3twnYaloAoGCCqGSM49AwEHoUQDQgAE
|
||||
Xzidp/9Niq/2NDlGGvw63/Qjqqnq+8UI3gCOvnmlN1hMbd0ByqtH34m2xxcfOPwdIBTdRcDgj5NO
|
||||
OAv86ZmhSQ==
|
||||
-----END EC PRIVATE KEY-----
|
23
contrib/bearssl/samples/key-ee-rsa.pem
Normal file
23
contrib/bearssl/samples/key-ee-rsa.pem
Normal file
@ -0,0 +1,23 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA1HodJ7orOmeykWr754NEyu0cda3dTYNi1qpolbIkIXsVriqZaBXtZvC4WOfT
|
||||
9S7G2Spe5w4u5/xnWcDIYX1LpG/dn9nIhYdkx7oaDynUlqh4mmtiIKky0O6pjChhR6JQKmP2Id7a
|
||||
2NXwf8UAgnDmo79ciSdPUZJ3A8OwzC477CPyL1NBr4mT/9KAsUOX3tYZoJISej1meeHBvOF3cKKL
|
||||
PUaEUz/kTkJBN5IeH/04s/fvhzmA01bP9OAT3mSwcqQDhMRB7W/6PuLKBCDS19wsgit64m2hHEjb
|
||||
z4lPNJc9KKhT2ufB4XMVozB2f48jQhQ9UTTSWq08m8vI/n9ujkDzvQIDAQABAoIBADzb40jzQpl+
|
||||
hT+wsIl96HDlXI76Z1Zh6SgKdF1YQpASdMHHstwE19Rx46OXd3cVWGBwifFNdzL8cU/cb6i43jcx
|
||||
0X2NQCm6/6tTi05HkXw7shus4VTwkb0VdxvNnxuJCsQxkJjf/7g3AyVdtIkoNG+3ipZAW7BGLu+1
|
||||
mAjLv18h4LniI8JGWQK75z8xNQzEdOFVyqC1PujjC5emesxlRW8Ks+MzQ+20WTpHGkLAoLJZJ1XE
|
||||
bDQqFbkRXu4imKLtA4iyBrEpXEKZR85tVO+NQOGdPyH/ugK23nSDcJlI2PTHSlGABTpZZUmigO4O
|
||||
b8lppU7cFa2JemKG3kEj0BWDOWMCgYEA+fYynFHXcbJi7YEk2vapLMMtVZSVUeU2Ep4uH47YIiJk
|
||||
XqP8YPAU3BBIb08afcw3Iyd2tjGq3nDJ7KsKUPHqeXl0vjurLmOXom8KRXvXbNJtG3AxA68miyjF
|
||||
+ElnRUHx0zUFJyp5IdoGtj2i6DxA+m/E/PXEBeuaMapAfl7uIlsCgYEA2Zwa3JRR9sGW2g4RPzco
|
||||
ejOwxL7faCvTHGVnejyvWVCrKTYXORVxl2LdzSXujf8mj3Ehvo+chU464STH4Urf0GCzxEQurHMW
|
||||
XwfJOnNe2pvu4rSpPTMUe+6n1Kz3U+Y+8IVXTIuWG93XNvyJN1l1lnWLLvcELSmJ2befcTvi7ccC
|
||||
gYEA5PwCLyvWRwTZFaRaI/EU17nRHPYpuEVXPMUFkclk/BgvhHeLay5knZiZEscPiLB8zkqHuK5V
|
||||
TsNaZ+HkaHTFjRSTuvWkgrGfpqE8cpzZo4o9g4ZKkIpyr8bhXOu5nDumEgsfNlr1bupxfZ+HTmJs
|
||||
UD/14JowQhAsSFUkEeBbHMMCgYEAjazgoDPAmVK4kAcQm4Ohys3UjINomD3QGHC8ygywbQnkJdSd
|
||||
kgCwD8vCdEn54mD4DfOt8I83bGLeWq7Do55H0TbkUyfA622SZxR+optyagmToe3VMY8MCxP6GLDz
|
||||
5Z/F4notuBw5ArOP5rDL9Uk9EVQ95bnU8kJVCXZPTD2dJQkCgYByDKfPBpVp9HUgNAPgz5pRk/VC
|
||||
LvKFvs5POLWMoplC871lOOI0PyGd9b2zv3M8GN728H+hwlXyOOkOHjHn21HFcY1ncTqfVVJg7kX2
|
||||
CJiBt3sv8pZ9c9Cmq6qDSUE1qZBnztO5c1SqhACIiJAdhpvluM6JChtHYjHCP8OMhgk8hg==
|
||||
-----END RSA PRIVATE KEY-----
|
5
contrib/bearssl/samples/key-ica-ec.pem
Normal file
5
contrib/bearssl/samples/key-ica-ec.pem
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIEJOkvo4MZ9N+wlTodEzmWor1RauybudPe92K15viDbzoAoGCCqGSM49AwEHoUQDQgAE
|
||||
cC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDNSZ4Hv9Cu
|
||||
nebQsycWoQ==
|
||||
-----END EC PRIVATE KEY-----
|
23
contrib/bearssl/samples/key-ica-rsa.pem
Normal file
23
contrib/bearssl/samples/key-ica-rsa.pem
Normal file
@ -0,0 +1,23 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAs+hrr5wWUuOBDFCrJc7MDcfyH39Q3yxcNdZiLmMnQafkU6hLJ/oTkaP6CUov
|
||||
O17Pd7OKwc1JlZx1DWR07+TXS7mhm2jSMHFI6vdLFN8/R6nYu+yPKMz637QflHyW/AgFKPno9C8v
|
||||
7mKcijrghVhgtg8tMLTAQVSRTB9frfEZ8MAipn3YP3k0WUJ7W7VBxGR/Us88NyKhL3kllCRBwj/6
|
||||
x3X7SLUNGKf0VPMubthDWMSrUOgFrZG2HgF1s1Sc3qCZFfus8VyXSVHM71gSb3NrszQUAQ9anfqq
|
||||
1pPT4urDq7xO7cxRobj4lLa0LKiGKx/2UUMpUl4TibNqeGBOTsAbpQIDAQABAoIBAAtBpQ85SGpK
|
||||
QsZG+9ZjQIAyPPN8j05PY7uYnM8DNC8W9qHHW2B2dKf9pwTSx+7CiV+Xc7yZgBukzOwYF3r1CgV6
|
||||
aWKkZdZTGDlfXKrDJx3wQhfL/s8SODYr+nfbbcT6KXx9WnaAx1J2iA3cDjU5qN9rRqwP+yF7TZYC
|
||||
NoXXGoTmHb7gj1H1IJNdiUgG0netXpM2HydRLzwHDweKav6sm4V4TTeHPYokVp8W7lL7xRhwQXVD
|
||||
lcE1noY5NczXV88k9n0EbqGDwX3pJoDC/xWzBFh/+oupxotM4KY2dKJGmtKTmiIef3u43CPv5SYh
|
||||
V2OcEXn+joV5qHGhg6yN+ri0/ucCgYEA4x2NBFNtbpx3lmc2r2hwfbawcTVKKlxqJWdoG2bd7HQz
|
||||
bO+uqtxhLOxEou4S9uPUVylvpNlDs3xQ+DF9p8oTo5XlHvA6DT/cAjWSQ+MRHqCV30T0lDSd0McZ
|
||||
4PaV1nq94bGuPVrGe/Dex5dL+VVhn2tpoqwudsyx5hHA8hFE1zcCgYEAysnhrQa1HZQ0hOaA2c/e
|
||||
A8I47dEIyGi4N6uJVBUMM1ecKifs4FKybOtI+XM3mwuAXUyVQGi2SZBBpE4bN3oUDWGwYF7SAJV0
|
||||
JJHpBxlZBvYRC7Vfh8HFPYIQCynP0Q4BeQVDaCPW3puJsTWnn2lNhT/PsSm3v76JwTRrBoqaGgMC
|
||||
gYAwyyiAxWu9V+BZb9NP3CBO4fEGYWyNrU0gvBahzHfhVRW3Ucc07iPygtA8MOniIRB9qWlTAVqK
|
||||
NSswJ3HXmpKdkpanDvVp405hKyFBdIc5DUclsKrbLHK7aAsnSdLnQXeKBaJpjBcYiadTOi4YYz+W
|
||||
AH2xdUyGOXP++dF6MDuaAQKBgQCtWyHygW5pR94R0t9J1FpuCiYSn4ULlgINjTXLzGZuqbGVlCX6
|
||||
qpdfZ1At92IMyCtHFwXsVtemUYzcAe1gYpsryVw3Njf+ScVM0fNMn02tFsQBp15wNqT/7OT8NhUz
|
||||
GO8HXwl9yE2SZZKzDDQsoZ+kjqVlRU2QvDkVElN/9xK/swKBgDz6m4XHvhvITo2bd8/i4FxTN1gr
|
||||
napgAc2DHOzCmeyYCjKvZAJDLeNleni1kj1UfrzVrH2BFM38asRJu8xPI4WjfH1fFktNjXVu6Ctk
|
||||
YFu0/0TlWkzowZHmE/K0M0tuJLt42m/DLW8deMyl38x+PUPUZb4OdVAKAua/voOMZtQw
|
||||
-----END RSA PRIVATE KEY-----
|
5
contrib/bearssl/samples/key-root-ec.pem
Normal file
5
contrib/bearssl/samples/key-root-ec.pem
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEINx41f6h/utlj52XNFbIGJdkF3qZy1/g9hH2/yV4t/tnoAoGCCqGSM49AwEHoUQDQgAE
|
||||
cXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eH
|
||||
wuXYxfN/jQ==
|
||||
-----END EC PRIVATE KEY-----
|
23
contrib/bearssl/samples/key-root-rsa.pem
Normal file
23
contrib/bearssl/samples/key-root-rsa.pem
Normal file
@ -0,0 +1,23 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAttk01FD9s696c/HOOL9db0Xh/U6xmMZggybSF9HFt5qjwd5jOZec8F5cyBwX
|
||||
uYgZbfC2LjBQoVRuk8DbzzDLnx4nefHDmVI1qj2237CtfMtJzcDt52YQKunOKB8hUPp3TC3a7zxY
|
||||
606/zun7Gtqjg6PNo8qTgNza8xfMeqszgJyy1H9GP8U83GGUtycpbiq8Wwk21MY7Deu+ztsdHLwQ
|
||||
anFxs/LKKJp38orsQu+xSo7i8hoyKs3ApkYsmsKFN5F/RqGTgaF0Zt+6szkgkZP6HaGohefk+Qf2
|
||||
EPaoJwG2fxLDQMPJ4rCrSRg6ZLZZt5W1ljbfImmqcmpUTicpow6XFQIDAQABAoIBAENjavKDBPWn
|
||||
yygXKqtEb/GWHlNmoNKO7jv33z9TGxzvW8IULZqos3jtNiG0JNRGgiTALcx5FwZWYUiIMBq8v5bd
|
||||
nKv3O+DyaP/crdzkNxRCsekoXSXGuleugsHLs1IudTA4yDMamSTkCZH/LwH3KYNXJ+9hNhqsiu9D
|
||||
yqM9HIad2k/hmVFv4NDdH3VWqsQJFfrGEXgKRJKNpuzKeST3oo4iLcwH9NGiKXfjW23ekOiLYFwZ
|
||||
q8Yd6tOgNLpGuDWk9rlXPJALyXFZ/3UXZaKU5f0ZRfPfMQgM8toeWeWJS0FW7g6aLCJATsfOu/II
|
||||
j3nTVCPryvGF4mwe/y+Rgbd67xMCgYEA3Wpiac27hvbLzwbSTWYsKql5uKV0HTim3haNDuzMHJVY
|
||||
ZRJSuTY+rZBoaiuDRKMCMI3dQM8AZUJfHQclyTxjtn17Ig8cTKMN6Wr2MRTBplCq3wNLVjbOPAE2
|
||||
cv74gUfgpRLdlyueYO7j6PcTS+l41+wB1A/zAEm346Eoxoztt5cCgYEA02ipYQFX4T+8BSkcEyzP
|
||||
qeMT9d3BLPm4tTeq2sXRgcfEbF/ENcAX9OfPSEx4kVtzsfJXma5/dg0fuVgl1hO5WLBT+L6MJ/A2
|
||||
sGX3Y7x+doXI0xcNd/Epr7oWqZuCO7477vzJcNtud/KQJj2EmRNaHKKtaohqO5dnNhsM540lnDMC
|
||||
gYBU40KT2eJ5ngkJeE4Mio2IVa1rE1PvGBcxsmemPzcKBl/7cAjzJU7mcCT3/3K2T+C5CMq43CQE
|
||||
rmuUz3a3LkX0YytgJXbuEt10jiORMaoEv4yjL7okdaKf8r8TW5mexxXjc9Ys7PYtp6kNWhy1z+8a
|
||||
qUsSKIM7qwerZ9AgP0usRQKBgQDEHy4y/coG/tdweii/aSzlT/Huf2B8VtaR1yi7eBTaLvb8CwO9
|
||||
UY1n970GN1sKjiqQhF/cBFPesmIh0bKYHQgvTLU555uiWWiC0LVmYzF2xrn9ij9GbAXeLeZkRg3V
|
||||
Wq/DD+PYvNiIkhBESYG/eIJ6WjhCwna6/cQUH5gjH4AqnQKBgQCsKyjLtx+FeFu7PZ8AgCGWRVvs
|
||||
suxB74pxlMqMgBbBHyAGQOTTuaaTr/gwNXAAErAXS1X9VsAcAkM/yFv19mdZmJQG9vUMOe48AZDB
|
||||
c7xt3t3Ul71eAlbAYkrQGtq64yO3w7ny4C7GUVqMX03XwKToCrXqeKfGwrZGNP+lgZYrbw==
|
||||
-----END RSA PRIVATE KEY-----
|
108
contrib/bearssl/samples/key-rsa.h
Normal file
108
contrib/bearssl/samples/key-rsa.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* The private key for the server certificate (RSA).
|
||||
*/
|
||||
|
||||
static const unsigned char RSA_P[] = {
|
||||
0xF9, 0xF6, 0x32, 0x9C, 0x51, 0xD7, 0x71, 0xB2, 0x62, 0xED, 0x81, 0x24,
|
||||
0xDA, 0xF6, 0xA9, 0x2C, 0xC3, 0x2D, 0x55, 0x94, 0x95, 0x51, 0xE5, 0x36,
|
||||
0x12, 0x9E, 0x2E, 0x1F, 0x8E, 0xD8, 0x22, 0x22, 0x64, 0x5E, 0xA3, 0xFC,
|
||||
0x60, 0xF0, 0x14, 0xDC, 0x10, 0x48, 0x6F, 0x4F, 0x1A, 0x7D, 0xCC, 0x37,
|
||||
0x23, 0x27, 0x76, 0xB6, 0x31, 0xAA, 0xDE, 0x70, 0xC9, 0xEC, 0xAB, 0x0A,
|
||||
0x50, 0xF1, 0xEA, 0x79, 0x79, 0x74, 0xBE, 0x3B, 0xAB, 0x2E, 0x63, 0x97,
|
||||
0xA2, 0x6F, 0x0A, 0x45, 0x7B, 0xD7, 0x6C, 0xD2, 0x6D, 0x1B, 0x70, 0x31,
|
||||
0x03, 0xAF, 0x26, 0x8B, 0x28, 0xC5, 0xF8, 0x49, 0x67, 0x45, 0x41, 0xF1,
|
||||
0xD3, 0x35, 0x05, 0x27, 0x2A, 0x79, 0x21, 0xDA, 0x06, 0xB6, 0x3D, 0xA2,
|
||||
0xE8, 0x3C, 0x40, 0xFA, 0x6F, 0xC4, 0xFC, 0xF5, 0xC4, 0x05, 0xEB, 0x9A,
|
||||
0x31, 0xAA, 0x40, 0x7E, 0x5E, 0xEE, 0x22, 0x5B
|
||||
};
|
||||
|
||||
static const unsigned char RSA_Q[] = {
|
||||
0xD9, 0x9C, 0x1A, 0xDC, 0x94, 0x51, 0xF6, 0xC1, 0x96, 0xDA, 0x0E, 0x11,
|
||||
0x3F, 0x37, 0x28, 0x7A, 0x33, 0xB0, 0xC4, 0xBE, 0xDF, 0x68, 0x2B, 0xD3,
|
||||
0x1C, 0x65, 0x67, 0x7A, 0x3C, 0xAF, 0x59, 0x50, 0xAB, 0x29, 0x36, 0x17,
|
||||
0x39, 0x15, 0x71, 0x97, 0x62, 0xDD, 0xCD, 0x25, 0xEE, 0x8D, 0xFF, 0x26,
|
||||
0x8F, 0x71, 0x21, 0xBE, 0x8F, 0x9C, 0x85, 0x4E, 0x3A, 0xE1, 0x24, 0xC7,
|
||||
0xE1, 0x4A, 0xDF, 0xD0, 0x60, 0xB3, 0xC4, 0x44, 0x2E, 0xAC, 0x73, 0x16,
|
||||
0x5F, 0x07, 0xC9, 0x3A, 0x73, 0x5E, 0xDA, 0x9B, 0xEE, 0xE2, 0xB4, 0xA9,
|
||||
0x3D, 0x33, 0x14, 0x7B, 0xEE, 0xA7, 0xD4, 0xAC, 0xF7, 0x53, 0xE6, 0x3E,
|
||||
0xF0, 0x85, 0x57, 0x4C, 0x8B, 0x96, 0x1B, 0xDD, 0xD7, 0x36, 0xFC, 0x89,
|
||||
0x37, 0x59, 0x75, 0x96, 0x75, 0x8B, 0x2E, 0xF7, 0x04, 0x2D, 0x29, 0x89,
|
||||
0xD9, 0xB7, 0x9F, 0x71, 0x3B, 0xE2, 0xED, 0xC7
|
||||
};
|
||||
|
||||
static const unsigned char RSA_DP[] = {
|
||||
0xE4, 0xFC, 0x02, 0x2F, 0x2B, 0xD6, 0x47, 0x04, 0xD9, 0x15, 0xA4, 0x5A,
|
||||
0x23, 0xF1, 0x14, 0xD7, 0xB9, 0xD1, 0x1C, 0xF6, 0x29, 0xB8, 0x45, 0x57,
|
||||
0x3C, 0xC5, 0x05, 0x91, 0xC9, 0x64, 0xFC, 0x18, 0x2F, 0x84, 0x77, 0x8B,
|
||||
0x6B, 0x2E, 0x64, 0x9D, 0x98, 0x99, 0x12, 0xC7, 0x0F, 0x88, 0xB0, 0x7C,
|
||||
0xCE, 0x4A, 0x87, 0xB8, 0xAE, 0x55, 0x4E, 0xC3, 0x5A, 0x67, 0xE1, 0xE4,
|
||||
0x68, 0x74, 0xC5, 0x8D, 0x14, 0x93, 0xBA, 0xF5, 0xA4, 0x82, 0xB1, 0x9F,
|
||||
0xA6, 0xA1, 0x3C, 0x72, 0x9C, 0xD9, 0xA3, 0x8A, 0x3D, 0x83, 0x86, 0x4A,
|
||||
0x90, 0x8A, 0x72, 0xAF, 0xC6, 0xE1, 0x5C, 0xEB, 0xB9, 0x9C, 0x3B, 0xA6,
|
||||
0x12, 0x0B, 0x1F, 0x36, 0x5A, 0xF5, 0x6E, 0xEA, 0x71, 0x7D, 0x9F, 0x87,
|
||||
0x4E, 0x62, 0x6C, 0x50, 0x3F, 0xF5, 0xE0, 0x9A, 0x30, 0x42, 0x10, 0x2C,
|
||||
0x48, 0x55, 0x24, 0x11, 0xE0, 0x5B, 0x1C, 0xC3
|
||||
};
|
||||
|
||||
static const unsigned char RSA_DQ[] = {
|
||||
0x8D, 0xAC, 0xE0, 0xA0, 0x33, 0xC0, 0x99, 0x52, 0xB8, 0x90, 0x07, 0x10,
|
||||
0x9B, 0x83, 0xA1, 0xCA, 0xCD, 0xD4, 0x8C, 0x83, 0x68, 0x98, 0x3D, 0xD0,
|
||||
0x18, 0x70, 0xBC, 0xCA, 0x0C, 0xB0, 0x6D, 0x09, 0xE4, 0x25, 0xD4, 0x9D,
|
||||
0x92, 0x00, 0xB0, 0x0F, 0xCB, 0xC2, 0x74, 0x49, 0xF9, 0xE2, 0x60, 0xF8,
|
||||
0x0D, 0xF3, 0xAD, 0xF0, 0x8F, 0x37, 0x6C, 0x62, 0xDE, 0x5A, 0xAE, 0xC3,
|
||||
0xA3, 0x9E, 0x47, 0xD1, 0x36, 0xE4, 0x53, 0x27, 0xC0, 0xEB, 0x6D, 0x92,
|
||||
0x67, 0x14, 0x7E, 0xA2, 0x9B, 0x72, 0x6A, 0x09, 0x93, 0xA1, 0xED, 0xD5,
|
||||
0x31, 0x8F, 0x0C, 0x0B, 0x13, 0xFA, 0x18, 0xB0, 0xF3, 0xE5, 0x9F, 0xC5,
|
||||
0xE2, 0x7A, 0x2D, 0xB8, 0x1C, 0x39, 0x02, 0xB3, 0x8F, 0xE6, 0xB0, 0xCB,
|
||||
0xF5, 0x49, 0x3D, 0x11, 0x54, 0x3D, 0xE5, 0xB9, 0xD4, 0xF2, 0x42, 0x55,
|
||||
0x09, 0x76, 0x4F, 0x4C, 0x3D, 0x9D, 0x25, 0x09
|
||||
};
|
||||
|
||||
static const unsigned char RSA_IQ[] = {
|
||||
0x72, 0x0C, 0xA7, 0xCF, 0x06, 0x95, 0x69, 0xF4, 0x75, 0x20, 0x34, 0x03,
|
||||
0xE0, 0xCF, 0x9A, 0x51, 0x93, 0xF5, 0x42, 0x2E, 0xF2, 0x85, 0xBE, 0xCE,
|
||||
0x4F, 0x38, 0xB5, 0x8C, 0xA2, 0x99, 0x42, 0xF3, 0xBD, 0x65, 0x38, 0xE2,
|
||||
0x34, 0x3F, 0x21, 0x9D, 0xF5, 0xBD, 0xB3, 0xBF, 0x73, 0x3C, 0x18, 0xDE,
|
||||
0xF6, 0xF0, 0x7F, 0xA1, 0xC2, 0x55, 0xF2, 0x38, 0xE9, 0x0E, 0x1E, 0x31,
|
||||
0xE7, 0xDB, 0x51, 0xC5, 0x71, 0x8D, 0x67, 0x71, 0x3A, 0x9F, 0x55, 0x52,
|
||||
0x60, 0xEE, 0x45, 0xF6, 0x08, 0x98, 0x81, 0xB7, 0x7B, 0x2F, 0xF2, 0x96,
|
||||
0x7D, 0x73, 0xD0, 0xA6, 0xAB, 0xAA, 0x83, 0x49, 0x41, 0x35, 0xA9, 0x90,
|
||||
0x67, 0xCE, 0xD3, 0xB9, 0x73, 0x54, 0xAA, 0x84, 0x00, 0x88, 0x88, 0x90,
|
||||
0x1D, 0x86, 0x9B, 0xE5, 0xB8, 0xCE, 0x89, 0x0A, 0x1B, 0x47, 0x62, 0x31,
|
||||
0xC2, 0x3F, 0xC3, 0x8C, 0x86, 0x09, 0x3C, 0x86
|
||||
};
|
||||
|
||||
static const br_rsa_private_key RSA = {
|
||||
2048,
|
||||
(unsigned char *)RSA_P, sizeof RSA_P,
|
||||
(unsigned char *)RSA_Q, sizeof RSA_Q,
|
||||
(unsigned char *)RSA_DP, sizeof RSA_DP,
|
||||
(unsigned char *)RSA_DQ, sizeof RSA_DQ,
|
||||
(unsigned char *)RSA_IQ, sizeof RSA_IQ
|
||||
};
|
436
contrib/bearssl/samples/server_basic.c
Normal file
436
contrib/bearssl/samples/server_basic.c
Normal file
@ -0,0 +1,436 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* This sample code can use three possible certificate chains:
|
||||
* -- A full-RSA chain (server key is RSA, certificates are signed with RSA)
|
||||
* -- A full-EC chain (server key is EC, certificates are signed with ECDSA)
|
||||
* -- A mixed chain (server key is EC, certificates are signed with RSA)
|
||||
*
|
||||
* The macros below define which chain is selected. This impacts the list
|
||||
* of supported cipher suites.
|
||||
*
|
||||
* Other macros, which can be defined (with a non-zero value):
|
||||
*
|
||||
* SERVER_PROFILE_MIN_FS
|
||||
* Select a "minimal" profile with forward security (ECDHE cipher
|
||||
* suite).
|
||||
*
|
||||
* SERVER_PROFILE_MIN_NOFS
|
||||
* Select a "minimal" profile without forward security (RSA or ECDH
|
||||
* cipher suite, but not ECDHE).
|
||||
*
|
||||
* SERVER_CHACHA20
|
||||
* If SERVER_PROFILE_MIN_FS is selected, then this macro selects
|
||||
* a cipher suite with ChaCha20+Poly1305; otherwise, AES/GCM is
|
||||
* used. This macro has no effect otherwise, since there is no
|
||||
* non-forward secure cipher suite that uses ChaCha20+Poly1305.
|
||||
*/
|
||||
|
||||
#if !(SERVER_RSA || SERVER_EC || SERVER_MIXED)
|
||||
#define SERVER_RSA 1
|
||||
#define SERVER_EC 0
|
||||
#define SERVER_MIXED 0
|
||||
#endif
|
||||
|
||||
#if SERVER_RSA
|
||||
#include "chain-rsa.h"
|
||||
#include "key-rsa.h"
|
||||
#define SKEY RSA
|
||||
#elif SERVER_EC
|
||||
#include "chain-ec.h"
|
||||
#include "key-ec.h"
|
||||
#define SKEY EC
|
||||
#elif SERVER_MIXED
|
||||
#include "chain-ec+rsa.h"
|
||||
#include "key-ec.h"
|
||||
#define SKEY EC
|
||||
#else
|
||||
#error Must use one of RSA, EC or MIXED chains.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create a server socket bound to the specified host and port. If 'host'
|
||||
* is NULL, this will bind "generically" (all addresses).
|
||||
*
|
||||
* Returned value is the server socket descriptor, or -1 on error.
|
||||
*/
|
||||
static int
|
||||
host_bind(const char *host, const char *port)
|
||||
{
|
||||
struct addrinfo hints, *si, *p;
|
||||
int fd;
|
||||
int err;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
err = getaddrinfo(host, port, &hints, &si);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "ERROR: getaddrinfo(): %s\n",
|
||||
gai_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
fd = -1;
|
||||
for (p = si; p != NULL; p = p->ai_next) {
|
||||
struct sockaddr *sa;
|
||||
struct sockaddr_in sa4;
|
||||
struct sockaddr_in6 sa6;
|
||||
size_t sa_len;
|
||||
void *addr;
|
||||
char tmp[INET6_ADDRSTRLEN + 50];
|
||||
int opt;
|
||||
|
||||
sa = (struct sockaddr *)p->ai_addr;
|
||||
if (sa->sa_family == AF_INET) {
|
||||
sa4 = *(struct sockaddr_in *)sa;
|
||||
sa = (struct sockaddr *)&sa4;
|
||||
sa_len = sizeof sa4;
|
||||
addr = &sa4.sin_addr;
|
||||
if (host == NULL) {
|
||||
sa4.sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
} else if (sa->sa_family == AF_INET6) {
|
||||
sa6 = *(struct sockaddr_in6 *)sa;
|
||||
sa = (struct sockaddr *)&sa6;
|
||||
sa_len = sizeof sa6;
|
||||
addr = &sa6.sin6_addr;
|
||||
if (host == NULL) {
|
||||
sa6.sin6_addr = in6addr_any;
|
||||
}
|
||||
} else {
|
||||
addr = NULL;
|
||||
sa_len = p->ai_addrlen;
|
||||
}
|
||||
if (addr != NULL) {
|
||||
inet_ntop(p->ai_family, addr, tmp, sizeof tmp);
|
||||
} else {
|
||||
sprintf(tmp, "<unknown family: %d>",
|
||||
(int)sa->sa_family);
|
||||
}
|
||||
fprintf(stderr, "binding to: %s\n", tmp);
|
||||
fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
if (fd < 0) {
|
||||
perror("socket()");
|
||||
continue;
|
||||
}
|
||||
opt = 1;
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt);
|
||||
opt = 0;
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt);
|
||||
if (bind(fd, sa, sa_len) < 0) {
|
||||
perror("bind()");
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (p == NULL) {
|
||||
freeaddrinfo(si);
|
||||
fprintf(stderr, "ERROR: failed to bind\n");
|
||||
return -1;
|
||||
}
|
||||
freeaddrinfo(si);
|
||||
if (listen(fd, 5) < 0) {
|
||||
perror("listen()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "bound.\n");
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a single client on the provided server socket. This is blocking.
|
||||
* On error, this returns -1.
|
||||
*/
|
||||
static int
|
||||
accept_client(int server_fd)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr sa;
|
||||
socklen_t sa_len;
|
||||
char tmp[INET6_ADDRSTRLEN + 50];
|
||||
const char *name;
|
||||
|
||||
sa_len = sizeof sa;
|
||||
fd = accept(server_fd, &sa, &sa_len);
|
||||
if (fd < 0) {
|
||||
perror("accept()");
|
||||
return -1;
|
||||
}
|
||||
name = NULL;
|
||||
switch (sa.sa_family) {
|
||||
case AF_INET:
|
||||
name = inet_ntop(AF_INET,
|
||||
&((struct sockaddr_in *)&sa)->sin_addr,
|
||||
tmp, sizeof tmp);
|
||||
break;
|
||||
case AF_INET6:
|
||||
name = inet_ntop(AF_INET6,
|
||||
&((struct sockaddr_in6 *)&sa)->sin6_addr,
|
||||
tmp, sizeof tmp);
|
||||
break;
|
||||
}
|
||||
if (name == NULL) {
|
||||
sprintf(tmp, "<unknown: %lu>", (unsigned long)sa.sa_family);
|
||||
name = tmp;
|
||||
}
|
||||
fprintf(stderr, "accepting connection from: %s\n", name);
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level data read callback for the simplified SSL I/O API.
|
||||
*/
|
||||
static int
|
||||
sock_read(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t rlen;
|
||||
|
||||
rlen = read(*(int *)ctx, buf, len);
|
||||
if (rlen <= 0) {
|
||||
if (rlen < 0 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return (int)rlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level data write callback for the simplified SSL I/O API.
|
||||
*/
|
||||
static int
|
||||
sock_write(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t wlen;
|
||||
|
||||
wlen = write(*(int *)ctx, buf, len);
|
||||
if (wlen <= 0) {
|
||||
if (wlen < 0 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return (int)wlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sample HTTP response to send.
|
||||
*/
|
||||
static const char *HTTP_RES =
|
||||
"HTTP/1.0 200 OK\r\n"
|
||||
"Content-Length: 46\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"
|
||||
"\r\n"
|
||||
"<html>\r\n"
|
||||
"<body>\r\n"
|
||||
"<p>Test!</p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>\r\n";
|
||||
|
||||
/*
|
||||
* Main program: this is a simple program that expects 1 argument: a
|
||||
* port number. This will start a simple network server on that port,
|
||||
* that expects incoming SSL clients. It handles only one client at a
|
||||
* time (handling several would require threads, sub-processes, or
|
||||
* multiplexing with select()/poll(), all of which being possible).
|
||||
*
|
||||
* For each client, the server will wait for two successive newline
|
||||
* characters (ignoring CR characters, so CR+LF is accepted), then
|
||||
* produce a sample static HTTP response. This is very crude, but
|
||||
* sufficient for explanatory purposes.
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *port;
|
||||
int fd;
|
||||
|
||||
if (argc != 2) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
port = argv[1];
|
||||
|
||||
/*
|
||||
* Ignore SIGPIPE to avoid crashing in case of abrupt socket close.
|
||||
*/
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/*
|
||||
* Open the server socket.
|
||||
*/
|
||||
fd = host_bind(NULL, port);
|
||||
if (fd < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process each client, one at a time.
|
||||
*/
|
||||
for (;;) {
|
||||
int cfd;
|
||||
br_ssl_server_context sc;
|
||||
unsigned char iobuf[BR_SSL_BUFSIZE_BIDI];
|
||||
br_sslio_context ioc;
|
||||
int lcwn, err;
|
||||
|
||||
cfd = accept_client(fd);
|
||||
if (cfd < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the context with the cipher suites and
|
||||
* algorithms. This depends on the server key type
|
||||
* (and, for EC keys, the signature algorithm used by
|
||||
* the CA to sign the server's certificate).
|
||||
*
|
||||
* Depending on the defined macros, we may select one of
|
||||
* the "minimal" profiles. Key exchange algorithm depends
|
||||
* on the key type:
|
||||
* RSA key: RSA or ECDHE_RSA
|
||||
* EC key, cert signed with ECDSA: ECDH_ECDSA or ECDHE_ECDSA
|
||||
* EC key, cert signed with RSA: ECDH_RSA or ECDHE_ECDSA
|
||||
*/
|
||||
#if SERVER_RSA
|
||||
#if SERVER_PROFILE_MIN_FS
|
||||
#if SERVER_CHACHA20
|
||||
br_ssl_server_init_mine2c(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#else
|
||||
br_ssl_server_init_mine2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#endif
|
||||
#elif SERVER_PROFILE_MIN_NOFS
|
||||
br_ssl_server_init_minr2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#else
|
||||
br_ssl_server_init_full_rsa(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#endif
|
||||
#elif SERVER_EC
|
||||
#if SERVER_PROFILE_MIN_FS
|
||||
#if SERVER_CHACHA20
|
||||
br_ssl_server_init_minf2c(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#else
|
||||
br_ssl_server_init_minf2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#endif
|
||||
#elif SERVER_PROFILE_MIN_NOFS
|
||||
br_ssl_server_init_minv2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#else
|
||||
br_ssl_server_init_full_ec(&sc, CHAIN, CHAIN_LEN,
|
||||
BR_KEYTYPE_EC, &SKEY);
|
||||
#endif
|
||||
#else /* SERVER_MIXED */
|
||||
#if SERVER_PROFILE_MIN_FS
|
||||
#if SERVER_CHACHA20
|
||||
br_ssl_server_init_minf2c(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#else
|
||||
br_ssl_server_init_minf2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#endif
|
||||
#elif SERVER_PROFILE_MIN_NOFS
|
||||
br_ssl_server_init_minu2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#else
|
||||
br_ssl_server_init_full_ec(&sc, CHAIN, CHAIN_LEN,
|
||||
BR_KEYTYPE_RSA, &SKEY);
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
* Set the I/O buffer to the provided array. We
|
||||
* allocated a buffer large enough for full-duplex
|
||||
* behaviour with all allowed sizes of SSL records,
|
||||
* hence we set the last argument to 1 (which means
|
||||
* "split the buffer into separate input and output
|
||||
* areas").
|
||||
*/
|
||||
br_ssl_engine_set_buffer(&sc.eng, iobuf, sizeof iobuf, 1);
|
||||
|
||||
/*
|
||||
* Reset the server context, for a new handshake.
|
||||
*/
|
||||
br_ssl_server_reset(&sc);
|
||||
|
||||
/*
|
||||
* Initialise the simplified I/O wrapper context.
|
||||
*/
|
||||
br_sslio_init(&ioc, &sc.eng, sock_read, &cfd, sock_write, &cfd);
|
||||
|
||||
/*
|
||||
* Read bytes until two successive LF (or CR+LF) are received.
|
||||
*/
|
||||
lcwn = 0;
|
||||
for (;;) {
|
||||
unsigned char x;
|
||||
|
||||
if (br_sslio_read(&ioc, &x, 1) < 0) {
|
||||
goto client_drop;
|
||||
}
|
||||
if (x == 0x0D) {
|
||||
continue;
|
||||
}
|
||||
if (x == 0x0A) {
|
||||
if (lcwn) {
|
||||
break;
|
||||
}
|
||||
lcwn = 1;
|
||||
} else {
|
||||
lcwn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a response and close the connection.
|
||||
*/
|
||||
br_sslio_write_all(&ioc, HTTP_RES, strlen(HTTP_RES));
|
||||
br_sslio_close(&ioc);
|
||||
|
||||
client_drop:
|
||||
err = br_ssl_engine_last_error(&sc.eng);
|
||||
if (err == 0) {
|
||||
fprintf(stderr, "SSL closed (correctly).\n");
|
||||
} else {
|
||||
fprintf(stderr, "SSL error: %d\n", err);
|
||||
}
|
||||
close(cfd);
|
||||
}
|
||||
}
|
346
contrib/bearssl/src/aead/ccm.c
Normal file
346
contrib/bearssl/src/aead/ccm.c
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Implementation Notes
|
||||
* ====================
|
||||
*
|
||||
* The combined CTR + CBC-MAC functions can only handle full blocks,
|
||||
* so some buffering is necessary.
|
||||
*
|
||||
* - 'ptr' contains a value from 0 to 15, which is the number of bytes
|
||||
* accumulated in buf[] that still needs to be processed with the
|
||||
* current CBC-MAC computation.
|
||||
*
|
||||
* - When processing the message itself, CTR encryption/decryption is
|
||||
* also done at the same time. The first 'ptr' bytes of buf[] then
|
||||
* contains the plaintext bytes, while the last '16 - ptr' bytes of
|
||||
* buf[] are the remnants of the stream block, to be used against
|
||||
* the next input bytes, when available. When 'ptr' is 0, the
|
||||
* contents of buf[] are to be ignored.
|
||||
*
|
||||
* - The current counter and running CBC-MAC values are kept in 'ctr'
|
||||
* and 'cbcmac', respectively.
|
||||
*/
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx)
|
||||
{
|
||||
ctx->bctx = bctx;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
int
|
||||
br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len,
|
||||
uint64_t aad_len, uint64_t data_len, size_t tag_len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
unsigned u, q;
|
||||
|
||||
if (nonce_len < 7 || nonce_len > 13) {
|
||||
return 0;
|
||||
}
|
||||
if (tag_len < 4 || tag_len > 16 || (tag_len & 1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
q = 15 - (unsigned)nonce_len;
|
||||
ctx->tag_len = tag_len;
|
||||
|
||||
/*
|
||||
* Block B0, to start CBC-MAC.
|
||||
*/
|
||||
tmp[0] = (aad_len > 0 ? 0x40 : 0x00)
|
||||
| (((unsigned)tag_len - 2) << 2)
|
||||
| (q - 1);
|
||||
memcpy(tmp + 1, nonce, nonce_len);
|
||||
for (u = 0; u < q; u ++) {
|
||||
tmp[15 - u] = (unsigned char)data_len;
|
||||
data_len >>= 8;
|
||||
}
|
||||
if (data_len != 0) {
|
||||
/*
|
||||
* If the data length was not entirely consumed in the
|
||||
* loop above, then it exceeds the maximum limit of
|
||||
* q bytes (when encoded).
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start CBC-MAC.
|
||||
*/
|
||||
memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, tmp, sizeof tmp);
|
||||
|
||||
/*
|
||||
* Assemble AAD length header.
|
||||
*/
|
||||
if ((aad_len >> 32) != 0) {
|
||||
ctx->buf[0] = 0xFF;
|
||||
ctx->buf[1] = 0xFF;
|
||||
br_enc64be(ctx->buf + 2, aad_len);
|
||||
ctx->ptr = 10;
|
||||
} else if (aad_len >= 0xFF00) {
|
||||
ctx->buf[0] = 0xFF;
|
||||
ctx->buf[1] = 0xFE;
|
||||
br_enc32be(ctx->buf + 2, (uint32_t)aad_len);
|
||||
ctx->ptr = 6;
|
||||
} else if (aad_len > 0) {
|
||||
br_enc16be(ctx->buf, (unsigned)aad_len);
|
||||
ctx->ptr = 2;
|
||||
} else {
|
||||
ctx->ptr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make initial counter value and compute tag mask.
|
||||
*/
|
||||
ctx->ctr[0] = q - 1;
|
||||
memcpy(ctx->ctr + 1, nonce, nonce_len);
|
||||
memset(ctx->ctr + 1 + nonce_len, 0, q);
|
||||
memset(ctx->tagmask, 0, sizeof ctx->tagmask);
|
||||
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr,
|
||||
ctx->tagmask, sizeof ctx->tagmask);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *dbuf;
|
||||
size_t ptr;
|
||||
|
||||
dbuf = data;
|
||||
|
||||
/*
|
||||
* Complete partial block, if needed.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = (sizeof ctx->buf) - ptr;
|
||||
if (clen > len) {
|
||||
memcpy(ctx->buf + ptr, dbuf, len);
|
||||
ctx->ptr = ptr + len;
|
||||
return;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, dbuf, clen);
|
||||
dbuf += clen;
|
||||
len -= clen;
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process complete blocks.
|
||||
*/
|
||||
ptr = len & 15;
|
||||
len -= ptr;
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, dbuf, len);
|
||||
dbuf += len;
|
||||
|
||||
/*
|
||||
* Copy last partial block in the context buffer.
|
||||
*/
|
||||
memcpy(ctx->buf, dbuf, ptr);
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_flip(br_ccm_context *ctx)
|
||||
{
|
||||
size_t ptr;
|
||||
|
||||
/*
|
||||
* Complete AAD partial block with zeros, if necessary.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr);
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
ctx->ptr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Counter was already set by br_ccm_reset().
|
||||
*/
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len)
|
||||
{
|
||||
unsigned char *dbuf;
|
||||
size_t ptr;
|
||||
|
||||
dbuf = data;
|
||||
|
||||
/*
|
||||
* Complete a partial block, if any: ctx->buf[] contains
|
||||
* ctx->ptr plaintext bytes (already reported), and the other
|
||||
* bytes are CTR stream output.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
size_t clen;
|
||||
size_t u;
|
||||
|
||||
clen = (sizeof ctx->buf) - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
if (encrypt) {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned w, x;
|
||||
|
||||
w = ctx->buf[ptr + u];
|
||||
x = dbuf[u];
|
||||
ctx->buf[ptr + u] = x;
|
||||
dbuf[u] = w ^ x;
|
||||
}
|
||||
} else {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned w;
|
||||
|
||||
w = ctx->buf[ptr + u] ^ dbuf[u];
|
||||
dbuf[u] = w;
|
||||
ctx->buf[ptr + u] = w;
|
||||
}
|
||||
}
|
||||
dbuf += clen;
|
||||
len -= clen;
|
||||
ptr += clen;
|
||||
if (ptr < sizeof ctx->buf) {
|
||||
ctx->ptr = ptr;
|
||||
return;
|
||||
}
|
||||
(*ctx->bctx)->mac(ctx->bctx,
|
||||
ctx->cbcmac, ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process all complete blocks. Note that the ctrcbc API is for
|
||||
* encrypt-then-MAC (CBC-MAC is computed over the encrypted
|
||||
* blocks) while CCM uses MAC-and-encrypt (CBC-MAC is computed
|
||||
* over the plaintext blocks). Therefore, we need to use the
|
||||
* _decryption_ function for encryption, and the encryption
|
||||
* function for decryption (this works because CTR encryption
|
||||
* and decryption are identical, so the choice really is about
|
||||
* computing the CBC-MAC before or after XORing with the CTR
|
||||
* stream).
|
||||
*/
|
||||
ptr = len & 15;
|
||||
len -= ptr;
|
||||
if (encrypt) {
|
||||
(*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
} else {
|
||||
(*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
}
|
||||
dbuf += len;
|
||||
|
||||
/*
|
||||
* If there is some remaining data, then we need to compute an
|
||||
* extra block of CTR stream.
|
||||
*/
|
||||
if (ptr != 0) {
|
||||
size_t u;
|
||||
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
if (encrypt) {
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
unsigned w, x;
|
||||
|
||||
w = ctx->buf[u];
|
||||
x = dbuf[u];
|
||||
ctx->buf[u] = x;
|
||||
dbuf[u] = w ^ x;
|
||||
}
|
||||
} else {
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
unsigned w;
|
||||
|
||||
w = ctx->buf[u] ^ dbuf[u];
|
||||
dbuf[u] = w;
|
||||
ctx->buf[u] = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
size_t
|
||||
br_ccm_get_tag(br_ccm_context *ctx, void *tag)
|
||||
{
|
||||
size_t ptr;
|
||||
size_t u;
|
||||
|
||||
/*
|
||||
* If there is some buffered data, then we need to pad it with
|
||||
* zeros and finish up CBC-MAC.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr);
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* XOR the tag mask into the CBC-MAC output.
|
||||
*/
|
||||
for (u = 0; u < ctx->tag_len; u ++) {
|
||||
ctx->cbcmac[u] ^= ctx->tagmask[u];
|
||||
}
|
||||
memcpy(tag, ctx->cbcmac, ctx->tag_len);
|
||||
return ctx->tag_len;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
uint32_t
|
||||
br_ccm_check_tag(br_ccm_context *ctx, const void *tag)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
size_t u, tag_len;
|
||||
uint32_t z;
|
||||
|
||||
tag_len = br_ccm_get_tag(ctx, tmp);
|
||||
z = 0;
|
||||
for (u = 0; u < tag_len; u ++) {
|
||||
z |= tmp[u] ^ ((const unsigned char *)tag)[u];
|
||||
}
|
||||
return EQ0(z);
|
||||
}
|
525
contrib/bearssl/src/aead/eax.c
Normal file
525
contrib/bearssl/src/aead/eax.c
Normal file
@ -0,0 +1,525 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Implementation Notes
|
||||
* ====================
|
||||
*
|
||||
* The combined CTR + CBC-MAC functions can only handle full blocks,
|
||||
* so some buffering is necessary. Moreover, EAX has a special padding
|
||||
* rule for CBC-MAC, which implies that we cannot compute the MAC over
|
||||
* the last received full block until we know whether we are at the
|
||||
* end of the data or not.
|
||||
*
|
||||
* - 'ptr' contains a value from 1 to 16, which is the number of bytes
|
||||
* accumulated in buf[] that still needs to be processed with the
|
||||
* current OMAC computation. Beware that this can go to 16: a
|
||||
* complete block cannot be processed until it is known whether it
|
||||
* is the last block or not. However, it can never be 0, because
|
||||
* OMAC^t works on an input that is at least one-block long.
|
||||
*
|
||||
* - When processing the message itself, CTR encryption/decryption is
|
||||
* also done at the same time. The first 'ptr' bytes of buf[] then
|
||||
* contains the encrypted bytes, while the last '16 - ptr' bytes of
|
||||
* buf[] are the remnants of the stream block, to be used against
|
||||
* the next input bytes, when available.
|
||||
*
|
||||
* - The current counter and running CBC-MAC values are kept in 'ctr'
|
||||
* and 'cbcmac', respectively.
|
||||
*
|
||||
* - The derived keys for padding are kept in L2 and L4 (double and
|
||||
* quadruple of Enc_K(0^n), in GF(2^128), respectively).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Start an OMAC computation; the first block is the big-endian
|
||||
* representation of the provided value ('val' must fit on one byte).
|
||||
* We make it a delayed block because it may also be the last one,
|
||||
*/
|
||||
static void
|
||||
omac_start(br_eax_context *ctx, unsigned val)
|
||||
{
|
||||
memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
ctx->buf[15] = val;
|
||||
ctx->ptr = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* Double a value in finite field GF(2^128), defined with modulus
|
||||
* X^128+X^7+X^2+X+1.
|
||||
*/
|
||||
static void
|
||||
double_gf128(unsigned char *dst, const unsigned char *src)
|
||||
{
|
||||
unsigned cc;
|
||||
int i;
|
||||
|
||||
cc = 0x87 & -((unsigned)src[0] >> 7);
|
||||
for (i = 15; i >= 0; i --) {
|
||||
unsigned z;
|
||||
|
||||
z = (src[i] << 1) ^ cc;
|
||||
cc = z >> 8;
|
||||
dst[i] = (unsigned char)z;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply padding to the last block, currently in ctx->buf (with
|
||||
* ctx->ptr bytes), and finalize OMAC computation.
|
||||
*/
|
||||
static void
|
||||
do_pad(br_eax_context *ctx)
|
||||
{
|
||||
unsigned char *pad;
|
||||
size_t ptr, u;
|
||||
|
||||
ptr = ctx->ptr;
|
||||
if (ptr == 16) {
|
||||
pad = ctx->L2;
|
||||
} else {
|
||||
ctx->buf[ptr ++] = 0x80;
|
||||
memset(ctx->buf + ptr, 0x00, 16 - ptr);
|
||||
pad = ctx->L4;
|
||||
}
|
||||
for (u = 0; u < sizeof ctx->buf; u ++) {
|
||||
ctx->buf[u] ^= pad[u];
|
||||
}
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply CBC-MAC on the provided data, with buffering management.
|
||||
*
|
||||
* Upon entry, two situations are acceptable:
|
||||
*
|
||||
* ctx->ptr == 0: there is no data to process in ctx->buf
|
||||
* ctx->ptr == 16: there is a full block of unprocessed data in ctx->buf
|
||||
*
|
||||
* Upon exit, ctx->ptr may be zero only if it was already zero on entry,
|
||||
* and len == 0. In all other situations, ctx->ptr will be non-zero on
|
||||
* exit (and may have value 16).
|
||||
*/
|
||||
static void
|
||||
do_cbcmac_chunk(br_eax_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
size_t ptr;
|
||||
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
ptr = len & (size_t)15;
|
||||
if (ptr == 0) {
|
||||
len -= 16;
|
||||
ptr = 16;
|
||||
} else {
|
||||
len -= ptr;
|
||||
}
|
||||
if (ctx->ptr == 16) {
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, data, len);
|
||||
memcpy(ctx->buf, (const unsigned char *)data + len, ptr);
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx)
|
||||
{
|
||||
unsigned char tmp[16], iv[16];
|
||||
|
||||
ctx->vtable = &br_eax_vtable;
|
||||
ctx->bctx = bctx;
|
||||
|
||||
/*
|
||||
* Encrypt a whole-zero block to compute L2 and L4.
|
||||
*/
|
||||
memset(tmp, 0, sizeof tmp);
|
||||
memset(iv, 0, sizeof iv);
|
||||
(*bctx)->ctr(bctx, iv, tmp, sizeof tmp);
|
||||
double_gf128(ctx->L2, tmp);
|
||||
double_gf128(ctx->L4, ctx->L2);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_capture(const br_eax_context *ctx, br_eax_state *st)
|
||||
{
|
||||
/*
|
||||
* We capture the three OMAC* states _after_ processing the
|
||||
* initial block (assuming that nonce, message and AAD are
|
||||
* all non-empty).
|
||||
*/
|
||||
int i;
|
||||
|
||||
memset(st->st, 0, sizeof st->st);
|
||||
for (i = 0; i < 3; i ++) {
|
||||
unsigned char tmp[16];
|
||||
|
||||
memset(tmp, 0, sizeof tmp);
|
||||
tmp[15] = (unsigned char)i;
|
||||
(*ctx->bctx)->mac(ctx->bctx, st->st[i], tmp, sizeof tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len)
|
||||
{
|
||||
/*
|
||||
* Process nonce with OMAC^0.
|
||||
*/
|
||||
omac_start(ctx, 0);
|
||||
do_cbcmac_chunk(ctx, nonce, len);
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
|
||||
/*
|
||||
* Start OMAC^1 for the AAD ("header" in the EAX specification).
|
||||
*/
|
||||
omac_start(ctx, 1);
|
||||
|
||||
/*
|
||||
* We use ctx->head[0] as temporary flag to mark that we are
|
||||
* using a "normal" reset().
|
||||
*/
|
||||
ctx->head[0] = 0;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
|
||||
const void *nonce, size_t len)
|
||||
{
|
||||
if (len == 0) {
|
||||
omac_start(ctx, 0);
|
||||
} else {
|
||||
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
do_cbcmac_chunk(ctx, nonce, len);
|
||||
}
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
|
||||
memcpy(ctx->cbcmac, st->st[1], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
|
||||
memcpy(ctx->ctr, st->st[2], sizeof ctx->ctr);
|
||||
|
||||
/*
|
||||
* We use ctx->head[0] as a flag to indicate that we use a
|
||||
* a recorded state, with ctx->ctr containing the preprocessed
|
||||
* first block for OMAC^2.
|
||||
*/
|
||||
ctx->head[0] = 1;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
|
||||
const void *nonce, size_t len)
|
||||
{
|
||||
if (len == 0) {
|
||||
omac_start(ctx, 0);
|
||||
} else {
|
||||
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
do_cbcmac_chunk(ctx, nonce, len);
|
||||
}
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
|
||||
|
||||
memcpy(ctx->head, st->st[1], sizeof ctx->head);
|
||||
|
||||
memcpy(ctx->cbcmac, st->st[2], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
size_t ptr;
|
||||
|
||||
ptr = ctx->ptr;
|
||||
|
||||
/*
|
||||
* If there is a partial block, first complete it.
|
||||
*/
|
||||
if (ptr < 16) {
|
||||
size_t clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len <= clen) {
|
||||
memcpy(ctx->buf + ptr, data, len);
|
||||
ctx->ptr = ptr + len;
|
||||
return;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, data, clen);
|
||||
data = (const unsigned char *)data + clen;
|
||||
len -= clen;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have a full block in buf[], and this is not the last
|
||||
* block.
|
||||
*/
|
||||
do_cbcmac_chunk(ctx, data, len);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_flip(br_eax_context *ctx)
|
||||
{
|
||||
int from_capture;
|
||||
|
||||
/*
|
||||
* ctx->head[0] may be non-zero if the context was reset with
|
||||
* a pre-AAD captured state. In that case, ctx->ctr[] contains
|
||||
* the state for OMAC^2 _after_ processing the first block.
|
||||
*/
|
||||
from_capture = ctx->head[0];
|
||||
|
||||
/*
|
||||
* Complete the OMAC computation on the AAD.
|
||||
*/
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->head, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
|
||||
/*
|
||||
* Start OMAC^2 for the encrypted data.
|
||||
* If the context was initialized from a captured state, then
|
||||
* the OMAC^2 value is in the ctr[] array.
|
||||
*/
|
||||
if (from_capture) {
|
||||
memcpy(ctx->cbcmac, ctx->ctr, sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
} else {
|
||||
omac_start(ctx, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initial counter value for CTR is the processed nonce.
|
||||
*/
|
||||
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len)
|
||||
{
|
||||
unsigned char *dbuf;
|
||||
size_t ptr;
|
||||
|
||||
/*
|
||||
* Ensure that there is actual data to process.
|
||||
*/
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dbuf = data;
|
||||
ptr = ctx->ptr;
|
||||
|
||||
/*
|
||||
* We may have ptr == 0 here if we initialized from a captured
|
||||
* state. In that case, there is no partially consumed block
|
||||
* or unprocessed data.
|
||||
*/
|
||||
if (ptr != 0 && ptr != 16) {
|
||||
/*
|
||||
* We have a partially consumed block.
|
||||
*/
|
||||
size_t u, clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len <= clen) {
|
||||
clen = len;
|
||||
}
|
||||
if (encrypt) {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
ctx->buf[ptr + u] ^= dbuf[u];
|
||||
}
|
||||
memcpy(dbuf, ctx->buf + ptr, clen);
|
||||
} else {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned dx, sx;
|
||||
|
||||
sx = ctx->buf[ptr + u];
|
||||
dx = dbuf[u];
|
||||
ctx->buf[ptr + u] = dx;
|
||||
dbuf[u] = sx ^ dx;
|
||||
}
|
||||
}
|
||||
|
||||
if (len <= clen) {
|
||||
ctx->ptr = ptr + clen;
|
||||
return;
|
||||
}
|
||||
dbuf += clen;
|
||||
len -= clen;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have a complete encrypted block in buf[] that must still
|
||||
* be processed with OMAC, and this is not the final buf.
|
||||
* Exception: when ptr == 0, no block has been produced yet.
|
||||
*/
|
||||
if (ptr != 0) {
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do CTR encryption or decryption and CBC-MAC for all full blocks
|
||||
* except the last.
|
||||
*/
|
||||
ptr = len & (size_t)15;
|
||||
if (ptr == 0) {
|
||||
len -= 16;
|
||||
ptr = 16;
|
||||
} else {
|
||||
len -= ptr;
|
||||
}
|
||||
if (encrypt) {
|
||||
(*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
} else {
|
||||
(*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
}
|
||||
dbuf += len;
|
||||
|
||||
/*
|
||||
* Compute next block of CTR stream, and use it to finish
|
||||
* encrypting or decrypting the data.
|
||||
*/
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf);
|
||||
if (encrypt) {
|
||||
size_t u;
|
||||
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
ctx->buf[u] ^= dbuf[u];
|
||||
}
|
||||
memcpy(dbuf, ctx->buf, ptr);
|
||||
} else {
|
||||
size_t u;
|
||||
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
unsigned dx, sx;
|
||||
|
||||
sx = ctx->buf[u];
|
||||
dx = dbuf[u];
|
||||
ctx->buf[u] = dx;
|
||||
dbuf[u] = sx ^ dx;
|
||||
}
|
||||
}
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Complete tag computation. The final tag is written in ctx->cbcmac.
|
||||
*/
|
||||
static void
|
||||
do_final(br_eax_context *ctx)
|
||||
{
|
||||
size_t u;
|
||||
|
||||
do_pad(ctx);
|
||||
|
||||
/*
|
||||
* Authentication tag is the XOR of the three OMAC outputs for
|
||||
* the nonce, AAD and encrypted data.
|
||||
*/
|
||||
for (u = 0; u < 16; u ++) {
|
||||
ctx->cbcmac[u] ^= ctx->nonce[u] ^ ctx->head[u];
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_get_tag(br_eax_context *ctx, void *tag)
|
||||
{
|
||||
do_final(ctx);
|
||||
memcpy(tag, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len)
|
||||
{
|
||||
do_final(ctx);
|
||||
memcpy(tag, ctx->cbcmac, len);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_eax_check_tag_trunc(br_eax_context *ctx, const void *tag, size_t len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
size_t u;
|
||||
int x;
|
||||
|
||||
br_eax_get_tag(ctx, tmp);
|
||||
x = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
x |= tmp[u] ^ ((const unsigned char *)tag)[u];
|
||||
}
|
||||
return EQ0(x);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_eax_check_tag(br_eax_context *ctx, const void *tag)
|
||||
{
|
||||
return br_eax_check_tag_trunc(ctx, tag, 16);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
const br_aead_class br_eax_vtable = {
|
||||
16,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_eax_reset,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_eax_aad_inject,
|
||||
(void (*)(const br_aead_class **))
|
||||
&br_eax_flip,
|
||||
(void (*)(const br_aead_class **, int, void *, size_t))
|
||||
&br_eax_run,
|
||||
(void (*)(const br_aead_class **, void *))
|
||||
&br_eax_get_tag,
|
||||
(uint32_t (*)(const br_aead_class **, const void *))
|
||||
&br_eax_check_tag,
|
||||
(void (*)(const br_aead_class **, void *, size_t))
|
||||
&br_eax_get_tag_trunc,
|
||||
(uint32_t (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_eax_check_tag_trunc
|
||||
};
|
318
contrib/bearssl/src/aead/gcm.c
Normal file
318
contrib/bearssl/src/aead/gcm.c
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Implementation Notes
|
||||
* ====================
|
||||
*
|
||||
* Since CTR and GHASH implementations can handle only full blocks, a
|
||||
* 16-byte buffer (buf[]) is maintained in the context:
|
||||
*
|
||||
* - When processing AAD, buf[] contains the 0-15 unprocessed bytes.
|
||||
*
|
||||
* - When doing CTR encryption / decryption, buf[] contains the AES output
|
||||
* for the last partial block, to be used with the next few bytes of
|
||||
* data, as well as the already encrypted bytes. For instance, if the
|
||||
* processed data length so far is 21 bytes, then buf[0..4] contains
|
||||
* the five last encrypted bytes, and buf[5..15] contains the next 11
|
||||
* AES output bytes to be XORed with the next 11 bytes of input.
|
||||
*
|
||||
* The recorded AES output bytes are used to complete the block when
|
||||
* the corresponding bytes are obtained. Note that buf[] always
|
||||
* contains the _encrypted_ bytes, whether we apply encryption or
|
||||
* decryption: these bytes are used as input to GHASH when the block
|
||||
* is complete.
|
||||
*
|
||||
* In both cases, the low bits of the data length counters (count_aad,
|
||||
* count_ctr) are used to work out the current situation.
|
||||
*/
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh)
|
||||
{
|
||||
unsigned char iv[12];
|
||||
|
||||
ctx->vtable = &br_gcm_vtable;
|
||||
ctx->bctx = bctx;
|
||||
ctx->gh = gh;
|
||||
|
||||
/*
|
||||
* The GHASH key h[] is the raw encryption of the all-zero
|
||||
* block. Since we only have a CTR implementation, we use it
|
||||
* with an all-zero IV and a zero counter, to CTR-encrypt an
|
||||
* all-zero block.
|
||||
*/
|
||||
memset(ctx->h, 0, sizeof ctx->h);
|
||||
memset(iv, 0, sizeof iv);
|
||||
(*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len)
|
||||
{
|
||||
/*
|
||||
* If the provided nonce is 12 bytes, then this is the initial
|
||||
* IV for CTR mode; it will be used with a counter that starts
|
||||
* at 2 (value 1 is for encrypting the GHASH output into the tag).
|
||||
*
|
||||
* If the provided nonce has any other length, then it is hashed
|
||||
* (with GHASH) into a 16-byte value that will be the IV for CTR
|
||||
* (both 12-byte IV and 32-bit counter).
|
||||
*/
|
||||
if (len == 12) {
|
||||
memcpy(ctx->j0_1, iv, 12);
|
||||
ctx->j0_2 = 1;
|
||||
} else {
|
||||
unsigned char ty[16], tmp[16];
|
||||
|
||||
memset(ty, 0, sizeof ty);
|
||||
ctx->gh(ty, ctx->h, iv, len);
|
||||
memset(tmp, 0, 8);
|
||||
br_enc64be(tmp + 8, (uint64_t)len << 3);
|
||||
ctx->gh(ty, ctx->h, tmp, 16);
|
||||
memcpy(ctx->j0_1, ty, 12);
|
||||
ctx->j0_2 = br_dec32be(ty + 12);
|
||||
}
|
||||
ctx->jc = ctx->j0_2 + 1;
|
||||
memset(ctx->y, 0, sizeof ctx->y);
|
||||
ctx->count_aad = 0;
|
||||
ctx->count_ctr = 0;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
size_t ptr, dlen;
|
||||
|
||||
ptr = (size_t)ctx->count_aad & (size_t)15;
|
||||
if (ptr != 0) {
|
||||
/*
|
||||
* If there is a partial block, then we first try to
|
||||
* complete it.
|
||||
*/
|
||||
size_t clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len < clen) {
|
||||
memcpy(ctx->buf + ptr, data, len);
|
||||
ctx->count_aad += (uint64_t)len;
|
||||
return;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, data, clen);
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
|
||||
data = (const unsigned char *)data + clen;
|
||||
len -= clen;
|
||||
ctx->count_aad += (uint64_t)clen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now AAD is aligned on a 16-byte block (with regards to GHASH).
|
||||
* We process all complete blocks, and save the last partial
|
||||
* block.
|
||||
*/
|
||||
dlen = len & ~(size_t)15;
|
||||
ctx->gh(ctx->y, ctx->h, data, dlen);
|
||||
memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen);
|
||||
ctx->count_aad += (uint64_t)len;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_flip(br_gcm_context *ctx)
|
||||
{
|
||||
/*
|
||||
* We complete the GHASH computation if there is a partial block.
|
||||
* The GHASH implementation automatically applies padding with
|
||||
* zeros.
|
||||
*/
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)ctx->count_aad & (size_t)15;
|
||||
if (ptr != 0) {
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t ptr, dlen;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)ctx->count_ctr & (size_t)15;
|
||||
if (ptr != 0) {
|
||||
/*
|
||||
* If we have a partial block, then we try to complete it.
|
||||
*/
|
||||
size_t u, clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len < clen) {
|
||||
clen = len;
|
||||
}
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned x, y;
|
||||
|
||||
x = buf[u];
|
||||
y = x ^ ctx->buf[ptr + u];
|
||||
ctx->buf[ptr + u] = encrypt ? y : x;
|
||||
buf[u] = y;
|
||||
}
|
||||
ctx->count_ctr += (uint64_t)clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
if (ptr + clen < 16) {
|
||||
return;
|
||||
}
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process full blocks.
|
||||
*/
|
||||
dlen = len & ~(size_t)15;
|
||||
if (!encrypt) {
|
||||
ctx->gh(ctx->y, ctx->h, buf, dlen);
|
||||
}
|
||||
ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, buf, dlen);
|
||||
if (encrypt) {
|
||||
ctx->gh(ctx->y, ctx->h, buf, dlen);
|
||||
}
|
||||
buf += dlen;
|
||||
len -= dlen;
|
||||
ctx->count_ctr += (uint64_t)dlen;
|
||||
|
||||
if (len > 0) {
|
||||
/*
|
||||
* There is a partial block.
|
||||
*/
|
||||
size_t u;
|
||||
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1,
|
||||
ctx->jc, ctx->buf, 16);
|
||||
for (u = 0; u < len; u ++) {
|
||||
unsigned x, y;
|
||||
|
||||
x = buf[u];
|
||||
y = x ^ ctx->buf[u];
|
||||
ctx->buf[u] = encrypt ? y : x;
|
||||
buf[u] = y;
|
||||
}
|
||||
ctx->count_ctr += (uint64_t)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_get_tag(br_gcm_context *ctx, void *tag)
|
||||
{
|
||||
size_t ptr;
|
||||
unsigned char tmp[16];
|
||||
|
||||
ptr = (size_t)ctx->count_ctr & (size_t)15;
|
||||
if (ptr > 0) {
|
||||
/*
|
||||
* There is a partial block: encrypted/decrypted data has
|
||||
* been produced, but the encrypted bytes must still be
|
||||
* processed by GHASH.
|
||||
*/
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final block for GHASH: the AAD and plaintext lengths (in bits).
|
||||
*/
|
||||
br_enc64be(tmp, ctx->count_aad << 3);
|
||||
br_enc64be(tmp + 8, ctx->count_ctr << 3);
|
||||
ctx->gh(ctx->y, ctx->h, tmp, 16);
|
||||
|
||||
/*
|
||||
* Tag is the GHASH output XORed with the encryption of the
|
||||
* nonce with the initial counter value.
|
||||
*/
|
||||
memcpy(tag, ctx->y, 16);
|
||||
(*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
|
||||
br_gcm_get_tag(ctx, tmp);
|
||||
memcpy(tag, tmp, len);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_gcm_check_tag_trunc(br_gcm_context *ctx, const void *tag, size_t len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
size_t u;
|
||||
int x;
|
||||
|
||||
br_gcm_get_tag(ctx, tmp);
|
||||
x = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
x |= tmp[u] ^ ((const unsigned char *)tag)[u];
|
||||
}
|
||||
return EQ0(x);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_gcm_check_tag(br_gcm_context *ctx, const void *tag)
|
||||
{
|
||||
return br_gcm_check_tag_trunc(ctx, tag, 16);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
const br_aead_class br_gcm_vtable = {
|
||||
16,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_gcm_reset,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_gcm_aad_inject,
|
||||
(void (*)(const br_aead_class **))
|
||||
&br_gcm_flip,
|
||||
(void (*)(const br_aead_class **, int, void *, size_t))
|
||||
&br_gcm_run,
|
||||
(void (*)(const br_aead_class **, void *))
|
||||
&br_gcm_get_tag,
|
||||
(uint32_t (*)(const br_aead_class **, const void *))
|
||||
&br_gcm_check_tag,
|
||||
(void (*)(const br_aead_class **, void *, size_t))
|
||||
&br_gcm_get_tag_trunc,
|
||||
(uint32_t (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_gcm_check_tag_trunc
|
||||
};
|
44
contrib/bearssl/src/codec/ccopy.c
Normal file
44
contrib/bearssl/src/codec/ccopy.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len)
|
||||
{
|
||||
unsigned char *d;
|
||||
const unsigned char *s;
|
||||
|
||||
d = dst;
|
||||
s = src;
|
||||
while (len -- > 0) {
|
||||
uint32_t x, y;
|
||||
|
||||
x = *s ++;
|
||||
y = *d;
|
||||
*d = MUX(ctl, x, y);
|
||||
d ++;
|
||||
}
|
||||
}
|
38
contrib/bearssl/src/codec/dec16be.c
Normal file
38
contrib/bearssl/src/codec/dec16be.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec16be(uint16_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec16be(buf);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user