Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: stable/12/contrib/bearssl/tools/brssl.h
===================================================================
--- stable/12/contrib/bearssl/tools/brssl.h (nonexistent)
+++ stable/12/contrib/bearssl/tools/brssl.h (revision 346145)
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef BRSSL_H__
+#define BRSSL_H__
+
+#ifndef _STANDALONE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#elif !defined(STAND_H)
+#include <stand.h>
+#endif
+
+#include "bearssl.h"
+
+/*
+ * malloc() wrapper:
+ * -- If len is 0, then NULL is returned.
+ * -- If len is non-zero, and allocation fails, then an error message is
+ * printed and the process exits with an error code.
+ */
+void *xmalloc(size_t len);
+
+/*
+ * free() wrapper, meant to release blocks allocated with xmalloc().
+ */
+void xfree(void *buf);
+
+/*
+ * Duplicate a character string into a newly allocated block.
+ */
+char *xstrdup(const void *src);
+
+/*
+ * Allocate a new block with the provided length, filled with a copy
+ * of exactly that many bytes starting at address 'src'.
+ */
+void *xblobdup(const void *src, size_t len);
+
+/*
+ * Duplicate a public key, into newly allocated blocks. The returned
+ * key must be later on released with xfreepkey().
+ */
+br_x509_pkey *xpkeydup(const br_x509_pkey *pk);
+
+/*
+ * Release a public key that was allocated with xpkeydup(). If pk is NULL,
+ * this function does nothing.
+ */
+void xfreepkey(br_x509_pkey *pk);
+
+/*
+ * Macros for growable arrays.
+ */
+
+/*
+ * Make a structure type for a vector of 'type'.
+ */
+#define VECTOR(type) struct { \
+ type *buf; \
+ size_t ptr, len; \
+ }
+
+/*
+ * Constant initialiser for a vector.
+ */
+#define VEC_INIT { 0, 0, 0 }
+
+/*
+ * Clear a vector.
+ */
+#define VEC_CLEAR(vec) do { \
+ xfree((vec).buf); \
+ (vec).buf = NULL; \
+ (vec).ptr = 0; \
+ (vec).len = 0; \
+ } while (0)
+
+/*
+ * Clear a vector, first calling the provided function on each vector
+ * element.
+ */
+#define VEC_CLEAREXT(vec, fun) do { \
+ size_t vec_tmp; \
+ for (vec_tmp = 0; vec_tmp < (vec).ptr; vec_tmp ++) { \
+ (fun)(&(vec).buf[vec_tmp]); \
+ } \
+ VEC_CLEAR(vec); \
+ } while (0)
+
+/*
+ * Add a value at the end of a vector.
+ */
+#define VEC_ADD(vec, x) do { \
+ (vec).buf = vector_expand((vec).buf, sizeof *((vec).buf), \
+ &(vec).ptr, &(vec).len, 1); \
+ (vec).buf[(vec).ptr ++] = (x); \
+ } while (0)
+
+/*
+ * Add several values at the end of a vector.
+ */
+#define VEC_ADDMANY(vec, xp, num) do { \
+ size_t vec_num = (num); \
+ (vec).buf = vector_expand((vec).buf, sizeof *((vec).buf), \
+ &(vec).ptr, &(vec).len, vec_num); \
+ memcpy((vec).buf + (vec).ptr, \
+ (xp), vec_num * sizeof *((vec).buf)); \
+ (vec).ptr += vec_num; \
+ } while (0)
+
+/*
+ * Access a vector element by index. This is a lvalue, and can be modified.
+ */
+#define VEC_ELT(vec, idx) ((vec).buf[idx])
+
+/*
+ * Get current vector length.
+ */
+#define VEC_LEN(vec) ((vec).ptr)
+
+/*
+ * Copy all vector elements into a newly allocated block.
+ */
+#define VEC_TOARRAY(vec) xblobdup((vec).buf, sizeof *((vec).buf) * (vec).ptr)
+
+/*
+ * Internal function used to handle memory allocations for vectors.
+ */
+void *vector_expand(void *buf,
+ size_t esize, size_t *ptr, size_t *len, size_t extra);
+
+/*
+ * Type for a vector of bytes.
+ */
+typedef VECTOR(unsigned char) bvector;
+
+/*
+ * Compare two strings for equality; returned value is 1 if the strings
+ * are to be considered equal, 0 otherwise. Comparison is case-insensitive
+ * (ASCII letters only) and skips some characters (all whitespace, defined
+ * as ASCII codes 0 to 32 inclusive, and also '-', '_', '.', '/', '+' and
+ * ':').
+ */
+int eqstr(const char *s1, const char *s2);
+
+/*
+ * Convert a string to a positive integer (size_t). Returned value is
+ * (size_t)-1 on error. On error, an explicit error message is printed.
+ */
+size_t parse_size(const char *s);
+
+/*
+ * Structure for a known protocol version.
+ */
+typedef struct {
+ const char *name;
+ unsigned version;
+ const char *comment;
+} protocol_version;
+
+/*
+ * Known protocol versions. Last element has a NULL name.
+ */
+extern const protocol_version protocol_versions[];
+
+/*
+ * Parse a version name. If the name is not recognized, then an error
+ * message is printed, and 0 is returned.
+ */
+unsigned parse_version(const char *name, size_t len);
+
+/*
+ * Type for a known hash function.
+ */
+typedef struct {
+ const char *name;
+ const br_hash_class *hclass;
+ const char *comment;
+} hash_function;
+
+/*
+ * Known hash functions. Last element has a NULL name.
+ */
+extern const hash_function hash_functions[];
+
+/*
+ * Parse hash function names. This function expects a comma-separated
+ * list of names, and returns a bit mask corresponding to the matched
+ * names. If one of the name does not match, or the list is empty, then
+ * an error message is printed, and 0 is returned.
+ */
+unsigned parse_hash_functions(const char *arg);
+
+/*
+ * Get a curve name (by ID). If the curve ID is not known, this returns
+ * NULL.
+ */
+const char *get_curve_name(int id);
+
+/*
+ * Get a curve name (by ID). The name is written in the provided buffer
+ * (zero-terminated). If the curve ID is not known, the name is
+ * "unknown (***)" where "***" is the decimal value of the identifier.
+ * If the name does not fit in the provided buffer, then dst[0] is set
+ * to 0 (unless len is 0, in which case nothing is written), and -1 is
+ * returned. Otherwise, the name is written in dst[] (with a terminating
+ * 0), and this function returns 0.
+ */
+int get_curve_name_ext(int id, char *dst, size_t len);
+
+/*
+ * Type for a known cipher suite.
+ */
+typedef struct {
+ const char *name;
+ uint16_t suite;
+ unsigned req;
+ const char *comment;
+} cipher_suite;
+
+/*
+ * Known cipher suites. Last element has a NULL name.
+ */
+extern const cipher_suite cipher_suites[];
+
+/*
+ * Flags for cipher suite requirements.
+ */
+#define REQ_TLS12 0x0001 /* suite needs TLS 1.2 */
+#define REQ_SHA1 0x0002 /* suite needs SHA-1 */
+#define REQ_SHA256 0x0004 /* suite needs SHA-256 */
+#define REQ_SHA384 0x0008 /* suite needs SHA-384 */
+#define REQ_AESCBC 0x0010 /* suite needs AES/CBC encryption */
+#define REQ_AESGCM 0x0020 /* suite needs AES/GCM encryption */
+#define REQ_AESCCM 0x0040 /* suite needs AES/CCM encryption */
+#define REQ_CHAPOL 0x0080 /* suite needs ChaCha20+Poly1305 */
+#define REQ_3DESCBC 0x0100 /* suite needs 3DES/CBC encryption */
+#define REQ_RSAKEYX 0x0200 /* suite uses RSA key exchange */
+#define REQ_ECDHE_RSA 0x0400 /* suite uses ECDHE_RSA key exchange */
+#define REQ_ECDHE_ECDSA 0x0800 /* suite uses ECDHE_ECDSA key exchange */
+#define REQ_ECDH 0x1000 /* suite uses static ECDH key exchange */
+
+/*
+ * Parse a list of cipher suite names. The names are comma-separated. If
+ * one of the name is not recognised, or the list is empty, then an
+ * appropriate error message is printed, and NULL is returned.
+ * The returned array is allocated with xmalloc() and must be released
+ * by the caller. That array is terminated with a dummy entry whose 'name'
+ * field is NULL. The number of entries (not counting the dummy entry)
+ * is also written into '*num'.
+ */
+cipher_suite *parse_suites(const char *arg, size_t *num);
+
+/*
+ * Get the name of a cipher suite. Returned value is NULL if the suite is
+ * not recognized.
+ */
+const char *get_suite_name(unsigned suite);
+
+/*
+ * Get the name of a cipher suite. The name is written in the provided
+ * buffer; if the suite is not recognised, then the name is
+ * "unknown (0x****)" where "****" is the hexadecimal value of the suite.
+ * If the name does not fit in the provided buffer, then dst[0] is set
+ * to 0 (unless len is 0, in which case nothing is written), and -1 is
+ * returned. Otherwise, the name is written in dst[] (with a terminating
+ * 0), and this function returns 0.
+ */
+int get_suite_name_ext(unsigned suite, char *dst, size_t len);
+
+/*
+ * Tell whether a cipher suite uses ECDHE key exchange.
+ */
+int uses_ecdhe(unsigned suite);
+
+/*
+ * Print out all known names (for protocol versions, cipher suites...).
+ */
+void list_names(void);
+
+/*
+ * Print out all known elliptic curve names.
+ */
+void list_curves(void);
+
+/*
+ * Get the symbolic name for an elliptic curve (by ID).
+ */
+const char *ec_curve_name(int curve);
+
+/*
+ * Get a curve by symbolic name. If the name is not recognized, -1 is
+ * returned.
+ */
+int get_curve_by_name(const char *str);
+
+/*
+ * Get the symbolic name for a hash function name (by ID).
+ */
+const char *hash_function_name(int id);
+
+/*
+ * Read a file completely. The returned block is allocated with xmalloc()
+ * and must be released by the caller.
+ * If the file cannot be found or read completely, or is empty, then an
+ * appropriate error message is written, and NULL is returned.
+ */
+unsigned char *read_file(const char *fname, size_t *len);
+
+/*
+ * Write a file completely. This returns 0 on success, -1 on error. On
+ * error, an appropriate error message is printed.
+ */
+int write_file(const char *fname, const void *data, size_t len);
+
+/*
+ * This function returns non-zero if the provided buffer "looks like"
+ * a DER-encoded ASN.1 object (criteria: it has the tag for a SEQUENCE
+ * with a definite length that matches the total object length).
+ */
+int looks_like_DER(const unsigned char *buf, size_t len);
+
+/*
+ * Type for a named blob (the 'name' is a normalised PEM header name).
+ */
+typedef struct {
+ char *name;
+ unsigned char *data;
+ size_t data_len;
+} pem_object;
+
+/*
+ * Release the contents of a named blob (buffer and name).
+ */
+void free_pem_object_contents(pem_object *po);
+
+/*
+ * Decode a buffer as a PEM file, and return all objects. On error, NULL
+ * is returned and an error message is printed. Absence of any object
+ * is an error.
+ *
+ * The returned array is terminated by a dummy object whose 'name' is
+ * NULL. The number of objects (not counting the dummy terminator) is
+ * written in '*num'.
+ */
+pem_object *decode_pem(const void *src, size_t len, size_t *num);
+
+/*
+ * Get the certificate(s) from a file. This accepts both a single
+ * DER-encoded certificate, and a text file that contains
+ * PEM-encoded certificates (and possibly other objects, which are
+ * then ignored).
+ *
+ * On decoding error, or if the file turns out to contain no certificate
+ * at all, then an error message is printed and NULL is returned.
+ *
+ * The returned array, and all referenced buffers, are allocated with
+ * xmalloc() and must be released by the caller. The returned array
+ * ends with a dummy entry whose 'data' field is NULL.
+ * The number of decoded certificates (not counting the dummy entry)
+ * is written into '*num'.
+ */
+br_x509_certificate *read_certificates(const char *fname, size_t *num);
+
+/*
+ * Release certificates. This releases all certificate data arrays,
+ * and the whole array as well.
+ */
+void free_certificates(br_x509_certificate *certs, size_t num);
+
+/*
+ * Interpret a certificate as a trust anchor. The trust anchor is
+ * newly allocated with xmalloc() and the caller must release it.
+ * On decoding error, an error message is printed, and this function
+ * returns NULL.
+ */
+br_x509_trust_anchor *certificate_to_trust_anchor(br_x509_certificate *xc);
+
+/*
+ * Type for a vector of trust anchors.
+ */
+typedef VECTOR(br_x509_trust_anchor) anchor_list;
+
+/*
+ * Release contents for a trust anchor (assuming they were dynamically
+ * allocated with xmalloc()). The structure itself is NOT released.
+ */
+void free_ta_contents(br_x509_trust_anchor *ta);
+
+/*
+ * Decode certificates from a file and interpret them as trust anchors.
+ * The trust anchors are added to the provided list. The number of found
+ * anchors is returned; on error, 0 is returned (finding no anchor at
+ * all is considered an error). An appropriate error message is displayed.
+ */
+size_t read_trust_anchors(anchor_list *dst, const char *fname);
+
+/*
+ * Get the "signer key type" for the certificate (key type of the
+ * issuing CA). On error, this prints a message on stderr, and returns 0.
+ */
+int get_cert_signer_algo(br_x509_certificate *xc);
+
+/*
+ * Special "no anchor" X.509 validator that wraps around another X.509
+ * validator and turns "not trusted" error codes into success. This is
+ * by definition insecure, but convenient for debug purposes.
+ */
+typedef struct {
+ const br_x509_class *vtable;
+ const br_x509_class **inner;
+} x509_noanchor_context;
+extern const br_x509_class x509_noanchor_vtable;
+
+/*
+ * Initialise a "no anchor" X.509 validator.
+ */
+void x509_noanchor_init(x509_noanchor_context *xwc,
+ const br_x509_class **inner);
+
+/*
+ * Aggregate type for a private key.
+ */
+typedef struct {
+ int key_type; /* BR_KEYTYPE_RSA or BR_KEYTYPE_EC */
+ union {
+ br_rsa_private_key rsa;
+ br_ec_private_key ec;
+ } key;
+} private_key;
+
+/*
+ * Decode a private key from a file. On error, this prints an error
+ * message and returns NULL.
+ */
+private_key *read_private_key(const char *fname);
+
+/*
+ * Free a private key.
+ */
+void free_private_key(private_key *sk);
+
+/*
+ * Get the encoded OID for a given hash function (to use with PKCS#1
+ * signatures). If the hash function ID is 0 (for MD5+SHA-1), or if
+ * the ID is not one of the SHA-* functions (SHA-1, SHA-224, SHA-256,
+ * SHA-384, SHA-512), then this function returns NULL.
+ */
+const unsigned char *get_hash_oid(int id);
+
+/*
+ * Get a hash implementation by ID. This returns NULL if the hash
+ * implementation is not available.
+ */
+const br_hash_class *get_hash_impl(int id);
+
+/*
+ * Find the symbolic name and the description for an error. If 'err' is
+ * recognised then the error symbolic name is returned; if 'comment' is
+ * not NULL then '*comment' is then set to a descriptive human-readable
+ * message. If the error code 'err' is not recognised, then '*comment' is
+ * untouched and this function returns NULL.
+ */
+const char *find_error_name(int err, const char **comment);
+
+/*
+ * Find the symbolic name for an algorithm implementation. Provided
+ * pointer should be a pointer to a vtable or to a function, where
+ * appropriate. If not recognised, then the string "UNKNOWN" is returned.
+ *
+ * If 'long_name' is non-zero, then the returned name recalls the
+ * algorithm type as well; otherwise, only the core implementation name
+ * is returned (e.g. the long name could be 'aes_big_cbcenc' while the
+ * short name is 'big').
+ */
+const char *get_algo_name(const void *algo, int long_name);
+
+/*
+ * Run a SSL engine, with a socket connected to the peer, and using
+ * stdin/stdout to exchange application data. The socket must be a
+ * non-blocking descriptor.
+ *
+ * To help with Win32 compatibility, the socket descriptor is provided
+ * as an "unsigned long" value.
+ *
+ * Returned value:
+ * 0 SSL connection closed successfully
+ * x > 0 SSL error "x"
+ * -1 early socket close
+ * -2 stdout was closed, or something failed badly
+ */
+int run_ssl_engine(br_ssl_engine_context *eng,
+ unsigned long fd, unsigned flags);
+
+#define RUN_ENGINE_VERBOSE 0x0001 /* enable verbose messages */
+#define RUN_ENGINE_TRACE 0x0002 /* hex dump of records */
+
+/*
+ * Do the "client" command. Returned value is 0 on success, -1 on failure.
+ * Command-line arguments start _after_ the command name.
+ */
+int do_client(int argc, char *argv[]);
+
+/*
+ * Do the "server" command. Returned value is 0 on success, -1 on failure.
+ * Command-line arguments start _after_ the command name.
+ */
+int do_server(int argc, char *argv[]);
+
+/*
+ * Do the "verify" command. Returned value is 0 on success, -1 on failure.
+ * Command-line arguments start _after_ the command name.
+ */
+int do_verify(int argc, char *argv[]);
+
+/*
+ * Do the "skey" command. Returned value is 0 on success, -1 on failure.
+ * Command-line arguments start _after_ the command name.
+ */
+int do_skey(int argc, char *argv[]);
+
+/*
+ * Do the "ta" command. Returned value is 0 on success, -1 on failure.
+ * Command-line arguments start _after_ the command name.
+ */
+int do_ta(int argc, char *argv[]);
+
+/*
+ * Do the "chain" command. Returned value is 0 on success, -1 on failure.
+ * Command-line arguments start _after_ the command name.
+ */
+int do_chain(int argc, char *argv[]);
+
+/*
+ * Do the "twrch" command. Returned value is 0 on success, -1 on failure
+ * (processing or arguments), or a non-zero exit code. Command-line
+ * arguments start _after_ the command name.
+ */
+int do_twrch(int argc, char *argv[]);
+
+/*
+ * Do the "impl" command. Returned value is 0 on success, -1 on failure.
+ * Command-line arguments start _after_ the command name.
+ */
+int do_impl(int argc, char *argv[]);
+
+#endif
Property changes on: stable/12/contrib/bearssl/tools/brssl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/xmem.c
===================================================================
--- stable/12/contrib/bearssl/tools/xmem.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/xmem.c (revision 346145)
@@ -0,0 +1,132 @@
+/*
+ * 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 "brssl.h"
+
+/* see brssl.h */
+void *
+xmalloc(size_t len)
+{
+ void *buf;
+
+ if (len == 0) {
+ return NULL;
+ }
+ buf = malloc(len);
+ if (buf == NULL) {
+#ifndef _STANDALONE
+ fprintf(stderr, "ERROR: could not allocate %lu byte(s)\n",
+ (unsigned long)len);
+ exit(EXIT_FAILURE);
+#else
+;
+#endif
+ }
+ return buf;
+}
+
+/* see brssl.h */
+void
+xfree(void *buf)
+{
+ if (buf != NULL) {
+ free(buf);
+ }
+}
+
+/* see brssl.h */
+void *
+xblobdup(const void *src, size_t len)
+{
+ void *buf;
+
+ buf = xmalloc(len);
+ memcpy(buf, src, len);
+ return buf;
+}
+
+/* see brssl.h */
+char *
+xstrdup(const void *src)
+{
+ return xblobdup(src, strlen(src) + 1);
+}
+
+/* see brssl.h */
+br_x509_pkey *
+xpkeydup(const br_x509_pkey *pk)
+{
+ br_x509_pkey *pk2;
+
+ pk2 = xmalloc(sizeof *pk2);
+ pk2->key_type = pk->key_type;
+ switch (pk->key_type) {
+ case BR_KEYTYPE_RSA:
+ pk2->key.rsa.n = xblobdup(pk->key.rsa.n, pk->key.rsa.nlen);
+ pk2->key.rsa.nlen = pk->key.rsa.nlen;
+ pk2->key.rsa.e = xblobdup(pk->key.rsa.e, pk->key.rsa.elen);
+ pk2->key.rsa.elen = pk->key.rsa.elen;
+ break;
+ case BR_KEYTYPE_EC:
+ pk2->key.ec.curve = pk->key.ec.curve;
+ pk2->key.ec.q = xblobdup(pk->key.ec.q, pk->key.ec.qlen);
+ pk2->key.ec.qlen = pk->key.ec.qlen;
+ break;
+ default:
+#ifndef _STANDALONE
+ fprintf(stderr, "Unknown public key type: %u\n",
+ (unsigned)pk->key_type);
+ exit(EXIT_FAILURE);
+#else
+;
+#endif
+ }
+ return pk2;
+}
+
+/* see brssl.h */
+void
+xfreepkey(br_x509_pkey *pk)
+{
+ if (pk != NULL) {
+ switch (pk->key_type) {
+ case BR_KEYTYPE_RSA:
+ xfree(pk->key.rsa.n);
+ xfree(pk->key.rsa.e);
+ break;
+ case BR_KEYTYPE_EC:
+ xfree(pk->key.ec.q);
+ break;
+ default:
+#ifndef _STANDALONE
+ fprintf(stderr, "Unknown public key type: %u\n",
+ (unsigned)pk->key_type);
+ exit(EXIT_FAILURE);
+#else
+;
+#endif
+ }
+ xfree(pk);
+ }
+}
Property changes on: stable/12/contrib/bearssl/tools/xmem.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/brssl.c
===================================================================
--- stable/12/contrib/bearssl/tools/brssl.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/brssl.c (revision 346145)
@@ -0,0 +1,122 @@
+/*
+ * 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>
+
+/*
+ * Network stuff on Windows requires some specific code.
+ */
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#pragma comment(lib, "Ws2_32.lib")
+#endif
+
+#include "brssl.h"
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: brssl command [ options ]\n");
+ fprintf(stderr, "available commands:\n");
+ fprintf(stderr, " client run SSL client\n");
+ fprintf(stderr, " server run SSL server\n");
+ fprintf(stderr, " verify verify certificate chain\n");
+ fprintf(stderr, " skey decode private key\n");
+ fprintf(stderr, " ta decode trust anchors\n");
+ fprintf(stderr, " chain make C code for certificate chains\n");
+ fprintf(stderr, " twrch run the Twrch protocol\n");
+ fprintf(stderr, " impl report on implementations\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *cmd;
+
+ if (argc < 2) {
+ usage();
+ return EXIT_FAILURE;
+ }
+#ifdef _WIN32
+ {
+ WSADATA wd;
+ int r;
+
+ r = WSAStartup(MAKEWORD(2, 2), &wd);
+ if (r != 0) {
+ fprintf(stderr, "WARNING: network initialisation"
+ " failed (WSAStartup() returned %d)\n", r);
+ }
+ }
+#endif
+ cmd = argv[1];
+ if (eqstr(cmd, "client")) {
+ if (do_client(argc - 2, argv + 2) < 0) {
+ return EXIT_FAILURE;
+ }
+ } else if (eqstr(cmd, "server")) {
+ if (do_server(argc - 2, argv + 2) < 0) {
+ return EXIT_FAILURE;
+ }
+ } else if (eqstr(cmd, "verify")) {
+ if (do_verify(argc - 2, argv + 2) < 0) {
+ return EXIT_FAILURE;
+ }
+ } else if (eqstr(cmd, "skey")) {
+ if (do_skey(argc - 2, argv + 2) < 0) {
+ return EXIT_FAILURE;
+ }
+ } else if (eqstr(cmd, "ta")) {
+ if (do_ta(argc - 2, argv + 2) < 0) {
+ return EXIT_FAILURE;
+ }
+ } else if (eqstr(cmd, "chain")) {
+ if (do_chain(argc - 2, argv + 2) < 0) {
+ return EXIT_FAILURE;
+ }
+ } else if (eqstr(cmd, "twrch")) {
+ int ret;
+
+ ret = do_twrch(argc - 2, argv + 2);
+ if (ret < 0) {
+ return EXIT_FAILURE;
+ } else {
+ return ret;
+ }
+ } else if (eqstr(cmd, "impl")) {
+ if (do_impl(argc - 2, argv + 2) < 0) {
+ return EXIT_FAILURE;
+ }
+ } else {
+ fprintf(stderr, "unknown command: '%s'\n", cmd);
+ usage();
+ return EXIT_FAILURE;
+ }
+ return 0;
+}
Property changes on: stable/12/contrib/bearssl/tools/brssl.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/certs.c
===================================================================
--- stable/12/contrib/bearssl/tools/certs.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/certs.c (revision 346145)
@@ -0,0 +1,237 @@
+/*
+ * 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 "brssl.h"
+
+static void
+dn_append(void *ctx, const void *buf, size_t len)
+{
+ VEC_ADDMANY(*(bvector *)ctx, buf, len);
+}
+
+static int
+certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,
+ br_x509_certificate *xc)
+{
+ br_x509_decoder_context dc;
+ bvector vdn = VEC_INIT;
+ br_x509_pkey *pk;
+
+ br_x509_decoder_init(&dc, dn_append, &vdn);
+ br_x509_decoder_push(&dc, xc->data, xc->data_len);
+ pk = br_x509_decoder_get_pkey(&dc);
+ if (pk == NULL) {
+ fprintf(stderr, "ERROR: CA decoding failed with error %d\n",
+ br_x509_decoder_last_error(&dc));
+ VEC_CLEAR(vdn);
+ return -1;
+ }
+ ta->dn.data = VEC_TOARRAY(vdn);
+ ta->dn.len = VEC_LEN(vdn);
+ VEC_CLEAR(vdn);
+ ta->flags = 0;
+ if (br_x509_decoder_isCA(&dc)) {
+ ta->flags |= BR_X509_TA_CA;
+ }
+ switch (pk->key_type) {
+ case BR_KEYTYPE_RSA:
+ ta->pkey.key_type = BR_KEYTYPE_RSA;
+ ta->pkey.key.rsa.n = xblobdup(pk->key.rsa.n, pk->key.rsa.nlen);
+ ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
+ ta->pkey.key.rsa.e = xblobdup(pk->key.rsa.e, pk->key.rsa.elen);
+ ta->pkey.key.rsa.elen = pk->key.rsa.elen;
+ break;
+ case BR_KEYTYPE_EC:
+ ta->pkey.key_type = BR_KEYTYPE_EC;
+ ta->pkey.key.ec.curve = pk->key.ec.curve;
+ ta->pkey.key.ec.q = xblobdup(pk->key.ec.q, pk->key.ec.qlen);
+ ta->pkey.key.ec.qlen = pk->key.ec.qlen;
+ break;
+ default:
+ fprintf(stderr, "ERROR: unsupported public key type in CA\n");
+ xfree(ta->dn.data);
+ return -1;
+ }
+ return 0;
+}
+
+/* see brssl.h */
+br_x509_trust_anchor *
+certificate_to_trust_anchor(br_x509_certificate *xc)
+{
+ br_x509_trust_anchor ta;
+
+ if (certificate_to_trust_anchor_inner(&ta, xc) < 0) {
+ return NULL;
+ } else {
+ return xblobdup(&ta, sizeof ta);
+ }
+}
+
+/* see brssl.h */
+void
+free_ta_contents(br_x509_trust_anchor *ta)
+{
+ xfree(ta->dn.data);
+ switch (ta->pkey.key_type) {
+ case BR_KEYTYPE_RSA:
+ xfree(ta->pkey.key.rsa.n);
+ xfree(ta->pkey.key.rsa.e);
+ break;
+ case BR_KEYTYPE_EC:
+ xfree(ta->pkey.key.ec.q);
+ break;
+ }
+}
+
+/* see brssl.h */
+size_t
+read_trust_anchors(anchor_list *dst, const char *fname)
+{
+ br_x509_certificate *xcs;
+ anchor_list tas = VEC_INIT;
+ size_t u, num;
+
+ xcs = read_certificates(fname, &num);
+ if (xcs == NULL) {
+ return 0;
+ }
+ for (u = 0; u < num; u ++) {
+ br_x509_trust_anchor ta;
+
+ if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
+ VEC_CLEAREXT(tas, free_ta_contents);
+ free_certificates(xcs, num);
+ return 0;
+ }
+ VEC_ADD(tas, ta);
+ }
+ VEC_ADDMANY(*dst, &VEC_ELT(tas, 0), num);
+ VEC_CLEAR(tas);
+ free_certificates(xcs, num);
+ return num;
+}
+
+/* see brssl.h */
+int
+get_cert_signer_algo(br_x509_certificate *xc)
+{
+ br_x509_decoder_context dc;
+ int err;
+
+ br_x509_decoder_init(&dc, 0, 0);
+ br_x509_decoder_push(&dc, xc->data, xc->data_len);
+ err = br_x509_decoder_last_error(&dc);
+ if (err != 0) {
+ fprintf(stderr,
+ "ERROR: certificate decoding failed with error %d\n",
+ -err);
+ return 0;
+ }
+ return br_x509_decoder_get_signer_key_type(&dc);
+}
+
+static void
+xwc_start_chain(const br_x509_class **ctx, const char *server_name)
+{
+ x509_noanchor_context *xwc;
+
+ xwc = (x509_noanchor_context *)ctx;
+ (*xwc->inner)->start_chain(xwc->inner, server_name);
+}
+
+static void
+xwc_start_cert(const br_x509_class **ctx, uint32_t length)
+{
+ x509_noanchor_context *xwc;
+
+ xwc = (x509_noanchor_context *)ctx;
+ (*xwc->inner)->start_cert(xwc->inner, length);
+}
+
+static void
+xwc_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)
+{
+ x509_noanchor_context *xwc;
+
+ xwc = (x509_noanchor_context *)ctx;
+ (*xwc->inner)->append(xwc->inner, buf, len);
+}
+
+static void
+xwc_end_cert(const br_x509_class **ctx)
+{
+ x509_noanchor_context *xwc;
+
+ xwc = (x509_noanchor_context *)ctx;
+ (*xwc->inner)->end_cert(xwc->inner);
+}
+
+static unsigned
+xwc_end_chain(const br_x509_class **ctx)
+{
+ x509_noanchor_context *xwc;
+ unsigned r;
+
+ xwc = (x509_noanchor_context *)ctx;
+ r = (*xwc->inner)->end_chain(xwc->inner);
+ if (r == BR_ERR_X509_NOT_TRUSTED) {
+ r = 0;
+ }
+ return r;
+}
+
+static const br_x509_pkey *
+xwc_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
+{
+ x509_noanchor_context *xwc;
+
+ xwc = (x509_noanchor_context *)ctx;
+ return (*xwc->inner)->get_pkey(xwc->inner, usages);
+}
+
+/* see brssl.h */
+const br_x509_class x509_noanchor_vtable = {
+ sizeof(x509_noanchor_context),
+ xwc_start_chain,
+ xwc_start_cert,
+ xwc_append,
+ xwc_end_cert,
+ xwc_end_chain,
+ xwc_get_pkey
+};
+
+/* see brssl.h */
+void
+x509_noanchor_init(x509_noanchor_context *xwc, const br_x509_class **inner)
+{
+ xwc->vtable = &x509_noanchor_vtable;
+ xwc->inner = inner;
+}
Property changes on: stable/12/contrib/bearssl/tools/certs.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/chain.c
===================================================================
--- stable/12/contrib/bearssl/tools/chain.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/chain.c (revision 346145)
@@ -0,0 +1,154 @@
+/*
+ * 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 "brssl.h"
+#include "bearssl.h"
+
+static void
+print_blob(const char *name, const unsigned char *buf, size_t len)
+{
+ size_t u;
+
+ printf("\nstatic const unsigned char %s[] = {", name);
+ for (u = 0; u < len; u ++) {
+ if (u != 0) {
+ printf(",");
+ }
+ if (u % 12 == 0) {
+ printf("\n\t");
+ } else {
+ printf(" ");
+ }
+ printf("0x%02X", buf[u]);
+ }
+ printf("\n};\n");
+}
+
+static void
+usage_chain(void)
+{
+ fprintf(stderr,
+"usage: brssl chain [ options ] file...\n");
+ fprintf(stderr,
+"options:\n");
+ fprintf(stderr,
+" -q suppress verbose messages\n");
+}
+
+/* see brssl.h */
+int
+do_chain(int argc, char *argv[])
+{
+ int retcode;
+ int verbose;
+ int i, num_files;
+ long k, ctr;
+
+ retcode = 0;
+ verbose = 1;
+ num_files = 0;
+ for (i = 0; i < argc; i ++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (arg[0] != '-') {
+ num_files ++;
+ continue;
+ }
+ argv[i] = NULL;
+ if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
+ verbose = 1;
+ } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
+ verbose = 0;
+ } else {
+ fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
+ usage_chain();
+ goto chain_exit_error;
+ }
+ }
+ if (num_files == 0) {
+ fprintf(stderr, "ERROR: no certificate file provided\n");
+ usage_chain();
+ goto chain_exit_error;
+ }
+
+ ctr = 0;
+ for (i = 0; i < argc; i ++) {
+ const char *fname;
+ br_x509_certificate *xcs;
+ size_t u, num;
+
+ fname = argv[i];
+ if (fname == NULL) {
+ continue;
+ }
+ if (verbose) {
+ fprintf(stderr, "Reading file '%s': ", fname);
+ fflush(stderr);
+ }
+ xcs = read_certificates(fname, &num);
+ if (xcs == NULL) {
+ goto chain_exit_error;
+ }
+ if (verbose) {
+ fprintf(stderr, "%lu certificate%s\n",
+ (unsigned long)num, num > 1 ? "s" : "");
+ }
+ for (u = 0; u < num; u ++) {
+ char tmp[50];
+
+ sprintf(tmp, "CERT%ld", ctr ++);
+ print_blob(tmp, xcs[u].data, xcs[u].data_len);
+ xfree(xcs[u].data);
+ }
+ xfree(xcs);
+ }
+
+ printf("\nstatic const br_x509_certificate CHAIN[] = {");
+ for (k = 0; k < ctr; k ++) {
+ if (k != 0) {
+ printf(",");
+ }
+ printf("\n\t{ (unsigned char *)CERT%ld, sizeof CERT%ld }",
+ k, k);
+ }
+ printf("\n};\n");
+ printf("\n#define CHAIN_LEN %ld\n", ctr);
+
+ /*
+ * Release allocated structures.
+ */
+chain_exit:
+ return retcode;
+
+chain_exit_error:
+ retcode = -1;
+ goto chain_exit;
+}
Property changes on: stable/12/contrib/bearssl/tools/chain.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/client.c
===================================================================
--- stable/12/contrib/bearssl/tools/client.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/client.c (revision 346145)
@@ -0,0 +1,1112 @@
+/*
+ * 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>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define SOCKET int
+#define INVALID_SOCKET (-1)
+#endif
+
+#include "brssl.h"
+
+static int
+host_connect(const char *host, const char *port, int verbose)
+{
+ struct addrinfo hints, *si, *p;
+ SOCKET 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 INVALID_SOCKET;
+ }
+ fd = INVALID_SOCKET;
+ for (p = si; p != NULL; p = p->ai_next) {
+ if (verbose) {
+ 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 *)
+ (void *)sa)->sin_addr;
+ } else if (sa->sa_family == AF_INET6) {
+ addr = &((struct sockaddr_in6 *)
+ (void *)sa)->sin6_addr;
+ } else {
+ addr = NULL;
+ }
+ if (addr != NULL) {
+ if (!inet_ntop(p->ai_family, addr,
+ tmp, sizeof tmp))
+ {
+ strcpy(tmp, "<invalid>");
+ }
+ } 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 == INVALID_SOCKET) {
+ if (verbose) {
+ perror("socket()");
+ }
+ continue;
+ }
+ if (connect(fd, p->ai_addr, p->ai_addrlen) == INVALID_SOCKET) {
+ if (verbose) {
+ perror("connect()");
+ }
+#ifdef _WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ continue;
+ }
+ break;
+ }
+ if (p == NULL) {
+ freeaddrinfo(si);
+ fprintf(stderr, "ERROR: failed to connect\n");
+ return INVALID_SOCKET;
+ }
+ freeaddrinfo(si);
+ if (verbose) {
+ fprintf(stderr, "connected.\n");
+ }
+
+ /*
+ * We make the socket non-blocking, since we are going to use
+ * poll() or select() to organise I/O.
+ */
+#ifdef _WIN32
+ {
+ u_long arg;
+
+ arg = 1;
+ ioctlsocket(fd, FIONBIO, &arg);
+ }
+#else
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+ return fd;
+}
+
+typedef struct {
+ const br_ssl_client_certificate_class *vtable;
+ int verbose;
+ br_x509_certificate *chain;
+ size_t chain_len;
+ private_key *sk;
+ int issuer_key_type;
+} ccert_context;
+
+static void
+cc_start_name_list(const br_ssl_client_certificate_class **pctx)
+{
+ ccert_context *zc;
+
+ zc = (ccert_context *)pctx;
+ if (zc->verbose) {
+ fprintf(stderr, "Server requests a client certificate.\n");
+ fprintf(stderr, "--- anchor DN list start ---\n");
+ }
+}
+
+static void
+cc_start_name(const br_ssl_client_certificate_class **pctx, size_t len)
+{
+ ccert_context *zc;
+
+ zc = (ccert_context *)pctx;
+ if (zc->verbose) {
+ fprintf(stderr, "new anchor name, length = %u\n",
+ (unsigned)len);
+ }
+}
+
+static void
+cc_append_name(const br_ssl_client_certificate_class **pctx,
+ const unsigned char *data, size_t len)
+{
+ ccert_context *zc;
+
+ zc = (ccert_context *)pctx;
+ if (zc->verbose) {
+ size_t u;
+
+ for (u = 0; u < len; u ++) {
+ if (u == 0) {
+ fprintf(stderr, " ");
+ } else if (u > 0 && u % 16 == 0) {
+ fprintf(stderr, "\n ");
+ }
+ fprintf(stderr, " %02x", data[u]);
+ }
+ if (len > 0) {
+ fprintf(stderr, "\n");
+ }
+ }
+}
+
+static void
+cc_end_name(const br_ssl_client_certificate_class **pctx)
+{
+ (void)pctx;
+}
+
+static void
+cc_end_name_list(const br_ssl_client_certificate_class **pctx)
+{
+ ccert_context *zc;
+
+ zc = (ccert_context *)pctx;
+ if (zc->verbose) {
+ fprintf(stderr, "--- anchor DN list end ---\n");
+ }
+}
+
+static void
+print_hashes(unsigned hh, unsigned hh2)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ const char *name;
+
+ name = hash_function_name(i);
+ if (((hh >> i) & 1) != 0) {
+ fprintf(stderr, " %s", name);
+ } else if (((hh2 >> i) & 1) != 0) {
+ fprintf(stderr, " (%s)", name);
+ }
+ }
+}
+
+static int
+choose_hash(unsigned hh)
+{
+ static const int f[] = {
+ br_sha256_ID, br_sha224_ID, br_sha384_ID, br_sha512_ID,
+ br_sha1_ID, br_md5sha1_ID, -1
+ };
+
+ size_t u;
+
+ for (u = 0; f[u] >= 0; u ++) {
+ if (((hh >> f[u]) & 1) != 0) {
+ return f[u];
+ }
+ }
+ return -1;
+}
+
+static void
+cc_choose(const br_ssl_client_certificate_class **pctx,
+ const br_ssl_client_context *cc, uint32_t auth_types,
+ br_ssl_client_certificate *choices)
+{
+ ccert_context *zc;
+ int scurve;
+
+ zc = (ccert_context *)pctx;
+ scurve = br_ssl_client_get_server_curve(cc);
+ if (zc->verbose) {
+ unsigned hashes;
+
+ hashes = br_ssl_client_get_server_hashes(cc);
+ if ((auth_types & 0x00FF) != 0) {
+ fprintf(stderr, "supported: RSA signatures:");
+ print_hashes(auth_types, hashes);
+ fprintf(stderr, "\n");
+ }
+ if ((auth_types & 0xFF00) != 0) {
+ fprintf(stderr, "supported: ECDSA signatures:");
+ print_hashes(auth_types >> 8, hashes >> 8);
+ fprintf(stderr, "\n");
+ }
+ if ((auth_types & 0x010000) != 0) {
+ fprintf(stderr, "supported:"
+ " fixed ECDH (cert signed with RSA)\n");
+ }
+ if ((auth_types & 0x020000) != 0) {
+ fprintf(stderr, "supported:"
+ " fixed ECDH (cert signed with ECDSA)\n");
+ }
+ if (scurve) {
+ fprintf(stderr, "server key curve: %s (%d)\n",
+ ec_curve_name(scurve), scurve);
+ } else {
+ fprintf(stderr, "server key is not EC\n");
+ }
+ }
+ switch (zc->sk->key_type) {
+ case BR_KEYTYPE_RSA:
+ if ((choices->hash_id = choose_hash(auth_types)) >= 0) {
+ if (zc->verbose) {
+ fprintf(stderr, "using RSA, hash = %d (%s)\n",
+ choices->hash_id,
+ hash_function_name(choices->hash_id));
+ }
+ choices->auth_type = BR_AUTH_RSA;
+ choices->chain = zc->chain;
+ choices->chain_len = zc->chain_len;
+ return;
+ }
+ break;
+ case BR_KEYTYPE_EC:
+ if (zc->issuer_key_type != 0
+ && scurve == zc->sk->key.ec.curve)
+ {
+ int x;
+
+ x = (zc->issuer_key_type == BR_KEYTYPE_RSA) ? 16 : 17;
+ if (((auth_types >> x) & 1) != 0) {
+ if (zc->verbose) {
+ fprintf(stderr, "using static ECDH\n");
+ }
+ choices->auth_type = BR_AUTH_ECDH;
+ choices->hash_id = -1;
+ choices->chain = zc->chain;
+ choices->chain_len = zc->chain_len;
+ return;
+ }
+ }
+ if ((choices->hash_id = choose_hash(auth_types >> 8)) >= 0) {
+ if (zc->verbose) {
+ fprintf(stderr, "using ECDSA, hash = %d (%s)\n",
+ choices->hash_id,
+ hash_function_name(choices->hash_id));
+ }
+ choices->auth_type = BR_AUTH_ECDSA;
+ choices->chain = zc->chain;
+ choices->chain_len = zc->chain_len;
+ return;
+ }
+ break;
+ }
+ if (zc->verbose) {
+ fprintf(stderr, "no matching client certificate\n");
+ }
+ choices->chain = NULL;
+ choices->chain_len = 0;
+}
+
+static uint32_t
+cc_do_keyx(const br_ssl_client_certificate_class **pctx,
+ unsigned char *data, size_t *len)
+{
+ const br_ec_impl *iec;
+ ccert_context *zc;
+ size_t xoff, xlen;
+ uint32_t r;
+
+ zc = (ccert_context *)pctx;
+ iec = br_ec_get_default();
+ r = iec->mul(data, *len, zc->sk->key.ec.x,
+ zc->sk->key.ec.xlen, zc->sk->key.ec.curve);
+ xoff = iec->xoff(zc->sk->key.ec.curve, &xlen);
+ memmove(data, data + xoff, xlen);
+ *len = xlen;
+ return r;
+}
+
+static size_t
+cc_do_sign(const br_ssl_client_certificate_class **pctx,
+ int hash_id, size_t hv_len, unsigned char *data, size_t len)
+{
+ ccert_context *zc;
+ unsigned char hv[64];
+
+ zc = (ccert_context *)pctx;
+ memcpy(hv, data, hv_len);
+ switch (zc->sk->key_type) {
+ const br_hash_class *hc;
+ const unsigned char *hash_oid;
+ uint32_t x;
+ size_t sig_len;
+
+ case BR_KEYTYPE_RSA:
+ hash_oid = get_hash_oid(hash_id);
+ if (hash_oid == NULL && hash_id != 0) {
+ if (zc->verbose) {
+ fprintf(stderr, "ERROR: cannot RSA-sign with"
+ " unknown hash function: %d\n",
+ hash_id);
+ }
+ return 0;
+ }
+ sig_len = (zc->sk->key.rsa.n_bitlen + 7) >> 3;
+ if (len < sig_len) {
+ if (zc->verbose) {
+ fprintf(stderr, "ERROR: cannot RSA-sign,"
+ " buffer is too small"
+ " (sig=%lu, buf=%lu)\n",
+ (unsigned long)sig_len,
+ (unsigned long)len);
+ }
+ return 0;
+ }
+ x = br_rsa_pkcs1_sign_get_default()(
+ hash_oid, hv, hv_len, &zc->sk->key.rsa, data);
+ if (!x) {
+ if (zc->verbose) {
+ fprintf(stderr, "ERROR: RSA-sign failure\n");
+ }
+ return 0;
+ }
+ return sig_len;
+
+ case BR_KEYTYPE_EC:
+ hc = get_hash_impl(hash_id);
+ if (hc == NULL) {
+ if (zc->verbose) {
+ fprintf(stderr, "ERROR: cannot ECDSA-sign with"
+ " unknown hash function: %d\n",
+ hash_id);
+ }
+ return 0;
+ }
+ if (len < 139) {
+ if (zc->verbose) {
+ fprintf(stderr, "ERROR: cannot ECDSA-sign"
+ " (output buffer = %lu)\n",
+ (unsigned long)len);
+ }
+ return 0;
+ }
+ sig_len = br_ecdsa_sign_asn1_get_default()(
+ br_ec_get_default(), hc, hv, &zc->sk->key.ec, data);
+ if (sig_len == 0) {
+ if (zc->verbose) {
+ fprintf(stderr, "ERROR: ECDSA-sign failure\n");
+ }
+ return 0;
+ }
+ return sig_len;
+
+ default:
+ return 0;
+ }
+}
+
+static const br_ssl_client_certificate_class ccert_vtable = {
+ sizeof(ccert_context),
+ cc_start_name_list,
+ cc_start_name,
+ cc_append_name,
+ cc_end_name,
+ cc_end_name_list,
+ cc_choose,
+ cc_do_keyx,
+ cc_do_sign
+};
+
+static void
+free_alpn(void *alpn)
+{
+ xfree(*(char **)alpn);
+}
+
+static void
+usage_client(void)
+{
+ fprintf(stderr,
+"usage: brssl client server[:port] [ options ]\n");
+ fprintf(stderr,
+"options:\n");
+ fprintf(stderr,
+" -q suppress verbose messages\n");
+ fprintf(stderr,
+" -trace activate extra debug messages (dump of all packets)\n");
+ fprintf(stderr,
+" -sni name use this specific name for SNI\n");
+ fprintf(stderr,
+" -nosni do not send any SNI\n");
+ fprintf(stderr,
+" -mono use monodirectional buffering\n");
+ fprintf(stderr,
+" -buf length set the I/O buffer length (in bytes)\n");
+ fprintf(stderr,
+" -CA file add certificates in 'file' to trust anchors\n");
+ fprintf(stderr,
+" -cert file set client certificate chain\n");
+ fprintf(stderr,
+" -key file set client private key (for certificate authentication)\n");
+ fprintf(stderr,
+" -nostaticecdh prohibit full-static ECDH (client certificate)\n");
+ fprintf(stderr,
+" -list list supported names (protocols, algorithms...)\n");
+ fprintf(stderr,
+" -vmin name set minimum supported version (default: TLS-1.0)\n");
+ fprintf(stderr,
+" -vmax name set maximum supported version (default: TLS-1.2)\n");
+ fprintf(stderr,
+" -cs names set list of supported cipher suites (comma-separated)\n");
+ fprintf(stderr,
+" -hf names add support for some hash functions (comma-separated)\n");
+ fprintf(stderr,
+" -minhello len set minimum ClientHello length (in bytes)\n");
+ fprintf(stderr,
+" -fallback send the TLS_FALLBACK_SCSV (i.e. claim a downgrade)\n");
+ fprintf(stderr,
+" -noreneg prohibit renegotiations\n");
+ fprintf(stderr,
+" -alpn name add protocol name to list of protocols (ALPN extension)\n");
+ fprintf(stderr,
+" -strictalpn fail on ALPN mismatch\n");
+}
+
+/* see brssl.h */
+int
+do_client(int argc, char *argv[])
+{
+ int retcode;
+ int verbose;
+ int trace;
+ int i, bidi;
+ const char *server_name;
+ char *host;
+ char *port;
+ const char *sni;
+ anchor_list anchors = VEC_INIT;
+ unsigned vmin, vmax;
+ VECTOR(char *) alpn_names = VEC_INIT;
+ cipher_suite *suites;
+ size_t num_suites;
+ uint16_t *suite_ids;
+ unsigned hfuns;
+ size_t u;
+ br_ssl_client_context cc;
+ br_x509_minimal_context xc;
+ x509_noanchor_context xwc;
+ const br_hash_class *dnhash;
+ ccert_context zc;
+ br_x509_certificate *chain;
+ size_t chain_len;
+ private_key *sk;
+ int nostaticecdh;
+ unsigned char *iobuf;
+ size_t iobuf_len;
+ size_t minhello_len;
+ int fallback;
+ uint32_t flags;
+ SOCKET fd;
+
+ retcode = 0;
+ verbose = 1;
+ trace = 0;
+ server_name = NULL;
+ host = NULL;
+ port = NULL;
+ sni = NULL;
+ bidi = 1;
+ vmin = 0;
+ vmax = 0;
+ suites = NULL;
+ num_suites = 0;
+ hfuns = 0;
+ suite_ids = NULL;
+ chain = NULL;
+ chain_len = 0;
+ sk = NULL;
+ nostaticecdh = 0;
+ iobuf = NULL;
+ iobuf_len = 0;
+ minhello_len = (size_t)-1;
+ fallback = 0;
+ flags = 0;
+ fd = INVALID_SOCKET;
+ for (i = 0; i < argc; i ++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (arg[0] != '-') {
+ if (server_name != NULL) {
+ fprintf(stderr,
+ "ERROR: duplicate server name\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ server_name = arg;
+ continue;
+ }
+ if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
+ verbose = 1;
+ } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
+ verbose = 0;
+ } else if (eqstr(arg, "-trace")) {
+ trace = 1;
+ } else if (eqstr(arg, "-sni")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-sni'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ if (sni != NULL) {
+ fprintf(stderr, "ERROR: duplicate SNI\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ sni = argv[i];
+ } else if (eqstr(arg, "-nosni")) {
+ if (sni != NULL) {
+ fprintf(stderr, "ERROR: duplicate SNI\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ sni = "";
+ } else if (eqstr(arg, "-mono")) {
+ bidi = 0;
+ } else if (eqstr(arg, "-buf")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-buf'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ if (iobuf_len != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate I/O buffer length\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ iobuf_len = parse_size(arg);
+ if (iobuf_len == (size_t)-1) {
+ usage_client();
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-CA")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-CA'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ if (read_trust_anchors(&anchors, arg) == 0) {
+ usage_client();
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-cert")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cert'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ if (chain != NULL) {
+ fprintf(stderr,
+ "ERROR: duplicate certificate chain\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ chain = read_certificates(arg, &chain_len);
+ if (chain == NULL || chain_len == 0) {
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-key")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-key'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ if (sk != NULL) {
+ fprintf(stderr,
+ "ERROR: duplicate private key\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ sk = read_private_key(arg);
+ if (sk == NULL) {
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-nostaticecdh")) {
+ nostaticecdh = 1;
+ } else if (eqstr(arg, "-list")) {
+ list_names();
+ goto client_exit;
+ } else if (eqstr(arg, "-vmin")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-vmin'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ if (vmin != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate minimum version\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ vmin = parse_version(arg, strlen(arg));
+ if (vmin == 0) {
+ fprintf(stderr,
+ "ERROR: unrecognised version '%s'\n",
+ arg);
+ usage_client();
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-vmax")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-vmax'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ if (vmax != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate maximum version\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ vmax = parse_version(arg, strlen(arg));
+ if (vmax == 0) {
+ fprintf(stderr,
+ "ERROR: unrecognised version '%s'\n",
+ arg);
+ usage_client();
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-cs")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cs'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ if (suites != NULL) {
+ fprintf(stderr, "ERROR: duplicate list"
+ " of cipher suites\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ suites = parse_suites(arg, &num_suites);
+ if (suites == NULL) {
+ usage_client();
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-hf")) {
+ unsigned x;
+
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-hf'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ x = parse_hash_functions(arg);
+ if (x == 0) {
+ usage_client();
+ goto client_exit_error;
+ }
+ hfuns |= x;
+ } else if (eqstr(arg, "-minhello")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-minhello'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ arg = argv[i];
+ if (minhello_len != (size_t)-1) {
+ fprintf(stderr, "ERROR: duplicate minimum"
+ " ClientHello length\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ minhello_len = parse_size(arg);
+ /*
+ * Minimum ClientHello length must fit on 16 bits.
+ */
+ if (minhello_len == (size_t)-1
+ || (((minhello_len >> 12) >> 4) != 0))
+ {
+ usage_client();
+ goto client_exit_error;
+ }
+ } else if (eqstr(arg, "-fallback")) {
+ fallback = 1;
+ } else if (eqstr(arg, "-noreneg")) {
+ flags |= BR_OPT_NO_RENEGOTIATION;
+ } else if (eqstr(arg, "-alpn")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-alpn'\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ VEC_ADD(alpn_names, xstrdup(argv[i]));
+ } else if (eqstr(arg, "-strictalpn")) {
+ flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH;
+ } else {
+ fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
+ usage_client();
+ goto client_exit_error;
+ }
+ }
+ if (server_name == NULL) {
+ fprintf(stderr, "ERROR: no server name/address provided\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ for (u = strlen(server_name); u > 0; u --) {
+ int c = server_name[u - 1];
+ if (c == ':') {
+ break;
+ }
+ if (c < '0' || c > '9') {
+ u = 0;
+ break;
+ }
+ }
+ if (u == 0) {
+ host = xstrdup(server_name);
+ port = xstrdup("443");
+ } else {
+ port = xstrdup(server_name + u);
+ host = xmalloc(u);
+ memcpy(host, server_name, u - 1);
+ host[u - 1] = 0;
+ }
+ if (sni == NULL) {
+ sni = host;
+ }
+
+ if (chain == NULL && sk != NULL) {
+ fprintf(stderr, "ERROR: private key specified, but"
+ " no certificate chain\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ if (chain != NULL && sk == NULL) {
+ fprintf(stderr, "ERROR: certificate chain specified, but"
+ " no private key\n");
+ usage_client();
+ goto client_exit_error;
+ }
+
+ if (vmin == 0) {
+ vmin = BR_TLS10;
+ }
+ if (vmax == 0) {
+ vmax = BR_TLS12;
+ }
+ if (vmax < vmin) {
+ fprintf(stderr, "ERROR: impossible minimum/maximum protocol"
+ " version combination\n");
+ usage_client();
+ goto client_exit_error;
+ }
+ if (suites == NULL) {
+ num_suites = 0;
+
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if ((cipher_suites[u].req & REQ_TLS12) == 0
+ || vmax >= BR_TLS12)
+ {
+ num_suites ++;
+ }
+ }
+ suites = xmalloc(num_suites * sizeof *suites);
+ num_suites = 0;
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if ((cipher_suites[u].req & REQ_TLS12) == 0
+ || vmax >= BR_TLS12)
+ {
+ suites[num_suites ++] = cipher_suites[u];
+ }
+ }
+ }
+ if (hfuns == 0) {
+ hfuns = (unsigned)-1;
+ }
+ if (iobuf_len == 0) {
+ if (bidi) {
+ iobuf_len = BR_SSL_BUFSIZE_BIDI;
+ } else {
+ iobuf_len = BR_SSL_BUFSIZE_MONO;
+ }
+ }
+ iobuf = xmalloc(iobuf_len);
+
+ /*
+ * Compute implementation requirements and inject implementations.
+ */
+ suite_ids = xmalloc((num_suites + 1) * sizeof *suite_ids);
+ br_ssl_client_zero(&cc);
+ br_ssl_engine_set_versions(&cc.eng, vmin, vmax);
+ dnhash = NULL;
+ for (u = 0; hash_functions[u].name; u ++) {
+ const br_hash_class *hc;
+ int id;
+
+ hc = hash_functions[u].hclass;
+ id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
+ if ((hfuns & ((unsigned)1 << id)) != 0) {
+ dnhash = hc;
+ }
+ }
+ if (dnhash == NULL) {
+ fprintf(stderr, "ERROR: no supported hash function\n");
+ goto client_exit_error;
+ }
+ br_x509_minimal_init(&xc, dnhash,
+ &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+ if (vmin <= BR_TLS11) {
+ if (!(hfuns & (1 << br_md5_ID))) {
+ fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need MD5\n");
+ goto client_exit_error;
+ }
+ if (!(hfuns & (1 << br_sha1_ID))) {
+ fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need SHA-1\n");
+ goto client_exit_error;
+ }
+ }
+ for (u = 0; u < num_suites; u ++) {
+ unsigned req;
+
+ req = suites[u].req;
+ suite_ids[u] = suites[u].suite;
+ if ((req & REQ_TLS12) != 0 && vmax < BR_TLS12) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires TLS 1.2\n",
+ suites[u].name);
+ goto client_exit_error;
+ }
+ if ((req & REQ_SHA1) != 0 && !(hfuns & (1 << br_sha1_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-1\n",
+ suites[u].name);
+ goto client_exit_error;
+ }
+ if ((req & REQ_SHA256) != 0 && !(hfuns & (1 << br_sha256_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-256\n",
+ suites[u].name);
+ goto client_exit_error;
+ }
+ if ((req & REQ_SHA384) != 0 && !(hfuns & (1 << br_sha384_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-384\n",
+ suites[u].name);
+ goto client_exit_error;
+ }
+ /* TODO: algorithm implementation selection */
+ if ((req & REQ_AESCBC) != 0) {
+ br_ssl_engine_set_default_aes_cbc(&cc.eng);
+ }
+ if ((req & REQ_AESCCM) != 0) {
+ br_ssl_engine_set_default_aes_ccm(&cc.eng);
+ }
+ if ((req & REQ_AESGCM) != 0) {
+ br_ssl_engine_set_default_aes_gcm(&cc.eng);
+ }
+ if ((req & REQ_CHAPOL) != 0) {
+ br_ssl_engine_set_default_chapol(&cc.eng);
+ }
+ if ((req & REQ_3DESCBC) != 0) {
+ br_ssl_engine_set_default_des_cbc(&cc.eng);
+ }
+ if ((req & REQ_RSAKEYX) != 0) {
+ br_ssl_client_set_default_rsapub(&cc);
+ }
+ if ((req & REQ_ECDHE_RSA) != 0) {
+ br_ssl_engine_set_default_ec(&cc.eng);
+ br_ssl_engine_set_default_rsavrfy(&cc.eng);
+ }
+ if ((req & REQ_ECDHE_ECDSA) != 0) {
+ br_ssl_engine_set_default_ecdsa(&cc.eng);
+ }
+ if ((req & REQ_ECDH) != 0) {
+ br_ssl_engine_set_default_ec(&cc.eng);
+ }
+ }
+ if (fallback) {
+ suite_ids[num_suites ++] = 0x5600;
+ }
+ br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites);
+
+ for (u = 0; hash_functions[u].name; u ++) {
+ const br_hash_class *hc;
+ int id;
+
+ hc = hash_functions[u].hclass;
+ id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
+ if ((hfuns & ((unsigned)1 << id)) != 0) {
+ br_ssl_engine_set_hash(&cc.eng, id, hc);
+ br_x509_minimal_set_hash(&xc, id, hc);
+ }
+ }
+ if (vmin <= BR_TLS11) {
+ br_ssl_engine_set_prf10(&cc.eng, &br_tls10_prf);
+ }
+ if (vmax >= BR_TLS12) {
+ if ((hfuns & ((unsigned)1 << br_sha256_ID)) != 0) {
+ br_ssl_engine_set_prf_sha256(&cc.eng,
+ &br_tls12_sha256_prf);
+ }
+ if ((hfuns & ((unsigned)1 << br_sha384_ID)) != 0) {
+ br_ssl_engine_set_prf_sha384(&cc.eng,
+ &br_tls12_sha384_prf);
+ }
+ }
+ br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default());
+ br_x509_minimal_set_ecdsa(&xc,
+ br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
+
+ /*
+ * If there is no provided trust anchor, then certificate validation
+ * will always fail. In that situation, we use our custom wrapper
+ * that tolerates unknown anchors.
+ */
+ if (VEC_LEN(anchors) == 0) {
+ if (verbose) {
+ fprintf(stderr,
+ "WARNING: no configured trust anchor\n");
+ }
+ x509_noanchor_init(&xwc, &xc.vtable);
+ br_ssl_engine_set_x509(&cc.eng, &xwc.vtable);
+ } else {
+ br_ssl_engine_set_x509(&cc.eng, &xc.vtable);
+ }
+
+ if (minhello_len != (size_t)-1) {
+ br_ssl_client_set_min_clienthello_len(&cc, minhello_len);
+ }
+ br_ssl_engine_set_all_flags(&cc.eng, flags);
+ if (VEC_LEN(alpn_names) != 0) {
+ br_ssl_engine_set_protocol_names(&cc.eng,
+ (const char **)&VEC_ELT(alpn_names, 0),
+ VEC_LEN(alpn_names));
+ }
+
+ if (chain != NULL) {
+ zc.vtable = &ccert_vtable;
+ zc.verbose = verbose;
+ zc.chain = chain;
+ zc.chain_len = chain_len;
+ zc.sk = sk;
+ if (nostaticecdh || sk->key_type != BR_KEYTYPE_EC) {
+ zc.issuer_key_type = 0;
+ } else {
+ zc.issuer_key_type = get_cert_signer_algo(&chain[0]);
+ if (zc.issuer_key_type == 0) {
+ goto client_exit_error;
+ }
+ }
+ br_ssl_client_set_client_certificate(&cc, &zc.vtable);
+ }
+
+ br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
+ br_ssl_client_reset(&cc, sni, 0);
+
+ /*
+ * On Unix systems, we need to avoid SIGPIPE.
+ */
+#ifndef _WIN32
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /*
+ * Connect to the peer.
+ */
+ fd = host_connect(host, port, verbose);
+ if (fd == INVALID_SOCKET) {
+ goto client_exit_error;
+ }
+
+ /*
+ * Run the engine until completion.
+ */
+ if (run_ssl_engine(&cc.eng, fd,
+ (verbose ? RUN_ENGINE_VERBOSE : 0)
+ | (trace ? RUN_ENGINE_TRACE : 0)) != 0)
+ {
+ goto client_exit_error;
+ } else {
+ goto client_exit;
+ }
+
+ /*
+ * Release allocated structures.
+ */
+client_exit:
+ xfree(host);
+ xfree(port);
+ xfree(suites);
+ xfree(suite_ids);
+ VEC_CLEAREXT(anchors, &free_ta_contents);
+ VEC_CLEAREXT(alpn_names, &free_alpn);
+ free_certificates(chain, chain_len);
+ free_private_key(sk);
+ xfree(iobuf);
+ if (fd != INVALID_SOCKET) {
+#ifdef _WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ }
+ return retcode;
+
+client_exit_error:
+ retcode = -1;
+ goto client_exit;
+}
Property changes on: stable/12/contrib/bearssl/tools/client.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/errors.c
===================================================================
--- stable/12/contrib/bearssl/tools/errors.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/errors.c (revision 346145)
@@ -0,0 +1,344 @@
+/*
+ * 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 "brssl.h"
+#include "bearssl.h"
+
+static struct {
+ int err;
+ const char *name;
+ const char *comment;
+} errors[] = {
+ {
+ BR_ERR_BAD_PARAM,
+ "BR_ERR_BAD_PARAM",
+ "Caller-provided parameter is incorrect."
+ }, {
+ BR_ERR_BAD_STATE,
+ "BR_ERR_BAD_STATE",
+ "Operation requested by the caller cannot be applied with"
+ " the current context state (e.g. reading data while"
+ " outgoing data is waiting to be sent)."
+ }, {
+ BR_ERR_UNSUPPORTED_VERSION,
+ "BR_ERR_UNSUPPORTED_VERSION",
+ "Incoming protocol or record version is unsupported."
+ }, {
+ BR_ERR_BAD_VERSION,
+ "BR_ERR_BAD_VERSION",
+ "Incoming record version does not match the expected version."
+ }, {
+ BR_ERR_BAD_LENGTH,
+ "BR_ERR_BAD_LENGTH",
+ "Incoming record length is invalid."
+ }, {
+ BR_ERR_TOO_LARGE,
+ "BR_ERR_TOO_LARGE",
+ "Incoming record is too large to be processed, or buffer"
+ " is too small for the handshake message to send."
+ }, {
+ BR_ERR_BAD_MAC,
+ "BR_ERR_BAD_MAC",
+ "Decryption found an invalid padding, or the record MAC is"
+ " not correct."
+ }, {
+ BR_ERR_NO_RANDOM,
+ "BR_ERR_NO_RANDOM",
+ "No initial entropy was provided, and none can be obtained"
+ " from the OS."
+ }, {
+ BR_ERR_UNKNOWN_TYPE,
+ "BR_ERR_UNKNOWN_TYPE",
+ "Incoming record type is unknown."
+ }, {
+ BR_ERR_UNEXPECTED,
+ "BR_ERR_UNEXPECTED",
+ "Incoming record or message has wrong type with regards to"
+ " the current engine state."
+ }, {
+ BR_ERR_BAD_CCS,
+ "BR_ERR_BAD_CCS",
+ "ChangeCipherSpec message from the peer has invalid contents."
+ }, {
+ BR_ERR_BAD_ALERT,
+ "BR_ERR_BAD_ALERT",
+ "Alert message from the peer has invalid contents"
+ " (odd length)."
+ }, {
+ BR_ERR_BAD_HANDSHAKE,
+ "BR_ERR_BAD_HANDSHAKE",
+ "Incoming handshake message decoding failed."
+ }, {
+ BR_ERR_OVERSIZED_ID,
+ "BR_ERR_OVERSIZED_ID",
+ "ServerHello contains a session ID which is larger than"
+ " 32 bytes."
+ }, {
+ BR_ERR_BAD_CIPHER_SUITE,
+ "BR_ERR_BAD_CIPHER_SUITE",
+ "Server wants to use a cipher suite that we did not claim"
+ " to support. This is also reported if we tried to advertise"
+ " a cipher suite that we do not support."
+ }, {
+ BR_ERR_BAD_COMPRESSION,
+ "BR_ERR_BAD_COMPRESSION",
+ "Server wants to use a compression that we did not claim"
+ " to support."
+ }, {
+ BR_ERR_BAD_FRAGLEN,
+ "BR_ERR_BAD_FRAGLEN",
+ "Server's max fragment length does not match client's."
+ }, {
+ BR_ERR_BAD_SECRENEG,
+ "BR_ERR_BAD_SECRENEG",
+ "Secure renegotiation failed."
+ }, {
+ BR_ERR_EXTRA_EXTENSION,
+ "BR_ERR_EXTRA_EXTENSION",
+ "Server sent an extension type that we did not announce,"
+ " or used the same extension type several times in a"
+ " single ServerHello."
+ }, {
+ BR_ERR_BAD_SNI,
+ "BR_ERR_BAD_SNI",
+ "Invalid Server Name Indication contents (when used by"
+ " the server, this extension shall be empty)."
+ }, {
+ BR_ERR_BAD_HELLO_DONE,
+ "BR_ERR_BAD_HELLO_DONE",
+ "Invalid ServerHelloDone from the server (length is not 0)."
+ }, {
+ BR_ERR_LIMIT_EXCEEDED,
+ "BR_ERR_LIMIT_EXCEEDED",
+ "Internal limit exceeded (e.g. server's public key is too"
+ " large)."
+ }, {
+ BR_ERR_BAD_FINISHED,
+ "BR_ERR_BAD_FINISHED",
+ "Finished message from peer does not match the expected"
+ " value."
+ }, {
+ BR_ERR_RESUME_MISMATCH,
+ "BR_ERR_RESUME_MISMATCH",
+ "Session resumption attempt with distinct version or cipher"
+ " suite."
+ }, {
+ BR_ERR_INVALID_ALGORITHM,
+ "BR_ERR_INVALID_ALGORITHM",
+ "Unsupported or invalid algorithm (ECDHE curve, signature"
+ " algorithm, hash function)."
+ }, {
+ BR_ERR_BAD_SIGNATURE,
+ "BR_ERR_BAD_SIGNATURE",
+ "Invalid signature in ServerKeyExchange or"
+ " CertificateVerify message."
+ }, {
+ BR_ERR_WRONG_KEY_USAGE,
+ "BR_ERR_WRONG_KEY_USAGE",
+ "Peer's public key does not have the proper type or is"
+ " not allowed for the requested operation."
+ }, {
+ BR_ERR_NO_CLIENT_AUTH,
+ "BR_ERR_NO_CLIENT_AUTH",
+ "Client did not send a certificate upon request, or the"
+ " client certificate could not be validated."
+ }, {
+ BR_ERR_IO,
+ "BR_ERR_IO",
+ "I/O error or premature close on transport stream."
+ }, {
+ BR_ERR_X509_INVALID_VALUE,
+ "BR_ERR_X509_INVALID_VALUE",
+ "Invalid value in an ASN.1 structure."
+ },
+ {
+ BR_ERR_X509_TRUNCATED,
+ "BR_ERR_X509_TRUNCATED",
+ "Truncated certificate or other ASN.1 object."
+ },
+ {
+ BR_ERR_X509_EMPTY_CHAIN,
+ "BR_ERR_X509_EMPTY_CHAIN",
+ "Empty certificate chain (no certificate at all)."
+ },
+ {
+ BR_ERR_X509_INNER_TRUNC,
+ "BR_ERR_X509_INNER_TRUNC",
+ "Decoding error: inner element extends beyond outer element"
+ " size."
+ },
+ {
+ BR_ERR_X509_BAD_TAG_CLASS,
+ "BR_ERR_X509_BAD_TAG_CLASS",
+ "Decoding error: unsupported tag class (application or"
+ " private)."
+ },
+ {
+ BR_ERR_X509_BAD_TAG_VALUE,
+ "BR_ERR_X509_BAD_TAG_VALUE",
+ "Decoding error: unsupported tag value."
+ },
+ {
+ BR_ERR_X509_INDEFINITE_LENGTH,
+ "BR_ERR_X509_INDEFINITE_LENGTH",
+ "Decoding error: indefinite length."
+ },
+ {
+ BR_ERR_X509_EXTRA_ELEMENT,
+ "BR_ERR_X509_EXTRA_ELEMENT",
+ "Decoding error: extraneous element."
+ },
+ {
+ BR_ERR_X509_UNEXPECTED,
+ "BR_ERR_X509_UNEXPECTED",
+ "Decoding error: unexpected element."
+ },
+ {
+ BR_ERR_X509_NOT_CONSTRUCTED,
+ "BR_ERR_X509_NOT_CONSTRUCTED",
+ "Decoding error: expected constructed element, but is"
+ " primitive."
+ },
+ {
+ BR_ERR_X509_NOT_PRIMITIVE,
+ "BR_ERR_X509_NOT_PRIMITIVE",
+ "Decoding error: expected primitive element, but is"
+ " constructed."
+ },
+ {
+ BR_ERR_X509_PARTIAL_BYTE,
+ "BR_ERR_X509_PARTIAL_BYTE",
+ "Decoding error: BIT STRING length is not multiple of 8."
+ },
+ {
+ BR_ERR_X509_BAD_BOOLEAN,
+ "BR_ERR_X509_BAD_BOOLEAN",
+ "Decoding error: BOOLEAN value has invalid length."
+ },
+ {
+ BR_ERR_X509_OVERFLOW,
+ "BR_ERR_X509_OVERFLOW",
+ "Decoding error: value is off-limits."
+ },
+ {
+ BR_ERR_X509_BAD_DN,
+ "BR_ERR_X509_BAD_DN",
+ "Invalid distinguished name."
+ },
+ {
+ BR_ERR_X509_BAD_TIME,
+ "BR_ERR_X509_BAD_TIME",
+ "Invalid date/time representation."
+ },
+ {
+ BR_ERR_X509_UNSUPPORTED,
+ "BR_ERR_X509_UNSUPPORTED",
+ "Certificate contains unsupported features that cannot be"
+ " ignored."
+ },
+ {
+ BR_ERR_X509_LIMIT_EXCEEDED,
+ "BR_ERR_X509_LIMIT_EXCEEDED",
+ "Key or signature size exceeds internal limits."
+ },
+ {
+ BR_ERR_X509_WRONG_KEY_TYPE,
+ "BR_ERR_X509_WRONG_KEY_TYPE",
+ "Key type does not match that which was expected."
+ },
+ {
+ BR_ERR_X509_BAD_SIGNATURE,
+ "BR_ERR_X509_BAD_SIGNATURE",
+ "Signature is invalid."
+ },
+ {
+ BR_ERR_X509_TIME_UNKNOWN,
+ "BR_ERR_X509_TIME_UNKNOWN",
+ "Validation time is unknown."
+ },
+ {
+ BR_ERR_X509_EXPIRED,
+ "BR_ERR_X509_EXPIRED",
+ "Certificate is expired or not yet valid."
+ },
+ {
+ BR_ERR_X509_DN_MISMATCH,
+ "BR_ERR_X509_DN_MISMATCH",
+ "Issuer/Subject DN mismatch in the chain."
+ },
+ {
+ BR_ERR_X509_BAD_SERVER_NAME,
+ "BR_ERR_X509_BAD_SERVER_NAME",
+ "Expected server name was not found in the chain."
+ },
+ {
+ BR_ERR_X509_CRITICAL_EXTENSION,
+ "BR_ERR_X509_CRITICAL_EXTENSION",
+ "Unknown critical extension in certificate."
+ },
+ {
+ BR_ERR_X509_NOT_CA,
+ "BR_ERR_X509_NOT_CA",
+ "Not a CA, or path length constraint violation."
+ },
+ {
+ BR_ERR_X509_FORBIDDEN_KEY_USAGE,
+ "BR_ERR_X509_FORBIDDEN_KEY_USAGE",
+ "Key Usage extension prohibits intended usage."
+ },
+ {
+ BR_ERR_X509_WEAK_PUBLIC_KEY,
+ "BR_ERR_X509_WEAK_PUBLIC_KEY",
+ "Public key found in certificate is too small."
+ },
+ {
+ BR_ERR_X509_NOT_TRUSTED,
+ "BR_ERR_X509_NOT_TRUSTED",
+ "Chain could not be linked to a trust anchor."
+ },
+ { 0, 0, 0 }
+};
+
+/* see brssl.h */
+const char *
+find_error_name(int err, const char **comment)
+{
+ size_t u;
+
+ for (u = 0; errors[u].name; u ++) {
+ if (errors[u].err == err) {
+ if (comment != NULL) {
+ *comment = errors[u].comment;
+ }
+ return errors[u].name;
+ }
+ }
+ return NULL;
+}
Property changes on: stable/12/contrib/bearssl/tools/errors.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/files.c
===================================================================
--- stable/12/contrib/bearssl/tools/files.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/files.c (revision 346145)
@@ -0,0 +1,329 @@
+/*
+ * 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 "brssl.h"
+
+/* see brssl.h */
+unsigned char *
+read_file(const char *fname, size_t *len)
+{
+ bvector vbuf = VEC_INIT;
+ FILE *f;
+
+ *len = 0;
+ f = fopen(fname, "rb");
+ if (f == NULL) {
+ fprintf(stderr,
+ "ERROR: could not open file '%s' for reading\n", fname);
+ return NULL;
+ }
+ for (;;) {
+ unsigned char tmp[1024];
+ size_t rlen;
+
+ rlen = fread(tmp, 1, sizeof tmp, f);
+ if (rlen == 0) {
+ unsigned char *buf;
+
+ if (ferror(f)) {
+ fprintf(stderr,
+ "ERROR: read error on file '%s'\n",
+ fname);
+ fclose(f);
+ return NULL;
+ }
+ buf = VEC_TOARRAY(vbuf);
+ *len = VEC_LEN(vbuf);
+ VEC_CLEAR(vbuf);
+ fclose(f);
+ return buf;
+ }
+ VEC_ADDMANY(vbuf, tmp, rlen);
+ }
+}
+
+/* see brssl.h */
+int
+write_file(const char *fname, const void *data, size_t len)
+{
+ FILE *f;
+ const unsigned char *buf;
+
+ f = fopen(fname, "wb");
+ if (f == NULL) {
+ fprintf(stderr,
+ "ERROR: could not open file '%s' for reading\n", fname);
+ return -1;
+ }
+ buf = data;
+ while (len > 0) {
+ size_t wlen;
+
+ wlen = fwrite(buf, 1, len, f);
+ if (wlen == 0) {
+ fprintf(stderr,
+ "ERROR: could not write all bytes to '%s'\n",
+ fname);
+ fclose(f);
+ return -1;
+ }
+ buf += wlen;
+ len -= wlen;
+ }
+ if (ferror(f)) {
+ fprintf(stderr, "ERROR: write error on file '%s'\n", fname);
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ return 0;
+}
+
+/* see brssl.h */
+int
+looks_like_DER(const unsigned char *buf, size_t len)
+{
+ int fb;
+ size_t dlen;
+
+ if (len < 2) {
+ return 0;
+ }
+ if (*buf ++ != 0x30) {
+ return 0;
+ }
+ fb = *buf ++;
+ len -= 2;
+ if (fb < 0x80) {
+ return (size_t)fb == len;
+ } else if (fb == 0x80) {
+ return 0;
+ } else {
+ fb -= 0x80;
+ if (len < (size_t)fb + 2) {
+ return 0;
+ }
+ len -= (size_t)fb;
+ dlen = 0;
+ while (fb -- > 0) {
+ if (dlen > (len >> 8)) {
+ return 0;
+ }
+ dlen = (dlen << 8) + (size_t)*buf ++;
+ }
+ return dlen == len;
+ }
+}
+
+static void
+vblob_append(void *cc, const void *data, size_t len)
+{
+ bvector *bv;
+
+ bv = cc;
+ VEC_ADDMANY(*bv, data, len);
+}
+
+/* see brssl.h */
+void
+free_pem_object_contents(pem_object *po)
+{
+ if (po != NULL) {
+ xfree(po->name);
+ xfree(po->data);
+ }
+}
+
+/* see brssl.h */
+pem_object *
+decode_pem(const void *src, size_t len, size_t *num)
+{
+ VECTOR(pem_object) pem_list = VEC_INIT;
+ br_pem_decoder_context pc;
+ pem_object po, *pos;
+ const unsigned char *buf;
+ bvector bv = VEC_INIT;
+ int inobj;
+ int extra_nl;
+
+ *num = 0;
+ br_pem_decoder_init(&pc);
+ buf = src;
+ inobj = 0;
+ po.name = NULL;
+ po.data = NULL;
+ po.data_len = 0;
+ extra_nl = 1;
+ while (len > 0) {
+ size_t tlen;
+
+ tlen = br_pem_decoder_push(&pc, buf, len);
+ buf += tlen;
+ len -= tlen;
+ switch (br_pem_decoder_event(&pc)) {
+
+ case BR_PEM_BEGIN_OBJ:
+ po.name = xstrdup(br_pem_decoder_name(&pc));
+ br_pem_decoder_setdest(&pc, vblob_append, &bv);
+ inobj = 1;
+ break;
+
+ case BR_PEM_END_OBJ:
+ if (inobj) {
+ po.data = VEC_TOARRAY(bv);
+ po.data_len = VEC_LEN(bv);
+ VEC_ADD(pem_list, po);
+ VEC_CLEAR(bv);
+ po.name = NULL;
+ po.data = NULL;
+ po.data_len = 0;
+ inobj = 0;
+ }
+ break;
+
+ case BR_PEM_ERROR:
+ xfree(po.name);
+ VEC_CLEAR(bv);
+ fprintf(stderr,
+ "ERROR: invalid PEM encoding\n");
+ VEC_CLEAREXT(pem_list, &free_pem_object_contents);
+ return NULL;
+ }
+
+ /*
+ * We add an extra newline at the end, in order to
+ * support PEM files that lack the newline on their last
+ * line (this is somwehat invalid, but PEM format is not
+ * standardised and such files do exist in the wild, so
+ * we'd better accept them).
+ */
+ if (len == 0 && extra_nl) {
+ extra_nl = 0;
+ buf = (const unsigned char *)"\n";
+ len = 1;
+ }
+ }
+ if (inobj) {
+ fprintf(stderr, "ERROR: unfinished PEM object\n");
+ xfree(po.name);
+ VEC_CLEAR(bv);
+ VEC_CLEAREXT(pem_list, &free_pem_object_contents);
+ return NULL;
+ }
+
+ *num = VEC_LEN(pem_list);
+ VEC_ADD(pem_list, po);
+ pos = VEC_TOARRAY(pem_list);
+ VEC_CLEAR(pem_list);
+ return pos;
+}
+
+/* see brssl.h */
+br_x509_certificate *
+read_certificates(const char *fname, size_t *num)
+{
+ VECTOR(br_x509_certificate) cert_list = VEC_INIT;
+ unsigned char *buf;
+ size_t len;
+ pem_object *pos;
+ size_t u, num_pos;
+ br_x509_certificate *xcs;
+ br_x509_certificate dummy;
+
+ *num = 0;
+
+ /*
+ * TODO: reading the whole file is crude; we could parse them
+ * in a streamed fashion. But it does not matter much in practice.
+ */
+ buf = read_file(fname, &len);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Check for a DER-encoded certificate.
+ */
+ if (looks_like_DER(buf, len)) {
+ xcs = xmalloc(2 * sizeof *xcs);
+ xcs[0].data = buf;
+ xcs[0].data_len = len;
+ xcs[1].data = NULL;
+ xcs[1].data_len = 0;
+ *num = 1;
+ return xcs;
+ }
+
+ pos = decode_pem(buf, len, &num_pos);
+ xfree(buf);
+ if (pos == NULL) {
+ return NULL;
+ }
+ for (u = 0; u < num_pos; u ++) {
+ if (eqstr(pos[u].name, "CERTIFICATE")
+ || eqstr(pos[u].name, "X509 CERTIFICATE"))
+ {
+ br_x509_certificate xc;
+
+ xc.data = pos[u].data;
+ xc.data_len = pos[u].data_len;
+ pos[u].data = NULL;
+ VEC_ADD(cert_list, xc);
+ }
+ }
+ for (u = 0; u < num_pos; u ++) {
+ free_pem_object_contents(&pos[u]);
+ }
+ xfree(pos);
+
+ if (VEC_LEN(cert_list) == 0) {
+ fprintf(stderr, "ERROR: no certificate in file '%s'\n", fname);
+ return NULL;
+ }
+ *num = VEC_LEN(cert_list);
+ dummy.data = NULL;
+ dummy.data_len = 0;
+ VEC_ADD(cert_list, dummy);
+ xcs = VEC_TOARRAY(cert_list);
+ VEC_CLEAR(cert_list);
+ return xcs;
+}
+
+/* see brssl.h */
+void
+free_certificates(br_x509_certificate *certs, size_t num)
+{
+ size_t u;
+
+ for (u = 0; u < num; u ++) {
+ xfree(certs[u].data);
+ }
+ xfree(certs);
+}
Property changes on: stable/12/contrib/bearssl/tools/files.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/impl.c
===================================================================
--- stable/12/contrib/bearssl/tools/impl.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/impl.c (revision 346145)
@@ -0,0 +1,48 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include "brssl.h"
+#include "bearssl.h"
+
+/* see brssl.h */
+int
+do_impl(int argc, char *argv[])
+{
+ const br_config_option *opt;
+
+ (void)argc;
+ (void)argv;
+
+ for (opt = br_get_config(); opt->name != NULL; opt ++) {
+ printf("%-25s %8ld\n", opt->name, opt->value);
+ }
+
+ return 0;
+}
Property changes on: stable/12/contrib/bearssl/tools/impl.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/keys.c
===================================================================
--- stable/12/contrib/bearssl/tools/keys.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/keys.c (revision 346145)
@@ -0,0 +1,234 @@
+/*
+ * 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 "brssl.h"
+#include "bearssl.h"
+
+static private_key *
+decode_key(const unsigned char *buf, size_t len)
+{
+ br_skey_decoder_context dc;
+ int err;
+ private_key *sk;
+
+ br_skey_decoder_init(&dc);
+ br_skey_decoder_push(&dc, buf, len);
+ err = br_skey_decoder_last_error(&dc);
+ if (err != 0) {
+ const char *errname, *errmsg;
+
+ fprintf(stderr, "ERROR (decoding): err=%d\n", err);
+ errname = find_error_name(err, &errmsg);
+ if (errname != NULL) {
+ fprintf(stderr, " %s: %s\n", errname, errmsg);
+ } else {
+ fprintf(stderr, " (unknown)\n");
+ }
+ return NULL;
+ }
+ switch (br_skey_decoder_key_type(&dc)) {
+ const br_rsa_private_key *rk;
+ const br_ec_private_key *ek;
+
+ case BR_KEYTYPE_RSA:
+ rk = br_skey_decoder_get_rsa(&dc);
+ sk = xmalloc(sizeof *sk);
+ sk->key_type = BR_KEYTYPE_RSA;
+ sk->key.rsa.n_bitlen = rk->n_bitlen;
+ sk->key.rsa.p = xblobdup(rk->p, rk->plen);
+ sk->key.rsa.plen = rk->plen;
+ sk->key.rsa.q = xblobdup(rk->q, rk->qlen);
+ sk->key.rsa.qlen = rk->qlen;
+ sk->key.rsa.dp = xblobdup(rk->dp, rk->dplen);
+ sk->key.rsa.dplen = rk->dplen;
+ sk->key.rsa.dq = xblobdup(rk->dq, rk->dqlen);
+ sk->key.rsa.dqlen = rk->dqlen;
+ sk->key.rsa.iq = xblobdup(rk->iq, rk->iqlen);
+ sk->key.rsa.iqlen = rk->iqlen;
+ break;
+
+ case BR_KEYTYPE_EC:
+ ek = br_skey_decoder_get_ec(&dc);
+ sk = xmalloc(sizeof *sk);
+ sk->key_type = BR_KEYTYPE_EC;
+ sk->key.ec.curve = ek->curve;
+ sk->key.ec.x = xblobdup(ek->x, ek->xlen);
+ sk->key.ec.xlen = ek->xlen;
+ break;
+
+ default:
+ fprintf(stderr, "Unknown key type: %d\n",
+ br_skey_decoder_key_type(&dc));
+ sk = NULL;
+ break;
+ }
+
+ return sk;
+}
+
+/* see brssl.h */
+private_key *
+read_private_key(const char *fname)
+{
+ unsigned char *buf;
+ size_t len;
+ private_key *sk;
+ pem_object *pos;
+ size_t num, u;
+
+ buf = NULL;
+ pos = NULL;
+ sk = NULL;
+ buf = read_file(fname, &len);
+ if (buf == NULL) {
+ goto deckey_exit;
+ }
+ if (looks_like_DER(buf, len)) {
+ sk = decode_key(buf, len);
+ goto deckey_exit;
+ } else {
+ pos = decode_pem(buf, len, &num);
+ if (pos == NULL) {
+ goto deckey_exit;
+ }
+ for (u = 0; pos[u].name; u ++) {
+ const char *name;
+
+ name = pos[u].name;
+ if (eqstr(name, "RSA PRIVATE KEY")
+ || eqstr(name, "EC PRIVATE KEY")
+ || eqstr(name, "PRIVATE KEY"))
+ {
+ sk = decode_key(pos[u].data, pos[u].data_len);
+ goto deckey_exit;
+ }
+ }
+ fprintf(stderr, "ERROR: no private key in file '%s'\n", fname);
+ goto deckey_exit;
+ }
+
+deckey_exit:
+ if (buf != NULL) {
+ xfree(buf);
+ }
+ if (pos != NULL) {
+ for (u = 0; pos[u].name; u ++) {
+ free_pem_object_contents(&pos[u]);
+ }
+ xfree(pos);
+ }
+ return sk;
+}
+
+/* see brssl.h */
+void
+free_private_key(private_key *sk)
+{
+ if (sk == NULL) {
+ return;
+ }
+ switch (sk->key_type) {
+ case BR_KEYTYPE_RSA:
+ xfree(sk->key.rsa.p);
+ xfree(sk->key.rsa.q);
+ xfree(sk->key.rsa.dp);
+ xfree(sk->key.rsa.dq);
+ xfree(sk->key.rsa.iq);
+ break;
+ case BR_KEYTYPE_EC:
+ xfree(sk->key.ec.x);
+ break;
+ }
+ xfree(sk);
+}
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+ 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+ HASH_OID_SHA1,
+ HASH_OID_SHA224,
+ HASH_OID_SHA256,
+ HASH_OID_SHA384,
+ HASH_OID_SHA512
+};
+
+/* see brssl.h */
+const unsigned char *
+get_hash_oid(int id)
+{
+ if (id >= 2 && id <= 6) {
+ return HASH_OID[id - 2];
+ } else {
+ return NULL;
+ }
+}
+
+/* see brssl.h */
+const br_hash_class *
+get_hash_impl(int hash_id)
+{
+ size_t u;
+
+ if (hash_id == 0) {
+ return &br_md5sha1_vtable;
+ }
+ for (u = 0; hash_functions[u].name; u ++) {
+ const br_hash_class *hc;
+ int id;
+
+ hc = hash_functions[u].hclass;
+ id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
+ if (id == hash_id) {
+ return hc;
+ }
+ }
+ return NULL;
+}
Property changes on: stable/12/contrib/bearssl/tools/keys.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/names.c
===================================================================
--- stable/12/contrib/bearssl/tools/names.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/names.c (revision 346145)
@@ -0,0 +1,1056 @@
+/*
+ * 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 "brssl.h"
+#include "bearssl.h"
+
+/* see brssl.h */
+const protocol_version protocol_versions[] = {
+ { "tls10", BR_TLS10, "TLS 1.0" },
+ { "tls11", BR_TLS11, "TLS 1.1" },
+ { "tls12", BR_TLS12, "TLS 1.2" },
+ { NULL, 0, NULL }
+};
+
+/* see brssl.h */
+const hash_function hash_functions[] = {
+ { "md5", &br_md5_vtable, "MD5" },
+ { "sha1", &br_sha1_vtable, "SHA-1" },
+ { "sha224", &br_sha224_vtable, "SHA-224" },
+ { "sha256", &br_sha256_vtable, "SHA-256" },
+ { "sha384", &br_sha384_vtable, "SHA-384" },
+ { "sha512", &br_sha512_vtable, "SHA-512" },
+ { NULL, 0, NULL }
+};
+
+/* see brssl.h */
+const cipher_suite cipher_suites[] = {
+ {
+ "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ REQ_ECDHE_ECDSA | REQ_CHAPOL | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with ECDSA, ChaCha20+Poly1305 encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ REQ_ECDHE_RSA | REQ_CHAPOL | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with RSA, ChaCha20+Poly1305 encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ REQ_ECDHE_ECDSA | REQ_AESGCM | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-128/GCM encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ REQ_ECDHE_RSA | REQ_AESGCM | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with RSA, AES-128/GCM encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ REQ_ECDHE_ECDSA | REQ_AESGCM | REQ_SHA384 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-256/GCM encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ REQ_ECDHE_RSA | REQ_AESGCM | REQ_SHA384 | REQ_TLS12,
+ "ECDHE with RSA, AES-256/GCM encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_128_CCM",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
+ REQ_ECDHE_ECDSA | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-128/CCM encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_256_CCM",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
+ REQ_ECDHE_ECDSA | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-256/CCM encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_128_CCM_8",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ REQ_ECDHE_ECDSA | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-128/CCM_8 encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_256_CCM_8",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
+ REQ_ECDHE_ECDSA | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-256/CCM_8 encryption (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ REQ_ECDHE_ECDSA | REQ_AESCBC | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-128/CBC + SHA-256 (TLS 1.2+)"
+ },
+ {
+ "ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+ BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ REQ_ECDHE_RSA | REQ_AESCBC | REQ_SHA256 | REQ_TLS12,
+ "ECDHE with RSA, AES-128/CBC + SHA-256 (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ REQ_ECDHE_ECDSA | REQ_AESCBC | REQ_SHA384 | REQ_TLS12,
+ "ECDHE with ECDSA, AES-256/CBC + SHA-384 (TLS 1.2+)"
+ },
+ {
+ "ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+ BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ REQ_ECDHE_RSA | REQ_AESCBC | REQ_SHA384 | REQ_TLS12,
+ "ECDHE with RSA, AES-256/CBC + SHA-384 (TLS 1.2+)"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ REQ_ECDHE_ECDSA | REQ_AESCBC | REQ_SHA1,
+ "ECDHE with ECDSA, AES-128/CBC + SHA-1"
+ },
+ {
+ "ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ REQ_ECDHE_RSA | REQ_AESCBC | REQ_SHA1,
+ "ECDHE with RSA, AES-128/CBC + SHA-1"
+ },
+ {
+ "ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ REQ_ECDHE_ECDSA | REQ_AESCBC | REQ_SHA1,
+ "ECDHE with ECDSA, AES-256/CBC + SHA-1"
+ },
+ {
+ "ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ REQ_ECDHE_RSA | REQ_AESCBC | REQ_SHA1,
+ "ECDHE with RSA, AES-256/CBC + SHA-1"
+ },
+ {
+ "ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+ BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ REQ_ECDH | REQ_AESGCM | REQ_SHA256 | REQ_TLS12,
+ "ECDH key exchange (EC cert), AES-128/GCM (TLS 1.2+)"
+ },
+ {
+ "ECDH_RSA_WITH_AES_128_GCM_SHA256",
+ BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ REQ_ECDH | REQ_AESGCM | REQ_SHA256 | REQ_TLS12,
+ "ECDH key exchange (RSA cert), AES-128/GCM (TLS 1.2+)"
+ },
+ {
+ "ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+ BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ REQ_ECDH | REQ_AESGCM | REQ_SHA384 | REQ_TLS12,
+ "ECDH key exchange (EC cert), AES-256/GCM (TLS 1.2+)"
+ },
+ {
+ "ECDH_RSA_WITH_AES_256_GCM_SHA384",
+ BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+ REQ_ECDH | REQ_AESGCM | REQ_SHA384 | REQ_TLS12,
+ "ECDH key exchange (RSA cert), AES-256/GCM (TLS 1.2+)"
+ },
+ {
+ "ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+ BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA256 | REQ_TLS12,
+ "ECDH key exchange (EC cert), AES-128/CBC + HMAC/SHA-256 (TLS 1.2+)"
+ },
+ {
+ "ECDH_RSA_WITH_AES_128_CBC_SHA256",
+ BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA256 | REQ_TLS12,
+ "ECDH key exchange (RSA cert), AES-128/CBC + HMAC/SHA-256 (TLS 1.2+)"
+ },
+ {
+ "ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
+ BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA384 | REQ_TLS12,
+ "ECDH key exchange (EC cert), AES-256/CBC + HMAC/SHA-384 (TLS 1.2+)"
+ },
+ {
+ "ECDH_RSA_WITH_AES_256_CBC_SHA384",
+ BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA384 | REQ_TLS12,
+ "ECDH key exchange (RSA cert), AES-256/CBC + HMAC/SHA-384 (TLS 1.2+)"
+ },
+ {
+ "ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+ BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA1,
+ "ECDH key exchange (EC cert), AES-128/CBC + HMAC/SHA-1"
+ },
+ {
+ "ECDH_RSA_WITH_AES_128_CBC_SHA",
+ BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA1,
+ "ECDH key exchange (RSA cert), AES-128/CBC + HMAC/SHA-1"
+ },
+ {
+ "ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA1,
+ "ECDH key exchange (EC cert), AES-256/CBC + HMAC/SHA-1"
+ },
+ {
+ "ECDH_RSA_WITH_AES_256_CBC_SHA",
+ BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+ REQ_ECDH | REQ_AESCBC | REQ_SHA1,
+ "ECDH key exchange (RSA cert), AES-256/CBC + HMAC/SHA-1"
+ },
+ {
+ "RSA_WITH_AES_128_GCM_SHA256",
+ BR_TLS_RSA_WITH_AES_128_GCM_SHA256,
+ REQ_RSAKEYX | REQ_AESGCM | REQ_SHA256 | REQ_TLS12,
+ "RSA key exchange, AES-128/GCM encryption (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_256_GCM_SHA384",
+ BR_TLS_RSA_WITH_AES_256_GCM_SHA384,
+ REQ_RSAKEYX | REQ_AESGCM | REQ_SHA384 | REQ_TLS12,
+ "RSA key exchange, AES-256/GCM encryption (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_128_CCM",
+ BR_TLS_RSA_WITH_AES_128_CCM,
+ REQ_RSAKEYX | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "RSA key exchange, AES-128/CCM encryption (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_256_CCM",
+ BR_TLS_RSA_WITH_AES_256_CCM,
+ REQ_RSAKEYX | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "RSA key exchange, AES-256/CCM encryption (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_128_CCM_8",
+ BR_TLS_RSA_WITH_AES_128_CCM_8,
+ REQ_RSAKEYX | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "RSA key exchange, AES-128/CCM_8 encryption (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_256_CCM_8",
+ BR_TLS_RSA_WITH_AES_256_CCM_8,
+ REQ_RSAKEYX | REQ_AESCCM | REQ_SHA256 | REQ_TLS12,
+ "RSA key exchange, AES-256/CCM_8 encryption (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_128_CBC_SHA256",
+ BR_TLS_RSA_WITH_AES_128_CBC_SHA256,
+ REQ_RSAKEYX | REQ_AESCBC | REQ_SHA256 | REQ_TLS12,
+ "RSA key exchange, AES-128/CBC + HMAC/SHA-256 (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_256_CBC_SHA256",
+ BR_TLS_RSA_WITH_AES_256_CBC_SHA256,
+ REQ_RSAKEYX | REQ_AESCBC | REQ_SHA256 | REQ_TLS12,
+ "RSA key exchange, AES-256/CBC + HMAC/SHA-256 (TLS 1.2+)"
+ },
+ {
+ "RSA_WITH_AES_128_CBC_SHA",
+ BR_TLS_RSA_WITH_AES_128_CBC_SHA,
+ REQ_RSAKEYX | REQ_AESCBC | REQ_SHA1,
+ "RSA key exchange, AES-128/CBC + HMAC/SHA-1"
+ },
+ {
+ "RSA_WITH_AES_256_CBC_SHA",
+ BR_TLS_RSA_WITH_AES_256_CBC_SHA,
+ REQ_RSAKEYX | REQ_AESCBC | REQ_SHA1,
+ "RSA key exchange, AES-256/CBC + HMAC/SHA-1"
+ },
+ {
+ "ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ REQ_ECDHE_ECDSA | REQ_3DESCBC | REQ_SHA1,
+ "ECDHE with ECDSA, 3DES/CBC + SHA-1"
+ },
+ {
+ "ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ REQ_ECDHE_RSA | REQ_3DESCBC | REQ_SHA1,
+ "ECDHE with RSA, 3DES/CBC + SHA-1"
+ },
+ {
+ "ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ REQ_ECDH | REQ_3DESCBC | REQ_SHA1,
+ "ECDH key exchange (EC cert), 3DES/CBC + HMAC/SHA-1"
+ },
+ {
+ "ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+ BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ REQ_ECDH | REQ_3DESCBC | REQ_SHA1,
+ "ECDH key exchange (RSA cert), 3DES/CBC + HMAC/SHA-1"
+ },
+ {
+ "RSA_WITH_3DES_EDE_CBC_SHA",
+ BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ REQ_RSAKEYX | REQ_3DESCBC | REQ_SHA1,
+ "RSA key exchange, 3DES/CBC + HMAC/SHA-1"
+ },
+ { NULL, 0, 0, NULL }
+};
+
+static const struct {
+ int id;
+ const char *name;
+ const char *sid[4];
+} curves[] = {
+ { BR_EC_sect163k1,
+ "sect163k1",
+ { "sect163k1", "K-163", NULL, NULL } },
+ { BR_EC_sect163r1,
+ "sect163r1",
+ { "sect163r1", NULL, NULL, NULL } },
+ { BR_EC_sect163r2,
+ "sect163r2",
+ { "sect163r2", "B-163", NULL, NULL } },
+ { BR_EC_sect193r1,
+ "sect193r1",
+ { "sect193r1", NULL, NULL, NULL } },
+ { BR_EC_sect193r2,
+ "sect193r2",
+ { "sect193r2", NULL, NULL, NULL } },
+ { BR_EC_sect233k1,
+ "sect233k1",
+ { "sect233k1", "K-233", NULL, NULL } },
+ { BR_EC_sect233r1,
+ "sect233r1",
+ { "sect233r1", "B-233", NULL, NULL } },
+ { BR_EC_sect239k1,
+ "sect239k1",
+ { "sect239k1", NULL, NULL, NULL } },
+ { BR_EC_sect283k1,
+ "sect283k1",
+ { "sect283k1", "K-283", NULL, NULL } },
+ { BR_EC_sect283r1,
+ "sect283r1",
+ { "sect283r1", "B-283", NULL, NULL } },
+ { BR_EC_sect409k1,
+ "sect409k1",
+ { "sect409k1", "K-409", NULL, NULL } },
+ { BR_EC_sect409r1,
+ "sect409r1",
+ { "sect409r1", "B-409", NULL, NULL } },
+ { BR_EC_sect571k1,
+ "sect571k1",
+ { "sect571k1", "K-571", NULL, NULL } },
+ { BR_EC_sect571r1,
+ "sect571r1",
+ { "sect571r1", "B-571", NULL, NULL } },
+ { BR_EC_secp160k1,
+ "secp160k1",
+ { "secp160k1", NULL, NULL, NULL } },
+ { BR_EC_secp160r1,
+ "secp160r1",
+ { "secp160r1", NULL, NULL, NULL } },
+ { BR_EC_secp160r2,
+ "secp160r2",
+ { "secp160r2", NULL, NULL, NULL } },
+ { BR_EC_secp192k1,
+ "secp192k1",
+ { "secp192k1", NULL, NULL, NULL } },
+ { BR_EC_secp192r1,
+ "secp192r1",
+ { "secp192r1", "P-192", NULL, NULL } },
+ { BR_EC_secp224k1,
+ "secp224k1",
+ { "secp224k1", NULL, NULL, NULL } },
+ { BR_EC_secp224r1,
+ "secp224r1",
+ { "secp224r1", "P-224", NULL, NULL } },
+ { BR_EC_secp256k1,
+ "secp256k1",
+ { "secp256k1", NULL, NULL, NULL } },
+ { BR_EC_secp256r1,
+ "secp256r1 (P-256)",
+ { "secp256r1", "P-256", "prime256v1", NULL } },
+ { BR_EC_secp384r1,
+ "secp384r1 (P-384)",
+ { "secp384r1", "P-384", NULL, NULL } },
+ { BR_EC_secp521r1,
+ "secp521r1 (P-521)",
+ { "secp521r1", "P-521", NULL, NULL } },
+ { BR_EC_brainpoolP256r1,
+ "brainpoolP256r1",
+ { "brainpoolP256r1", NULL, NULL, NULL } },
+ { BR_EC_brainpoolP384r1,
+ "brainpoolP384r1",
+ { "brainpoolP384r1", NULL, NULL, NULL } },
+ { BR_EC_brainpoolP512r1,
+ "brainpoolP512r1",
+ { "brainpoolP512r1", NULL, NULL, NULL } },
+ { BR_EC_curve25519,
+ "Curve25519",
+ { "curve25519", "c25519", NULL, NULL } },
+ { BR_EC_curve448,
+ "Curve448",
+ { "curve448", "c448", NULL, NULL } },
+ { 0, 0, { 0, 0, 0, 0 } }
+};
+
+static const struct {
+ const char *long_name;
+ const char *short_name;
+ const void *impl;
+} algo_names[] = {
+ /* Block ciphers */
+ { "aes_big_cbcenc", "big", &br_aes_big_cbcenc_vtable },
+ { "aes_big_cbcdec", "big", &br_aes_big_cbcdec_vtable },
+ { "aes_big_ctr", "big", &br_aes_big_ctr_vtable },
+ { "aes_big_ctrcbc", "big", &br_aes_big_ctrcbc_vtable },
+ { "aes_small_cbcenc", "small", &br_aes_small_cbcenc_vtable },
+ { "aes_small_cbcdec", "small", &br_aes_small_cbcdec_vtable },
+ { "aes_small_ctr", "small", &br_aes_small_ctr_vtable },
+ { "aes_small_ctrcbc", "small", &br_aes_small_ctrcbc_vtable },
+ { "aes_ct_cbcenc", "ct", &br_aes_ct_cbcenc_vtable },
+ { "aes_ct_cbcdec", "ct", &br_aes_ct_cbcdec_vtable },
+ { "aes_ct_ctr", "ct", &br_aes_ct_ctr_vtable },
+ { "aes_ct_ctrcbc", "ct", &br_aes_ct_ctrcbc_vtable },
+ { "aes_ct64_cbcenc", "ct64", &br_aes_ct64_cbcenc_vtable },
+ { "aes_ct64_cbcdec", "ct64", &br_aes_ct64_cbcdec_vtable },
+ { "aes_ct64_ctr", "ct64", &br_aes_ct64_ctr_vtable },
+ { "aes_ct64_ctrcbc", "ct64", &br_aes_ct64_ctrcbc_vtable },
+
+ { "des_tab_cbcenc", "tab", &br_des_tab_cbcenc_vtable },
+ { "des_tab_cbcdec", "tab", &br_des_tab_cbcdec_vtable },
+ { "des_ct_cbcenc", "ct", &br_des_ct_cbcenc_vtable },
+ { "des_ct_cbcdec", "ct", &br_des_ct_cbcdec_vtable },
+
+ { "chacha20_ct", "ct", &br_chacha20_ct_run },
+
+ { "ghash_ctmul", "ctmul", &br_ghash_ctmul },
+ { "ghash_ctmul32", "ctmul32", &br_ghash_ctmul32 },
+ { "ghash_ctmul64", "ctmul64", &br_ghash_ctmul64 },
+
+ { "poly1305_ctmul", "ctmul", &br_poly1305_ctmul_run },
+ { "poly1305_ctmul32", "ctmul32", &br_poly1305_ctmul32_run },
+
+ { "ec_all_m15", "all_m15", &br_ec_all_m15 },
+ { "ec_all_m31", "all_m31", &br_ec_all_m31 },
+ { "ec_c25519_i15", "c25519_i15", &br_ec_c25519_i15 },
+ { "ec_c25519_i31", "c25519_i31", &br_ec_c25519_i31 },
+ { "ec_c25519_m15", "c25519_m15", &br_ec_c25519_m15 },
+ { "ec_c25519_m31", "c25519_m31", &br_ec_c25519_m31 },
+ { "ec_p256_m15", "p256_m15", &br_ec_p256_m15 },
+ { "ec_p256_m31", "p256_m31", &br_ec_p256_m31 },
+ { "ec_prime_i15", "prime_i15", &br_ec_prime_i15 },
+ { "ec_prime_i31", "prime_i31", &br_ec_prime_i31 },
+
+ { "ecdsa_i15_sign_asn1", "i15_asn1", &br_ecdsa_i15_sign_asn1 },
+ { "ecdsa_i15_sign_raw", "i15_raw", &br_ecdsa_i15_sign_raw },
+ { "ecdsa_i31_sign_asn1", "i31_asn1", &br_ecdsa_i31_sign_asn1 },
+ { "ecdsa_i31_sign_raw", "i31_raw", &br_ecdsa_i31_sign_raw },
+ { "ecdsa_i15_vrfy_asn1", "i15_asn1", &br_ecdsa_i15_vrfy_asn1 },
+ { "ecdsa_i15_vrfy_raw", "i15_raw", &br_ecdsa_i15_vrfy_raw },
+ { "ecdsa_i31_vrfy_asn1", "i31_asn1", &br_ecdsa_i31_vrfy_asn1 },
+ { "ecdsa_i31_vrfy_raw", "i31_raw", &br_ecdsa_i31_vrfy_raw },
+
+ { "rsa_i15_pkcs1_sign", "i15", &br_rsa_i15_pkcs1_sign },
+ { "rsa_i31_pkcs1_sign", "i31", &br_rsa_i31_pkcs1_sign },
+ { "rsa_i32_pkcs1_sign", "i32", &br_rsa_i32_pkcs1_sign },
+ { "rsa_i15_pkcs1_vrfy", "i15", &br_rsa_i15_pkcs1_vrfy },
+ { "rsa_i31_pkcs1_vrfy", "i31", &br_rsa_i31_pkcs1_vrfy },
+ { "rsa_i32_pkcs1_vrfy", "i32", &br_rsa_i32_pkcs1_vrfy },
+
+ { 0, 0, 0 }
+};
+
+static const struct {
+ const char *long_name;
+ const char *short_name;
+ const void *(*get)(void);
+} algo_names_dyn[] = {
+ { "aes_pwr8_cbcenc", "pwr8",
+ (const void *(*)(void))&br_aes_pwr8_cbcenc_get_vtable },
+ { "aes_pwr8_cbcdec", "pwr8",
+ (const void *(*)(void))&br_aes_pwr8_cbcdec_get_vtable },
+ { "aes_pwr8_ctr", "pwr8",
+ (const void *(*)(void))&br_aes_pwr8_ctr_get_vtable },
+ { "aes_pwr8_ctrcbc", "pwr8",
+ (const void *(*)(void))&br_aes_pwr8_ctrcbc_get_vtable },
+ { "aes_x86ni_cbcenc", "x86ni",
+ (const void *(*)(void))&br_aes_x86ni_cbcenc_get_vtable },
+ { "aes_x86ni_cbcdec", "x86ni",
+ (const void *(*)(void))&br_aes_x86ni_cbcdec_get_vtable },
+ { "aes_x86ni_ctr", "x86ni",
+ (const void *(*)(void))&br_aes_x86ni_ctr_get_vtable },
+ { "aes_x86ni_ctrcbc", "x86ni",
+ (const void *(*)(void))&br_aes_x86ni_ctrcbc_get_vtable },
+ { "chacha20_sse2", "sse2",
+ (const void *(*)(void))&br_chacha20_sse2_get },
+ { "ghash_pclmul", "pclmul",
+ (const void *(*)(void))&br_ghash_pclmul_get },
+ { "ghash_pwr8", "pwr8",
+ (const void *(*)(void))&br_ghash_pwr8_get },
+ { "poly1305_ctmulq", "ctmulq",
+ (const void *(*)(void))&br_poly1305_ctmulq_get },
+ { "rsa_i62_pkcs1_sign", "i62",
+ (const void *(*)(void))&br_rsa_i62_pkcs1_sign_get },
+ { "rsa_i62_pkcs1_vrfy", "i62",
+ (const void *(*)(void))&br_rsa_i62_pkcs1_vrfy_get },
+ { "ec_c25519_m62", "m62",
+ (const void *(*)(void))&br_ec_c25519_m62_get },
+ { "ec_c25519_m64", "m64",
+ (const void *(*)(void))&br_ec_c25519_m64_get },
+ { "ec_p256_m62", "m62",
+ (const void *(*)(void))&br_ec_p256_m62_get },
+ { "ec_p256_m64", "m64",
+ (const void *(*)(void))&br_ec_p256_m64_get },
+ { 0, 0, 0, }
+};
+
+/* see brssl.h */
+const char *
+get_algo_name(const void *impl, int long_name)
+{
+ size_t u;
+
+ for (u = 0; algo_names[u].long_name; u ++) {
+ if (impl == algo_names[u].impl) {
+ return long_name
+ ? algo_names[u].long_name
+ : algo_names[u].short_name;
+ }
+ }
+ for (u = 0; algo_names_dyn[u].long_name; u ++) {
+ if (impl == algo_names_dyn[u].get()) {
+ return long_name
+ ? algo_names_dyn[u].long_name
+ : algo_names_dyn[u].short_name;
+ }
+ }
+ return "UNKNOWN";
+}
+
+/* see brssl.h */
+const char *
+get_curve_name(int id)
+{
+ size_t u;
+
+ for (u = 0; curves[u].name; u ++) {
+ if (curves[u].id == id) {
+ return curves[u].name;
+ }
+ }
+ return NULL;
+}
+
+/* see brssl.h */
+int
+get_curve_name_ext(int id, char *dst, size_t len)
+{
+ const char *name;
+ char tmp[30];
+ size_t n;
+
+ name = get_curve_name(id);
+ if (name == NULL) {
+ sprintf(tmp, "unknown (%d)", id);
+ name = tmp;
+ }
+ n = 1 + strlen(name);
+ if (n > len) {
+ if (len > 0) {
+ dst[0] = 0;
+ }
+ return -1;
+ }
+ memcpy(dst, name, n);
+ return 0;
+}
+
+/* see brssl.h */
+const char *
+get_suite_name(unsigned suite)
+{
+ size_t u;
+
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if (cipher_suites[u].suite == suite) {
+ return cipher_suites[u].name;
+ }
+ }
+ return NULL;
+}
+
+/* see brssl.h */
+int
+get_suite_name_ext(unsigned suite, char *dst, size_t len)
+{
+ const char *name;
+ char tmp[30];
+ size_t n;
+
+ name = get_suite_name(suite);
+ if (name == NULL) {
+ sprintf(tmp, "unknown (0x%04X)", suite);
+ name = tmp;
+ }
+ n = 1 + strlen(name);
+ if (n > len) {
+ if (len > 0) {
+ dst[0] = 0;
+ }
+ return -1;
+ }
+ memcpy(dst, name, n);
+ return 0;
+}
+
+/* see brssl.h */
+int
+uses_ecdhe(unsigned suite)
+{
+ size_t u;
+
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if (cipher_suites[u].suite == suite) {
+ return (cipher_suites[u].req
+ & (REQ_ECDHE_RSA | REQ_ECDHE_ECDSA)) != 0;
+ }
+ }
+ return 0;
+}
+
+/* see brssl.h */
+void
+list_names(void)
+{
+ size_t u;
+
+ printf("Protocol versions:\n");
+ for (u = 0; protocol_versions[u].name; u ++) {
+ printf(" %-8s %s\n",
+ protocol_versions[u].name,
+ protocol_versions[u].comment);
+ }
+ printf("Hash functions:\n");
+ for (u = 0; hash_functions[u].name; u ++) {
+ printf(" %-8s %s\n",
+ hash_functions[u].name,
+ hash_functions[u].comment);
+ }
+ printf("Cipher suites:\n");
+ for (u = 0; cipher_suites[u].name; u ++) {
+ printf(" %s\n %s\n",
+ cipher_suites[u].name,
+ cipher_suites[u].comment);
+ }
+}
+
+/* see brssl.h */
+void
+list_curves(void)
+{
+ size_t u;
+ for (u = 0; curves[u].name; u ++) {
+ size_t v;
+
+ for (v = 0; curves[u].sid[v]; v ++) {
+ if (v == 0) {
+ printf(" ");
+ } else if (v == 1) {
+ printf(" (");
+ } else {
+ printf(", ");
+ }
+ printf("%s", curves[u].sid[v]);
+ }
+ if (v > 1) {
+ printf(")");
+ }
+ printf("\n");
+ }
+}
+
+static int
+is_ign(int c)
+{
+ if (c == 0) {
+ return 0;
+ }
+ if (c <= 32 || c == '-' || c == '_' || c == '.'
+ || c == '/' || c == '+' || c == ':')
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Get next non-ignored character, normalised:
+ * ASCII letters are converted to lowercase
+ * control characters, space, '-', '_', '.', '/', '+' and ':' are ignored
+ * A terminating zero is returned as 0.
+ */
+static int
+next_char(const char **ps, const char *limit)
+{
+ for (;;) {
+ int c;
+
+ if (*ps == limit) {
+ return 0;
+ }
+ c = *(*ps) ++;
+ if (c == 0) {
+ return 0;
+ }
+ if (c >= 'A' && c <= 'Z') {
+ c += 'a' - 'A';
+ }
+ if (!is_ign(c)) {
+ return c;
+ }
+ }
+}
+
+/*
+ * Partial string equality comparison, with normalisation.
+ */
+static int
+eqstr_chunk(const char *s1, size_t s1_len, const char *s2, size_t s2_len)
+{
+ const char *lim1, *lim2;
+
+ lim1 = s1 + s1_len;
+ lim2 = s2 + s2_len;
+ for (;;) {
+ int c1, c2;
+
+ c1 = next_char(&s1, lim1);
+ c2 = next_char(&s2, lim2);
+ if (c1 != c2) {
+ return 0;
+ }
+ if (c1 == 0) {
+ return 1;
+ }
+ }
+}
+
+/* see brssl.h */
+int
+eqstr(const char *s1, const char *s2)
+{
+ return eqstr_chunk(s1, strlen(s1), s2, strlen(s2));
+}
+
+static int
+hexval(int c)
+{
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ } else if (c >= 'A' && c <= 'F') {
+ return c - 'A' + 10;
+ } else if (c >= 'a' && c <= 'f') {
+ return c - 'a' + 10;
+ } else {
+ return -1;
+ }
+}
+
+/* see brssl.h */
+size_t
+parse_size(const char *s)
+{
+ int radix;
+ size_t acc;
+ const char *t;
+
+ t = s;
+ if (t[0] == '0' && (t[1] == 'x' || t[1] == 'X')) {
+ radix = 16;
+ t += 2;
+ } else {
+ radix = 10;
+ }
+ acc = 0;
+ for (;;) {
+ int c, d;
+ size_t z;
+
+ c = *t ++;
+ if (c == 0) {
+ return acc;
+ }
+ d = hexval(c);
+ if (d < 0 || d >= radix) {
+ fprintf(stderr, "ERROR: not a valid digit: '%c'\n", c);
+ return (size_t)-1;
+ }
+ z = acc * (size_t)radix + (size_t)d;
+ if (z < (size_t)d || (z / (size_t)radix) != acc
+ || z == (size_t)-1)
+ {
+ fprintf(stderr, "ERROR: value too large: %s\n", s);
+ return (size_t)-1;
+ }
+ acc = z;
+ }
+}
+
+/*
+ * Comma-separated list enumeration. This returns a pointer to the first
+ * word in the string, skipping leading ignored characters. '*len' is
+ * set to the word length (not counting trailing ignored characters).
+ * '*str' is updated to point to immediately after the next comma, or to
+ * the terminating zero, whichever comes first.
+ *
+ * Empty words are skipped. If there is no next non-empty word, then this
+ * function returns NULL and sets *len to 0.
+ */
+static const char *
+next_word(const char **str, size_t *len)
+{
+ int c;
+ const char *begin;
+ size_t u;
+
+ /*
+ * Find next non-ignored character which is not a comma.
+ */
+ for (;;) {
+ c = **str;
+ if (c == 0) {
+ *len = 0;
+ return NULL;
+ }
+ if (!is_ign(c) && c != ',') {
+ break;
+ }
+ (*str) ++;
+ }
+
+ /*
+ * Find next comma or terminator.
+ */
+ begin = *str;
+ for (;;) {
+ c = *(*str);
+ if (c == 0 || c == ',') {
+ break;
+ }
+ (*str) ++;
+ }
+
+ /*
+ * Remove trailing ignored characters.
+ */
+ u = (size_t)(*str - begin);
+ while (u > 0 && is_ign(begin[u - 1])) {
+ u --;
+ }
+ if (c == ',') {
+ (*str) ++;
+ }
+ *len = u;
+ return begin;
+}
+
+/* see brssl.h */
+unsigned
+parse_version(const char *name, size_t len)
+{
+ size_t u;
+
+ for (u = 0;; u ++) {
+ const char *ref;
+
+ ref = protocol_versions[u].name;
+ if (ref == NULL) {
+ fprintf(stderr, "ERROR: unrecognised protocol"
+ " version name: '%s'\n", name);
+ return 0;
+ }
+ if (eqstr_chunk(ref, strlen(ref), name, len)) {
+ return protocol_versions[u].version;
+ }
+ }
+}
+
+/* see brssl.h */
+unsigned
+parse_hash_functions(const char *arg)
+{
+ unsigned r;
+
+ r = 0;
+ for (;;) {
+ const char *name;
+ size_t len;
+ size_t u;
+
+ name = next_word(&arg, &len);
+ if (name == NULL) {
+ break;
+ }
+ for (u = 0;; u ++) {
+ const char *ref;
+
+ ref = hash_functions[u].name;
+ if (ref == 0) {
+ fprintf(stderr, "ERROR: unrecognised"
+ " hash function name: '");
+ fwrite(name, 1, len, stderr);
+ fprintf(stderr, "'\n");
+ return 0;
+ }
+ if (eqstr_chunk(ref, strlen(ref), name, len)) {
+ int id;
+
+ id = (hash_functions[u].hclass->desc
+ >> BR_HASHDESC_ID_OFF)
+ & BR_HASHDESC_ID_MASK;
+ r |= (unsigned)1 << id;
+ break;
+ }
+ }
+ }
+ if (r == 0) {
+ fprintf(stderr, "ERROR: no hash function name provided\n");
+ }
+ return r;
+}
+
+/* see brssl.h */
+cipher_suite *
+parse_suites(const char *arg, size_t *num)
+{
+ VECTOR(cipher_suite) suites = VEC_INIT;
+ cipher_suite *r;
+
+ for (;;) {
+ const char *name;
+ size_t u, len;
+
+ name = next_word(&arg, &len);
+ if (name == NULL) {
+ break;
+ }
+ for (u = 0;; u ++) {
+ const char *ref;
+
+ ref = cipher_suites[u].name;
+ if (ref == NULL) {
+ fprintf(stderr, "ERROR: unrecognised"
+ " cipher suite '");
+ fwrite(name, 1, len, stderr);
+ fprintf(stderr, "'\n");
+ return 0;
+ }
+ if (eqstr_chunk(ref, strlen(ref), name, len)) {
+ VEC_ADD(suites, cipher_suites[u]);
+ break;
+ }
+ }
+ }
+ if (VEC_LEN(suites) == 0) {
+ fprintf(stderr, "ERROR: no cipher suite provided\n");
+ }
+ r = VEC_TOARRAY(suites);
+ *num = VEC_LEN(suites);
+ VEC_CLEAR(suites);
+ return r;
+}
+
+/* see brssl.h */
+const char *
+ec_curve_name(int curve)
+{
+ switch (curve) {
+ case BR_EC_sect163k1: return "sect163k1";
+ case BR_EC_sect163r1: return "sect163r1";
+ case BR_EC_sect163r2: return "sect163r2";
+ case BR_EC_sect193r1: return "sect193r1";
+ case BR_EC_sect193r2: return "sect193r2";
+ case BR_EC_sect233k1: return "sect233k1";
+ case BR_EC_sect233r1: return "sect233r1";
+ case BR_EC_sect239k1: return "sect239k1";
+ case BR_EC_sect283k1: return "sect283k1";
+ case BR_EC_sect283r1: return "sect283r1";
+ case BR_EC_sect409k1: return "sect409k1";
+ case BR_EC_sect409r1: return "sect409r1";
+ case BR_EC_sect571k1: return "sect571k1";
+ case BR_EC_sect571r1: return "sect571r1";
+ case BR_EC_secp160k1: return "secp160k1";
+ case BR_EC_secp160r1: return "secp160r1";
+ case BR_EC_secp160r2: return "secp160r2";
+ case BR_EC_secp192k1: return "secp192k1";
+ case BR_EC_secp192r1: return "secp192r1";
+ case BR_EC_secp224k1: return "secp224k1";
+ case BR_EC_secp224r1: return "secp224r1";
+ case BR_EC_secp256k1: return "secp256k1";
+ case BR_EC_secp256r1: return "secp256r1";
+ case BR_EC_secp384r1: return "secp384r1";
+ case BR_EC_secp521r1: return "secp521r1";
+ case BR_EC_brainpoolP256r1: return "brainpoolP256r1";
+ case BR_EC_brainpoolP384r1: return "brainpoolP384r1";
+ case BR_EC_brainpoolP512r1: return "brainpoolP512r1";
+ default:
+ return "unknown";
+ }
+}
+
+/* see brssl.h */
+int
+get_curve_by_name(const char *str)
+{
+ size_t u, v;
+
+ for (u = 0; curves[u].name; u ++) {
+ for (v = 0; curves[u].sid[v]; v ++) {
+ if (eqstr(curves[u].sid[v], str)) {
+ return curves[u].id;
+ }
+ }
+ }
+ return -1;
+}
+
+/* see brssl.h */
+const char *
+hash_function_name(int id)
+{
+ switch (id) {
+ case br_md5sha1_ID: return "MD5+SHA-1";
+ case br_md5_ID: return "MD5";
+ case br_sha1_ID: return "SHA-1";
+ case br_sha224_ID: return "SHA-224";
+ case br_sha256_ID: return "SHA-256";
+ case br_sha384_ID: return "SHA-384";
+ case br_sha512_ID: return "SHA-512";
+ default:
+ return "unknown";
+ }
+}
Property changes on: stable/12/contrib/bearssl/tools/names.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/server.c
===================================================================
--- stable/12/contrib/bearssl/tools/server.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/server.c (revision 346145)
@@ -0,0 +1,1235 @@
+/*
+ * 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>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define SOCKET int
+#define INVALID_SOCKET (-1)
+#define SOCKADDR_STORAGE struct sockaddr_storage
+#endif
+
+#include "brssl.h"
+
+static SOCKET
+host_bind(const char *host, const char *port, int verbose)
+{
+ struct addrinfo hints, *si, *p;
+ SOCKET 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 INVALID_SOCKET;
+ }
+ fd = INVALID_SOCKET;
+ 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;
+ int opt;
+
+ sa = (struct sockaddr *)p->ai_addr;
+ if (sa->sa_family == AF_INET) {
+ memcpy(&sa4, sa, sizeof sa4);
+ 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) {
+ memcpy(&sa6, sa, sizeof sa6);
+ 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 (verbose) {
+ char tmp[INET6_ADDRSTRLEN + 50];
+
+ if (addr != NULL) {
+ if (!inet_ntop(p->ai_family, addr,
+ tmp, sizeof tmp))
+ {
+ strcpy(tmp, "<invalid>");
+ }
+ } 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 == INVALID_SOCKET) {
+ if (verbose) {
+ perror("socket()");
+ }
+ continue;
+ }
+ opt = 1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&opt, sizeof opt);
+#ifdef IPV6_V6ONLY
+ /*
+ * We want to make sure that the server socket works for
+ * both IPv4 and IPv6. But IPV6_V6ONLY is not defined on
+ * some very old systems.
+ */
+ opt = 0;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (void *)&opt, sizeof opt);
+#endif
+ if (bind(fd, sa, sa_len) < 0) {
+ if (verbose) {
+ perror("bind()");
+ }
+#ifdef _WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ continue;
+ }
+ break;
+ }
+ if (p == NULL) {
+ freeaddrinfo(si);
+ fprintf(stderr, "ERROR: failed to bind\n");
+ return INVALID_SOCKET;
+ }
+ freeaddrinfo(si);
+ if (listen(fd, 5) < 0) {
+ if (verbose) {
+ perror("listen()");
+ }
+#ifdef _WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ return INVALID_SOCKET;
+ }
+ if (verbose) {
+ fprintf(stderr, "bound.\n");
+ }
+ return fd;
+}
+
+static SOCKET
+accept_client(SOCKET server_fd, int verbose, int nonblock)
+{
+ int fd;
+ SOCKADDR_STORAGE sa;
+ socklen_t sa_len;
+
+ sa_len = sizeof sa;
+ fd = accept(server_fd, (struct sockaddr *)&sa, &sa_len);
+ if (fd == INVALID_SOCKET) {
+ if (verbose) {
+ perror("accept()");
+ }
+ return INVALID_SOCKET;
+ }
+ if (verbose) {
+ char tmp[INET6_ADDRSTRLEN + 50];
+ const char *name;
+
+ name = NULL;
+ switch (((struct sockaddr *)&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)
+ ((struct sockaddr *)&sa)->sa_family);
+ name = tmp;
+ }
+ fprintf(stderr, "accepting connection from: %s\n", name);
+ }
+
+ /*
+ * We make the socket non-blocking, since we are going to use
+ * poll() or select() to organise I/O.
+ */
+ if (nonblock) {
+#ifdef _WIN32
+ u_long arg;
+
+ arg = 1;
+ ioctlsocket(fd, FIONBIO, &arg);
+#else
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+ }
+ return fd;
+}
+
+static void
+usage_server(void)
+{
+ fprintf(stderr,
+"usage: brssl server [ options ]\n");
+ fprintf(stderr,
+"options:\n");
+ fprintf(stderr,
+" -q suppress verbose messages\n");
+ fprintf(stderr,
+" -trace activate extra debug messages (dump of all packets)\n");
+ fprintf(stderr,
+" -b name bind to a specific address or host name\n");
+ fprintf(stderr,
+" -p port bind to a specific port (default: 4433)\n");
+ fprintf(stderr,
+" -mono use monodirectional buffering\n");
+ fprintf(stderr,
+" -buf length set the I/O buffer length (in bytes)\n");
+ fprintf(stderr,
+" -cache length set the session cache storage length (in bytes)\n");
+ fprintf(stderr,
+" -cert fname read certificate chain from file 'fname'\n");
+ fprintf(stderr,
+" -key fname read private key from file 'fname'\n");
+ fprintf(stderr,
+" -CA file add trust anchors from 'file' (for client auth)\n");
+ fprintf(stderr,
+" -anon_ok request but do not require a client certificate\n");
+ fprintf(stderr,
+" -list list supported names (protocols, algorithms...)\n");
+ fprintf(stderr,
+" -vmin name set minimum supported version (default: TLS-1.0)\n");
+ fprintf(stderr,
+" -vmax name set maximum supported version (default: TLS-1.2)\n");
+ fprintf(stderr,
+" -cs names set list of supported cipher suites (comma-separated)\n");
+ fprintf(stderr,
+" -hf names add support for some hash functions (comma-separated)\n");
+ fprintf(stderr,
+" -cbhash test hashing in policy callback\n");
+ fprintf(stderr,
+" -serverpref enforce server's preferences for cipher suites\n");
+ fprintf(stderr,
+" -noreneg prohibit renegotiations\n");
+ fprintf(stderr,
+" -alpn name add protocol name to list of protocols (ALPN extension)\n");
+ fprintf(stderr,
+" -strictalpn fail on ALPN mismatch\n");
+ exit(EXIT_FAILURE);
+}
+
+typedef struct {
+ const br_ssl_server_policy_class *vtable;
+ int verbose;
+ br_x509_certificate *chain;
+ size_t chain_len;
+ int cert_signer_algo;
+ private_key *sk;
+ int cbhash;
+} policy_context;
+
+static void
+print_hashes(unsigned chashes)
+{
+ int i;
+
+ for (i = 2; i <= 6; i ++) {
+ if ((chashes >> i) & 1) {
+ int z;
+
+ switch (i) {
+ case 3: z = 224; break;
+ case 4: z = 256; break;
+ case 5: z = 384; break;
+ case 6: z = 512; break;
+ default:
+ z = 1;
+ break;
+ }
+ fprintf(stderr, " sha%d", z);
+ }
+ }
+}
+
+static unsigned
+choose_hash(unsigned chashes)
+{
+ unsigned hash_id;
+
+ for (hash_id = 6; hash_id >= 2; hash_id --) {
+ if (((chashes >> hash_id) & 1) != 0) {
+ return hash_id;
+ }
+ }
+ /*
+ * Normally unreachable.
+ */
+ return 0;
+}
+
+static int
+sp_choose(const br_ssl_server_policy_class **pctx,
+ const br_ssl_server_context *cc,
+ br_ssl_server_choices *choices)
+{
+ policy_context *pc;
+ const br_suite_translated *st;
+ size_t u, st_num;
+ unsigned chashes;
+
+ pc = (policy_context *)pctx;
+ st = br_ssl_server_get_client_suites(cc, &st_num);
+ chashes = br_ssl_server_get_client_hashes(cc);
+ if (pc->verbose) {
+ fprintf(stderr, "Client parameters:\n");
+ fprintf(stderr, " Maximum version: ");
+ switch (cc->client_max_version) {
+ case BR_SSL30:
+ fprintf(stderr, "SSL 3.0");
+ break;
+ case BR_TLS10:
+ fprintf(stderr, "TLS 1.0");
+ break;
+ case BR_TLS11:
+ fprintf(stderr, "TLS 1.1");
+ break;
+ case BR_TLS12:
+ fprintf(stderr, "TLS 1.2");
+ break;
+ default:
+ fprintf(stderr, "unknown (0x%04X)",
+ (unsigned)cc->client_max_version);
+ break;
+ }
+ fprintf(stderr, "\n");
+ fprintf(stderr, " Compatible cipher suites:\n");
+ for (u = 0; u < st_num; u ++) {
+ char csn[80];
+
+ get_suite_name_ext(st[u][0], csn, sizeof csn);
+ fprintf(stderr, " %s\n", csn);
+ }
+ fprintf(stderr, " Common sign+hash functions:\n");
+ if ((chashes & 0xFF) != 0) {
+ fprintf(stderr, " with RSA:");
+ print_hashes(chashes);
+ fprintf(stderr, "\n");
+ }
+ if ((chashes >> 8) != 0) {
+ fprintf(stderr, " with ECDSA:");
+ print_hashes(chashes >> 8);
+ fprintf(stderr, "\n");
+ }
+ }
+ for (u = 0; u < st_num; u ++) {
+ unsigned tt;
+
+ tt = st[u][1];
+ switch (tt >> 12) {
+ case BR_SSLKEYX_RSA:
+ if (pc->sk->key_type == BR_KEYTYPE_RSA) {
+ choices->cipher_suite = st[u][0];
+ goto choose_ok;
+ }
+ break;
+ case BR_SSLKEYX_ECDHE_RSA:
+ if (pc->sk->key_type == BR_KEYTYPE_RSA) {
+ choices->cipher_suite = st[u][0];
+ if (br_ssl_engine_get_version(&cc->eng)
+ < BR_TLS12)
+ {
+ if (pc->cbhash) {
+ choices->algo_id = 0x0001;
+ } else {
+ choices->algo_id = 0xFF00;
+ }
+ } else {
+ unsigned id;
+
+ id = choose_hash(chashes);
+ if (pc->cbhash) {
+ choices->algo_id =
+ (id << 8) + 0x01;
+ } else {
+ choices->algo_id = 0xFF00 + id;
+ }
+ }
+ goto choose_ok;
+ }
+ break;
+ case BR_SSLKEYX_ECDHE_ECDSA:
+ if (pc->sk->key_type == BR_KEYTYPE_EC) {
+ choices->cipher_suite = st[u][0];
+ if (br_ssl_engine_get_version(&cc->eng)
+ < BR_TLS12)
+ {
+ if (pc->cbhash) {
+ choices->algo_id = 0x0203;
+ } else {
+ choices->algo_id =
+ 0xFF00 + br_sha1_ID;
+ }
+ } else {
+ unsigned id;
+
+ id = choose_hash(chashes >> 8);
+ if (pc->cbhash) {
+ choices->algo_id =
+ (id << 8) + 0x03;
+ } else {
+ choices->algo_id =
+ 0xFF00 + id;
+ }
+ }
+ goto choose_ok;
+ }
+ break;
+ case BR_SSLKEYX_ECDH_RSA:
+ if (pc->sk->key_type == BR_KEYTYPE_EC
+ && pc->cert_signer_algo == BR_KEYTYPE_RSA)
+ {
+ choices->cipher_suite = st[u][0];
+ goto choose_ok;
+ }
+ break;
+ case BR_SSLKEYX_ECDH_ECDSA:
+ if (pc->sk->key_type == BR_KEYTYPE_EC
+ && pc->cert_signer_algo == BR_KEYTYPE_EC)
+ {
+ choices->cipher_suite = st[u][0];
+ goto choose_ok;
+ }
+ break;
+ }
+ }
+ return 0;
+
+choose_ok:
+ choices->chain = pc->chain;
+ choices->chain_len = pc->chain_len;
+ if (pc->verbose) {
+ char csn[80];
+
+ get_suite_name_ext(choices->cipher_suite, csn, sizeof csn);
+ fprintf(stderr, "Using: %s\n", csn);
+ }
+ return 1;
+}
+
+static uint32_t
+sp_do_keyx(const br_ssl_server_policy_class **pctx,
+ unsigned char *data, size_t *len)
+{
+ policy_context *pc;
+ uint32_t r;
+ size_t xoff, xlen;
+
+ pc = (policy_context *)pctx;
+ switch (pc->sk->key_type) {
+ const br_ec_impl *iec;
+
+ case BR_KEYTYPE_RSA:
+ return br_rsa_ssl_decrypt(
+ br_rsa_private_get_default(),
+ &pc->sk->key.rsa, data, *len);
+ case BR_KEYTYPE_EC:
+ iec = br_ec_get_default();
+ r = iec->mul(data, *len, pc->sk->key.ec.x,
+ pc->sk->key.ec.xlen, pc->sk->key.ec.curve);
+ xoff = iec->xoff(pc->sk->key.ec.curve, &xlen);
+ memmove(data, data + xoff, xlen);
+ *len = xlen;
+ return r;
+ default:
+ fprintf(stderr, "ERROR: unknown private key type (%d)\n",
+ (int)pc->sk->key_type);
+ return 0;
+ }
+}
+
+static size_t
+sp_do_sign(const br_ssl_server_policy_class **pctx,
+ unsigned algo_id, unsigned char *data, size_t hv_len, size_t len)
+{
+ policy_context *pc;
+ unsigned char hv[64];
+
+ pc = (policy_context *)pctx;
+ if (algo_id >= 0xFF00) {
+ algo_id &= 0xFF;
+ memcpy(hv, data, hv_len);
+ } else {
+ const br_hash_class *hc;
+ br_hash_compat_context zc;
+
+ if (pc->verbose) {
+ fprintf(stderr, "Callback hashing, algo = 0x%04X,"
+ " data_len = %lu\n",
+ algo_id, (unsigned long)hv_len);
+ }
+ algo_id >>= 8;
+ hc = get_hash_impl(algo_id);
+ if (hc == NULL) {
+ if (pc->verbose) {
+ fprintf(stderr,
+ "ERROR: unsupported hash function %u\n",
+ algo_id);
+ }
+ return 0;
+ }
+ hc->init(&zc.vtable);
+ hc->update(&zc.vtable, data, hv_len);
+ hc->out(&zc.vtable, hv);
+ hv_len = (hc->desc >> BR_HASHDESC_OUT_OFF)
+ & BR_HASHDESC_OUT_MASK;
+ }
+ switch (pc->sk->key_type) {
+ size_t sig_len;
+ uint32_t x;
+ const unsigned char *hash_oid;
+ const br_hash_class *hc;
+
+ case BR_KEYTYPE_RSA:
+ hash_oid = get_hash_oid(algo_id);
+ if (hash_oid == NULL && algo_id != 0) {
+ if (pc->verbose) {
+ fprintf(stderr, "ERROR: cannot RSA-sign with"
+ " unknown hash function: %u\n",
+ algo_id);
+ }
+ return 0;
+ }
+ sig_len = (pc->sk->key.rsa.n_bitlen + 7) >> 3;
+ if (len < sig_len) {
+ if (pc->verbose) {
+ fprintf(stderr, "ERROR: cannot RSA-sign,"
+ " buffer is too small"
+ " (sig=%lu, buf=%lu)\n",
+ (unsigned long)sig_len,
+ (unsigned long)len);
+ }
+ return 0;
+ }
+ x = br_rsa_pkcs1_sign_get_default()(
+ hash_oid, hv, hv_len, &pc->sk->key.rsa, data);
+ if (!x) {
+ if (pc->verbose) {
+ fprintf(stderr, "ERROR: RSA-sign failure\n");
+ }
+ return 0;
+ }
+ return sig_len;
+
+ case BR_KEYTYPE_EC:
+ hc = get_hash_impl(algo_id);
+ if (hc == NULL) {
+ if (pc->verbose) {
+ fprintf(stderr, "ERROR: cannot ECDSA-sign with"
+ " unknown hash function: %u\n",
+ algo_id);
+ }
+ return 0;
+ }
+ if (len < 139) {
+ if (pc->verbose) {
+ fprintf(stderr, "ERROR: cannot ECDSA-sign"
+ " (output buffer = %lu)\n",
+ (unsigned long)len);
+ }
+ return 0;
+ }
+ sig_len = br_ecdsa_sign_asn1_get_default()(
+ br_ec_get_default(), hc, hv, &pc->sk->key.ec, data);
+ if (sig_len == 0) {
+ if (pc->verbose) {
+ fprintf(stderr, "ERROR: ECDSA-sign failure\n");
+ }
+ return 0;
+ }
+ return sig_len;
+
+ default:
+ return 0;
+ }
+}
+
+static const br_ssl_server_policy_class policy_vtable = {
+ sizeof(policy_context),
+ sp_choose,
+ sp_do_keyx,
+ sp_do_sign
+};
+
+void
+free_alpn(void *alpn)
+{
+ xfree(*(char **)alpn);
+}
+
+/* see brssl.h */
+int
+do_server(int argc, char *argv[])
+{
+ int retcode;
+ int verbose;
+ int trace;
+ int i, bidi;
+ const char *bind_name;
+ const char *port;
+ unsigned vmin, vmax;
+ cipher_suite *suites;
+ size_t num_suites;
+ uint16_t *suite_ids;
+ unsigned hfuns;
+ int cbhash;
+ br_x509_certificate *chain;
+ size_t chain_len;
+ int cert_signer_algo;
+ private_key *sk;
+ anchor_list anchors = VEC_INIT;
+ VECTOR(char *) alpn_names = VEC_INIT;
+ br_x509_minimal_context xc;
+ const br_hash_class *dnhash;
+ size_t u;
+ br_ssl_server_context cc;
+ policy_context pc;
+ br_ssl_session_cache_lru lru;
+ unsigned char *iobuf, *cache;
+ size_t iobuf_len, cache_len;
+ uint32_t flags;
+ SOCKET server_fd, fd;
+
+ retcode = 0;
+ verbose = 1;
+ trace = 0;
+ bind_name = NULL;
+ port = NULL;
+ bidi = 1;
+ vmin = 0;
+ vmax = 0;
+ suites = NULL;
+ num_suites = 0;
+ hfuns = 0;
+ cbhash = 0;
+ suite_ids = NULL;
+ chain = NULL;
+ chain_len = 0;
+ sk = NULL;
+ iobuf = NULL;
+ iobuf_len = 0;
+ cache = NULL;
+ cache_len = (size_t)-1;
+ flags = 0;
+ server_fd = INVALID_SOCKET;
+ fd = INVALID_SOCKET;
+ for (i = 0; i < argc; i ++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (arg[0] != '-') {
+ usage_server();
+ goto server_exit_error;
+ }
+ if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
+ verbose = 1;
+ } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
+ verbose = 0;
+ } else if (eqstr(arg, "-trace")) {
+ trace = 1;
+ } else if (eqstr(arg, "-b")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-b'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ if (bind_name != NULL) {
+ fprintf(stderr, "ERROR: duplicate bind host\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ bind_name = argv[i];
+ } else if (eqstr(arg, "-p")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-p'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ if (port != NULL) {
+ fprintf(stderr, "ERROR: duplicate bind port\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ port = argv[i];
+ } else if (eqstr(arg, "-mono")) {
+ bidi = 0;
+ } else if (eqstr(arg, "-buf")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-buf'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ if (iobuf_len != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate I/O buffer length\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ iobuf_len = parse_size(arg);
+ if (iobuf_len == (size_t)-1) {
+ usage_server();
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-cache")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cache'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ if (cache_len != (size_t)-1) {
+ fprintf(stderr, "ERROR: duplicate session"
+ " cache length\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ cache_len = parse_size(arg);
+ if (cache_len == (size_t)-1) {
+ usage_server();
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-cert")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cert'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ if (chain != NULL) {
+ fprintf(stderr,
+ "ERROR: duplicate certificate chain\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ chain = read_certificates(arg, &chain_len);
+ if (chain == NULL || chain_len == 0) {
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-key")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-key'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ if (sk != NULL) {
+ fprintf(stderr,
+ "ERROR: duplicate private key\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ sk = read_private_key(arg);
+ if (sk == NULL) {
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-CA")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-CA'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ if (read_trust_anchors(&anchors, arg) == 0) {
+ usage_server();
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-anon_ok")) {
+ flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH;
+ } else if (eqstr(arg, "-list")) {
+ list_names();
+ goto server_exit;
+ } else if (eqstr(arg, "-vmin")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-vmin'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ if (vmin != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate minimum version\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ vmin = parse_version(arg, strlen(arg));
+ if (vmin == 0) {
+ fprintf(stderr,
+ "ERROR: unrecognised version '%s'\n",
+ arg);
+ usage_server();
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-vmax")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-vmax'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ if (vmax != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate maximum version\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ vmax = parse_version(arg, strlen(arg));
+ if (vmax == 0) {
+ fprintf(stderr,
+ "ERROR: unrecognised version '%s'\n",
+ arg);
+ usage_server();
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-cs")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cs'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ if (suites != NULL) {
+ fprintf(stderr, "ERROR: duplicate list"
+ " of cipher suites\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ suites = parse_suites(arg, &num_suites);
+ if (suites == NULL) {
+ usage_server();
+ goto server_exit_error;
+ }
+ } else if (eqstr(arg, "-hf")) {
+ unsigned x;
+
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-hf'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ arg = argv[i];
+ x = parse_hash_functions(arg);
+ if (x == 0) {
+ usage_server();
+ goto server_exit_error;
+ }
+ hfuns |= x;
+ } else if (eqstr(arg, "-cbhash")) {
+ cbhash = 1;
+ } else if (eqstr(arg, "-serverpref")) {
+ flags |= BR_OPT_ENFORCE_SERVER_PREFERENCES;
+ } else if (eqstr(arg, "-noreneg")) {
+ flags |= BR_OPT_NO_RENEGOTIATION;
+ } else if (eqstr(arg, "-alpn")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-alpn'\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ VEC_ADD(alpn_names, xstrdup(argv[i]));
+ } else if (eqstr(arg, "-strictalpn")) {
+ flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH;
+ } else {
+ fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
+ usage_server();
+ goto server_exit_error;
+ }
+ }
+ if (port == NULL) {
+ port = "4433";
+ }
+ if (vmin == 0) {
+ vmin = BR_TLS10;
+ }
+ if (vmax == 0) {
+ vmax = BR_TLS12;
+ }
+ if (vmax < vmin) {
+ fprintf(stderr, "ERROR: impossible minimum/maximum protocol"
+ " version combination\n");
+ usage_server();
+ goto server_exit_error;
+ }
+ if (suites == NULL) {
+ num_suites = 0;
+
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if ((cipher_suites[u].req & REQ_TLS12) == 0
+ || vmax >= BR_TLS12)
+ {
+ num_suites ++;
+ }
+ }
+ suites = xmalloc(num_suites * sizeof *suites);
+ num_suites = 0;
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if ((cipher_suites[u].req & REQ_TLS12) == 0
+ || vmax >= BR_TLS12)
+ {
+ suites[num_suites ++] = cipher_suites[u];
+ }
+ }
+ }
+ if (hfuns == 0) {
+ hfuns = (unsigned)-1;
+ }
+ if (chain == NULL || chain_len == 0) {
+ fprintf(stderr, "ERROR: no certificate chain provided\n");
+ goto server_exit_error;
+ }
+ if (sk == NULL) {
+ fprintf(stderr, "ERROR: no private key provided\n");
+ goto server_exit_error;
+ }
+ switch (sk->key_type) {
+ int curve;
+ uint32_t supp;
+
+ case BR_KEYTYPE_RSA:
+ break;
+ case BR_KEYTYPE_EC:
+ curve = sk->key.ec.curve;
+ supp = br_ec_get_default()->supported_curves;
+ if (curve > 31 || !((supp >> curve) & 1)) {
+ fprintf(stderr, "ERROR: private key curve (%d)"
+ " is not supported\n", curve);
+ goto server_exit_error;
+ }
+ break;
+ default:
+ fprintf(stderr, "ERROR: unsupported private key type (%d)\n",
+ sk->key_type);
+ break;
+ }
+ cert_signer_algo = get_cert_signer_algo(chain);
+ if (cert_signer_algo == 0) {
+ goto server_exit_error;
+ }
+ if (verbose) {
+ const char *csas;
+
+ switch (cert_signer_algo) {
+ case BR_KEYTYPE_RSA: csas = "RSA"; break;
+ case BR_KEYTYPE_EC: csas = "EC"; break;
+ default:
+ csas = "unknown";
+ break;
+ }
+ fprintf(stderr, "Issuing CA key type: %d (%s)\n",
+ cert_signer_algo, csas);
+ }
+ if (iobuf_len == 0) {
+ if (bidi) {
+ iobuf_len = BR_SSL_BUFSIZE_BIDI;
+ } else {
+ iobuf_len = BR_SSL_BUFSIZE_MONO;
+ }
+ }
+ iobuf = xmalloc(iobuf_len);
+ if (cache_len == (size_t)-1) {
+ cache_len = 5000;
+ }
+ cache = xmalloc(cache_len);
+
+ /*
+ * Compute implementation requirements and inject implementations.
+ */
+ suite_ids = xmalloc(num_suites * sizeof *suite_ids);
+ br_ssl_server_zero(&cc);
+ br_ssl_engine_set_versions(&cc.eng, vmin, vmax);
+ br_ssl_engine_set_all_flags(&cc.eng, flags);
+ if (vmin <= BR_TLS11) {
+ if (!(hfuns & (1 << br_md5_ID))) {
+ fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need MD5\n");
+ goto server_exit_error;
+ }
+ if (!(hfuns & (1 << br_sha1_ID))) {
+ fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need SHA-1\n");
+ goto server_exit_error;
+ }
+ }
+ for (u = 0; u < num_suites; u ++) {
+ unsigned req;
+
+ req = suites[u].req;
+ suite_ids[u] = suites[u].suite;
+ if ((req & REQ_TLS12) != 0 && vmax < BR_TLS12) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires TLS 1.2\n",
+ suites[u].name);
+ goto server_exit_error;
+ }
+ if ((req & REQ_SHA1) != 0 && !(hfuns & (1 << br_sha1_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-1\n",
+ suites[u].name);
+ goto server_exit_error;
+ }
+ if ((req & REQ_SHA256) != 0 && !(hfuns & (1 << br_sha256_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-256\n",
+ suites[u].name);
+ goto server_exit_error;
+ }
+ if ((req & REQ_SHA384) != 0 && !(hfuns & (1 << br_sha384_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-384\n",
+ suites[u].name);
+ goto server_exit_error;
+ }
+ /* TODO: algorithm implementation selection */
+ if ((req & REQ_AESCBC) != 0) {
+ br_ssl_engine_set_default_aes_cbc(&cc.eng);
+ }
+ if ((req & REQ_AESCCM) != 0) {
+ br_ssl_engine_set_default_aes_ccm(&cc.eng);
+ }
+ if ((req & REQ_AESGCM) != 0) {
+ br_ssl_engine_set_default_aes_gcm(&cc.eng);
+ }
+ if ((req & REQ_CHAPOL) != 0) {
+ br_ssl_engine_set_default_chapol(&cc.eng);
+ }
+ if ((req & REQ_3DESCBC) != 0) {
+ br_ssl_engine_set_default_des_cbc(&cc.eng);
+ }
+ if ((req & (REQ_ECDHE_RSA | REQ_ECDHE_ECDSA)) != 0) {
+ br_ssl_engine_set_default_ec(&cc.eng);
+ }
+ }
+ br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites);
+
+ dnhash = NULL;
+ for (u = 0; hash_functions[u].name; u ++) {
+ const br_hash_class *hc;
+ int id;
+
+ hc = hash_functions[u].hclass;
+ id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
+ if ((hfuns & ((unsigned)1 << id)) != 0) {
+ dnhash = hc;
+ br_ssl_engine_set_hash(&cc.eng, id, hc);
+ }
+ }
+ if (vmin <= BR_TLS11) {
+ br_ssl_engine_set_prf10(&cc.eng, &br_tls10_prf);
+ }
+ if (vmax >= BR_TLS12) {
+ if ((hfuns & ((unsigned)1 << br_sha256_ID)) != 0) {
+ br_ssl_engine_set_prf_sha256(&cc.eng,
+ &br_tls12_sha256_prf);
+ }
+ if ((hfuns & ((unsigned)1 << br_sha384_ID)) != 0) {
+ br_ssl_engine_set_prf_sha384(&cc.eng,
+ &br_tls12_sha384_prf);
+ }
+ }
+
+ br_ssl_session_cache_lru_init(&lru, cache, cache_len);
+ br_ssl_server_set_cache(&cc, &lru.vtable);
+
+ if (VEC_LEN(alpn_names) != 0) {
+ br_ssl_engine_set_protocol_names(&cc.eng,
+ (const char **)&VEC_ELT(alpn_names, 0),
+ VEC_LEN(alpn_names));
+ }
+
+ /*
+ * Set the policy handler (that chooses the actual cipher suite,
+ * selects the certificate chain, and runs the private key
+ * operations).
+ */
+ pc.vtable = &policy_vtable;
+ pc.verbose = verbose;
+ pc.chain = chain;
+ pc.chain_len = chain_len;
+ pc.cert_signer_algo = cert_signer_algo;
+ pc.sk = sk;
+ pc.cbhash = cbhash;
+ br_ssl_server_set_policy(&cc, &pc.vtable);
+
+ /*
+ * If trust anchors have been configured, then set an X.509
+ * validation engine and activate client certificate
+ * authentication.
+ */
+ if (VEC_LEN(anchors) != 0) {
+ br_x509_minimal_init(&xc, dnhash,
+ &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+ for (u = 0; hash_functions[u].name; u ++) {
+ const br_hash_class *hc;
+ int id;
+
+ hc = hash_functions[u].hclass;
+ id = (hc->desc >> BR_HASHDESC_ID_OFF)
+ & BR_HASHDESC_ID_MASK;
+ if ((hfuns & ((unsigned)1 << id)) != 0) {
+ br_x509_minimal_set_hash(&xc, id, hc);
+ }
+ }
+ br_ssl_engine_set_default_rsavrfy(&cc.eng);
+ br_ssl_engine_set_default_ecdsa(&cc.eng);
+ br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default());
+ br_x509_minimal_set_ecdsa(&xc,
+ br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
+ br_ssl_engine_set_x509(&cc.eng, &xc.vtable);
+ br_ssl_server_set_trust_anchor_names_alt(&cc,
+ &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+ }
+
+ br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
+
+ /*
+ * On Unix systems, we need to ignore SIGPIPE.
+ */
+#ifndef _WIN32
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /*
+ * Open the server socket.
+ */
+ server_fd = host_bind(bind_name, port, verbose);
+ if (server_fd == INVALID_SOCKET) {
+ goto server_exit_error;
+ }
+
+ /*
+ * Process incoming clients, one at a time. Note that we do not
+ * accept any client until the previous connection has finished:
+ * this is voluntary, since the tool uses stdin/stdout for
+ * application data, and thus cannot really run two connections
+ * simultaneously.
+ */
+ for (;;) {
+ int x;
+ unsigned run_flags;
+
+ fd = accept_client(server_fd, verbose, 1);
+ if (fd == INVALID_SOCKET) {
+ goto server_exit_error;
+ }
+ br_ssl_server_reset(&cc);
+ run_flags = (verbose ? RUN_ENGINE_VERBOSE : 0)
+ | (trace ? RUN_ENGINE_TRACE : 0);
+ x = run_ssl_engine(&cc.eng, fd, run_flags);
+#ifdef _WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ fd = INVALID_SOCKET;
+ if (x < -1) {
+ goto server_exit_error;
+ }
+ }
+
+ /*
+ * Release allocated structures.
+ */
+server_exit:
+ xfree(suites);
+ xfree(suite_ids);
+ free_certificates(chain, chain_len);
+ free_private_key(sk);
+ VEC_CLEAREXT(anchors, &free_ta_contents);
+ VEC_CLEAREXT(alpn_names, &free_alpn);
+ xfree(iobuf);
+ xfree(cache);
+ if (fd != INVALID_SOCKET) {
+#ifdef _WIN32
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ }
+ if (server_fd != INVALID_SOCKET) {
+#ifdef _WIN32
+ closesocket(server_fd);
+#else
+ close(server_fd);
+#endif
+ }
+ return retcode;
+
+server_exit_error:
+ retcode = -1;
+ goto server_exit;
+}
Property changes on: stable/12/contrib/bearssl/tools/server.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/skey.c
===================================================================
--- stable/12/contrib/bearssl/tools/skey.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/skey.c (revision 346145)
@@ -0,0 +1,784 @@
+/*
+ * 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 "brssl.h"
+#include "bearssl.h"
+
+typedef struct {
+ int print_text;
+ int print_C;
+ const char *rawder;
+ const char *rawpem;
+ const char *pk8der;
+ const char *pk8pem;
+} outspec;
+
+static void
+print_int_text(const char *name, const unsigned char *buf, size_t len)
+{
+ size_t u;
+
+ printf("%s = ", name);
+ for (u = 0; u < len; u ++) {
+ printf("%02X", buf[u]);
+ }
+ printf("\n");
+}
+
+static void
+print_int_C(const char *name, const unsigned char *buf, size_t len)
+{
+ size_t u;
+
+ printf("\nstatic const unsigned char %s[] = {", name);
+ for (u = 0; u < len; u ++) {
+ if (u != 0) {
+ printf(",");
+ }
+ if (u % 12 == 0) {
+ printf("\n\t");
+ } else {
+ printf(" ");
+ }
+ printf("0x%02X", buf[u]);
+ }
+ printf("\n};\n");
+}
+
+static int
+write_to_file(const char *name, const void *data, size_t len)
+{
+ FILE *f;
+
+ f = fopen(name, "wb");
+ if (f == NULL) {
+ fprintf(stderr,
+ "ERROR: cannot open file '%s' for writing\n",
+ name);
+ return 0;
+ }
+ if (fwrite(data, 1, len, f) != len) {
+ fclose(f);
+ fprintf(stderr,
+ "ERROR: cannot write to file '%s'\n",
+ name);
+ return 0;
+ }
+ fclose(f);
+ return 1;
+}
+
+static int
+write_to_pem_file(const char *name,
+ const void *data, size_t len, const char *banner)
+{
+ void *pem;
+ size_t pemlen;
+ int r;
+
+ pemlen = br_pem_encode(NULL, NULL, len, banner, 0);
+ pem = xmalloc(pemlen + 1);
+ br_pem_encode(pem, data, len, banner, 0);
+ r = write_to_file(name, pem, pemlen);
+ xfree(pem);
+ return r;
+}
+
+static int
+print_rsa(const br_rsa_private_key *sk, outspec *os)
+{
+ int ret;
+ unsigned char *n, *d, *buf;
+ uint32_t e;
+ size_t nlen, dlen, len;
+ br_rsa_compute_modulus cm;
+ br_rsa_compute_pubexp ce;
+ br_rsa_compute_privexp cd;
+ br_rsa_public_key pk;
+ unsigned char ebuf[4];
+
+ n = NULL;
+ d = NULL;
+ buf = NULL;
+ ret = 1;
+ if (os->print_text) {
+ print_int_text("p ", sk->p, sk->plen);
+ print_int_text("q ", sk->q, sk->qlen);
+ print_int_text("dp", sk->dp, sk->dplen);
+ print_int_text("dq", sk->dq, sk->dqlen);
+ print_int_text("iq", sk->iq, sk->iqlen);
+ }
+ if (os->print_C) {
+ print_int_C("RSA_P", sk->p, sk->plen);
+ print_int_C("RSA_Q", sk->q, sk->qlen);
+ print_int_C("RSA_DP", sk->dp, sk->dplen);
+ print_int_C("RSA_DQ", sk->dq, sk->dqlen);
+ print_int_C("RSA_IQ", sk->iq, sk->iqlen);
+ printf("\nstatic const br_rsa_private_key RSA = {\n");
+ printf("\t%lu,\n", (unsigned long)sk->n_bitlen);
+ printf("\t(unsigned char *)RSA_P, sizeof RSA_P,\n");
+ printf("\t(unsigned char *)RSA_Q, sizeof RSA_Q,\n");
+ printf("\t(unsigned char *)RSA_DP, sizeof RSA_DP,\n");
+ printf("\t(unsigned char *)RSA_DQ, sizeof RSA_DQ,\n");
+ printf("\t(unsigned char *)RSA_IQ, sizeof RSA_IQ\n");
+ printf("};\n");
+ }
+
+ if (os->rawder == NULL && os->rawpem == NULL
+ && os->pk8der == NULL && os->pk8pem == NULL)
+ {
+ return ret;
+ }
+
+ cm = br_rsa_compute_modulus_get_default();
+ ce = br_rsa_compute_pubexp_get_default();
+ cd = br_rsa_compute_privexp_get_default();
+ nlen = cm(NULL, sk);
+ if (nlen == 0) {
+ goto print_RSA_error;
+ }
+ n = xmalloc(nlen);
+ if (cm(n, sk) != nlen) {
+ goto print_RSA_error;
+ }
+ e = ce(sk);
+ if (e == 0) {
+ goto print_RSA_error;
+ }
+ dlen = cd(NULL, sk, e);
+ if (dlen == 0) {
+ goto print_RSA_error;
+ }
+ d = xmalloc(dlen);
+ if (cd(d, sk, e) != dlen) {
+ goto print_RSA_error;
+ }
+ ebuf[0] = e >> 24;
+ ebuf[1] = e >> 16;
+ ebuf[2] = e >> 8;
+ ebuf[3] = e;
+ pk.n = n;
+ pk.nlen = nlen;
+ pk.e = ebuf;
+ pk.elen = sizeof ebuf;
+
+ if (os->rawder != NULL || os->rawpem != NULL) {
+ len = br_encode_rsa_raw_der(NULL, sk, &pk, d, dlen);
+ if (len == 0) {
+ goto print_RSA_error;
+ }
+ buf = xmalloc(len);
+ if (br_encode_rsa_raw_der(buf, sk, &pk, d, dlen) != len) {
+ goto print_RSA_error;
+ }
+ if (os->rawder != NULL) {
+ ret &= write_to_file(os->rawder, buf, len);
+ }
+ if (os->rawpem != NULL) {
+ ret &= write_to_pem_file(os->rawpem,
+ buf, len, "RSA PRIVATE KEY");
+ }
+ xfree(buf);
+ buf = NULL;
+ }
+
+ if (os->pk8der != NULL || os->pk8pem != NULL) {
+ len = br_encode_rsa_pkcs8_der(NULL, sk, &pk, d, dlen);
+ if (len == 0) {
+ goto print_RSA_error;
+ }
+ buf = xmalloc(len);
+ if (br_encode_rsa_pkcs8_der(buf, sk, &pk, d, dlen) != len) {
+ goto print_RSA_error;
+ }
+ if (os->pk8der != NULL) {
+ ret &= write_to_file(os->pk8der, buf, len);
+ }
+ if (os->pk8pem != NULL) {
+ ret &= write_to_pem_file(os->pk8pem,
+ buf, len, "PRIVATE KEY");
+ }
+ xfree(buf);
+ buf = NULL;
+ }
+
+print_RSA_exit:
+ xfree(n);
+ xfree(d);
+ xfree(buf);
+ return ret;
+
+print_RSA_error:
+ fprintf(stderr, "ERROR: cannot encode RSA key\n");
+ ret = 0;
+ goto print_RSA_exit;
+}
+
+static int
+print_ec(const br_ec_private_key *sk, outspec *os)
+{
+ br_ec_public_key pk;
+ unsigned kbuf[BR_EC_KBUF_PUB_MAX_SIZE];
+ unsigned char *buf;
+ size_t len;
+ int r;
+
+ if (os->print_text) {
+ print_int_text("x", sk->x, sk->xlen);
+ }
+ if (os->print_C) {
+ print_int_C("EC_X", sk->x, sk->xlen);
+ printf("\nstatic const br_ec_private_key EC = {\n");
+ printf("\t%d,\n", sk->curve);
+ printf("\t(unsigned char *)EC_X, sizeof EC_X\n");
+ printf("};\n");
+ }
+
+ if (os->rawder == NULL && os->rawpem == NULL
+ && os->pk8der == NULL && os->pk8pem == NULL)
+ {
+ return 1;
+ }
+ if (br_ec_compute_pub(br_ec_get_default(), &pk, kbuf, sk) == 0) {
+ fprintf(stderr,
+ "ERROR: cannot re-encode (unsupported curve)\n");
+ return 0;
+ }
+
+ r = 1;
+ if (os->rawder != NULL || os->rawpem != NULL) {
+ len = br_encode_ec_raw_der(NULL, sk, &pk);
+ if (len == 0) {
+ fprintf(stderr, "ERROR: cannot re-encode"
+ " (unsupported curve)\n");
+ return 0;
+ }
+ buf = xmalloc(len);
+ if (br_encode_ec_raw_der(buf, sk, &pk) != len) {
+ fprintf(stderr, "ERROR: re-encode failure\n");
+ xfree(buf);
+ return 0;
+ }
+ if (os->rawder != NULL) {
+ r &= write_to_file(os->rawder, buf, len);
+ }
+ if (os->rawpem != NULL) {
+ r &= write_to_pem_file(os->rawpem,
+ buf, len, "EC PRIVATE KEY");
+ }
+ xfree(buf);
+ }
+ if (os->pk8der != NULL || os->pk8pem != NULL) {
+ len = br_encode_ec_pkcs8_der(NULL, sk, &pk);
+ if (len == 0) {
+ fprintf(stderr, "ERROR: cannot re-encode"
+ " (unsupported curve)\n");
+ return 0;
+ }
+ buf = xmalloc(len);
+ if (br_encode_ec_pkcs8_der(buf, sk, &pk) != len) {
+ fprintf(stderr, "ERROR: re-encode failure\n");
+ xfree(buf);
+ return 0;
+ }
+ if (os->pk8der != NULL) {
+ r &= write_to_file(os->pk8der, buf, len);
+ }
+ if (os->pk8pem != NULL) {
+ r &= write_to_pem_file(os->pk8pem,
+ buf, len, "PRIVATE KEY");
+ }
+ xfree(buf);
+ }
+ return r;
+}
+
+static int
+parse_rsa_spec(const char *kgen_spec, unsigned *size, uint32_t *pubexp)
+{
+ const char *p;
+ char *end;
+ unsigned long ul;
+
+ p = kgen_spec;
+ if (*p != 'r' && *p != 'R') {
+ return 0;
+ }
+ p ++;
+ if (*p != 's' && *p != 'S') {
+ return 0;
+ }
+ p ++;
+ if (*p != 'a' && *p != 'A') {
+ return 0;
+ }
+ p ++;
+ if (*p == 0) {
+ *size = 2048;
+ *pubexp = 3;
+ return 1;
+ } else if (*p != ':') {
+ return 0;
+ }
+ p ++;
+ ul = strtoul(p, &end, 10);
+ if (ul < 512 || ul > 32768) {
+ return 0;
+ }
+ *size = ul;
+ p = end;
+ if (*p == 0) {
+ *pubexp = 3;
+ return 1;
+ } else if (*p != ':') {
+ return 0;
+ }
+ p ++;
+ ul = strtoul(p, &end, 10);
+ if ((ul & 1) == 0 || ul == 1 || ((ul >> 30) >> 2) != 0) {
+ return 0;
+ }
+ *pubexp = ul;
+ if (*end != 0) {
+ return 0;
+ }
+ return 1;
+}
+
+static int
+keygen_rsa(unsigned size, uint32_t pubexp, outspec *os)
+{
+ br_hmac_drbg_context rng;
+ br_prng_seeder seeder;
+ br_rsa_keygen kg;
+ br_rsa_private_key sk;
+ unsigned char *kbuf_priv;
+ uint32_t r;
+
+ seeder = br_prng_seeder_system(NULL);
+ if (seeder == 0) {
+ fprintf(stderr, "ERROR: no system source of randomness\n");
+ return 0;
+ }
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
+ if (!seeder(&rng.vtable)) {
+ fprintf(stderr, "ERROR: system source of randomness failed\n");
+ return 0;
+ }
+ kbuf_priv = xmalloc(BR_RSA_KBUF_PRIV_SIZE(size));
+ kg = br_rsa_keygen_get_default();
+ r = kg(&rng.vtable, &sk, kbuf_priv, NULL, NULL, size, pubexp);
+ if (!r) {
+ fprintf(stderr, "ERROR: RSA key pair generation failed\n");
+ } else {
+ r = print_rsa(&sk, os);
+ }
+ xfree(kbuf_priv);
+ return r;
+}
+
+static int
+parse_ec_spec(const char *kgen_spec, int *curve)
+{
+ const char *p;
+
+ *curve = 0;
+ p = kgen_spec;
+ if (*p != 'e' && *p != 'E') {
+ return 0;
+ }
+ p ++;
+ if (*p != 'c' && *p != 'C') {
+ return 0;
+ }
+ p ++;
+ if (*p == 0) {
+ *curve = BR_EC_secp256r1;
+ return 1;
+ }
+ if (*p != ':') {
+ return 0;
+ }
+ *curve = get_curve_by_name(p);
+ return *curve > 0;
+}
+
+static int
+keygen_ec(int curve, outspec *os)
+{
+ br_hmac_drbg_context rng;
+ br_prng_seeder seeder;
+ const br_ec_impl *impl;
+ br_ec_private_key sk;
+ unsigned char kbuf_priv[BR_EC_KBUF_PRIV_MAX_SIZE];
+ size_t len;
+
+ seeder = br_prng_seeder_system(NULL);
+ if (seeder == 0) {
+ fprintf(stderr, "ERROR: no system source of randomness\n");
+ return 0;
+ }
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, NULL, 0);
+ if (!seeder(&rng.vtable)) {
+ fprintf(stderr, "ERROR: system source of randomness failed\n");
+ return 0;
+ }
+ impl = br_ec_get_default();
+ len = br_ec_keygen(&rng.vtable, impl, &sk, kbuf_priv, curve);
+ if (len == 0) {
+ fprintf(stderr, "ERROR: curve is not supported\n");
+ return 0;
+ }
+ return print_ec(&sk, os);
+}
+
+static int
+decode_key(const unsigned char *buf, size_t len, outspec *os)
+{
+ br_skey_decoder_context dc;
+ int err, ret;
+
+ br_skey_decoder_init(&dc);
+ br_skey_decoder_push(&dc, buf, len);
+ err = br_skey_decoder_last_error(&dc);
+ if (err != 0) {
+ const char *errname, *errmsg;
+
+ fprintf(stderr, "ERROR (decoding): err=%d\n", err);
+ errname = find_error_name(err, &errmsg);
+ if (errname != NULL) {
+ fprintf(stderr, " %s: %s\n", errname, errmsg);
+ } else {
+ fprintf(stderr, " (unknown)\n");
+ }
+ return 0;
+ }
+ ret = 1;
+ switch (br_skey_decoder_key_type(&dc)) {
+ const br_rsa_private_key *rk;
+ const br_ec_private_key *ek;
+
+ case BR_KEYTYPE_RSA:
+ rk = br_skey_decoder_get_rsa(&dc);
+ printf("RSA key (%lu bits)\n", (unsigned long)rk->n_bitlen);
+ ret = print_rsa(rk, os);
+ break;
+
+ case BR_KEYTYPE_EC:
+ ek = br_skey_decoder_get_ec(&dc);
+ printf("EC key (curve = %d: %s)\n",
+ ek->curve, ec_curve_name(ek->curve));
+ ret = print_ec(ek, os);
+ break;
+
+ default:
+ fprintf(stderr, "Unknown key type: %d\n",
+ br_skey_decoder_key_type(&dc));
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static void
+usage_skey(void)
+{
+ fprintf(stderr,
+"usage: brssl skey [ options ] file...\n");
+ fprintf(stderr,
+"options:\n");
+ fprintf(stderr,
+" -q suppress verbose messages\n");
+ fprintf(stderr,
+" -text print private key details (human-readable)\n");
+ fprintf(stderr,
+" -C print private key details (C code)\n");
+ fprintf(stderr,
+" -rawder file save private key in 'file' (raw format, DER)\n");
+ fprintf(stderr,
+" -rawpem file save private key in 'file' (raw format, PEM)\n");
+ fprintf(stderr,
+" -pk8der file save private key in 'file' (PKCS#8 format, DER)\n");
+ fprintf(stderr,
+" -pk8pem file save private key in 'file' (PKCS#8 format, PEM)\n");
+ fprintf(stderr,
+" -gen spec generate a new key using the provided key specification\n");
+ fprintf(stderr,
+" -list list known elliptic curve names\n");
+ fprintf(stderr,
+"Key specification begins with a key type, followed by optional parameters\n");
+ fprintf(stderr,
+"that depend on the key type, separated by colon characters:\n");
+ fprintf(stderr,
+" rsa[:size[:pubexep]] RSA key (defaults: size = 2048, pubexp = 3)\n");
+ fprintf(stderr,
+" ec[:curvename] EC key (default curve: secp256r1)\n");
+}
+
+/* see brssl.h */
+int
+do_skey(int argc, char *argv[])
+{
+ int retcode;
+ int verbose;
+ int i, num_files;
+ outspec os;
+ unsigned char *buf;
+ size_t len;
+ pem_object *pos;
+ const char *kgen_spec;
+
+ retcode = 0;
+ verbose = 1;
+ os.print_text = 0;
+ os.print_C = 0;
+ os.rawder = NULL;
+ os.rawpem = NULL;
+ os.pk8der = NULL;
+ os.pk8pem = NULL;
+ num_files = 0;
+ buf = NULL;
+ pos = NULL;
+ kgen_spec = NULL;
+ for (i = 0; i < argc; i ++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (arg[0] != '-') {
+ num_files ++;
+ continue;
+ }
+ argv[i] = NULL;
+ if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
+ verbose = 1;
+ } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
+ verbose = 0;
+ } else if (eqstr(arg, "-text")) {
+ os.print_text = 1;
+ } else if (eqstr(arg, "-C")) {
+ os.print_C = 1;
+ } else if (eqstr(arg, "-rawder")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-rawder'\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ if (os.rawder != NULL) {
+ fprintf(stderr,
+ "ERROR: multiple '-rawder' options\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ os.rawder = argv[i];
+ argv[i] = NULL;
+ } else if (eqstr(arg, "-rawpem")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-rawpem'\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ if (os.rawpem != NULL) {
+ fprintf(stderr,
+ "ERROR: multiple '-rawpem' options\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ os.rawpem = argv[i];
+ argv[i] = NULL;
+ } else if (eqstr(arg, "-pk8der")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-pk8der'\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ if (os.pk8der != NULL) {
+ fprintf(stderr,
+ "ERROR: multiple '-pk8der' options\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ os.pk8der = argv[i];
+ argv[i] = NULL;
+ } else if (eqstr(arg, "-pk8pem")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-pk8pem'\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ if (os.pk8pem != NULL) {
+ fprintf(stderr,
+ "ERROR: multiple '-pk8pem' options\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ os.pk8pem = argv[i];
+ argv[i] = NULL;
+ } else if (eqstr(arg, "-gen")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-gen'\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ if (kgen_spec != NULL) {
+ fprintf(stderr,
+ "ERROR: multiple '-gen' options\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+ kgen_spec = argv[i];
+ argv[i] = NULL;
+ } else if (eqstr(arg, "-list")) {
+ list_curves();
+ goto skey_exit;
+ } else {
+ fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
+ usage_skey();
+ goto skey_exit_error;
+ }
+ }
+ if (kgen_spec != NULL) {
+ unsigned rsa_size;
+ uint32_t rsa_pubexp;
+ int curve;
+
+ if (num_files != 0) {
+ fprintf(stderr,
+ "ERROR: key files provided while generating\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+
+ if (parse_rsa_spec(kgen_spec, &rsa_size, &rsa_pubexp)) {
+ if (!keygen_rsa(rsa_size, rsa_pubexp, &os)) {
+ goto skey_exit_error;
+ }
+ } else if (parse_ec_spec(kgen_spec, &curve)) {
+ if (!keygen_ec(curve, &os)) {
+ goto skey_exit_error;
+ }
+ } else {
+ fprintf(stderr,
+ "ERROR: unknown key specification: '%s'\n",
+ kgen_spec);
+ usage_skey();
+ goto skey_exit_error;
+ }
+ } else if (num_files == 0) {
+ fprintf(stderr, "ERROR: no private key provided\n");
+ usage_skey();
+ goto skey_exit_error;
+ }
+
+ for (i = 0; i < argc; i ++) {
+ const char *fname;
+
+ fname = argv[i];
+ if (fname == NULL) {
+ continue;
+ }
+ buf = read_file(fname, &len);
+ if (buf == NULL) {
+ goto skey_exit_error;
+ }
+ if (looks_like_DER(buf, len)) {
+ if (verbose) {
+ fprintf(stderr, "File '%s': ASN.1/DER object\n",
+ fname);
+ }
+ if (!decode_key(buf, len, &os)) {
+ goto skey_exit_error;
+ }
+ } else {
+ size_t u, num;
+
+ if (verbose) {
+ fprintf(stderr, "File '%s': decoding as PEM\n",
+ fname);
+ }
+ pos = decode_pem(buf, len, &num);
+ if (pos == NULL) {
+ goto skey_exit_error;
+ }
+ for (u = 0; pos[u].name; u ++) {
+ const char *name;
+
+ name = pos[u].name;
+ if (eqstr(name, "RSA PRIVATE KEY")
+ || eqstr(name, "EC PRIVATE KEY")
+ || eqstr(name, "PRIVATE KEY"))
+ {
+ if (!decode_key(pos[u].data,
+ pos[u].data_len, &os))
+ {
+ goto skey_exit_error;
+ }
+ } else {
+ if (verbose) {
+ fprintf(stderr,
+ "(skipping '%s')\n",
+ name);
+ }
+ }
+ }
+ for (u = 0; pos[u].name; u ++) {
+ free_pem_object_contents(&pos[u]);
+ }
+ xfree(pos);
+ pos = NULL;
+ }
+ xfree(buf);
+ buf = NULL;
+ }
+
+ /*
+ * Release allocated structures.
+ */
+skey_exit:
+ xfree(buf);
+ if (pos != NULL) {
+ size_t u;
+
+ for (u = 0; pos[u].name; u ++) {
+ free_pem_object_contents(&pos[u]);
+ }
+ xfree(pos);
+ }
+ return retcode;
+
+skey_exit_error:
+ retcode = -1;
+ goto skey_exit;
+}
Property changes on: stable/12/contrib/bearssl/tools/skey.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/sslio.c
===================================================================
--- stable/12/contrib/bearssl/tools/sslio.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/sslio.c (revision 346145)
@@ -0,0 +1,760 @@
+/*
+ * 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>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+
+#define SOCKET int
+#define INVALID_SOCKET (-1)
+#endif
+
+#include "brssl.h"
+
+static void
+dump_blob(const char *name, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t u;
+
+ buf = data;
+ fprintf(stderr, "%s (len = %lu)", name, (unsigned long)len);
+ for (u = 0; u < len; u ++) {
+ if ((u & 15) == 0) {
+ fprintf(stderr, "\n%08lX ", (unsigned long)u);
+ } else if ((u & 7) == 0) {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, " %02x", buf[u]);
+ }
+ fprintf(stderr, "\n");
+}
+
+/*
+ * Inspect the provided data in case it is a "command" to trigger a
+ * special behaviour. If the command is recognised, then it is executed
+ * and this function returns 1. Otherwise, this function returns 0.
+ */
+static int
+run_command(br_ssl_engine_context *cc, unsigned char *buf, size_t len)
+{
+ /*
+ * A single static slot for saving session parameters.
+ */
+ static br_ssl_session_parameters slot;
+ static int slot_used = 0;
+
+ size_t u;
+
+ if (len < 2 || len > 3) {
+ return 0;
+ }
+ if (len == 3 && (buf[1] != '\r' || buf[2] != '\n')) {
+ return 0;
+ }
+ if (len == 2 && buf[1] != '\n') {
+ return 0;
+ }
+ switch (buf[0]) {
+ case 'Q':
+ fprintf(stderr, "closing...\n");
+ br_ssl_engine_close(cc);
+ return 1;
+ case 'R':
+ if (br_ssl_engine_renegotiate(cc)) {
+ fprintf(stderr, "renegotiating...\n");
+ } else {
+ fprintf(stderr, "not renegotiating.\n");
+ }
+ return 1;
+ case 'F':
+ /*
+ * Session forget is nominally client-only. But the
+ * session parameters are in the engine structure, which
+ * is the first field of the client context, so the cast
+ * still works properly. On the server, this forgetting
+ * has no effect.
+ */
+ fprintf(stderr, "forgetting session...\n");
+ br_ssl_client_forget_session((br_ssl_client_context *)cc);
+ return 1;
+ case 'S':
+ fprintf(stderr, "saving session parameters...\n");
+ br_ssl_engine_get_session_parameters(cc, &slot);
+ fprintf(stderr, " id = ");
+ for (u = 0; u < slot.session_id_len; u ++) {
+ fprintf(stderr, "%02X", slot.session_id[u]);
+ }
+ fprintf(stderr, "\n");
+ slot_used = 1;
+ return 1;
+ case 'P':
+ if (slot_used) {
+ fprintf(stderr, "restoring session parameters...\n");
+ fprintf(stderr, " id = ");
+ for (u = 0; u < slot.session_id_len; u ++) {
+ fprintf(stderr, "%02X", slot.session_id[u]);
+ }
+ fprintf(stderr, "\n");
+ br_ssl_engine_set_session_parameters(cc, &slot);
+ return 1;
+ }
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+#ifdef _WIN32
+
+typedef struct {
+ unsigned char buf[1024];
+ size_t ptr, len;
+} in_buffer;
+
+static int
+in_return_bytes(in_buffer *bb, unsigned char *buf, size_t len)
+{
+ if (bb->ptr < bb->len) {
+ size_t clen;
+
+ if (buf == NULL) {
+ return 1;
+ }
+ clen = bb->len - bb->ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(buf, bb->buf + bb->ptr, clen);
+ bb->ptr += clen;
+ if (bb->ptr == bb->len) {
+ bb->ptr = bb->len = 0;
+ }
+ return (int)clen;
+ }
+ return 0;
+}
+
+/*
+ * A buffered version of in_read(), using a buffer to return only
+ * full lines when feasible.
+ */
+static int
+in_read_buffered(HANDLE h_in, in_buffer *bb, unsigned char *buf, size_t len)
+{
+ int n;
+
+ if (len == 0) {
+ return 0;
+ }
+ n = in_return_bytes(bb, buf, len);
+ if (n != 0) {
+ return n;
+ }
+ for (;;) {
+ INPUT_RECORD inrec;
+ DWORD v;
+
+ if (!PeekConsoleInput(h_in, &inrec, 1, &v)) {
+ fprintf(stderr, "ERROR: PeekConsoleInput()"
+ " failed with 0x%08lX\n",
+ (unsigned long)GetLastError());
+ return -1;
+ }
+ if (v == 0) {
+ return 0;
+ }
+ if (!ReadConsoleInput(h_in, &inrec, 1, &v)) {
+ fprintf(stderr, "ERROR: ReadConsoleInput()"
+ " failed with 0x%08lX\n",
+ (unsigned long)GetLastError());
+ return -1;
+ }
+ if (v == 0) {
+ return 0;
+ }
+ if (inrec.EventType == KEY_EVENT
+ && inrec.Event.KeyEvent.bKeyDown)
+ {
+ int c;
+
+ c = inrec.Event.KeyEvent.uChar.AsciiChar;
+ if (c == '\n' || c == '\r' || c == '\t'
+ || (c >= 32 && c != 127))
+ {
+ if (c == '\r') {
+ c = '\n';
+ }
+ bb->buf[bb->ptr ++] = (unsigned char)c;
+ printf("%c", c);
+ fflush(stdout);
+ bb->len = bb->ptr;
+ if (bb->len == sizeof bb->buf || c == '\n') {
+ bb->ptr = 0;
+ return in_return_bytes(bb, buf, len);
+ }
+ }
+ }
+ }
+}
+
+static int
+in_avail_buffered(HANDLE h_in, in_buffer *bb)
+{
+ return in_read_buffered(h_in, bb, NULL, 1);
+}
+
+#endif
+
+/* see brssl.h */
+int
+run_ssl_engine(br_ssl_engine_context *cc, unsigned long fd, unsigned flags)
+{
+ int hsdetails;
+ int retcode;
+ int verbose;
+ int trace;
+#ifdef _WIN32
+ WSAEVENT fd_event;
+ int can_send, can_recv;
+ HANDLE h_in, h_out;
+ in_buffer bb;
+#endif
+
+ hsdetails = 0;
+ retcode = 0;
+ verbose = (flags & RUN_ENGINE_VERBOSE) != 0;
+ trace = (flags & RUN_ENGINE_TRACE) != 0;
+
+ /*
+ * Print algorithm details.
+ */
+ if (verbose) {
+ const char *rngname;
+
+ fprintf(stderr, "Algorithms:\n");
+ br_prng_seeder_system(&rngname);
+ fprintf(stderr, " RNG: %s\n", rngname);
+ if (cc->iaes_cbcenc != 0) {
+ fprintf(stderr, " AES/CBC (enc): %s\n",
+ get_algo_name(cc->iaes_cbcenc, 0));
+ }
+ if (cc->iaes_cbcdec != 0) {
+ fprintf(stderr, " AES/CBC (dec): %s\n",
+ get_algo_name(cc->iaes_cbcdec, 0));
+ }
+ if (cc->iaes_ctr != 0) {
+ fprintf(stderr, " AES/CTR: %s\n",
+ get_algo_name(cc->iaes_cbcdec, 0));
+ }
+ if (cc->iaes_ctrcbc != 0) {
+ fprintf(stderr, " AES/CCM: %s\n",
+ get_algo_name(cc->iaes_ctrcbc, 0));
+ }
+ if (cc->ides_cbcenc != 0) {
+ fprintf(stderr, " DES/CBC (enc): %s\n",
+ get_algo_name(cc->ides_cbcenc, 0));
+ }
+ if (cc->ides_cbcdec != 0) {
+ fprintf(stderr, " DES/CBC (dec): %s\n",
+ get_algo_name(cc->ides_cbcdec, 0));
+ }
+ if (cc->ighash != 0) {
+ fprintf(stderr, " GHASH (GCM): %s\n",
+ get_algo_name(cc->ighash, 0));
+ }
+ if (cc->ichacha != 0) {
+ fprintf(stderr, " ChaCha20: %s\n",
+ get_algo_name(cc->ichacha, 0));
+ }
+ if (cc->ipoly != 0) {
+ fprintf(stderr, " Poly1305: %s\n",
+ get_algo_name(cc->ipoly, 0));
+ }
+ if (cc->iec != 0) {
+ fprintf(stderr, " EC: %s\n",
+ get_algo_name(cc->iec, 0));
+ }
+ if (cc->iecdsa != 0) {
+ fprintf(stderr, " ECDSA: %s\n",
+ get_algo_name(cc->iecdsa, 0));
+ }
+ if (cc->irsavrfy != 0) {
+ fprintf(stderr, " RSA (vrfy): %s\n",
+ get_algo_name(cc->irsavrfy, 0));
+ }
+ }
+
+#ifdef _WIN32
+ fd_event = WSA_INVALID_EVENT;
+ can_send = 0;
+ can_recv = 0;
+ bb.ptr = bb.len = 0;
+#endif
+
+ /*
+ * On Unix systems, we need to follow three descriptors:
+ * standard input (0), standard output (1), and the socket
+ * itself (for both read and write). This is done with a poll()
+ * call.
+ *
+ * On Windows systems, we use WSAEventSelect() to associate
+ * an event handle with the network activity, and we use
+ * WaitForMultipleObjectsEx() on that handle and the standard
+ * input handle, when appropriate. Standard output is assumed
+ * to be always writeable, and standard input to be the console;
+ * this does not work well (or at all) with redirections (to
+ * pipes or files) but it should be enough for a debug tool
+ * (TODO: make something that handles redirections as well).
+ */
+
+#ifdef _WIN32
+ fd_event = WSACreateEvent();
+ if (fd_event == WSA_INVALID_EVENT) {
+ fprintf(stderr, "ERROR: WSACreateEvent() failed with %d\n",
+ WSAGetLastError());
+ retcode = -2;
+ goto engine_exit;
+ }
+ WSAEventSelect(fd, fd_event, FD_READ | FD_WRITE | FD_CLOSE);
+ h_in = GetStdHandle(STD_INPUT_HANDLE);
+ h_out = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetConsoleMode(h_in, ENABLE_ECHO_INPUT
+ | ENABLE_LINE_INPUT
+ | ENABLE_PROCESSED_INPUT
+ | ENABLE_PROCESSED_OUTPUT
+ | ENABLE_WRAP_AT_EOL_OUTPUT);
+#else
+ /*
+ * Make sure that stdin and stdout are non-blocking.
+ */
+ fcntl(0, F_SETFL, O_NONBLOCK);
+ fcntl(1, F_SETFL, O_NONBLOCK);
+#endif
+
+ /*
+ * Perform the loop.
+ */
+ for (;;) {
+ unsigned st;
+ int sendrec, recvrec, sendapp, recvapp;
+#ifdef _WIN32
+ HANDLE pfd[2];
+ DWORD wt;
+#else
+ struct pollfd pfd[3];
+ int n;
+#endif
+ size_t u, k_fd, k_in, k_out;
+ int sendrec_ok, recvrec_ok, sendapp_ok, recvapp_ok;
+
+ /*
+ * Get current engine state.
+ */
+ st = br_ssl_engine_current_state(cc);
+ if (st == BR_SSL_CLOSED) {
+ int err;
+
+ err = br_ssl_engine_last_error(cc);
+ if (err == BR_ERR_OK) {
+ if (verbose) {
+ fprintf(stderr,
+ "SSL closed normally\n");
+ }
+ retcode = 0;
+ goto engine_exit;
+ } else {
+ fprintf(stderr, "ERROR: SSL error %d", err);
+ retcode = err;
+ if (err >= BR_ERR_SEND_FATAL_ALERT) {
+ err -= BR_ERR_SEND_FATAL_ALERT;
+ fprintf(stderr,
+ " (sent alert %d)\n", err);
+ } else if (err >= BR_ERR_RECV_FATAL_ALERT) {
+ err -= BR_ERR_RECV_FATAL_ALERT;
+ fprintf(stderr,
+ " (received alert %d)\n", err);
+ } else {
+ const char *ename;
+
+ ename = find_error_name(err, NULL);
+ if (ename == NULL) {
+ ename = "unknown";
+ }
+ fprintf(stderr, " (%s)\n", ename);
+ }
+ goto engine_exit;
+ }
+ }
+
+ /*
+ * Compute descriptors that must be polled, depending
+ * on engine state.
+ */
+ sendrec = ((st & BR_SSL_SENDREC) != 0);
+ recvrec = ((st & BR_SSL_RECVREC) != 0);
+ sendapp = ((st & BR_SSL_SENDAPP) != 0);
+ recvapp = ((st & BR_SSL_RECVAPP) != 0);
+ if (verbose && sendapp && !hsdetails) {
+ char csn[80];
+ const char *pname;
+
+ fprintf(stderr, "Handshake completed\n");
+ fprintf(stderr, " version: ");
+ switch (cc->session.version) {
+ case BR_SSL30:
+ fprintf(stderr, "SSL 3.0");
+ break;
+ case BR_TLS10:
+ fprintf(stderr, "TLS 1.0");
+ break;
+ case BR_TLS11:
+ fprintf(stderr, "TLS 1.1");
+ break;
+ case BR_TLS12:
+ fprintf(stderr, "TLS 1.2");
+ break;
+ default:
+ fprintf(stderr, "unknown (0x%04X)",
+ (unsigned)cc->session.version);
+ break;
+ }
+ fprintf(stderr, "\n");
+ get_suite_name_ext(
+ cc->session.cipher_suite, csn, sizeof csn);
+ fprintf(stderr, " cipher suite: %s\n", csn);
+ if (uses_ecdhe(cc->session.cipher_suite)) {
+ get_curve_name_ext(
+ br_ssl_engine_get_ecdhe_curve(cc),
+ csn, sizeof csn);
+ fprintf(stderr,
+ " ECDHE curve: %s\n", csn);
+ }
+ fprintf(stderr, " secure renegotiation: %s\n",
+ cc->reneg == 1 ? "no" : "yes");
+ pname = br_ssl_engine_get_selected_protocol(cc);
+ if (pname != NULL) {
+ fprintf(stderr,
+ " protocol name (ALPN): %s\n",
+ pname);
+ }
+ hsdetails = 1;
+ }
+
+ k_fd = (size_t)-1;
+ k_in = (size_t)-1;
+ k_out = (size_t)-1;
+
+ u = 0;
+#ifdef _WIN32
+ /*
+ * If we recorded that we can send or receive data, and we
+ * want to do exactly that, then we don't wait; we just do
+ * it.
+ */
+ recvapp_ok = 0;
+ sendrec_ok = 0;
+ recvrec_ok = 0;
+ sendapp_ok = 0;
+
+ if (sendrec && can_send) {
+ sendrec_ok = 1;
+ } else if (recvrec && can_recv) {
+ recvrec_ok = 1;
+ } else if (recvapp) {
+ recvapp_ok = 1;
+ } else if (sendapp && in_avail_buffered(h_in, &bb)) {
+ sendapp_ok = 1;
+ } else {
+ /*
+ * If we cannot do I/O right away, then we must
+ * wait for some event, and try again.
+ */
+ pfd[u] = (HANDLE)fd_event;
+ k_fd = u;
+ u ++;
+ if (sendapp) {
+ pfd[u] = h_in;
+ k_in = u;
+ u ++;
+ }
+ wt = WaitForMultipleObjectsEx(u, pfd,
+ FALSE, INFINITE, FALSE);
+ if (wt == WAIT_FAILED) {
+ fprintf(stderr, "ERROR:"
+ " WaitForMultipleObjectsEx()"
+ " failed with 0x%08lX",
+ (unsigned long)GetLastError());
+ retcode = -2;
+ goto engine_exit;
+ }
+ if (wt == k_fd) {
+ WSANETWORKEVENTS e;
+
+ if (WSAEnumNetworkEvents(fd, fd_event, &e)) {
+ fprintf(stderr, "ERROR:"
+ " WSAEnumNetworkEvents()"
+ " failed with %d\n",
+ WSAGetLastError());
+ retcode = -2;
+ goto engine_exit;
+ }
+ if (e.lNetworkEvents & (FD_WRITE | FD_CLOSE)) {
+ can_send = 1;
+ }
+ if (e.lNetworkEvents & (FD_READ | FD_CLOSE)) {
+ can_recv = 1;
+ }
+ }
+ continue;
+ }
+#else
+ if (sendrec || recvrec) {
+ pfd[u].fd = fd;
+ pfd[u].revents = 0;
+ pfd[u].events = 0;
+ if (sendrec) {
+ pfd[u].events |= POLLOUT;
+ }
+ if (recvrec) {
+ pfd[u].events |= POLLIN;
+ }
+ k_fd = u;
+ u ++;
+ }
+ if (sendapp) {
+ pfd[u].fd = 0;
+ pfd[u].revents = 0;
+ pfd[u].events = POLLIN;
+ k_in = u;
+ u ++;
+ }
+ if (recvapp) {
+ pfd[u].fd = 1;
+ pfd[u].revents = 0;
+ pfd[u].events = POLLOUT;
+ k_out = u;
+ u ++;
+ }
+ n = poll(pfd, u, -1);
+ if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ perror("ERROR: poll()");
+ retcode = -2;
+ goto engine_exit;
+ }
+ if (n == 0) {
+ continue;
+ }
+
+ /*
+ * We transform closures/errors into read+write accesses
+ * so as to force the read() or write() call that will
+ * detect the situation.
+ */
+ while (u -- > 0) {
+ if (pfd[u].revents & (POLLERR | POLLHUP)) {
+ pfd[u].revents |= POLLIN | POLLOUT;
+ }
+ }
+
+ recvapp_ok = recvapp && (pfd[k_out].revents & POLLOUT) != 0;
+ sendrec_ok = sendrec && (pfd[k_fd].revents & POLLOUT) != 0;
+ recvrec_ok = recvrec && (pfd[k_fd].revents & POLLIN) != 0;
+ sendapp_ok = sendapp && (pfd[k_in].revents & POLLIN) != 0;
+#endif
+
+ /*
+ * We give preference to outgoing data, on stdout and on
+ * the socket.
+ */
+ if (recvapp_ok) {
+ unsigned char *buf;
+ size_t len;
+#ifdef _WIN32
+ DWORD wlen;
+#else
+ ssize_t wlen;
+#endif
+
+ buf = br_ssl_engine_recvapp_buf(cc, &len);
+#ifdef _WIN32
+ if (!WriteFile(h_out, buf, len, &wlen, NULL)) {
+ if (verbose) {
+ fprintf(stderr, "stdout closed...\n");
+ }
+ retcode = -2;
+ goto engine_exit;
+ }
+#else
+ wlen = write(1, buf, len);
+ if (wlen <= 0) {
+ if (verbose) {
+ fprintf(stderr, "stdout closed...\n");
+ }
+ retcode = -2;
+ goto engine_exit;
+ }
+#endif
+ br_ssl_engine_recvapp_ack(cc, wlen);
+ continue;
+ }
+ if (sendrec_ok) {
+ unsigned char *buf;
+ size_t len;
+ int wlen;
+
+ buf = br_ssl_engine_sendrec_buf(cc, &len);
+ wlen = send(fd, buf, len, 0);
+ if (wlen <= 0) {
+#ifdef _WIN32
+ int err;
+
+ err = WSAGetLastError();
+ if (err == EWOULDBLOCK
+ || err == WSAEWOULDBLOCK)
+ {
+ can_send = 0;
+ continue;
+ }
+#else
+ if (errno == EINTR || errno == EWOULDBLOCK) {
+ continue;
+ }
+#endif
+ if (verbose) {
+ fprintf(stderr, "socket closed...\n");
+ }
+ retcode = -1;
+ goto engine_exit;
+ }
+ if (trace) {
+ dump_blob("Outgoing bytes", buf, wlen);
+ }
+ br_ssl_engine_sendrec_ack(cc, wlen);
+ continue;
+ }
+ if (recvrec_ok) {
+ unsigned char *buf;
+ size_t len;
+ int rlen;
+
+ buf = br_ssl_engine_recvrec_buf(cc, &len);
+ rlen = recv(fd, buf, len, 0);
+ if (rlen == 0) {
+ if (verbose) {
+ fprintf(stderr, "socket closed...\n");
+ }
+ retcode = -1;
+ goto engine_exit;
+ }
+ if (rlen < 0) {
+#ifdef _WIN32
+ int err;
+
+ err = WSAGetLastError();
+ if (err == EWOULDBLOCK
+ || err == WSAEWOULDBLOCK)
+ {
+ can_recv = 0;
+ continue;
+ }
+#else
+ if (errno == EINTR || errno == EWOULDBLOCK) {
+ continue;
+ }
+#endif
+ if (verbose) {
+ fprintf(stderr, "socket broke...\n");
+ }
+ retcode = -1;
+ goto engine_exit;
+ }
+ if (trace) {
+ dump_blob("Incoming bytes", buf, rlen);
+ }
+ br_ssl_engine_recvrec_ack(cc, rlen);
+ continue;
+ }
+ if (sendapp_ok) {
+ unsigned char *buf;
+ size_t len;
+#ifdef _WIN32
+ int rlen;
+#else
+ ssize_t rlen;
+#endif
+
+ buf = br_ssl_engine_sendapp_buf(cc, &len);
+#ifdef _WIN32
+ rlen = in_read_buffered(h_in, &bb, buf, len);
+#else
+ rlen = read(0, buf, len);
+#endif
+ if (rlen <= 0) {
+ if (verbose) {
+ fprintf(stderr, "stdin closed...\n");
+ }
+ br_ssl_engine_close(cc);
+ } else if (!run_command(cc, buf, rlen)) {
+ br_ssl_engine_sendapp_ack(cc, rlen);
+ }
+ br_ssl_engine_flush(cc, 0);
+ continue;
+ }
+
+ /* We should never reach that point. */
+ fprintf(stderr, "ERROR: poll() misbehaves\n");
+ retcode = -2;
+ goto engine_exit;
+ }
+
+ /*
+ * Release allocated structures.
+ */
+engine_exit:
+#ifdef _WIN32
+ if (fd_event != WSA_INVALID_EVENT) {
+ WSACloseEvent(fd_event);
+ }
+#endif
+ return retcode;
+}
Property changes on: stable/12/contrib/bearssl/tools/sslio.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/ta.c
===================================================================
--- stable/12/contrib/bearssl/tools/ta.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/ta.c (revision 346145)
@@ -0,0 +1,254 @@
+/*
+ * 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 "brssl.h"
+#include "bearssl.h"
+
+static const char *
+curve_to_sym(int curve)
+{
+ switch (curve) {
+ case BR_EC_sect163k1: return "BR_EC_sect163k1";
+ case BR_EC_sect163r1: return "BR_EC_sect163r1";
+ case BR_EC_sect163r2: return "BR_EC_sect163r2";
+ case BR_EC_sect193r1: return "BR_EC_sect193r1";
+ case BR_EC_sect193r2: return "BR_EC_sect193r2";
+ case BR_EC_sect233k1: return "BR_EC_sect233k1";
+ case BR_EC_sect233r1: return "BR_EC_sect233r1";
+ case BR_EC_sect239k1: return "BR_EC_sect239k1";
+ case BR_EC_sect283k1: return "BR_EC_sect283k1";
+ case BR_EC_sect283r1: return "BR_EC_sect283r1";
+ case BR_EC_sect409k1: return "BR_EC_sect409k1";
+ case BR_EC_sect409r1: return "BR_EC_sect409r1";
+ case BR_EC_sect571k1: return "BR_EC_sect571k1";
+ case BR_EC_sect571r1: return "BR_EC_sect571r1";
+ case BR_EC_secp160k1: return "BR_EC_secp160k1";
+ case BR_EC_secp160r1: return "BR_EC_secp160r1";
+ case BR_EC_secp160r2: return "BR_EC_secp160r2";
+ case BR_EC_secp192k1: return "BR_EC_secp192k1";
+ case BR_EC_secp192r1: return "BR_EC_secp192r1";
+ case BR_EC_secp224k1: return "BR_EC_secp224k1";
+ case BR_EC_secp224r1: return "BR_EC_secp224r1";
+ case BR_EC_secp256k1: return "BR_EC_secp256k1";
+ case BR_EC_secp256r1: return "BR_EC_secp256r1";
+ case BR_EC_secp384r1: return "BR_EC_secp384r1";
+ case BR_EC_secp521r1: return "BR_EC_secp521r1";
+ case BR_EC_brainpoolP256r1: return "BR_EC_brainpoolP256r1";
+ case BR_EC_brainpoolP384r1: return "BR_EC_brainpoolP384r1";
+ case BR_EC_brainpoolP512r1: return "BR_EC_brainpoolP512r1";
+ }
+ return NULL;
+}
+
+static void
+print_blob(const char *name, const unsigned char *buf, size_t len)
+{
+ size_t u;
+
+ printf("\nstatic const unsigned char %s[] = {", name);
+ for (u = 0; u < len; u ++) {
+ if (u != 0) {
+ printf(",");
+ }
+ if (u % 12 == 0) {
+ printf("\n\t");
+ } else {
+ printf(" ");
+ }
+ printf("0x%02X", buf[u]);
+ }
+ printf("\n};\n");
+}
+
+static int
+print_ta_internals(br_x509_trust_anchor *ta, long ctr)
+{
+ char tmp[25];
+
+ sprintf(tmp, "TA%ld_DN", ctr);
+ print_blob(tmp, ta->dn.data, ta->dn.len);
+ switch (ta->pkey.key_type) {
+ case BR_KEYTYPE_RSA:
+ sprintf(tmp, "TA%ld_RSA_N", ctr);
+ print_blob(tmp, ta->pkey.key.rsa.n, ta->pkey.key.rsa.nlen);
+ sprintf(tmp, "TA%ld_RSA_E", ctr);
+ print_blob(tmp, ta->pkey.key.rsa.e, ta->pkey.key.rsa.elen);
+ break;
+ case BR_KEYTYPE_EC:
+ sprintf(tmp, "TA%ld_EC_Q", ctr);
+ print_blob(tmp, ta->pkey.key.ec.q, ta->pkey.key.ec.qlen);
+ break;
+ default:
+ fprintf(stderr, "ERROR: unknown anchor key type '%d'\n",
+ ta->pkey.key_type);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+print_ta(br_x509_trust_anchor *ta, long ctr)
+{
+ char tmp[25];
+
+ printf("\t{\n");
+ printf("\t\t{ (unsigned char *)TA%ld_DN, sizeof TA%ld_DN },\n",
+ ctr, ctr);
+ printf("\t\t%s,\n", (ta->flags & BR_X509_TA_CA)
+ ? "BR_X509_TA_CA" : "0");
+ printf("\t\t{\n");
+ switch (ta->pkey.key_type) {
+ const char *cname;
+
+ case BR_KEYTYPE_RSA:
+ printf("\t\t\tBR_KEYTYPE_RSA,\n");
+ printf("\t\t\t{ .rsa = {\n");
+ printf("\t\t\t\t(unsigned char *)TA%ld_RSA_N,"
+ " sizeof TA%ld_RSA_N,\n", ctr, ctr);
+ printf("\t\t\t\t(unsigned char *)TA%ld_RSA_E,"
+ " sizeof TA%ld_RSA_E,\n", ctr, ctr);
+ printf("\t\t\t} }\n");
+ break;
+ case BR_KEYTYPE_EC:
+ printf("\t\t\tBR_KEYTYPE_EC,\n");
+ printf("\t\t\t{ .ec = {\n");
+ cname = curve_to_sym(ta->pkey.key.ec.curve);
+ if (cname == NULL) {
+ sprintf(tmp, "%d", ta->pkey.key.ec.curve);
+ cname = tmp;
+ }
+ printf("\t\t\t\t%s,\n", cname);
+ printf("\t\t\t\t(unsigned char *)TA%ld_EC_Q,"
+ " sizeof TA%ld_EC_Q,\n", ctr, ctr);
+ printf("\t\t\t} }\n");
+ }
+ printf("\t\t}\n");
+ printf("\t}");
+}
+
+static void
+usage_ta(void)
+{
+ fprintf(stderr,
+"usage: brssl ta [ options ] file...\n");
+ fprintf(stderr,
+"options:\n");
+ fprintf(stderr,
+" -q suppress verbose messages\n");
+}
+
+/* see brssl.h */
+int
+do_ta(int argc, char *argv[])
+{
+ int retcode;
+ int verbose;
+ int i, num_files;
+ anchor_list tas = VEC_INIT;
+ size_t u, num;
+
+ retcode = 0;
+ verbose = 1;
+ num_files = 0;
+ for (i = 0; i < argc; i ++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (arg[0] != '-') {
+ num_files ++;
+ continue;
+ }
+ argv[i] = NULL;
+ if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
+ verbose = 1;
+ } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
+ verbose = 0;
+ } else {
+ fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
+ usage_ta();
+ goto ta_exit_error;
+ }
+ }
+ if (num_files == 0) {
+ fprintf(stderr, "ERROR: no certificate file provided\n");
+ usage_ta();
+ goto ta_exit_error;
+ }
+
+ for (i = 0; i < argc; i ++) {
+ const char *fname;
+ size_t len1, len2;
+
+ fname = argv[i];
+ if (fname == NULL) {
+ continue;
+ }
+ if (verbose) {
+ fprintf(stderr, "Reading file '%s': ", fname);
+ fflush(stderr);
+ }
+ len1 = VEC_LEN(tas);
+ if (read_trust_anchors(&tas, fname) == 0) {
+ goto ta_exit_error;
+ }
+ len2 = VEC_LEN(tas) - len1;
+ if (verbose) {
+ fprintf(stderr, "%lu trust anchor%s\n",
+ (unsigned long)len2, len2 > 1 ? "s" : "");
+ }
+ }
+ num = VEC_LEN(tas);
+ for (u = 0; u < num; u ++) {
+ if (print_ta_internals(&VEC_ELT(tas, u), u) < 0) {
+ goto ta_exit_error;
+ }
+ }
+ printf("\nstatic const br_x509_trust_anchor TAs[%ld] = {", (long)num);
+ for (u = 0; u < num; u ++) {
+ if (u != 0) {
+ printf(",");
+ }
+ printf("\n");
+ print_ta(&VEC_ELT(tas, u), u);
+ }
+ printf("\n};\n");
+ printf("\n#define TAs_NUM %ld\n", (long)num);
+
+ /*
+ * Release allocated structures.
+ */
+ta_exit:
+ VEC_CLEAREXT(tas, free_ta_contents);
+ return retcode;
+
+ta_exit_error:
+ retcode = -1;
+ goto ta_exit;
+}
Property changes on: stable/12/contrib/bearssl/tools/ta.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/twrch.c
===================================================================
--- stable/12/contrib/bearssl/tools/twrch.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/twrch.c (revision 346145)
@@ -0,0 +1,1069 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include "brssl.h"
+
+static int verbose = 0;
+
+static void
+usage_twrch(void)
+{
+ fprintf(stderr,
+"usage: brssl twrch [ options ]\n");
+ fprintf(stderr,
+"options:\n");
+ fprintf(stderr,
+" -trace dump all packets on stderr\n");
+ fprintf(stderr,
+" -v verbose error messages on stderr\n");
+ fprintf(stderr,
+" -server act as an SSL server\n");
+ fprintf(stderr,
+" -client act as an SSL client\n");
+ fprintf(stderr,
+" -sni name use specified name for SNI\n");
+ fprintf(stderr,
+" -mono use monodirectional buffering\n");
+ fprintf(stderr,
+" -buf length set the I/O buffer length (in bytes)\n");
+ fprintf(stderr,
+" -cache length set the session cache storage length (in bytes)\n");
+ fprintf(stderr,
+" -cert fname read certificate chain from file 'fname'\n");
+ fprintf(stderr,
+" -key fname read private key from file 'fname'\n");
+ fprintf(stderr,
+" -CA file add trust anchors from 'file' (for peer auth)\n");
+ fprintf(stderr,
+" -anon_ok request but do not require a client certificate\n");
+ fprintf(stderr,
+" -nostaticecdh prohibit full-static ECDH (client only)\n");
+ fprintf(stderr,
+" -list list supported names (protocols, algorithms...)\n");
+ fprintf(stderr,
+" -vmin name set minimum supported version (default: TLS-1.0)\n");
+ fprintf(stderr,
+" -vmax name set maximum supported version (default: TLS-1.2)\n");
+ fprintf(stderr,
+" -cs names set list of supported cipher suites (comma-separated)\n");
+ fprintf(stderr,
+" -hf names add support for some hash functions (comma-separated)\n");
+ fprintf(stderr,
+" -minhello len set minimum ClientHello length (in bytes)\n");
+ fprintf(stderr,
+" -serverpref enforce server's preferences for cipher suites\n");
+ fprintf(stderr,
+" -noreneg prohibit renegotiations\n");
+ fprintf(stderr,
+" -alpn name add protocol name to list of protocols (ALPN extension)\n");
+ fprintf(stderr,
+" -strictalpn fail on ALPN mismatch\n");
+}
+
+static void
+free_alpn(void *alpn)
+{
+ xfree(*(char **)alpn);
+}
+
+static void
+dump_blob(const char *name, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t u;
+
+ buf = data;
+ fprintf(stderr, "%s (len = %lu)", name, (unsigned long)len);
+ for (u = 0; u < len; u ++) {
+ if ((u & 15) == 0) {
+ fprintf(stderr, "\n%08lX ", (unsigned long)u);
+ } else if ((u & 7) == 0) {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, " %02x", buf[u]);
+ }
+ fprintf(stderr, "\n");
+}
+
+/*
+ * Callback for reading bytes from standard input.
+ */
+static int
+stdin_read(void *ctx, unsigned char *buf, size_t len)
+{
+ for (;;) {
+#ifdef _WIN32
+ DWORD rlen;
+#else
+ ssize_t rlen;
+#endif
+ int eof;
+
+#ifdef _WIN32
+ eof = !ReadFile(GetStdHandle(STD_INPUT_HANDLE),
+ buf, len, &rlen, NULL) || rlen == 0;
+#else
+ rlen = read(0, buf, len);
+ if (rlen <= 0) {
+ if (rlen < 0 && errno == EINTR) {
+ continue;
+ }
+ eof = 1;
+ } else {
+ eof = 0;
+ }
+#endif
+ if (eof) {
+ if (*(int *)ctx) {
+ if (verbose) {
+ fprintf(stderr, "recv: EOF\n");
+ }
+ }
+ return -1;
+ }
+ if (*(int *)ctx) {
+ dump_blob("recv", buf, (size_t)rlen);
+ }
+ return (int)rlen;
+ }
+}
+
+/*
+ * Callback for writing bytes on standard output.
+ */
+static int
+stdout_write(void *ctx, const unsigned char *buf, size_t len)
+{
+ for (;;) {
+#ifdef _WIN32
+ DWORD wlen;
+#else
+ ssize_t wlen;
+#endif
+ int eof;
+
+#ifdef _WIN32
+ eof = !WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
+ buf, len, &wlen, NULL);
+#else
+ wlen = write(1, buf, len);
+ if (wlen <= 0) {
+ if (wlen < 0 && errno == EINTR) {
+ continue;
+ }
+ eof = 1;
+ } else {
+ eof = 0;
+ }
+#endif
+ if (eof) {
+ if (*(int *)ctx) {
+ if (verbose) {
+ fprintf(stderr, "send: EOF\n");
+ }
+ }
+ return -1;
+ }
+ if (*(int *)ctx) {
+ dump_blob("send", buf, (size_t)wlen);
+ }
+ return (int)wlen;
+ }
+}
+
+static void
+print_error(int err)
+{
+ const char *name, *comment;
+
+ name = find_error_name(err, &comment);
+ if (name != NULL) {
+ fprintf(stderr, "ERR %d: %s\n %s\n", err, name, comment);
+ return;
+ }
+ if (err >= BR_ERR_RECV_FATAL_ALERT
+ && err < BR_ERR_RECV_FATAL_ALERT + 256)
+ {
+ fprintf(stderr, "ERR %d: received fatal alert %d\n",
+ err, err - BR_ERR_RECV_FATAL_ALERT);
+ return;
+ }
+ if (err >= BR_ERR_SEND_FATAL_ALERT
+ && err < BR_ERR_SEND_FATAL_ALERT + 256)
+ {
+ fprintf(stderr, "ERR %d: sent fatal alert %d\n",
+ err, err - BR_ERR_SEND_FATAL_ALERT);
+ return;
+ }
+ fprintf(stderr, "ERR %d: UNKNOWN\n", err);
+}
+
+/* see brssl.h */
+int
+do_twrch(int argc, char *argv[])
+{
+ int retcode;
+ int trace;
+ int is_client;
+ int is_server;
+ const char *sni;
+ int i, bidi;
+ unsigned vmin, vmax;
+ cipher_suite *suites;
+ size_t num_suites;
+ uint16_t *suite_ids;
+ unsigned hfuns;
+ br_x509_certificate *chain;
+ size_t chain_len;
+ int cert_signer_algo;
+ private_key *sk;
+ int nostaticecdh;
+ anchor_list anchors = VEC_INIT;
+ VECTOR(char *) alpn_names = VEC_INIT;
+ br_x509_minimal_context xc;
+ x509_noanchor_context xwc;
+ const br_hash_class *dnhash;
+ size_t u;
+ union {
+ br_ssl_engine_context eng;
+ br_ssl_server_context srv;
+ br_ssl_client_context cnt;
+ } cc;
+ br_ssl_session_cache_lru lru;
+ unsigned char *iobuf, *cache;
+ size_t iobuf_len, cache_len, minhello_len;
+ br_sslio_context ioc;
+ uint32_t flags;
+ int reconnect;
+
+ retcode = 0;
+ trace = 0;
+ is_client = 0;
+ is_server = 0;
+ sni = NULL;
+ bidi = 1;
+ vmin = 0;
+ vmax = 0;
+ suites = NULL;
+ num_suites = 0;
+ suite_ids = NULL;
+ hfuns = 0;
+ chain = NULL;
+ chain_len = 0;
+ cert_signer_algo = 0;
+ sk = NULL;
+ nostaticecdh = 0;
+ iobuf = NULL;
+ iobuf_len = 0;
+ cache = NULL;
+ cache_len = (size_t)-1;
+ minhello_len = (size_t)-1;
+ flags = 0;
+ reconnect = 0;
+ for (i = 0; i < argc; i ++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (arg[0] != '-') {
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ if (eqstr(arg, "-trace")) {
+ trace = 1;
+ } else if (eqstr(arg, "-v")) {
+ verbose = 1;
+ } else if (eqstr(arg, "-server")) {
+ is_server = 1;
+ } else if (eqstr(arg, "-client")) {
+ is_client = 1;
+ } else if (eqstr(arg, "-sni")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-sni'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (sni != NULL) {
+ fprintf(stderr, "ERROR: duplicate SNI\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ sni = arg;
+ } else if (eqstr(arg, "-mono")) {
+ bidi = 0;
+ } else if (eqstr(arg, "-buf")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-buf'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (iobuf_len != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate I/O buffer length\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ iobuf_len = parse_size(arg);
+ if (iobuf_len == (size_t)-1) {
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-cache")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cache'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (cache_len != (size_t)-1) {
+ fprintf(stderr, "ERROR: duplicate session"
+ " cache length\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ cache_len = parse_size(arg);
+ if (cache_len == (size_t)-1) {
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-cert")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cert'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ if (chain != NULL) {
+ fprintf(stderr,
+ "ERROR: duplicate certificate chain\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ chain = read_certificates(arg, &chain_len);
+ if (chain == NULL || chain_len == 0) {
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-key")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-key'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ if (sk != NULL) {
+ fprintf(stderr,
+ "ERROR: duplicate private key\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ sk = read_private_key(arg);
+ if (sk == NULL) {
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-CA")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-CA'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (read_trust_anchors(&anchors, arg) == 0) {
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-anon_ok")) {
+ flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH;
+ } else if (eqstr(arg, "-nostaticecdh")) {
+ nostaticecdh = 1;
+ } else if (eqstr(arg, "-list")) {
+ list_names();
+ goto twrch_exit;
+ } else if (eqstr(arg, "-vmin")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-vmin'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (vmin != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate minimum version\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ vmin = parse_version(arg, strlen(arg));
+ if (vmin == 0) {
+ fprintf(stderr,
+ "ERROR: unrecognised version '%s'\n",
+ arg);
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-vmax")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-vmax'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (vmax != 0) {
+ fprintf(stderr,
+ "ERROR: duplicate maximum version\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ vmax = parse_version(arg, strlen(arg));
+ if (vmax == 0) {
+ fprintf(stderr,
+ "ERROR: unrecognised version '%s'\n",
+ arg);
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-cs")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-cs'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (suites != NULL) {
+ fprintf(stderr, "ERROR: duplicate list"
+ " of cipher suites\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ suites = parse_suites(arg, &num_suites);
+ if (suites == NULL) {
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-hf")) {
+ unsigned x;
+
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-hf'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ x = parse_hash_functions(arg);
+ if (x == 0) {
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ hfuns |= x;
+ } else if (eqstr(arg, "-minhello")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-minhello'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ arg = argv[i];
+ if (minhello_len != (size_t)-1) {
+ fprintf(stderr, "ERROR: duplicate minimum"
+ " ClientHello length\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ minhello_len = parse_size(arg);
+ /*
+ * Minimum ClientHello length must fit on 16 bits.
+ */
+ if (minhello_len == (size_t)-1
+ || (((minhello_len >> 12) >> 4) != 0))
+ {
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else if (eqstr(arg, "-serverpref")) {
+ flags |= BR_OPT_ENFORCE_SERVER_PREFERENCES;
+ } else if (eqstr(arg, "-noreneg")) {
+ flags |= BR_OPT_NO_RENEGOTIATION;
+ } else if (eqstr(arg, "-alpn")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-alpn'\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ VEC_ADD(alpn_names, xstrdup(argv[i]));
+ } else if (eqstr(arg, "-strictalpn")) {
+ flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH;
+ } else {
+ fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ }
+
+ /*
+ * Verify consistency of options.
+ */
+ if (!is_client && !is_server) {
+ fprintf(stderr, "ERROR:"
+ " one of -server and -client must be specified\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ if (is_client && is_server) {
+ fprintf(stderr, "ERROR:"
+ " -server and -client may not be both specified\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+
+ if (vmin == 0) {
+ vmin = BR_TLS10;
+ }
+ if (vmax == 0) {
+ vmax = BR_TLS12;
+ }
+ if (vmax < vmin) {
+ fprintf(stderr, "ERROR: impossible minimum/maximum protocol"
+ " version combination\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ if (is_server) {
+ if (chain == NULL) {
+ fprintf(stderr, "ERROR: no certificate specified"
+ " for server (-cert)\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ if (sk == NULL) {
+ fprintf(stderr, "ERROR: no private key specified"
+ " for server (-key)\n");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ } else {
+ if (chain == NULL && sk != NULL) {
+ fprintf(stderr, "ERROR: private key (-key)"
+ " but no certificate (-cert)");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ if (chain != NULL && sk == NULL) {
+ fprintf(stderr, "ERROR: certificate (-cert)"
+ " but no private key (-key)");
+ usage_twrch();
+ goto twrch_exit_error;
+ }
+ }
+ if (suites == NULL) {
+ num_suites = 0;
+
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if ((cipher_suites[u].req & REQ_TLS12) == 0
+ || vmax >= BR_TLS12)
+ {
+ num_suites ++;
+ }
+ }
+ suites = xmalloc(num_suites * sizeof *suites);
+ num_suites = 0;
+ for (u = 0; cipher_suites[u].name; u ++) {
+ if ((cipher_suites[u].req & REQ_TLS12) == 0
+ || vmax >= BR_TLS12)
+ {
+ suites[num_suites ++] = cipher_suites[u];
+ }
+ }
+ }
+ if (hfuns == 0) {
+ hfuns = (unsigned)-1;
+ }
+ if (sk != NULL) {
+ switch (sk->key_type) {
+ int curve;
+ uint32_t supp;
+
+ case BR_KEYTYPE_RSA:
+ break;
+ case BR_KEYTYPE_EC:
+ curve = sk->key.ec.curve;
+ supp = br_ec_get_default()->supported_curves;
+ if (curve > 31 || !((supp >> curve) & 1)) {
+ fprintf(stderr, "ERROR: private key curve (%d)"
+ " is not supported\n", curve);
+ goto twrch_exit_error;
+ }
+ break;
+ default:
+ fprintf(stderr, "ERROR: unsupported"
+ " private key type (%d)\n", sk->key_type);
+ goto twrch_exit_error;
+ }
+ }
+ if (chain != NULL) {
+ cert_signer_algo = get_cert_signer_algo(chain);
+ if (cert_signer_algo == 0) {
+ goto twrch_exit_error;
+ }
+ }
+ if (iobuf_len == 0) {
+ if (bidi) {
+ iobuf_len = BR_SSL_BUFSIZE_BIDI;
+ } else {
+ iobuf_len = BR_SSL_BUFSIZE_MONO;
+ }
+ }
+ iobuf = xmalloc(iobuf_len);
+ if (is_server) {
+ if (cache_len == (size_t)-1) {
+ cache_len = 5000;
+ }
+ cache = xmalloc(cache_len);
+ }
+
+ /*
+ * Initialise the relevant context.
+ */
+ if (is_client) {
+ br_ssl_client_zero(&cc.cnt);
+ } else {
+ br_ssl_server_zero(&cc.srv);
+ }
+
+ /*
+ * Compute implementation requirements and inject implementations.
+ */
+ suite_ids = xmalloc(num_suites * sizeof *suite_ids);
+ br_ssl_engine_set_versions(&cc.eng, vmin, vmax);
+ br_ssl_engine_set_all_flags(&cc.eng, flags);
+ if (vmin <= BR_TLS11) {
+ if (!(hfuns & (1 << br_md5_ID))) {
+ fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need MD5\n");
+ goto twrch_exit_error;
+ }
+ if (!(hfuns & (1 << br_sha1_ID))) {
+ fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need SHA-1\n");
+ goto twrch_exit_error;
+ }
+ }
+ for (u = 0; u < num_suites; u ++) {
+ unsigned req;
+
+ req = suites[u].req;
+ suite_ids[u] = suites[u].suite;
+ if ((req & REQ_TLS12) != 0 && vmax < BR_TLS12) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires TLS 1.2\n",
+ suites[u].name);
+ goto twrch_exit_error;
+ }
+ if ((req & REQ_SHA1) != 0 && !(hfuns & (1 << br_sha1_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-1\n",
+ suites[u].name);
+ goto twrch_exit_error;
+ }
+ if ((req & REQ_SHA256) != 0 && !(hfuns & (1 << br_sha256_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-256\n",
+ suites[u].name);
+ goto twrch_exit_error;
+ }
+ if ((req & REQ_SHA384) != 0 && !(hfuns & (1 << br_sha384_ID))) {
+ fprintf(stderr,
+ "ERROR: cipher suite %s requires SHA-384\n",
+ suites[u].name);
+ goto twrch_exit_error;
+ }
+ /* TODO: algorithm implementation selection */
+ if ((req & REQ_AESCBC) != 0) {
+ br_ssl_engine_set_default_aes_cbc(&cc.eng);
+ }
+ if ((req & REQ_AESCCM) != 0) {
+ br_ssl_engine_set_default_aes_ccm(&cc.eng);
+ }
+ if ((req & REQ_AESGCM) != 0) {
+ br_ssl_engine_set_default_aes_gcm(&cc.eng);
+ }
+ if ((req & REQ_CHAPOL) != 0) {
+ br_ssl_engine_set_default_chapol(&cc.eng);
+ }
+ if ((req & REQ_3DESCBC) != 0) {
+ br_ssl_engine_set_default_des_cbc(&cc.eng);
+ }
+ if (is_client && (req & REQ_RSAKEYX) != 0) {
+ br_ssl_client_set_default_rsapub(&cc.cnt);
+ }
+ if (is_client && (req & REQ_ECDHE_RSA) != 0) {
+ br_ssl_engine_set_default_rsavrfy(&cc.eng);
+ }
+ if (is_client && (req & REQ_ECDH) != 0) {
+ br_ssl_engine_set_default_ec(&cc.eng);
+ }
+ if ((req & (REQ_ECDHE_RSA | REQ_ECDHE_ECDSA)) != 0) {
+ br_ssl_engine_set_default_ec(&cc.eng);
+ }
+ }
+ br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites);
+
+ dnhash = NULL;
+ for (u = 0; hash_functions[u].name; u ++) {
+ const br_hash_class *hc;
+ int id;
+
+ hc = hash_functions[u].hclass;
+ id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
+ if ((hfuns & ((unsigned)1 << id)) != 0) {
+ dnhash = hc;
+ br_ssl_engine_set_hash(&cc.eng, id, hc);
+ }
+ }
+ if (vmin <= BR_TLS11) {
+ br_ssl_engine_set_prf10(&cc.eng, &br_tls10_prf);
+ }
+ if (vmax >= BR_TLS12) {
+ if ((hfuns & ((unsigned)1 << br_sha256_ID)) != 0) {
+ br_ssl_engine_set_prf_sha256(&cc.eng,
+ &br_tls12_sha256_prf);
+ }
+ if ((hfuns & ((unsigned)1 << br_sha384_ID)) != 0) {
+ br_ssl_engine_set_prf_sha384(&cc.eng,
+ &br_tls12_sha384_prf);
+ }
+ }
+ if (VEC_LEN(alpn_names) != 0) {
+ br_ssl_engine_set_protocol_names(&cc.eng,
+ (const char **)&VEC_ELT(alpn_names, 0),
+ VEC_LEN(alpn_names));
+ }
+
+ /*
+ * In server role, we use a session cache (size can be
+ * specified; if size is zero, then no cache is set).
+ */
+ if (is_server && cache != NULL) {
+ br_ssl_session_cache_lru_init(&lru, cache, cache_len);
+ br_ssl_server_set_cache(&cc.srv, &lru.vtable);
+ }
+
+ /*
+ * For a server, set the policy handler.
+ */
+ if (is_server) {
+ switch (sk->key_type) {
+ case BR_KEYTYPE_RSA:
+ br_ssl_server_set_single_rsa(&cc.srv,
+ chain, chain_len, &sk->key.rsa,
+ BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
+ br_rsa_private_get_default(),
+ br_rsa_pkcs1_sign_get_default());
+ break;
+ case BR_KEYTYPE_EC:
+ br_ssl_server_set_single_ec(&cc.srv,
+ chain, chain_len, &sk->key.ec,
+ BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
+ cert_signer_algo,
+ br_ec_get_default(),
+ br_ecdsa_sign_asn1_get_default());
+ break;
+ default:
+ fprintf(stderr, "ERROR: unsupported"
+ " private key type (%d)\n", sk->key_type);
+ goto twrch_exit_error;
+ }
+ }
+
+ /*
+ * For a client, if a certificate was specified, use it.
+ */
+ if (is_client && chain != NULL) {
+ switch (sk->key_type) {
+ unsigned usages;
+
+ case BR_KEYTYPE_RSA:
+ br_ssl_client_set_single_rsa(&cc.cnt,
+ chain, chain_len, &sk->key.rsa,
+ br_rsa_pkcs1_sign_get_default());
+ break;
+ case BR_KEYTYPE_EC:
+ if (nostaticecdh) {
+ cert_signer_algo = 0;
+ usages = BR_KEYTYPE_SIGN;
+ } else {
+ usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN;
+ }
+ br_ssl_client_set_single_ec(&cc.cnt,
+ chain, chain_len, &sk->key.ec,
+ usages, cert_signer_algo,
+ br_ec_get_default(),
+ br_ecdsa_sign_asn1_get_default());
+ break;
+ default:
+ fprintf(stderr, "ERROR: unsupported"
+ " private key type (%d)\n", sk->key_type);
+ goto twrch_exit_error;
+ }
+ }
+
+ /*
+ * On a client, or if trust anchors have been configured, then
+ * set an X.509 validation engine. If there are no trust anchors
+ * (client only), then a "no anchor" wrapper will be applied.
+ */
+ if (is_client || VEC_LEN(anchors) != 0) {
+ br_x509_minimal_init(&xc, dnhash,
+ &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+ for (u = 0; hash_functions[u].name; u ++) {
+ const br_hash_class *hc;
+ int id;
+
+ hc = hash_functions[u].hclass;
+ id = (hc->desc >> BR_HASHDESC_ID_OFF)
+ & BR_HASHDESC_ID_MASK;
+ if ((hfuns & ((unsigned)1 << id)) != 0) {
+ br_x509_minimal_set_hash(&xc, id, hc);
+ }
+ }
+ br_ssl_engine_set_default_rsavrfy(&cc.eng);
+ br_ssl_engine_set_default_ecdsa(&cc.eng);
+ br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default());
+ br_x509_minimal_set_ecdsa(&xc,
+ br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
+ br_ssl_engine_set_x509(&cc.eng, &xc.vtable);
+
+ if (VEC_LEN(anchors) == 0) {
+ x509_noanchor_init(&xwc, &xc.vtable);
+ br_ssl_engine_set_x509(&cc.eng, &xwc.vtable);
+ } else {
+ br_ssl_engine_set_x509(&cc.eng, &xc.vtable);
+ }
+ if (is_server) {
+ br_ssl_server_set_trust_anchor_names_alt(&cc.srv,
+ &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+ }
+ }
+
+ /*
+ * Set I/O buffer.
+ */
+ br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
+
+ /*
+ * Start the engine.
+ */
+ if (is_client) {
+ br_ssl_client_reset(&cc.cnt, sni, 0);
+ }
+ if (is_server) {
+ br_ssl_server_reset(&cc.srv);
+ }
+
+ /*
+ * On Unix systems, we want to ignore SIGPIPE: if the peer
+ * closes the connection abruptly, then we want to report it
+ * as a "normal" error (exit code = 1).
+ */
+#ifndef _WIN32
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /*
+ * Initialize the callbacks for exchanging data over stdin and
+ * stdout.
+ */
+ br_sslio_init(&ioc, &cc.eng, stdin_read, &trace, stdout_write, &trace);
+
+ /*
+ * Run the Twrch protocol.
+ */
+ for (;;) {
+ br_sha1_context sc;
+ unsigned char hv[20], tmp[41];
+ uint64_t count;
+ int fb, i;
+
+ /*
+ * Read line, byte by byte, hashing it on the fly.
+ */
+ br_sha1_init(&sc);
+ count = 0;
+ fb = 0;
+ for (;;) {
+ unsigned char x;
+
+ if (br_sslio_read(&ioc, &x, 1) < 0) {
+ if (count == 0 && reconnect) {
+ reconnect = 0;
+ if (br_sslio_close(&ioc) < 0) {
+ goto twrch_loop_finished;
+ }
+ if (is_client) {
+ br_ssl_client_reset(
+ &cc.cnt, sni, 1);
+ }
+ if (is_server) {
+ br_ssl_server_reset(&cc.srv);
+ }
+ br_sslio_init(&ioc, &cc.eng,
+ stdin_read, &trace,
+ stdout_write, &trace);
+ continue;
+ }
+ goto twrch_loop_finished;
+ }
+ if (count == 0) {
+ fb = x;
+ }
+ if (x == 0x0A) {
+ break;
+ }
+ br_sha1_update(&sc, &x, 1);
+ count ++;
+ }
+ if (count == 1) {
+ switch (fb) {
+ case 'C':
+ br_sslio_close(&ioc);
+ goto twrch_loop_finished;
+ case 'T':
+ if (br_sslio_close(&ioc) < 0) {
+ goto twrch_loop_finished;
+ }
+ if (is_client) {
+ br_ssl_client_reset(&cc.cnt, sni, 1);
+ }
+ if (is_server) {
+ br_ssl_server_reset(&cc.srv);
+ }
+ br_sslio_init(&ioc, &cc.eng,
+ stdin_read, &trace,
+ stdout_write, &trace);
+ continue;
+ case 'G':
+ if (!br_ssl_engine_renegotiate(&cc.eng)) {
+ br_sslio_write_all(&ioc, "DENIED\n", 7);
+ br_sslio_flush(&ioc);
+ } else {
+ br_sslio_write_all(&ioc, "OK\n", 3);
+ br_sslio_flush(&ioc);
+ }
+ continue;
+ case 'R':
+ reconnect = 1;
+ br_sslio_write_all(&ioc, "OK\n", 3);
+ br_sslio_flush(&ioc);
+ continue;
+ case 'U':
+ if (is_client) {
+ br_ssl_client_forget_session(&cc.cnt);
+ }
+ if (is_server && cache != NULL) {
+ br_ssl_session_parameters pp;
+
+ br_ssl_engine_get_session_parameters(
+ &cc.eng, &pp);
+ if (pp.session_id_len == 32) {
+ br_ssl_session_cache_lru_forget(
+ &lru, pp.session_id);
+ }
+ }
+ br_sslio_write_all(&ioc, "DONE\n", 5);
+ br_sslio_flush(&ioc);
+ continue;
+ }
+ }
+ br_sha1_out(&sc, hv);
+ for (i = 0; i < 20; i ++) {
+ int x;
+
+ x = hv[i];
+ tmp[(i << 1) + 0] = "0123456789abcdef"[x >> 4];
+ tmp[(i << 1) + 1] = "0123456789abcdef"[x & 15];
+ }
+ tmp[40] = 0x0A;
+ br_sslio_write_all(&ioc, tmp, 41);
+ br_sslio_flush(&ioc);
+ }
+
+twrch_loop_finished:
+ if (br_ssl_engine_current_state(&cc.eng) == BR_SSL_CLOSED) {
+ int err;
+
+ err = br_ssl_engine_last_error(&cc.eng);
+ if (err == 0) {
+ retcode = 0;
+ } else {
+ if (verbose) {
+ print_error(err);
+ }
+ retcode = 1;
+ }
+ } else {
+ if (verbose) {
+ fprintf(stderr, "Engine not closed!\n");
+ }
+ retcode = 1;
+ }
+
+ /*
+ * Release allocated structures.
+ */
+twrch_exit:
+ xfree(suites);
+ xfree(suite_ids);
+ free_certificates(chain, chain_len);
+ free_private_key(sk);
+ VEC_CLEAREXT(anchors, &free_ta_contents);
+ VEC_CLEAREXT(alpn_names, &free_alpn);
+ xfree(iobuf);
+ xfree(cache);
+ return retcode;
+
+twrch_exit_error:
+ retcode = -1;
+ goto twrch_exit;
+}
Property changes on: stable/12/contrib/bearssl/tools/twrch.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/vector.c
===================================================================
--- stable/12/contrib/bearssl/tools/vector.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/vector.c (revision 346145)
@@ -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.
+ */
+
+#include "brssl.h"
+
+/*
+ * Prepare a vector buffer for adding 'extra' elements.
+ * buf current buffer
+ * esize size of a vector element
+ * ptr pointer to the 'ptr' vector field
+ * len pointer to the 'len' vector field
+ * extra number of elements to add
+ *
+ * If the buffer must be enlarged, then this function allocates the new
+ * buffer and releases the old one. The new buffer address is then returned.
+ * If the buffer needs not be enlarged, then the buffer address is returned.
+ *
+ * In case of enlargement, the 'len' field is adjusted accordingly. The
+ * 'ptr' field is not modified.
+ */
+void *
+vector_expand(void *buf,
+ size_t esize, size_t *ptr, size_t *len, size_t extra)
+{
+ size_t nlen;
+ void *nbuf;
+
+ if (*len - *ptr >= extra) {
+ return buf;
+ }
+ nlen = (*len << 1);
+ if (nlen - *ptr < extra) {
+ nlen = extra + *ptr;
+ if (nlen < 8) {
+ nlen = 8;
+ }
+ }
+ nbuf = xmalloc(nlen * esize);
+ if (buf != NULL) {
+ memcpy(nbuf, buf, *len * esize);
+ xfree(buf);
+ }
+ *len = nlen;
+ return nbuf;
+}
Property changes on: stable/12/contrib/bearssl/tools/vector.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/tools/verify.c
===================================================================
--- stable/12/contrib/bearssl/tools/verify.c (nonexistent)
+++ stable/12/contrib/bearssl/tools/verify.c (revision 346145)
@@ -0,0 +1,353 @@
+/*
+ * 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 "brssl.h"
+#include "bearssl.h"
+
+static unsigned
+rsa_bit_length(const br_rsa_public_key *pk)
+{
+ size_t u;
+ unsigned x, bl;
+
+ for (u = 0; u < pk->nlen; u ++) {
+ if (pk->n[u] != 0) {
+ break;
+ }
+ }
+ if (u == pk->nlen) {
+ return 0;
+ }
+ bl = (unsigned)(pk->nlen - u - 1) << 3;
+ x = pk->n[u];
+ while (x != 0) {
+ bl ++;
+ x >>= 1;
+ }
+ return bl;
+}
+
+static void
+print_rsa(const br_rsa_public_key *pk, int print_text, int print_C)
+{
+ if (print_text) {
+ size_t u;
+
+ printf("n = ");
+ for (u = 0; u < pk->nlen; u ++) {
+ printf("%02X", pk->n[u]);
+ }
+ printf("\n");
+ printf("e = ");
+ for (u = 0; u < pk->elen; u ++) {
+ printf("%02X", pk->e[u]);
+ }
+ printf("\n");
+ }
+ if (print_C) {
+ size_t u;
+
+ printf("\nstatic const unsigned char RSA_N[] = {");
+ for (u = 0; u < pk->nlen; u ++) {
+ if (u != 0) {
+ printf(",");
+ }
+ if (u % 12 == 0) {
+ printf("\n\t");
+ } else {
+ printf(" ");
+ }
+ printf("0x%02X", pk->n[u]);
+ }
+ printf("\n};\n");
+ printf("\nstatic const unsigned char RSA_E[] = {");
+ for (u = 0; u < pk->elen; u ++) {
+ if (u != 0) {
+ printf(",");
+ }
+ if (u % 12 == 0) {
+ printf("\n\t");
+ } else {
+ printf(" ");
+ }
+ printf("0x%02X", pk->e[u]);
+ }
+ printf("\n};\n");
+ printf("\nstatic const br_rsa_public_key RSA = {\n");
+ printf("\t(unsigned char *)RSA_N, sizeof RSA_N,\n");
+ printf("\t(unsigned char *)RSA_E, sizeof RSA_E\n");
+ printf("};\n");
+ }
+}
+
+static void
+print_ec(const br_ec_public_key *pk, int print_text, int print_C)
+{
+ if (print_text) {
+ size_t u;
+
+ printf("Q = ");
+ for (u = 0; u < pk->qlen; u ++) {
+ printf("%02X", pk->q[u]);
+ }
+ printf("\n");
+ }
+ if (print_C) {
+ size_t u;
+
+ printf("\nstatic const unsigned char EC_Q[] = {");
+ for (u = 0; u < pk->qlen; u ++) {
+ if (u != 0) {
+ printf(",");
+ }
+ if (u % 12 == 0) {
+ printf("\n\t");
+ } else {
+ printf(" ");
+ }
+ printf("0x%02X", pk->q[u]);
+ }
+ printf("\n};\n");
+ printf("\nstatic const br_ec_public_key EC = {\n");
+ printf("\t%d,\n", pk->curve);
+ printf("\t(unsigned char *)EC_Q, sizeof EC_Q\n");
+ printf("};\n");
+ }
+}
+
+static void
+usage_verify(void)
+{
+ fprintf(stderr,
+"usage: brssl verify [ options ] file...\n");
+ fprintf(stderr,
+"options:\n");
+ fprintf(stderr,
+" -q suppress verbose messages\n");
+ fprintf(stderr,
+" -sni name check presence of a specific server name\n");
+ fprintf(stderr,
+" -CA file add certificates in 'file' to trust anchors\n");
+ fprintf(stderr,
+" -text print public key details (human-readable)\n");
+ fprintf(stderr,
+" -C print public key details (C code)\n");
+}
+
+typedef VECTOR(br_x509_certificate) cert_list;
+
+static void
+free_cert_contents(br_x509_certificate *xc)
+{
+ xfree(xc->data);
+}
+
+/* see brssl.h */
+int
+do_verify(int argc, char *argv[])
+{
+ int retcode;
+ int verbose;
+ int i;
+ const char *sni;
+ anchor_list anchors = VEC_INIT;
+ cert_list chain = VEC_INIT;
+ size_t u;
+ br_x509_minimal_context mc;
+ int err;
+ int print_text, print_C;
+ br_x509_pkey *pk;
+ const br_x509_pkey *tpk;
+ unsigned usages;
+
+ retcode = 0;
+ verbose = 1;
+ sni = NULL;
+ print_text = 0;
+ print_C = 0;
+ pk = NULL;
+ for (i = 0; i < argc; i ++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (arg[0] != '-') {
+ br_x509_certificate *xcs;
+ size_t num;
+
+ xcs = read_certificates(arg, &num);
+ if (xcs == NULL) {
+ usage_verify();
+ goto verify_exit_error;
+ }
+ VEC_ADDMANY(chain, xcs, num);
+ xfree(xcs);
+ continue;
+ }
+ if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
+ verbose = 1;
+ } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
+ verbose = 0;
+ } else if (eqstr(arg, "-sni")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-sni'\n");
+ usage_verify();
+ goto verify_exit_error;
+ }
+ if (sni != NULL) {
+ fprintf(stderr, "ERROR: duplicate SNI\n");
+ usage_verify();
+ goto verify_exit_error;
+ }
+ sni = argv[i];
+ continue;
+ } else if (eqstr(arg, "-CA")) {
+ if (++ i >= argc) {
+ fprintf(stderr,
+ "ERROR: no argument for '-CA'\n");
+ usage_verify();
+ goto verify_exit_error;
+ }
+ arg = argv[i];
+ if (read_trust_anchors(&anchors, arg) == 0) {
+ usage_verify();
+ goto verify_exit_error;
+ }
+ continue;
+ } else if (eqstr(arg, "-text")) {
+ print_text = 1;
+ } else if (eqstr(arg, "-C")) {
+ print_C = 1;
+ } else {
+ fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
+ usage_verify();
+ goto verify_exit_error;
+ }
+ }
+ if (VEC_LEN(chain) == 0) {
+ fprintf(stderr, "ERROR: no certificate chain provided\n");
+ usage_verify();
+ goto verify_exit_error;
+ }
+ br_x509_minimal_init(&mc, &br_sha256_vtable,
+ &VEC_ELT(anchors, 0), VEC_LEN(anchors));
+ br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
+ br_x509_minimal_set_hash(&mc, br_sha224_ID, &br_sha224_vtable);
+ br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
+ br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
+ br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
+ br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
+ br_x509_minimal_set_ecdsa(&mc,
+ &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
+
+ mc.vtable->start_chain(&mc.vtable, sni);
+ for (u = 0; u < VEC_LEN(chain); u ++) {
+ br_x509_certificate *xc;
+
+ xc = &VEC_ELT(chain, u);
+ mc.vtable->start_cert(&mc.vtable, xc->data_len);
+ mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
+ mc.vtable->end_cert(&mc.vtable);
+ }
+ err = mc.vtable->end_chain(&mc.vtable);
+ tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
+ if (tpk != NULL) {
+ pk = xpkeydup(tpk);
+ }
+
+ if (err == 0) {
+ if (verbose) {
+ int hkx;
+
+ fprintf(stderr, "Validation success; usages:");
+ hkx = 0;
+ if (usages & BR_KEYTYPE_KEYX) {
+ fprintf(stderr, " key exchange");
+ hkx = 1;
+ }
+ if (usages & BR_KEYTYPE_SIGN) {
+ if (hkx) {
+ fprintf(stderr, ",");
+ }
+ fprintf(stderr, " signature");
+ }
+ fprintf(stderr, "\n");
+ }
+ } else {
+ if (verbose) {
+ const char *errname, *errmsg;
+
+ fprintf(stderr, "Validation failed, err = %d", err);
+ errname = find_error_name(err, &errmsg);
+ if (errname != NULL) {
+ fprintf(stderr, " (%s): %s\n", errname, errmsg);
+ } else {
+ fprintf(stderr, " (unknown)\n");
+ }
+ }
+ retcode = -1;
+ }
+ if (pk != NULL) {
+ switch (pk->key_type) {
+ case BR_KEYTYPE_RSA:
+ if (verbose) {
+ fprintf(stderr, "Key type: RSA (%u bits)\n",
+ rsa_bit_length(&pk->key.rsa));
+ }
+ print_rsa(&pk->key.rsa, print_text, print_C);
+ break;
+ case BR_KEYTYPE_EC:
+ if (verbose) {
+ fprintf(stderr, "Key type: EC (%s)\n",
+ ec_curve_name(pk->key.ec.curve));
+ }
+ print_ec(&pk->key.ec, print_text, print_C);
+ break;
+ default:
+ if (verbose) {
+ fprintf(stderr, "Unknown key type\n");
+ break;
+ }
+ }
+ }
+
+ /*
+ * Release allocated structures.
+ */
+verify_exit:
+ VEC_CLEAREXT(anchors, &free_ta_contents);
+ VEC_CLEAREXT(chain, &free_cert_contents);
+ xfreepkey(pk);
+ return retcode;
+
+verify_exit_error:
+ retcode = -1;
+ goto verify_exit;
+}
Property changes on: stable/12/contrib/bearssl/tools/verify.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/Doxyfile
===================================================================
--- stable/12/contrib/bearssl/Doxyfile (nonexistent)
+++ stable/12/contrib/bearssl/Doxyfile (revision 346145)
@@ -0,0 +1,2427 @@
+# Doxyfile 1.8.11
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "BearSSL"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = apidoc
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = 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
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
+# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse-libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX = br_ BR_
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 45
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 150
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = BR_DOXYGEN_IGNORE
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
Index: stable/12/contrib/bearssl/LICENSE.txt
===================================================================
--- stable/12/contrib/bearssl/LICENSE.txt (nonexistent)
+++ stable/12/contrib/bearssl/LICENSE.txt (revision 346145)
@@ -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.
Property changes on: stable/12/contrib/bearssl/LICENSE.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/Makefile
===================================================================
--- stable/12/contrib/bearssl/Makefile (nonexistent)
+++ stable/12/contrib/bearssl/Makefile (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/README.txt
===================================================================
--- stable/12/contrib/bearssl/README.txt (nonexistent)
+++ stable/12/contrib/bearssl/README.txt (revision 346145)
@@ -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.
Property changes on: stable/12/contrib/bearssl/README.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/T0/BlobWriter.cs
===================================================================
--- stable/12/contrib/bearssl/T0/BlobWriter.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/BlobWriter.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/CPU.cs
===================================================================
--- stable/12/contrib/bearssl/T0/CPU.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/CPU.cs (revision 346145)
@@ -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];
+ }
+ }
+}
Index: stable/12/contrib/bearssl/T0/CodeElement.cs
===================================================================
--- stable/12/contrib/bearssl/T0/CodeElement.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/CodeElement.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/CodeElementJump.cs
===================================================================
--- stable/12/contrib/bearssl/T0/CodeElementJump.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/CodeElementJump.cs (revision 346145)
@@ -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);
+ }
+}
Index: stable/12/contrib/bearssl/T0/CodeElementUInt.cs
===================================================================
--- stable/12/contrib/bearssl/T0/CodeElementUInt.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/CodeElementUInt.cs (revision 346145)
@@ -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);
+ }
+}
Index: stable/12/contrib/bearssl/T0/CodeElementUIntExpr.cs
===================================================================
--- stable/12/contrib/bearssl/T0/CodeElementUIntExpr.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/CodeElementUIntExpr.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/CodeElementUIntInt.cs
===================================================================
--- stable/12/contrib/bearssl/T0/CodeElementUIntInt.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/CodeElementUIntInt.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/CodeElementUIntUInt.cs
===================================================================
--- stable/12/contrib/bearssl/T0/CodeElementUIntUInt.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/CodeElementUIntUInt.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/ConstData.cs
===================================================================
--- stable/12/contrib/bearssl/T0/ConstData.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/ConstData.cs (revision 346145)
@@ -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]);
+ }
+ }
+}
Index: stable/12/contrib/bearssl/T0/Opcode.cs
===================================================================
--- stable/12/contrib/bearssl/T0/Opcode.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/Opcode.cs (revision 346145)
@@ -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)
+ {
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeCall.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeCall.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeCall.cs (revision 346145)
@@ -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);
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeConst.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeConst.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeConst.cs (revision 346145)
@@ -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();
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeGetLocal.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeGetLocal.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeGetLocal.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeJump.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeJump.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeJump.cs (revision 346145)
@@ -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]);
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeJumpIf.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeJumpIf.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeJumpIf.cs (revision 346145)
@@ -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;
+ }
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeJumpIfNot.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeJumpIfNot.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeJumpIfNot.cs (revision 346145)
@@ -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;
+ }
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeJumpUncond.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeJumpUncond.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeJumpUncond.cs (revision 346145)
@@ -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;
+ }
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodePutLocal.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodePutLocal.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodePutLocal.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/OpcodeRet.cs
===================================================================
--- stable/12/contrib/bearssl/T0/OpcodeRet.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/OpcodeRet.cs (revision 346145)
@@ -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";
+ }
+}
Index: stable/12/contrib/bearssl/T0/SType.cs
===================================================================
--- stable/12/contrib/bearssl/T0/SType.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/SType.cs (revision 346145)
@@ -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);
+ }
+}
Index: stable/12/contrib/bearssl/T0/T0Comp.cs
===================================================================
--- stable/12/contrib/bearssl/T0/T0Comp.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/T0Comp.cs (revision 346145)
@@ -0,0 +1,2123 @@
+/*
+ * 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.IO;
+using System.Reflection;
+using System.Text;
+
+/*
+ * This is the main compiler class.
+ */
+
+public class T0Comp {
+
+ /*
+ * Command-line entry point.
+ */
+ public static void Main(string[] args)
+ {
+ try {
+ List<string> r = new List<string>();
+ string outBase = null;
+ List<string> entryPoints = new List<string>();
+ string coreRun = null;
+ bool flow = true;
+ int dsLim = 32;
+ int rsLim = 32;
+ for (int i = 0; i < args.Length; i ++) {
+ string a = args[i];
+ if (!a.StartsWith("-")) {
+ r.Add(a);
+ continue;
+ }
+ if (a == "--") {
+ for (;;) {
+ if (++ i >= args.Length) {
+ break;
+ }
+ r.Add(args[i]);
+ }
+ break;
+ }
+ while (a.StartsWith("-")) {
+ a = a.Substring(1);
+ }
+ int j = a.IndexOf('=');
+ string pname;
+ string pval, pval2;
+ if (j < 0) {
+ pname = a.ToLowerInvariant();
+ pval = null;
+ pval2 = (i + 1) < args.Length
+ ? args[i + 1] : null;
+ } else {
+ pname = a.Substring(0, j).Trim()
+ .ToLowerInvariant();
+ pval = a.Substring(j + 1);
+ pval2 = null;
+ }
+ switch (pname) {
+ case "o":
+ case "out":
+ if (pval == null) {
+ if (pval2 == null) {
+ Usage();
+ }
+ i ++;
+ pval = pval2;
+ }
+ if (outBase != null) {
+ Usage();
+ }
+ outBase = pval;
+ break;
+ case "r":
+ case "run":
+ if (pval == null) {
+ if (pval2 == null) {
+ Usage();
+ }
+ i ++;
+ pval = pval2;
+ }
+ coreRun = pval;
+ break;
+ case "m":
+ case "main":
+ if (pval == null) {
+ if (pval2 == null) {
+ Usage();
+ }
+ i ++;
+ pval = pval2;
+ }
+ foreach (string ep in pval.Split(',')) {
+ string epz = ep.Trim();
+ if (epz.Length > 0) {
+ entryPoints.Add(epz);
+ }
+ }
+ break;
+ case "nf":
+ case "noflow":
+ flow = false;
+ break;
+ default:
+ Usage();
+ break;
+ }
+ }
+ if (r.Count == 0) {
+ Usage();
+ }
+ if (outBase == null) {
+ outBase = "t0out";
+ }
+ if (entryPoints.Count == 0) {
+ entryPoints.Add("main");
+ }
+ if (coreRun == null) {
+ coreRun = outBase;
+ }
+ T0Comp tc = new T0Comp();
+ tc.enableFlowAnalysis = flow;
+ tc.dsLimit = dsLim;
+ tc.rsLimit = rsLim;
+ using (TextReader tr = new StreamReader(
+ Assembly.GetExecutingAssembly()
+ .GetManifestResourceStream("t0-kernel")))
+ {
+ tc.ProcessInput(tr);
+ }
+ foreach (string a in r) {
+ Console.WriteLine("[{0}]", a);
+ using (TextReader tr = File.OpenText(a)) {
+ tc.ProcessInput(tr);
+ }
+ }
+ tc.Generate(outBase, coreRun, entryPoints.ToArray());
+ } catch (Exception e) {
+ Console.WriteLine(e.ToString());
+ Environment.Exit(1);
+ }
+ }
+
+ static void Usage()
+ {
+ Console.WriteLine(
+"usage: T0Comp.exe [ options... ] file...");
+ Console.WriteLine(
+"options:");
+ Console.WriteLine(
+" -o file use 'file' as base for output file name (default: 't0out')");
+ Console.WriteLine(
+" -r name use 'name' as base for run function (default: same as output)");
+ Console.WriteLine(
+" -m name[,name...]");
+ Console.WriteLine(
+" define entry point(s)");
+ Console.WriteLine(
+" -nf disable flow analysis");
+ Environment.Exit(1);
+ }
+
+ /*
+ * If 'delayedChar' is Int32.MinValue then there is no delayed
+ * character.
+ * If 'delayedChar' equals x >= 0 then there is one delayed
+ * character of value x.
+ * If 'delayedChar' equals y < 0 then there are two delayed
+ * characters, a newline (U+000A) followed by character of
+ * value -(y+1).
+ */
+ TextReader currentInput;
+ int delayedChar;
+
+ /*
+ * Common StringBuilder used to parse tokens; it is reused for
+ * each new token.
+ */
+ StringBuilder tokenBuilder;
+
+ /*
+ * There may be a delayed token in some cases.
+ */
+ String delayedToken;
+
+ /*
+ * Defined words are referenced by name in this map. Names are
+ * string-sensitive; for better reproducibility, the map is sorted
+ * (ordinal order).
+ */
+ IDictionary<string, Word> words;
+
+ /*
+ * Last defined word is also referenced in 'lastWord'. This is
+ * used by 'immediate'.
+ */
+ Word lastWord;
+
+ /*
+ * When compiling, this builder is used. A stack saves other
+ * builders in case of nested definition.
+ */
+ WordBuilder wordBuilder;
+ Stack<WordBuilder> savedWordBuilders;
+
+ /*
+ * C code defined for words is kept in this map, by word name.
+ */
+ IDictionary<string, string> allCCode;
+
+ /*
+ * 'compiling' is true when compiling tokens to a word, false
+ * when interpreting them.
+ */
+ bool compiling;
+
+ /*
+ * 'quitRunLoop' is set to true to trigger exit of the
+ * interpretation loop when the end of the current input file
+ * is reached.
+ */
+ bool quitRunLoop;
+
+ /*
+ * 'extraCode' is for C code that is to be added as preamble to
+ * the C output.
+ */
+ List<string> extraCode;
+
+ /*
+ * 'extraCodeDefer' is for C code that is to be added in the C
+ * output _after_ the data and code blocks.
+ */
+ List<string> extraCodeDefer;
+
+ /*
+ * 'dataBlock' is the data block in which constant data bytes
+ * are accumulated.
+ */
+ ConstData dataBlock;
+
+ /*
+ * Counter for blocks of constant data.
+ */
+ long currentBlobID;
+
+ /*
+ * Flow analysis enable flag.
+ */
+ bool enableFlowAnalysis;
+
+ /*
+ * Data stack size limit.
+ */
+ int dsLimit;
+
+ /*
+ * Return stack size limit.
+ */
+ int rsLimit;
+
+ T0Comp()
+ {
+ tokenBuilder = new StringBuilder();
+ words = new SortedDictionary<string, Word>(
+ StringComparer.Ordinal);
+ savedWordBuilders = new Stack<WordBuilder>();
+ allCCode = new SortedDictionary<string, string>(
+ StringComparer.Ordinal);
+ compiling = false;
+ extraCode = new List<string>();
+ extraCodeDefer = new List<string>();
+ enableFlowAnalysis = true;
+
+ /*
+ * Native words are predefined and implemented only with
+ * native code. Some may be part of the generated output,
+ * if C code is set for them.
+ */
+
+ /*
+ * add-cc:
+ * Parses next token as a word name, then a C code snippet.
+ * Sets the C code for that word.
+ */
+ AddNative("add-cc:", false, SType.BLANK, cpu => {
+ string tt = Next();
+ if (tt == null) {
+ throw new Exception(
+ "EOF reached (missing name)");
+ }
+ if (allCCode.ContainsKey(tt)) {
+ throw new Exception(
+ "C code already set for: " + tt);
+ }
+ allCCode[tt] = ParseCCode();
+ });
+
+ /*
+ * cc:
+ * Parses next token as a word name, then a C code snippet.
+ * A new word is defined, that throws an exception when
+ * invoked during compilation. The C code is set for that
+ * new word.
+ */
+ AddNative("cc:", false, SType.BLANK, cpu => {
+ string tt = Next();
+ if (tt == null) {
+ throw new Exception(
+ "EOF reached (missing name)");
+ }
+ Word w = AddNative(tt, false, cpu2 => {
+ throw new Exception(
+ "C-only word: " + tt);
+ });
+ if (allCCode.ContainsKey(tt)) {
+ throw new Exception(
+ "C code already set for: " + tt);
+ }
+ SType stackEffect;
+ allCCode[tt] = ParseCCode(out stackEffect);
+ w.StackEffect = stackEffect;
+ });
+
+ /*
+ * preamble
+ * Parses a C code snippet, then adds it to the generated
+ * output preamble.
+ */
+ AddNative("preamble", false, SType.BLANK, cpu => {
+ extraCode.Add(ParseCCode());
+ });
+
+ /*
+ * postamble
+ * Parses a C code snippet, then adds it to the generated
+ * output after the data and code blocks.
+ */
+ AddNative("postamble", false, SType.BLANK, cpu => {
+ extraCodeDefer.Add(ParseCCode());
+ });
+
+ /*
+ * make-CX
+ * Expects two integers and a string, and makes a
+ * constant that stands for the string as a C constant
+ * expression. The two integers are the expected range
+ * (min-max, inclusive).
+ */
+ AddNative("make-CX", false, new SType(3, 1), cpu => {
+ TValue c = cpu.Pop();
+ if (!(c.ptr is TPointerBlob)) {
+ throw new Exception(string.Format(
+ "'{0}' is not a string", c));
+ }
+ int max = cpu.Pop();
+ int min = cpu.Pop();
+ TValue tv = new TValue(0, new TPointerExpr(
+ c.ToString(), min, max));
+ cpu.Push(tv);
+ });
+
+ /*
+ * CX (immediate)
+ * Parses two integer constants, then a C code snippet.
+ * It then pushes on the stack, or compiles to the
+ * current word, a value consisting of the given C
+ * expression; the two integers indicate the expected
+ * range (min-max, inclusive) of the C expression when
+ * evaluated.
+ */
+ AddNative("CX", true, cpu => {
+ string tt = Next();
+ if (tt == null) {
+ throw new Exception(
+ "EOF reached (missing min value)");
+ }
+ int min = ParseInteger(tt);
+ tt = Next();
+ if (tt == null) {
+ throw new Exception(
+ "EOF reached (missing max value)");
+ }
+ int max = ParseInteger(tt);
+ if (max < min) {
+ throw new Exception("min/max in wrong order");
+ }
+ TValue tv = new TValue(0, new TPointerExpr(
+ ParseCCode().Trim(), min, max));
+ if (compiling) {
+ wordBuilder.Literal(tv);
+ } else {
+ cpu.Push(tv);
+ }
+ });
+
+ /*
+ * co
+ * Interrupt the current execution. This implements
+ * coroutines. It cannot be invoked during compilation.
+ */
+ AddNative("co", false, SType.BLANK, cpu => {
+ throw new Exception("No coroutine in compile mode");
+ });
+
+ /*
+ * :
+ * Parses next token as word name. It begins definition
+ * of that word, setting it as current target for
+ * word building. Any previously opened word is saved
+ * and will become available again as a target when that
+ * new word is finished building.
+ */
+ AddNative(":", false, cpu => {
+ string tt = Next();
+ if (tt == null) {
+ throw new Exception(
+ "EOF reached (missing name)");
+ }
+ if (compiling) {
+ savedWordBuilders.Push(wordBuilder);
+ } else {
+ compiling = true;
+ }
+ wordBuilder = new WordBuilder(this, tt);
+ tt = Next();
+ if (tt == null) {
+ throw new Exception(
+ "EOF reached (while compiling)");
+ }
+ if (tt == "(") {
+ SType stackEffect = ParseStackEffectNF();
+ if (!stackEffect.IsKnown) {
+ throw new Exception(
+ "Invalid stack effect syntax");
+ }
+ wordBuilder.StackEffect = stackEffect;
+ } else {
+ delayedToken = tt;
+ }
+ });
+
+ /*
+ * Pops a string as word name, and two integers as stack
+ * effect. It begins definition of that word, setting it
+ * as current target for word building. Any previously
+ * opened word is saved and will become available again as
+ * a target when that new word is finished building.
+ *
+ * Stack effect is the pair 'din dout'. If din is negative,
+ * then the stack effect is "unknown". If din is nonnegative
+ * but dout is negative, then the word is reputed never to
+ * return.
+ */
+ AddNative("define-word", false, cpu => {
+ int dout = cpu.Pop();
+ int din = cpu.Pop();
+ TValue s = cpu.Pop();
+ if (!(s.ptr is TPointerBlob)) {
+ throw new Exception(string.Format(
+ "Not a string: '{0}'", s));
+ }
+ string tt = s.ToString();
+ if (compiling) {
+ savedWordBuilders.Push(wordBuilder);
+ } else {
+ compiling = true;
+ }
+ wordBuilder = new WordBuilder(this, tt);
+ wordBuilder.StackEffect = new SType(din, dout);
+ });
+
+ /*
+ * ; (immediate)
+ * Ends current word. The current word is registered under
+ * its name, and the previously opened word (if any) becomes
+ * again the building target.
+ */
+ AddNative(";", true, cpu => {
+ if (!compiling) {
+ throw new Exception("Not compiling");
+ }
+ Word w = wordBuilder.Build();
+ string name = w.Name;
+ if (words.ContainsKey(name)) {
+ throw new Exception(
+ "Word already defined: " + name);
+ }
+ words[name] = w;
+ lastWord = w;
+ if (savedWordBuilders.Count > 0) {
+ wordBuilder = savedWordBuilders.Pop();
+ } else {
+ wordBuilder = null;
+ compiling = false;
+ }
+ });
+
+ /*
+ * immediate
+ * Sets the last defined word as immediate.
+ */
+ AddNative("immediate", false, cpu => {
+ if (lastWord == null) {
+ throw new Exception("No word defined yet");
+ }
+ lastWord.Immediate = true;
+ });
+
+ /*
+ * literal (immediate)
+ * Pops the current TOS value, and add in the current word
+ * the action of pushing that value. This cannot be used
+ * when no word is being built.
+ */
+ WordNative wliteral = AddNative("literal", true, cpu => {
+ CheckCompiling();
+ wordBuilder.Literal(cpu.Pop());
+ });
+
+ /*
+ * compile
+ * Pops the current TOS value, which must be an XT (pointer
+ * to a word); the action of calling that word is compiled
+ * in the current word.
+ */
+ WordNative wcompile = AddNative("compile", false, cpu => {
+ CheckCompiling();
+ wordBuilder.Call(cpu.Pop().ToXT());
+ });
+
+ /*
+ * postpone (immediate)
+ * Parses the next token as a word name, and add to the
+ * current word the action of calling that word. This
+ * basically removes immediatety from the next word.
+ */
+ AddNative("postpone", true, cpu => {
+ CheckCompiling();
+ string tt = Next();
+ if (tt == null) {
+ throw new Exception(
+ "EOF reached (missing name)");
+ }
+ TValue v;
+ bool isVal = TryParseLiteral(tt, out v);
+ Word w = LookupNF(tt);
+ if (isVal && w != null) {
+ throw new Exception(String.Format(
+ "Ambiguous: both defined word and"
+ + " literal: {0}", tt));
+ }
+ if (isVal) {
+ wordBuilder.Literal(v);
+ wordBuilder.CallExt(wliteral);
+ } else if (w != null) {
+ if (w.Immediate) {
+ wordBuilder.CallExt(w);
+ } else {
+ wordBuilder.Literal(new TValue(0,
+ new TPointerXT(w)));
+ wordBuilder.CallExt(wcompile);
+ }
+ } else {
+ wordBuilder.Literal(new TValue(0,
+ new TPointerXT(tt)));
+ wordBuilder.CallExt(wcompile);
+ }
+ });
+
+ /*
+ * Interrupt compilation with an error.
+ */
+ AddNative("exitvm", false, cpu => {
+ throw new Exception();
+ });
+
+ /*
+ * Open a new data block. Its symbolic address is pushed
+ * on the stack.
+ */
+ AddNative("new-data-block", false, cpu => {
+ dataBlock = new ConstData(this);
+ cpu.Push(new TValue(0, new TPointerBlob(dataBlock)));
+ });
+
+ /*
+ * Define a new data word. The data address and name are
+ * popped from the stack.
+ */
+ AddNative("define-data-word", false, cpu => {
+ string name = cpu.Pop().ToString();
+ TValue va = cpu.Pop();
+ TPointerBlob tb = va.ptr as TPointerBlob;
+ if (tb == null) {
+ throw new Exception(
+ "Address is not a data area");
+ }
+ Word w = new WordData(this, name, tb.Blob, va.x);
+ if (words.ContainsKey(name)) {
+ throw new Exception(
+ "Word already defined: " + name);
+ }
+ words[name] = w;
+ lastWord = w;
+ });
+
+ /*
+ * Get an address pointing at the end of the current
+ * data block. This is the address of the next byte that
+ * will be added.
+ */
+ AddNative("current-data", false, cpu => {
+ if (dataBlock == null) {
+ throw new Exception(
+ "No current data block");
+ }
+ cpu.Push(new TValue(dataBlock.Length,
+ new TPointerBlob(dataBlock)));
+ });
+
+ /*
+ * Add a byte value to the data block.
+ */
+ AddNative("data-add8", false, cpu => {
+ if (dataBlock == null) {
+ throw new Exception(
+ "No current data block");
+ }
+ int v = cpu.Pop();
+ if (v < 0 || v > 0xFF) {
+ throw new Exception(
+ "Byte value out of range: " + v);
+ }
+ dataBlock.Add8((byte)v);
+ });
+
+ /*
+ * Set a byte value in the data block.
+ */
+ AddNative("data-set8", false, cpu => {
+ TValue va = cpu.Pop();
+ TPointerBlob tb = va.ptr as TPointerBlob;
+ if (tb == null) {
+ throw new Exception(
+ "Address is not a data area");
+ }
+ int v = cpu.Pop();
+ if (v < 0 || v > 0xFF) {
+ throw new Exception(
+ "Byte value out of range: " + v);
+ }
+ tb.Blob.Set8(va.x, (byte)v);
+ });
+
+ /*
+ * Get a byte value from a data block.
+ */
+ AddNative("data-get8", false, new SType(1, 1), cpu => {
+ TValue va = cpu.Pop();
+ TPointerBlob tb = va.ptr as TPointerBlob;
+ if (tb == null) {
+ throw new Exception(
+ "Address is not a data area");
+ }
+ int v = tb.Blob.Read8(va.x);
+ cpu.Push(v);
+ });
+
+ /*
+ *
+ */
+ AddNative("compile-local-read", false, cpu => {
+ CheckCompiling();
+ wordBuilder.GetLocal(cpu.Pop().ToString());
+ });
+ AddNative("compile-local-write", false, cpu => {
+ CheckCompiling();
+ wordBuilder.PutLocal(cpu.Pop().ToString());
+ });
+
+ AddNative("ahead", true, cpu => {
+ CheckCompiling();
+ wordBuilder.Ahead();
+ });
+ AddNative("begin", true, cpu => {
+ CheckCompiling();
+ wordBuilder.Begin();
+ });
+ AddNative("again", true, cpu => {
+ CheckCompiling();
+ wordBuilder.Again();
+ });
+ AddNative("until", true, cpu => {
+ CheckCompiling();
+ wordBuilder.AgainIfNot();
+ });
+ AddNative("untilnot", true, cpu => {
+ CheckCompiling();
+ wordBuilder.AgainIf();
+ });
+ AddNative("if", true, cpu => {
+ CheckCompiling();
+ wordBuilder.AheadIfNot();
+ });
+ AddNative("ifnot", true, cpu => {
+ CheckCompiling();
+ wordBuilder.AheadIf();
+ });
+ AddNative("then", true, cpu => {
+ CheckCompiling();
+ wordBuilder.Then();
+ });
+ AddNative("cs-pick", false, cpu => {
+ CheckCompiling();
+ wordBuilder.CSPick(cpu.Pop());
+ });
+ AddNative("cs-roll", false, cpu => {
+ CheckCompiling();
+ wordBuilder.CSRoll(cpu.Pop());
+ });
+ AddNative("next-word", false, cpu => {
+ string s = Next();
+ if (s == null) {
+ throw new Exception("No next word (EOF)");
+ }
+ cpu.Push(StringToBlob(s));
+ });
+ AddNative("parse", false, cpu => {
+ int d = cpu.Pop();
+ string s = ReadTerm(d);
+ cpu.Push(StringToBlob(s));
+ });
+ AddNative("char", false, cpu => {
+ int c = NextChar();
+ if (c < 0) {
+ throw new Exception("No next character (EOF)");
+ }
+ cpu.Push(c);
+ });
+ AddNative("'", false, cpu => {
+ string name = Next();
+ cpu.Push(new TValue(0, new TPointerXT(name)));
+ });
+
+ /*
+ * The "execute" word is valid in generated C code, but
+ * since it jumps to a runtime pointer, its actual stack
+ * effect cannot be computed in advance.
+ */
+ AddNative("execute", false, cpu => {
+ cpu.Pop().Execute(this, cpu);
+ });
+
+ AddNative("[", true, cpu => {
+ CheckCompiling();
+ compiling = false;
+ });
+ AddNative("]", false, cpu => {
+ compiling = true;
+ });
+ AddNative("(local)", false, cpu => {
+ CheckCompiling();
+ wordBuilder.DefLocal(cpu.Pop().ToString());
+ });
+ AddNative("ret", true, cpu => {
+ CheckCompiling();
+ wordBuilder.Ret();
+ });
+
+ AddNative("drop", false, new SType(1, 0), cpu => {
+ cpu.Pop();
+ });
+ AddNative("dup", false, new SType(1, 2), cpu => {
+ cpu.Push(cpu.Peek(0));
+ });
+ AddNative("swap", false, new SType(2, 2), cpu => {
+ cpu.Rot(1);
+ });
+ AddNative("over", false, new SType(2, 3), cpu => {
+ cpu.Push(cpu.Peek(1));
+ });
+ AddNative("rot", false, new SType(3, 3), cpu => {
+ cpu.Rot(2);
+ });
+ AddNative("-rot", false, new SType(3, 3), cpu => {
+ cpu.NRot(2);
+ });
+
+ /*
+ * "roll" and "pick" are special in that the stack slot
+ * they inspect might be known only at runtime, so an
+ * absolute stack effect cannot be attributed. Instead,
+ * we simply hope that the caller knows what it is doing,
+ * and we use a simple stack effect for just the count
+ * value and picked value.
+ */
+ AddNative("roll", false, new SType(1, 0), cpu => {
+ cpu.Rot(cpu.Pop());
+ });
+ AddNative("pick", false, new SType(1, 1), cpu => {
+ cpu.Push(cpu.Peek(cpu.Pop()));
+ });
+
+ AddNative("+", false, new SType(2, 1), cpu => {
+ TValue b = cpu.Pop();
+ TValue a = cpu.Pop();
+ if (b.ptr == null) {
+ a.x += (int)b;
+ cpu.Push(a);
+ } else if (a.ptr is TPointerBlob
+ && b.ptr is TPointerBlob)
+ {
+ cpu.Push(StringToBlob(
+ a.ToString() + b.ToString()));
+ } else {
+ throw new Exception(string.Format(
+ "Cannot add '{0}' to '{1}'", b, a));
+ }
+ });
+ AddNative("-", false, new SType(2, 1), cpu => {
+ /*
+ * We can subtract two pointers, provided that
+ * they point to the same blob. Otherwise,
+ * the subtraction second operand must be an
+ * integer.
+ */
+ TValue b = cpu.Pop();
+ TValue a = cpu.Pop();
+ TPointerBlob ap = a.ptr as TPointerBlob;
+ TPointerBlob bp = b.ptr as TPointerBlob;
+ if (ap != null && bp != null && ap.Blob == bp.Blob) {
+ cpu.Push(new TValue(a.x - b.x));
+ return;
+ }
+ int bx = b;
+ a.x -= bx;
+ cpu.Push(a);
+ });
+ AddNative("neg", false, new SType(1, 1), cpu => {
+ int ax = cpu.Pop();
+ cpu.Push(-ax);
+ });
+ AddNative("*", false, new SType(2, 1), cpu => {
+ int bx = cpu.Pop();
+ int ax = cpu.Pop();
+ cpu.Push(ax * bx);
+ });
+ AddNative("/", false, new SType(2, 1), cpu => {
+ int bx = cpu.Pop();
+ int ax = cpu.Pop();
+ cpu.Push(ax / bx);
+ });
+ AddNative("u/", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop();
+ uint ax = cpu.Pop();
+ cpu.Push(ax / bx);
+ });
+ AddNative("%", false, new SType(2, 1), cpu => {
+ int bx = cpu.Pop();
+ int ax = cpu.Pop();
+ cpu.Push(ax % bx);
+ });
+ AddNative("u%", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop();
+ uint ax = cpu.Pop();
+ cpu.Push(ax % bx);
+ });
+ AddNative("<", false, new SType(2, 1), cpu => {
+ int bx = cpu.Pop();
+ int ax = cpu.Pop();
+ cpu.Push(ax < bx);
+ });
+ AddNative("<=", false, new SType(2, 1), cpu => {
+ int bx = cpu.Pop();
+ int ax = cpu.Pop();
+ cpu.Push(ax <= bx);
+ });
+ AddNative(">", false, new SType(2, 1), cpu => {
+ int bx = cpu.Pop();
+ int ax = cpu.Pop();
+ cpu.Push(ax > bx);
+ });
+ AddNative(">=", false, new SType(2, 1), cpu => {
+ int bx = cpu.Pop();
+ int ax = cpu.Pop();
+ cpu.Push(ax >= bx);
+ });
+ AddNative("=", false, new SType(2, 1), cpu => {
+ TValue b = cpu.Pop();
+ TValue a = cpu.Pop();
+ cpu.Push(a.Equals(b));
+ });
+ AddNative("<>", false, new SType(2, 1), cpu => {
+ TValue b = cpu.Pop();
+ TValue a = cpu.Pop();
+ cpu.Push(!a.Equals(b));
+ });
+ AddNative("u<", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop().UInt;
+ uint ax = cpu.Pop().UInt;
+ cpu.Push(new TValue(ax < bx));
+ });
+ AddNative("u<=", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop().UInt;
+ uint ax = cpu.Pop().UInt;
+ cpu.Push(new TValue(ax <= bx));
+ });
+ AddNative("u>", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop().UInt;
+ uint ax = cpu.Pop().UInt;
+ cpu.Push(new TValue(ax > bx));
+ });
+ AddNative("u>=", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop();
+ uint ax = cpu.Pop();
+ cpu.Push(ax >= bx);
+ });
+ AddNative("and", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop();
+ uint ax = cpu.Pop();
+ cpu.Push(ax & bx);
+ });
+ AddNative("or", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop();
+ uint ax = cpu.Pop();
+ cpu.Push(ax | bx);
+ });
+ AddNative("xor", false, new SType(2, 1), cpu => {
+ uint bx = cpu.Pop();
+ uint ax = cpu.Pop();
+ cpu.Push(ax ^ bx);
+ });
+ AddNative("not", false, new SType(1, 1), cpu => {
+ uint ax = cpu.Pop();
+ cpu.Push(~ax);
+ });
+ AddNative("<<", false, new SType(2, 1), cpu => {
+ int count = cpu.Pop();
+ if (count < 0 || count > 31) {
+ throw new Exception("Invalid shift count");
+ }
+ uint ax = cpu.Pop();
+ cpu.Push(ax << count);
+ });
+ AddNative(">>", false, new SType(2, 1), cpu => {
+ int count = cpu.Pop();
+ if (count < 0 || count > 31) {
+ throw new Exception("Invalid shift count");
+ }
+ int ax = cpu.Pop();
+ cpu.Push(ax >> count);
+ });
+ AddNative("u>>", false, new SType(2, 1), cpu => {
+ int count = cpu.Pop();
+ if (count < 0 || count > 31) {
+ throw new Exception("Invalid shift count");
+ }
+ uint ax = cpu.Pop();
+ cpu.Push(ax >> count);
+ });
+
+ AddNative(".", false, new SType(1, 0), cpu => {
+ Console.Write(" {0}", cpu.Pop().ToString());
+ });
+ AddNative(".s", false, SType.BLANK, cpu => {
+ int n = cpu.Depth;
+ for (int i = n - 1; i >= 0; i --) {
+ Console.Write(" {0}", cpu.Peek(i).ToString());
+ }
+ });
+ AddNative("putc", false, new SType(1, 0), cpu => {
+ Console.Write((char)cpu.Pop());
+ });
+ AddNative("puts", false, new SType(1, 0), cpu => {
+ Console.Write("{0}", cpu.Pop().ToString());
+ });
+ AddNative("cr", false, SType.BLANK, cpu => {
+ Console.WriteLine();
+ });
+ AddNative("eqstr", false, new SType(2, 1), cpu => {
+ string s2 = cpu.Pop().ToString();
+ string s1 = cpu.Pop().ToString();
+ cpu.Push(s1 == s2);
+ });
+ }
+
+ WordNative AddNative(string name, bool immediate,
+ WordNative.NativeRun code)
+ {
+ return AddNative(name, immediate, SType.UNKNOWN, code);
+ }
+
+ WordNative AddNative(string name, bool immediate, SType stackEffect,
+ WordNative.NativeRun code)
+ {
+ if (words.ContainsKey(name)) {
+ throw new Exception(
+ "Word already defined: " + name);
+ }
+ WordNative w = new WordNative(this, name, code);
+ w.Immediate = immediate;
+ w.StackEffect = stackEffect;
+ words[name] = w;
+ return w;
+ }
+
+ internal long NextBlobID()
+ {
+ return currentBlobID ++;
+ }
+
+ int NextChar()
+ {
+ int c = delayedChar;
+ if (c >= 0) {
+ delayedChar = Int32.MinValue;
+ } else if (c > Int32.MinValue) {
+ delayedChar = -(c + 1);
+ c = '\n';
+ } else {
+ c = currentInput.Read();
+ }
+ if (c == '\r') {
+ if (delayedChar >= 0) {
+ c = delayedChar;
+ delayedChar = Int32.MinValue;
+ } else {
+ c = currentInput.Read();
+ }
+ if (c != '\n') {
+ delayedChar = c;
+ c = '\n';
+ }
+ }
+ return c;
+ }
+
+ /*
+ * Un-read the character value 'c'. That value MUST be the one
+ * that was obtained from NextChar().
+ */
+ void Unread(int c)
+ {
+ if (c < 0) {
+ return;
+ }
+ if (delayedChar < 0) {
+ if (delayedChar != Int32.MinValue) {
+ throw new Exception(
+ "Already two delayed characters");
+ }
+ delayedChar = c;
+ } else if (c != '\n') {
+ throw new Exception("Cannot delay two characters");
+ } else {
+ delayedChar = -(delayedChar + 1);
+ }
+ }
+
+ string Next()
+ {
+ string r = delayedToken;
+ if (r != null) {
+ delayedToken = null;
+ return r;
+ }
+ tokenBuilder.Length = 0;
+ int c;
+ for (;;) {
+ c = NextChar();
+ if (c < 0) {
+ return null;
+ }
+ if (!IsWS(c)) {
+ break;
+ }
+ }
+ if (c == '"') {
+ return ParseString();
+ }
+ for (;;) {
+ tokenBuilder.Append((char)c);
+ c = NextChar();
+ if (c < 0 || IsWS(c)) {
+ Unread(c);
+ return tokenBuilder.ToString();
+ }
+ }
+ }
+
+ string ParseCCode()
+ {
+ SType stackEffect;
+ string r = ParseCCode(out stackEffect);
+ if (stackEffect.IsKnown) {
+ throw new Exception(
+ "Stack effect forbidden in this declaration");
+ }
+ return r;
+ }
+
+ string ParseCCode(out SType stackEffect)
+ {
+ string s = ParseCCodeNF(out stackEffect);
+ if (s == null) {
+ throw new Exception("Error while parsing C code");
+ }
+ return s;
+ }
+
+ string ParseCCodeNF(out SType stackEffect)
+ {
+ stackEffect = SType.UNKNOWN;
+ for (;;) {
+ int c = NextChar();
+ if (c < 0) {
+ return null;
+ }
+ if (!IsWS(c)) {
+ if (c == '(') {
+ if (stackEffect.IsKnown) {
+ Unread(c);
+ return null;
+ }
+ stackEffect = ParseStackEffectNF();
+ if (!stackEffect.IsKnown) {
+ return null;
+ }
+ continue;
+ } else if (c != '{') {
+ Unread(c);
+ return null;
+ }
+ break;
+ }
+ }
+ StringBuilder sb = new StringBuilder();
+ int count = 1;
+ for (;;) {
+ int c = NextChar();
+ if (c < 0) {
+ return null;
+ }
+ switch (c) {
+ case '{':
+ count ++;
+ break;
+ case '}':
+ if (-- count == 0) {
+ return sb.ToString();
+ }
+ break;
+ }
+ sb.Append((char)c);
+ }
+ }
+
+ /*
+ * Parse a stack effect declaration. This method assumes that the
+ * opening parenthesis has just been read. If the parsing fails,
+ * then this method returns SType.UNKNOWN.
+ */
+ SType ParseStackEffectNF()
+ {
+ bool seenSep = false;
+ bool seenBang = false;
+ int din = 0, dout = 0;
+ for (;;) {
+ string t = Next();
+ if (t == null) {
+ return SType.UNKNOWN;
+ }
+ if (t == "--") {
+ if (seenSep) {
+ return SType.UNKNOWN;
+ }
+ seenSep = true;
+ } else if (t == ")") {
+ if (seenSep) {
+ if (seenBang && dout == 1) {
+ dout = -1;
+ }
+ return new SType(din, dout);
+ } else {
+ return SType.UNKNOWN;
+ }
+ } else {
+ if (seenSep) {
+ if (dout == 0 && t == "!") {
+ seenBang = true;
+ }
+ dout ++;
+ } else {
+ din ++;
+ }
+ }
+ }
+ }
+
+ string ParseString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append('"');
+ bool lcwb = false;
+ int hexNum = 0;
+ int acc = 0;
+ for (;;) {
+ int c = NextChar();
+ if (c < 0) {
+ throw new Exception(
+ "Unfinished literal string");
+ }
+ if (hexNum > 0) {
+ int d = HexVal(c);
+ if (d < 0) {
+ throw new Exception(String.Format(
+ "not an hex digit: U+{0:X4}",
+ c));
+ }
+ acc = (acc << 4) + d;
+ if (-- hexNum == 0) {
+ sb.Append((char)acc);
+ acc = 0;
+ }
+ } else if (lcwb) {
+ lcwb = false;
+ switch (c) {
+ case '\n': SkipNL(); break;
+ case 'x':
+ hexNum = 2;
+ break;
+ case 'u':
+ hexNum = 4;
+ break;
+ default:
+ sb.Append(SingleCharEscape(c));
+ break;
+ }
+ } else {
+ switch (c) {
+ case '"':
+ return sb.ToString();
+ case '\\':
+ lcwb = true;
+ break;
+ default:
+ sb.Append((char)c);
+ break;
+ }
+ }
+ }
+ }
+
+ static char SingleCharEscape(int c)
+ {
+ switch (c) {
+ case 'n': return '\n';
+ case 'r': return '\r';
+ case 't': return '\t';
+ case 's': return ' ';
+ default:
+ return (char)c;
+ }
+ }
+
+ /*
+ * A backslash+newline sequence occurred in a literal string; we
+ * check and consume the newline escape sequence (whitespace at
+ * start of next line, then a double-quote character).
+ */
+ void SkipNL()
+ {
+ for (;;) {
+ int c = NextChar();
+ if (c < 0) {
+ throw new Exception("EOF in literal string");
+ }
+ if (c == '\n') {
+ throw new Exception(
+ "Unescaped newline in literal string");
+ }
+ if (IsWS(c)) {
+ continue;
+ }
+ if (c == '"') {
+ return;
+ }
+ throw new Exception(
+ "Invalid newline escape in literal string");
+ }
+ }
+
+ static char DecodeCharConst(string t)
+ {
+ if (t.Length == 1 && t[0] != '\\') {
+ return t[0];
+ }
+ if (t.Length >= 2 && t[0] == '\\') {
+ switch (t[1]) {
+ case 'x':
+ if (t.Length == 4) {
+ int x = DecHex(t.Substring(2));
+ if (x >= 0) {
+ return (char)x;
+ }
+ }
+ break;
+ case 'u':
+ if (t.Length == 6) {
+ int x = DecHex(t.Substring(2));
+ if (x >= 0) {
+ return (char)x;
+ }
+ }
+ break;
+ default:
+ if (t.Length == 2) {
+ return SingleCharEscape(t[1]);
+ }
+ break;
+ }
+ }
+ throw new Exception("Invalid literal char: `" + t);
+ }
+
+ static int DecHex(string s)
+ {
+ int acc = 0;
+ foreach (char c in s) {
+ int d = HexVal(c);
+ if (d < 0) {
+ return -1;
+ }
+ acc = (acc << 4) + d;
+ }
+ return acc;
+ }
+
+ static int HexVal(int c)
+ {
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ } else if (c >= 'A' && c <= 'F') {
+ return c - ('A' - 10);
+ } else if (c >= 'a' && c <= 'f') {
+ return c - ('a' - 10);
+ } else {
+ return -1;
+ }
+ }
+
+ string ReadTerm(int ct)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (;;) {
+ int c = NextChar();
+ if (c < 0) {
+ throw new Exception(String.Format(
+ "EOF reached before U+{0:X4}", ct));
+ }
+ if (c == ct) {
+ return sb.ToString();
+ }
+ sb.Append((char)c);
+ }
+ }
+
+ static bool IsWS(int c)
+ {
+ return c <= 32;
+ }
+
+ void ProcessInput(TextReader tr)
+ {
+ this.currentInput = tr;
+ delayedChar = -1;
+ Word w = new WordNative(this, "toplevel",
+ xcpu => { CompileStep(xcpu); });
+ CPU cpu = new CPU();
+ Opcode[] code = new Opcode[] {
+ new OpcodeCall(w),
+ new OpcodeJumpUncond(-2)
+ };
+ quitRunLoop = false;
+ cpu.Enter(code, 0);
+ for (;;) {
+ if (quitRunLoop) {
+ break;
+ }
+ Opcode op = cpu.ipBuf[cpu.ipOff ++];
+ op.Run(cpu);
+ }
+ }
+
+ void CompileStep(CPU cpu)
+ {
+ string tt = Next();
+ if (tt == null) {
+ if (compiling) {
+ throw new Exception("EOF while compiling");
+ }
+ quitRunLoop = true;
+ return;
+ }
+ TValue v;
+ bool isVal = TryParseLiteral(tt, out v);
+ Word w = LookupNF(tt);
+ if (isVal && w != null) {
+ throw new Exception(String.Format(
+ "Ambiguous: both defined word and literal: {0}",
+ tt));
+ }
+ if (compiling) {
+ if (isVal) {
+ wordBuilder.Literal(v);
+ } else if (w != null) {
+ if (w.Immediate) {
+ w.Run(cpu);
+ } else {
+ wordBuilder.CallExt(w);
+ }
+ } else {
+ wordBuilder.Call(tt);
+ }
+ } else {
+ if (isVal) {
+ cpu.Push(v);
+ } else if (w != null) {
+ w.Run(cpu);
+ } else {
+ throw new Exception(String.Format(
+ "Unknown word: '{0}'", tt));
+ }
+ }
+ }
+
+ string GetCCode(string name)
+ {
+ string ccode;
+ allCCode.TryGetValue(name, out ccode);
+ return ccode;
+ }
+
+ void Generate(string outBase, string coreRun,
+ params string[] entryPoints)
+ {
+ /*
+ * Gather all words that are part of the generated
+ * code. This is done by exploring references
+ * transitively. All such words are thus implicitly
+ * resolved.
+ */
+ IDictionary<string, Word> wordSet =
+ new SortedDictionary<string, Word>(
+ StringComparer.Ordinal);
+ Queue<Word> tx = new Queue<Word>();
+ foreach (string ep in entryPoints) {
+ if (wordSet.ContainsKey(ep)) {
+ continue;
+ }
+ Word w = Lookup(ep);
+ wordSet[w.Name] = w;
+ tx.Enqueue(w);
+ }
+ while (tx.Count > 0) {
+ Word w = tx.Dequeue();
+ foreach (Word w2 in w.GetReferences()) {
+ if (wordSet.ContainsKey(w2.Name)) {
+ continue;
+ }
+ wordSet[w2.Name] = w2;
+ tx.Enqueue(w2);
+ }
+ }
+
+ /*
+ * Do flow analysis.
+ */
+ if (enableFlowAnalysis) {
+ foreach (string ep in entryPoints) {
+ Word w = wordSet[ep];
+ w.AnalyseFlow();
+ Console.WriteLine("{0}: ds={1} rs={2}",
+ ep, w.MaxDataStack, w.MaxReturnStack);
+ if (w.MaxDataStack > dsLimit) {
+ throw new Exception("'" + ep
+ + "' exceeds data stack limit");
+ }
+ if (w.MaxReturnStack > rsLimit) {
+ throw new Exception("'" + ep
+ + "' exceeds return stack"
+ + " limit");
+ }
+ }
+ }
+
+ /*
+ * Gather referenced data areas and compute their
+ * addresses in the generated data block. The address
+ * 0 in the data block is unaffected so that no
+ * valid runtime pointer is equal to null.
+ */
+ IDictionary<long, ConstData> blocks =
+ new SortedDictionary<long, ConstData>();
+ foreach (Word w in wordSet.Values) {
+ foreach (ConstData cd in w.GetDataBlocks()) {
+ blocks[cd.ID] = cd;
+ }
+ }
+ int dataLen = 1;
+ foreach (ConstData cd in blocks.Values) {
+ cd.Address = dataLen;
+ dataLen += cd.Length;
+ }
+
+ /*
+ * Generated code is a sequence of "slot numbers", each
+ * referencing either a piece of explicit C code, or an
+ * entry in the table of interpreted words.
+ *
+ * Opcodes other than "call" get the slots 0 to 6:
+ *
+ * 0 ret no argument
+ * 1 const signed value
+ * 2 get local local number
+ * 3 put local local number
+ * 4 jump signed offset
+ * 5 jump if signed offset
+ * 6 jump if not signed offset
+ *
+ * The argument, if any, is in "7E" format: the value is
+ * encoded in 7-bit chunk, with big-endian signed
+ * convention. Each 7-bit chunk is encoded over one byte;
+ * the upper bit is 1 for all chunks except the last one.
+ *
+ * Words with explicit C code get the slot numbers
+ * immediately after 6. Interpreted words come afterwards.
+ */
+ IDictionary<string, int> slots = new Dictionary<string, int>();
+ int curSlot = 7;
+
+ /*
+ * Get explicit C code for words which have such code.
+ * We use string equality on C code so that words with
+ * identical implementations get merged.
+ *
+ * We also check that words with no explicit C code are
+ * interpreted.
+ */
+ IDictionary<string, int> ccodeUni =
+ new Dictionary<string, int>();
+ IDictionary<int, string> ccodeNames =
+ new Dictionary<int, string>();
+ foreach (Word w in wordSet.Values) {
+ string ccode = GetCCode(w.Name);
+ if (ccode == null) {
+ if (w is WordNative) {
+ throw new Exception(String.Format(
+ "No C code for native '{0}'",
+ w.Name));
+ }
+ continue;
+ }
+ int sn;
+ if (ccodeUni.ContainsKey(ccode)) {
+ sn = ccodeUni[ccode];
+ ccodeNames[sn] += " " + EscapeCComment(w.Name);
+ } else {
+ sn = curSlot ++;
+ ccodeUni[ccode] = sn;
+ ccodeNames[sn] = EscapeCComment(w.Name);
+ }
+ slots[w.Name] = sn;
+ w.Slot = sn;
+ }
+
+ /*
+ * Assign slot values to all remaining words; we know they
+ * are all interpreted.
+ */
+ int slotInterpreted = curSlot;
+ foreach (Word w in wordSet.Values) {
+ if (GetCCode(w.Name) != null) {
+ continue;
+ }
+ int sn = curSlot ++;
+ slots[w.Name] = sn;
+ w.Slot = sn;
+ }
+ int numInterpreted = curSlot - slotInterpreted;
+
+ /*
+ * Verify that all entry points are interpreted words.
+ */
+ foreach (string ep in entryPoints) {
+ if (GetCCode(ep) != null) {
+ throw new Exception(
+ "Non-interpreted entry point");
+ }
+ }
+
+ /*
+ * Compute the code block. Each word (without any C code)
+ * yields some CodeElement instances.
+ */
+ List<CodeElement> gcodeList = new List<CodeElement>();
+ CodeElement[] interpretedEntry =
+ new CodeElement[numInterpreted];
+ foreach (Word w in wordSet.Values) {
+ if (GetCCode(w.Name) != null) {
+ continue;
+ }
+ int n = gcodeList.Count;
+ w.GenerateCodeElements(gcodeList);
+ interpretedEntry[w.Slot - slotInterpreted] =
+ gcodeList[n];
+ }
+ CodeElement[] gcode = gcodeList.ToArray();
+
+ /*
+ * If there are less than 256 words in total (C +
+ * interpreted) then we can use "one-byte code" which is
+ * more compact when the number of words is in the
+ * 128..255 range.
+ */
+ bool oneByteCode;
+ if (slotInterpreted + numInterpreted >= 256) {
+ Console.WriteLine("WARNING: more than 255 words");
+ oneByteCode = false;
+ } else {
+ oneByteCode = true;
+ }
+
+ /*
+ * Compute all addresses and offsets. This loops until
+ * the addresses stabilize.
+ */
+ int totalLen = -1;
+ int[] gcodeLen = new int[gcode.Length];
+ for (;;) {
+ for (int i = 0; i < gcode.Length; i ++) {
+ gcodeLen[i] = gcode[i].GetLength(oneByteCode);
+ }
+ int off = 0;
+ for (int i = 0; i < gcode.Length; i ++) {
+ gcode[i].Address = off;
+ gcode[i].LastLength = gcodeLen[i];
+ off += gcodeLen[i];
+ }
+ if (off == totalLen) {
+ break;
+ }
+ totalLen = off;
+ }
+
+ /*
+ * Produce output file.
+ */
+ using (TextWriter tw = File.CreateText(outBase + ".c")) {
+ tw.NewLine = "\n";
+
+ tw.WriteLine("{0}",
+@"/* Automatically generated code; do not modify directly. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+} t0_context;
+
+static uint32_t
+t0_parse7E_unsigned(const unsigned char **p)
+{
+ uint32_t x;
+
+ x = 0;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ return x;
+ }
+ }
+}
+
+static int32_t
+t0_parse7E_signed(const unsigned char **p)
+{
+ int neg;
+ uint32_t x;
+
+ neg = ((**p) >> 6) & 1;
+ x = (uint32_t)-neg;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ if (neg) {
+ return -(int32_t)~x - 1;
+ } else {
+ return (int32_t)x;
+ }
+ }
+ }
+}
+
+#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
+#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
+#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
+#define T0_INT1(x) T0_FBYTE(x, 0)
+#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+
+/* static const unsigned char t0_datablock[]; */
+");
+
+ /*
+ * Add declarations (not definitions) for the
+ * entry point initialisation functions, and the
+ * runner.
+ */
+ tw.WriteLine();
+ foreach (string ep in entryPoints) {
+ tw.WriteLine("void {0}_init_{1}(void *t0ctx);",
+ coreRun, ep);
+ }
+ tw.WriteLine();
+ tw.WriteLine("void {0}_run(void *t0ctx);", coreRun);
+
+ /*
+ * Add preamble elements here. They may be needed
+ * for evaluating constant expressions in the
+ * code block.
+ */
+ foreach (string pp in extraCode) {
+ tw.WriteLine();
+ tw.WriteLine("{0}", pp);
+ }
+
+ BlobWriter bw;
+ tw.WriteLine();
+ tw.Write("static const unsigned char"
+ + " t0_datablock[] = {");
+ bw = new BlobWriter(tw, 78, 1);
+ bw.Append((byte)0);
+ foreach (ConstData cd in blocks.Values) {
+ cd.Encode(bw);
+ }
+ tw.WriteLine();
+ tw.WriteLine("};");
+
+ tw.WriteLine();
+ tw.Write("static const unsigned char"
+ + " t0_codeblock[] = {");
+ bw = new BlobWriter(tw, 78, 1);
+ foreach (CodeElement ce in gcode) {
+ ce.Encode(bw, oneByteCode);
+ }
+ tw.WriteLine();
+ tw.WriteLine("};");
+
+ tw.WriteLine();
+ tw.Write("static const uint16_t t0_caddr[] = {");
+ for (int i = 0; i < interpretedEntry.Length; i ++) {
+ if (i != 0) {
+ tw.Write(',');
+ }
+ tw.WriteLine();
+ tw.Write("\t{0}", interpretedEntry[i].Address);
+ }
+ tw.WriteLine();
+ tw.WriteLine("};");
+
+ tw.WriteLine();
+ tw.WriteLine("#define T0_INTERPRETED {0}",
+ slotInterpreted);
+ tw.WriteLine();
+ tw.WriteLine("{0}",
+@"#define T0_ENTER(ip, rp, slot) do { \
+ const unsigned char *t0_newip; \
+ uint32_t t0_lnum; \
+ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
+ t0_lnum = t0_parse7E_unsigned(&t0_newip); \
+ (rp) += t0_lnum; \
+ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
+ (ip) = t0_newip; \
+ } while (0)");
+ tw.WriteLine();
+ tw.WriteLine("{0}",
+@"#define T0_DEFENTRY(name, slot) \
+void \
+name(void *ctx) \
+{ \
+ t0_context *t0ctx = ctx; \
+ t0ctx->ip = &t0_codeblock[0]; \
+ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
+}");
+
+ tw.WriteLine();
+ foreach (string ep in entryPoints) {
+ tw.WriteLine("T0_DEFENTRY({0}, {1})",
+ coreRun + "_init_" + ep,
+ wordSet[ep].Slot);
+ }
+ tw.WriteLine();
+ if (oneByteCode) {
+ tw.WriteLine("{0}",
+@"#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)");
+ } else {
+ tw.WriteLine("{0}",
+@"#define T0_NEXT(t0ipp) t0_parse7E_unsigned(t0ipp)");
+ }
+ tw.WriteLine();
+ tw.WriteLine("void");
+ tw.WriteLine("{0}_run(void *t0ctx)", coreRun);
+ tw.WriteLine("{0}",
+@"{
+ uint32_t *dp, *rp;
+ const unsigned char *ip;
+
+#define T0_LOCAL(x) (*(rp - 2 - (x)))
+#define T0_POP() (*-- dp)
+#define T0_POPi() (*(int32_t *)(-- dp))
+#define T0_PEEK(x) (*(dp - 1 - (x)))
+#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
+#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
+#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
+#define T0_RPOP() (*-- rp)
+#define T0_RPOPi() (*(int32_t *)(-- rp))
+#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
+#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
+#define T0_ROLL(x) do { \
+ size_t t0len = (size_t)(x); \
+ uint32_t t0tmp = *(dp - 1 - t0len); \
+ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_SWAP() do { \
+ uint32_t t0tmp = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_ROT() do { \
+ uint32_t t0tmp = *(dp - 3); \
+ *(dp - 3) = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_NROT() do { \
+ uint32_t t0tmp = *(dp - 1); \
+ *(dp - 1) = *(dp - 2); \
+ *(dp - 2) = *(dp - 3); \
+ *(dp - 3) = t0tmp; \
+} while (0)
+#define T0_PICK(x) do { \
+ uint32_t t0depth = (x); \
+ T0_PUSH(T0_PEEK(t0depth)); \
+} while (0)
+#define T0_CO() do { \
+ goto t0_exit; \
+} while (0)
+#define T0_RET() goto t0_next
+
+ dp = ((t0_context *)t0ctx)->dp;
+ rp = ((t0_context *)t0ctx)->rp;
+ ip = ((t0_context *)t0ctx)->ip;
+ goto t0_next;
+ for (;;) {
+ uint32_t t0x;
+
+ t0_next:
+ t0x = T0_NEXT(&ip);
+ if (t0x < T0_INTERPRETED) {
+ switch (t0x) {
+ int32_t t0off;
+
+ case 0: /* ret */
+ t0x = T0_RPOP();
+ rp -= (t0x >> 16);
+ t0x &= 0xFFFF;
+ if (t0x == 0) {
+ ip = NULL;
+ goto t0_exit;
+ }
+ ip = &t0_codeblock[t0x];
+ break;
+ case 1: /* literal constant */
+ T0_PUSHi(t0_parse7E_signed(&ip));
+ break;
+ case 2: /* read local */
+ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
+ break;
+ case 3: /* write local */
+ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
+ break;
+ case 4: /* jump */
+ t0off = t0_parse7E_signed(&ip);
+ ip += t0off;
+ break;
+ case 5: /* jump if */
+ t0off = t0_parse7E_signed(&ip);
+ if (T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 6: /* jump if not */
+ t0off = t0_parse7E_signed(&ip);
+ if (!T0_POP()) {
+ ip += t0off;
+ }
+ break;");
+
+ SortedDictionary<int, string> nccode =
+ new SortedDictionary<int, string>();
+ foreach (string k in ccodeUni.Keys) {
+ nccode[ccodeUni[k]] = k;
+ }
+ foreach (int sn in nccode.Keys) {
+ tw.WriteLine(
+@" case {0}: {{
+ /* {1} */
+{2}
+ }}
+ break;", sn, ccodeNames[sn], nccode[sn]);
+ }
+
+ tw.WriteLine(
+@" }
+
+ } else {
+ T0_ENTER(ip, rp, t0x);
+ }
+ }
+t0_exit:
+ ((t0_context *)t0ctx)->dp = dp;
+ ((t0_context *)t0ctx)->rp = rp;
+ ((t0_context *)t0ctx)->ip = ip;
+}");
+
+ /*
+ * Add the "postamblr" elements here. These are
+ * elements that may need access to the data
+ * block or code block, so they must occur after
+ * their definition.
+ */
+ foreach (string pp in extraCodeDefer) {
+ tw.WriteLine();
+ tw.WriteLine("{0}", pp);
+ }
+ }
+
+ int codeLen = 0;
+ foreach (CodeElement ce in gcode) {
+ codeLen += ce.GetLength(oneByteCode);
+ }
+ int dataBlockLen = 0;
+ foreach (ConstData cd in blocks.Values) {
+ dataBlockLen += cd.Length;
+ }
+
+ /*
+ * Write some statistics on produced code.
+ */
+ Console.WriteLine("code length: {0,6} byte(s)", codeLen);
+ Console.WriteLine("data length: {0,6} byte(s)", dataLen);
+ Console.WriteLine("total words: {0} (interpreted: {1})",
+ slotInterpreted + numInterpreted, numInterpreted);
+ }
+
+ internal Word Lookup(string name)
+ {
+ Word w = LookupNF(name);
+ if (w != null) {
+ return w;
+ }
+ throw new Exception(String.Format("No such word: '{0}'", name));
+ }
+
+ internal Word LookupNF(string name)
+ {
+ Word w;
+ words.TryGetValue(name, out w);
+ return w;
+ }
+
+ internal TValue StringToBlob(string s)
+ {
+ return new TValue(0, new TPointerBlob(this, s));
+ }
+
+ internal bool TryParseLiteral(string tt, out TValue tv)
+ {
+ tv = new TValue(0);
+ if (tt.StartsWith("\"")) {
+ tv = StringToBlob(tt.Substring(1));
+ return true;
+ }
+ if (tt.StartsWith("`")) {
+ tv = DecodeCharConst(tt.Substring(1));
+ return true;
+ }
+ bool neg = false;
+ if (tt.StartsWith("-")) {
+ neg = true;
+ tt = tt.Substring(1);
+ } else if (tt.StartsWith("+")) {
+ tt = tt.Substring(1);
+ }
+ uint radix = 10;
+ if (tt.StartsWith("0x") || tt.StartsWith("0X")) {
+ radix = 16;
+ tt = tt.Substring(2);
+ } else if (tt.StartsWith("0b") || tt.StartsWith("0B")) {
+ radix = 2;
+ tt = tt.Substring(2);
+ }
+ if (tt.Length == 0) {
+ return false;
+ }
+ uint acc = 0;
+ bool overflow = false;
+ uint maxV = uint.MaxValue / radix;
+ foreach (char c in tt) {
+ int d = HexVal(c);
+ if (d < 0 || d >= radix) {
+ return false;
+ }
+ if (acc > maxV) {
+ overflow = true;
+ }
+ acc *= radix;
+ if ((uint)d > uint.MaxValue - acc) {
+ overflow = true;
+ }
+ acc += (uint)d;
+ }
+ int x = (int)acc;
+ if (neg) {
+ if (acc > (uint)0x80000000) {
+ overflow = true;
+ }
+ x = -x;
+ }
+ if (overflow) {
+ throw new Exception(
+ "invalid literal integer (overflow)");
+ }
+ tv = x;
+ return true;
+ }
+
+ int ParseInteger(string tt)
+ {
+ TValue tv;
+ if (!TryParseLiteral(tt, out tv)) {
+ throw new Exception("not an integer: " + ToString());
+ }
+ return (int)tv;
+ }
+
+ void CheckCompiling()
+ {
+ if (!compiling) {
+ throw new Exception("Not in compilation mode");
+ }
+ }
+
+ static string EscapeCComment(string s)
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (char c in s) {
+ if (c >= 33 && c <= 126 && c != '%') {
+ sb.Append(c);
+ } else if (c < 0x100) {
+ sb.AppendFormat("%{0:X2}", (int)c);
+ } else if (c < 0x800) {
+ sb.AppendFormat("%{0:X2}%{0:X2}",
+ ((int)c >> 6) | 0xC0,
+ ((int)c & 0x3F) | 0x80);
+ } else {
+ sb.AppendFormat("%{0:X2}%{0:X2}%{0:X2}",
+ ((int)c >> 12) | 0xE0,
+ (((int)c >> 6) & 0x3F) | 0x80,
+ ((int)c & 0x3F) | 0x80);
+ }
+ }
+ return sb.ToString().Replace("*/", "%2A/");
+ }
+}
Index: stable/12/contrib/bearssl/T0/TPointerBase.cs
===================================================================
--- stable/12/contrib/bearssl/T0/TPointerBase.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/TPointerBase.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/TPointerBlob.cs
===================================================================
--- stable/12/contrib/bearssl/T0/TPointerBlob.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/TPointerBlob.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/TPointerExpr.cs
===================================================================
--- stable/12/contrib/bearssl/T0/TPointerExpr.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/TPointerExpr.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/TPointerNull.cs
===================================================================
--- stable/12/contrib/bearssl/T0/TPointerNull.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/TPointerNull.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/TPointerXT.cs
===================================================================
--- stable/12/contrib/bearssl/T0/TPointerXT.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/TPointerXT.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/TValue.cs
===================================================================
--- stable/12/contrib/bearssl/T0/TValue.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/TValue.cs (revision 346145)
@@ -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;
+ }
+}
Index: stable/12/contrib/bearssl/T0/Word.cs
===================================================================
--- stable/12/contrib/bearssl/T0/Word.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/Word.cs (revision 346145)
@@ -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;
+ }
+ }
+}
Index: stable/12/contrib/bearssl/T0/WordBuilder.cs
===================================================================
--- stable/12/contrib/bearssl/T0/WordBuilder.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/WordBuilder.cs (revision 346145)
@@ -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));
+ }
+}
Index: stable/12/contrib/bearssl/T0/WordData.cs
===================================================================
--- stable/12/contrib/bearssl/T0/WordData.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/WordData.cs (revision 346145)
@@ -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));
+ }
+}
Index: stable/12/contrib/bearssl/T0/WordInterpreted.cs
===================================================================
--- stable/12/contrib/bearssl/T0/WordInterpreted.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/WordInterpreted.cs (revision 346145)
@@ -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;
+ }
+ }
+}
Index: stable/12/contrib/bearssl/T0/WordNative.cs
===================================================================
--- stable/12/contrib/bearssl/T0/WordNative.cs (nonexistent)
+++ stable/12/contrib/bearssl/T0/WordNative.cs (revision 346145)
@@ -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);
+ }
+}
Index: stable/12/contrib/bearssl/T0/kern.t0
===================================================================
--- stable/12/contrib/bearssl/T0/kern.t0 (nonexistent)
+++ stable/12/contrib/bearssl/T0/kern.t0 (revision 346145)
@@ -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));
+}
Index: stable/12/contrib/bearssl/T0Comp.exe
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/T0Comp.exe
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/build/.do_not_remove
===================================================================
Index: stable/12/contrib/bearssl/conf/Unix.mk
===================================================================
--- stable/12/contrib/bearssl/conf/Unix.mk (nonexistent)
+++ stable/12/contrib/bearssl/conf/Unix.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/conf/Unix.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/conf/Unix32.mk
===================================================================
--- stable/12/contrib/bearssl/conf/Unix32.mk (nonexistent)
+++ stable/12/contrib/bearssl/conf/Unix32.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/conf/Unix32.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/conf/UnixClang.mk
===================================================================
--- stable/12/contrib/bearssl/conf/UnixClang.mk (nonexistent)
+++ stable/12/contrib/bearssl/conf/UnixClang.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/conf/UnixClang.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/conf/Win.mk
===================================================================
--- stable/12/contrib/bearssl/conf/Win.mk (nonexistent)
+++ stable/12/contrib/bearssl/conf/Win.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/conf/Win.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/conf/samd20.mk
===================================================================
--- stable/12/contrib/bearssl/conf/samd20.mk (nonexistent)
+++ stable/12/contrib/bearssl/conf/samd20.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/conf/samd20.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/inc/bearssl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_aead.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_aead.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_aead.h (revision 346145)
@@ -0,0 +1,1059 @@
+/*
+ * 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.
+ */
+
+#ifndef BR_BEARSSL_AEAD_H__
+#define BR_BEARSSL_AEAD_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "bearssl_block.h"
+#include "bearssl_hash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file bearssl_aead.h
+ *
+ * # Authenticated Encryption with Additional Data
+ *
+ * This file documents the API for AEAD encryption.
+ *
+ *
+ * ## Procedural API
+ *
+ * An AEAD algorithm processes messages and provides confidentiality
+ * (encryption) and checked integrity (MAC). It uses the following
+ * parameters:
+ *
+ * - A symmetric key. Exact size depends on the AEAD algorithm.
+ *
+ * - A nonce (IV). Size depends on the AEAD algorithm; for most
+ * algorithms, it is crucial for security that any given nonce
+ * value is never used twice for the same key and distinct
+ * messages.
+ *
+ * - Data to encrypt and protect.
+ *
+ * - Additional authenticated data, which is covered by the MAC but
+ * otherwise left untouched (i.e. not encrypted).
+ *
+ * The AEAD algorithm encrypts the data, and produces an authentication
+ * tag. It is assumed that the encrypted data, the tag, the additional
+ * authenticated data and the nonce are sent to the receiver; the
+ * additional data and the nonce may be implicit (e.g. using elements of
+ * the underlying transport protocol, such as record sequence numbers).
+ * The receiver will recompute the tag value and compare it with the one
+ * received; if they match, then the data is correct, and can be
+ * decrypted and used; otherwise, at least one of the elements was
+ * altered in transit, normally leading to wholesale rejection of the
+ * complete message.
+ *
+ * For each AEAD algorithm, identified by a symbolic name (hereafter
+ * denoted as "`xxx`"), the following functions are defined:
+ *
+ * - `br_xxx_init()`
+ *
+ * Initialise the AEAD algorithm, on a provided context structure.
+ * Exact parameters depend on the algorithm, and may include
+ * pointers to extra implementations and context structures. The
+ * secret key is provided at this point, either directly or
+ * indirectly.
+ *
+ * - `br_xxx_reset()`
+ *
+ * Start a new AEAD computation. The nonce value is provided as
+ * parameter to this function.
+ *
+ * - `br_xxx_aad_inject()`
+ *
+ * Inject some additional authenticated data. Additional data may
+ * be provided in several chunks of arbitrary length.
+ *
+ * - `br_xxx_flip()`
+ *
+ * This function MUST be called after injecting all additional
+ * authenticated data, and before beginning to encrypt the plaintext
+ * (or decrypt the ciphertext).
+ *
+ * - `br_xxx_run()`
+ *
+ * Process some plaintext (to encrypt) or ciphertext (to decrypt).
+ * Encryption/decryption is done in place. Data may be provided in
+ * several chunks of arbitrary length.
+ *
+ * - `br_xxx_get_tag()`
+ *
+ * Compute the authentication tag. All message data (encrypted or
+ * decrypted) must have been injected at that point. Also, this
+ * call may modify internal context elements, so it may be called
+ * only once for a given AEAD computation.
+ *
+ * - `br_xxx_check_tag()`
+ *
+ * An alternative to `br_xxx_get_tag()`, meant to be used by the
+ * receiver: the authentication tag is internally recomputed, and
+ * compared with the one provided as parameter.
+ *
+ * This API makes the following assumptions on the AEAD algorithm:
+ *
+ * - Encryption does not expand the size of the ciphertext; there is
+ * no padding. This is true of most modern AEAD modes such as GCM.
+ *
+ * - The additional authenticated data must be processed first,
+ * before the encrypted/decrypted data.
+ *
+ * - Nonce, plaintext and additional authenticated data all consist
+ * in an integral number of bytes. There is no provision to use
+ * elements whose length in bits is not a multiple of 8.
+ *
+ * Each AEAD algorithm has its own requirements and limits on the sizes
+ * of additional data and plaintext. This API does not provide any
+ * way to report invalid usage; it is up to the caller to ensure that
+ * the provided key, nonce, and data elements all fit the algorithm's
+ * requirements.
+ *
+ *
+ * ## Object-Oriented API
+ *
+ * Each context structure begins with a field (called `vtable`) that
+ * points to an instance of a structure that references the relevant
+ * functions through pointers. Each such structure contains the
+ * following:
+ *
+ * - `reset`
+ *
+ * Pointer to the reset function, that allows starting a new
+ * computation.
+ *
+ * - `aad_inject`
+ *
+ * Pointer to the additional authenticated data injection function.
+ *
+ * - `flip`
+ *
+ * Pointer to the function that transitions from additional data
+ * to main message data processing.
+ *
+ * - `get_tag`
+ *
+ * Pointer to the function that computes and returns the tag.
+ *
+ * - `check_tag`
+ *
+ * Pointer to the function that computes and verifies the tag against
+ * a received value.
+ *
+ * Note that there is no OOP method for context initialisation: the
+ * various AEAD algorithms have different requirements that would not
+ * map well to a single initialisation API.
+ *
+ * The OOP API is not provided for CCM, due to its specific requirements
+ * (length of plaintext must be known in advance).
+ */
+
+/**
+ * \brief Class type of an AEAD algorithm.
+ */
+typedef struct br_aead_class_ br_aead_class;
+struct br_aead_class_ {
+
+ /**
+ * \brief Size (in bytes) of authentication tags created by
+ * this AEAD algorithm.
+ */
+ size_t tag_size;
+
+ /**
+ * \brief Reset an AEAD context.
+ *
+ * This function resets an already initialised AEAD context for
+ * a new computation run. Implementations and keys are
+ * conserved. This function can be called at any time; it
+ * cancels any ongoing AEAD computation that uses the provided
+ * context structure.
+
+ * The provided IV is a _nonce_. Each AEAD algorithm has its
+ * own requirements on IV size and contents; for most of them,
+ * it is crucial to security that each nonce value is used
+ * only once for a given secret key.
+ *
+ * \param cc AEAD context structure.
+ * \param iv AEAD nonce to use.
+ * \param len AEAD nonce length (in bytes).
+ */
+ void (*reset)(const br_aead_class **cc, const void *iv, size_t len);
+
+ /**
+ * \brief Inject additional authenticated data.
+ *
+ * The provided data is injected into a running AEAD
+ * computation. Additional data must be injected _before_ the
+ * call to `flip()`. Additional data can be injected in several
+ * chunks of arbitrary length.
+ *
+ * \param cc AEAD context structure.
+ * \param data pointer to additional authenticated data.
+ * \param len length of additional authenticated data (in bytes).
+ */
+ void (*aad_inject)(const br_aead_class **cc,
+ const void *data, size_t len);
+
+ /**
+ * \brief Finish injection of additional authenticated data.
+ *
+ * This function MUST be called before beginning the actual
+ * encryption or decryption (with `run()`), even if no
+ * additional authenticated data was injected. No additional
+ * authenticated data may be injected after this function call.
+ *
+ * \param cc AEAD context structure.
+ */
+ void (*flip)(const br_aead_class **cc);
+
+ /**
+ * \brief Encrypt or decrypt some data.
+ *
+ * Data encryption or decryption can be done after `flip()` has
+ * been called on the context. If `encrypt` is non-zero, then
+ * the provided data shall be plaintext, and it is encrypted in
+ * place. Otherwise, the data shall be ciphertext, and it is
+ * decrypted in place.
+ *
+ * Data may be provided in several chunks of arbitrary length.
+ *
+ * \param cc AEAD context structure.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ */
+ void (*run)(const br_aead_class **cc, int encrypt,
+ void *data, size_t len);
+
+ /**
+ * \brief Compute authentication tag.
+ *
+ * Compute the AEAD authentication tag. The tag length depends
+ * on the AEAD algorithm; it is written in the provided `tag`
+ * buffer. This call terminates the AEAD run: no data may be
+ * processed with that AEAD context afterwards, until `reset()`
+ * is called to initiate a new AEAD run.
+ *
+ * The tag value must normally be sent along with the encrypted
+ * data. When decrypting, the tag value must be recomputed and
+ * compared with the received tag: if the two tag values differ,
+ * then either the tag or the encrypted data was altered in
+ * transit. As an alternative to this function, the
+ * `check_tag()` function may be used to compute and check the
+ * tag value.
+ *
+ * Tag length depends on the AEAD algorithm.
+ *
+ * \param cc AEAD context structure.
+ * \param tag destination buffer for the tag.
+ */
+ void (*get_tag)(const br_aead_class **cc, void *tag);
+
+ /**
+ * \brief Compute and check authentication tag.
+ *
+ * This function is an alternative to `get_tag()`, and is
+ * normally used on the receiving end (i.e. when decrypting
+ * messages). The tag value is recomputed and compared with the
+ * provided tag value. If they match, 1 is returned; on
+ * mismatch, 0 is returned. A returned value of 0 means that the
+ * data or the tag was altered in transit, normally leading to
+ * wholesale rejection of the complete message.
+ *
+ * Tag length depends on the AEAD algorithm.
+ *
+ * \param cc AEAD context structure.
+ * \param tag tag value to compare with.
+ * \return 1 on success (exact match of tag value), 0 otherwise.
+ */
+ uint32_t (*check_tag)(const br_aead_class **cc, const void *tag);
+
+ /**
+ * \brief Compute authentication tag (with truncation).
+ *
+ * This function is similar to `get_tag()`, except that the tag
+ * length is provided. Some AEAD algorithms allow several tag
+ * lengths, usually by truncating the normal tag. Shorter tags
+ * mechanically increase success probability of forgeries.
+ * The range of allowed tag lengths depends on the algorithm.
+ *
+ * \param cc AEAD context structure.
+ * \param tag destination buffer for the tag.
+ * \param len tag length (in bytes).
+ */
+ void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len);
+
+ /**
+ * \brief Compute and check authentication tag (with truncation).
+ *
+ * This function is similar to `check_tag()` except that it
+ * works over an explicit tag length. See `get_tag()` for a
+ * discussion of explicit tag lengths; the range of allowed tag
+ * lengths depends on the algorithm.
+ *
+ * \param cc AEAD context structure.
+ * \param tag tag value to compare with.
+ * \param len tag length (in bytes).
+ * \return 1 on success (exact match of tag value), 0 otherwise.
+ */
+ uint32_t (*check_tag_trunc)(const br_aead_class **cc,
+ const void *tag, size_t len);
+};
+
+/**
+ * \brief Context structure for GCM.
+ *
+ * GCM is an AEAD mode that combines a block cipher in CTR mode with a
+ * MAC based on GHASH, to provide authenticated encryption:
+ *
+ * - Any block cipher with 16-byte blocks can be used with GCM.
+ *
+ * - The nonce can have any length, from 0 up to 2^64-1 bits; however,
+ * 96-bit nonces (12 bytes) are recommended (nonces with a length
+ * distinct from 12 bytes are internally hashed, which risks reusing
+ * nonce value with a small but not always negligible probability).
+ *
+ * - Additional authenticated data may have length up to 2^64-1 bits.
+ *
+ * - Message length may range up to 2^39-256 bits at most.
+ *
+ * - The authentication tag has length 16 bytes.
+ *
+ * The GCM initialisation function receives as parameter an
+ * _initialised_ block cipher implementation context, with the secret
+ * key already set. A pointer to that context will be kept within the
+ * GCM context structure. It is up to the caller to allocate and
+ * initialise that block cipher context.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_aead_class *vtable;
+
+#ifndef BR_DOXYGEN_IGNORE
+ const br_block_ctr_class **bctx;
+ br_ghash gh;
+ unsigned char h[16];
+ unsigned char j0_1[12];
+ unsigned char buf[16];
+ unsigned char y[16];
+ uint32_t j0_2, jc;
+ uint64_t count_aad, count_ctr;
+#endif
+} br_gcm_context;
+
+/**
+ * \brief Initialize a GCM context.
+ *
+ * A block cipher implementation, with its initialised context structure,
+ * is provided. The block cipher MUST use 16-byte blocks in CTR mode,
+ * and its secret key MUST have been already set in the provided context.
+ * A GHASH implementation must also be provided. The parameters are linked
+ * in the GCM context.
+ *
+ * After this function has been called, the `br_gcm_reset()` function must
+ * be called, to provide the IV for GCM computation.
+ *
+ * \param ctx GCM context structure.
+ * \param bctx block cipher context (already initialised with secret key).
+ * \param gh GHASH implementation.
+ */
+void br_gcm_init(br_gcm_context *ctx,
+ const br_block_ctr_class **bctx, br_ghash gh);
+
+/**
+ * \brief Reset a GCM context.
+ *
+ * This function resets an already initialised GCM context for a new
+ * computation run. Implementations and keys are conserved. This function
+ * can be called at any time; it cancels any ongoing GCM computation that
+ * uses the provided context structure.
+ *
+ * The provided IV is a _nonce_. It is critical to GCM security that IV
+ * values are not repeated for the same encryption key. IV can have
+ * arbitrary length (up to 2^64-1 bits), but the "normal" length is
+ * 96 bits (12 bytes).
+ *
+ * \param ctx GCM context structure.
+ * \param iv GCM nonce to use.
+ * \param len GCM nonce length (in bytes).
+ */
+void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len);
+
+/**
+ * \brief Inject additional authenticated data into GCM.
+ *
+ * The provided data is injected into a running GCM computation. Additional
+ * data must be injected _before_ the call to `br_gcm_flip()`.
+ * Additional data can be injected in several chunks of arbitrary length;
+ * the maximum total size of additional authenticated data is 2^64-1
+ * bits.
+ *
+ * \param ctx GCM context structure.
+ * \param data pointer to additional authenticated data.
+ * \param len length of additional authenticated data (in bytes).
+ */
+void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Finish injection of additional authenticated data into GCM.
+ *
+ * This function MUST be called before beginning the actual encryption
+ * or decryption (with `br_gcm_run()`), even if no additional authenticated
+ * data was injected. No additional authenticated data may be injected
+ * after this function call.
+ *
+ * \param ctx GCM context structure.
+ */
+void br_gcm_flip(br_gcm_context *ctx);
+
+/**
+ * \brief Encrypt or decrypt some data with GCM.
+ *
+ * Data encryption or decryption can be done after `br_gcm_flip()`
+ * has been called on the context. If `encrypt` is non-zero, then the
+ * provided data shall be plaintext, and it is encrypted in place.
+ * Otherwise, the data shall be ciphertext, and it is decrypted in place.
+ *
+ * Data may be provided in several chunks of arbitrary length. The maximum
+ * total length for data is 2^39-256 bits, i.e. about 65 gigabytes.
+ *
+ * \param ctx GCM context structure.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ */
+void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len);
+
+/**
+ * \brief Compute GCM authentication tag.
+ *
+ * Compute the GCM authentication tag. The tag is a 16-byte value which
+ * is written in the provided `tag` buffer. This call terminates the
+ * GCM run: no data may be processed with that GCM context afterwards,
+ * until `br_gcm_reset()` is called to initiate a new GCM run.
+ *
+ * The tag value must normally be sent along with the encrypted data.
+ * When decrypting, the tag value must be recomputed and compared with
+ * the received tag: if the two tag values differ, then either the tag
+ * or the encrypted data was altered in transit. As an alternative to
+ * this function, the `br_gcm_check_tag()` function can be used to
+ * compute and check the tag value.
+ *
+ * \param ctx GCM context structure.
+ * \param tag destination buffer for the tag (16 bytes).
+ */
+void br_gcm_get_tag(br_gcm_context *ctx, void *tag);
+
+/**
+ * \brief Compute and check GCM authentication tag.
+ *
+ * This function is an alternative to `br_gcm_get_tag()`, normally used
+ * on the receiving end (i.e. when decrypting value). The tag value is
+ * recomputed and compared with the provided tag value. If they match, 1
+ * is returned; on mismatch, 0 is returned. A returned value of 0 means
+ * that the data or the tag was altered in transit, normally leading to
+ * wholesale rejection of the complete message.
+ *
+ * \param ctx GCM context structure.
+ * \param tag tag value to compare with (16 bytes).
+ * \return 1 on success (exact match of tag value), 0 otherwise.
+ */
+uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag);
+
+/**
+ * \brief Compute GCM authentication tag (with truncation).
+ *
+ * This function is similar to `br_gcm_get_tag()`, except that it allows
+ * the tag to be truncated to a smaller length. The intended tag length
+ * is provided as `len` (in bytes); it MUST be no more than 16, but
+ * it may be smaller. Note that decreasing tag length mechanically makes
+ * forgeries easier; NIST SP 800-38D specifies that the tag length shall
+ * lie between 12 and 16 bytes (inclusive), but may be truncated down to
+ * 4 or 8 bytes, for specific applications that can tolerate it. It must
+ * also be noted that successful forgeries leak information on the
+ * authentication key, making subsequent forgeries easier. Therefore,
+ * tag truncation, and in particular truncation to sizes lower than 12
+ * bytes, shall be envisioned only with great care.
+ *
+ * The tag is written in the provided `tag` buffer. This call terminates
+ * the GCM run: no data may be processed with that GCM context
+ * afterwards, until `br_gcm_reset()` is called to initiate a new GCM
+ * run.
+ *
+ * The tag value must normally be sent along with the encrypted data.
+ * When decrypting, the tag value must be recomputed and compared with
+ * the received tag: if the two tag values differ, then either the tag
+ * or the encrypted data was altered in transit. As an alternative to
+ * this function, the `br_gcm_check_tag_trunc()` function can be used to
+ * compute and check the tag value.
+ *
+ * \param ctx GCM context structure.
+ * \param tag destination buffer for the tag.
+ * \param len tag length (16 bytes or less).
+ */
+void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len);
+
+/**
+ * \brief Compute and check GCM authentication tag (with truncation).
+ *
+ * This function is an alternative to `br_gcm_get_tag_trunc()`, normally used
+ * on the receiving end (i.e. when decrypting value). The tag value is
+ * recomputed and compared with the provided tag value. If they match, 1
+ * is returned; on mismatch, 0 is returned. A returned value of 0 means
+ * that the data or the tag was altered in transit, normally leading to
+ * wholesale rejection of the complete message.
+ *
+ * Tag length MUST be 16 bytes or less. The normal GCM tag length is 16
+ * bytes. See `br_check_tag_trunc()` for some discussion on the potential
+ * perils of truncating authentication tags.
+ *
+ * \param ctx GCM context structure.
+ * \param tag tag value to compare with.
+ * \param len tag length (in bytes).
+ * \return 1 on success (exact match of tag value), 0 otherwise.
+ */
+uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx,
+ const void *tag, size_t len);
+
+/**
+ * \brief Class instance for GCM.
+ */
+extern const br_aead_class br_gcm_vtable;
+
+/**
+ * \brief Context structure for EAX.
+ *
+ * EAX is an AEAD mode that combines a block cipher in CTR mode with
+ * CBC-MAC using the same block cipher and the same key, to provide
+ * authenticated encryption:
+ *
+ * - Any block cipher with 16-byte blocks can be used with EAX
+ * (technically, other block sizes are defined as well, but this
+ * is not implemented by these functions; shorter blocks also
+ * imply numerous security issues).
+ *
+ * - The nonce can have any length, as long as nonce values are
+ * not reused (thus, if nonces are randomly selected, the nonce
+ * size should be such that reuse probability is negligible).
+ *
+ * - Additional authenticated data length is unlimited.
+ *
+ * - Message length is unlimited.
+ *
+ * - The authentication tag has length 16 bytes.
+ *
+ * The EAX initialisation function receives as parameter an
+ * _initialised_ block cipher implementation context, with the secret
+ * key already set. A pointer to that context will be kept within the
+ * EAX context structure. It is up to the caller to allocate and
+ * initialise that block cipher context.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_aead_class *vtable;
+
+#ifndef BR_DOXYGEN_IGNORE
+ const br_block_ctrcbc_class **bctx;
+ unsigned char L2[16];
+ unsigned char L4[16];
+ unsigned char nonce[16];
+ unsigned char head[16];
+ unsigned char ctr[16];
+ unsigned char cbcmac[16];
+ unsigned char buf[16];
+ size_t ptr;
+#endif
+} br_eax_context;
+
+/**
+ * \brief EAX captured state.
+ *
+ * Some internal values computed by EAX may be captured at various
+ * points, and reused for another EAX run with the same secret key,
+ * for lower per-message overhead. Captured values do not depend on
+ * the nonce.
+ */
+typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char st[3][16];
+#endif
+} br_eax_state;
+
+/**
+ * \brief Initialize an EAX context.
+ *
+ * A block cipher implementation, with its initialised context
+ * structure, is provided. The block cipher MUST use 16-byte blocks in
+ * CTR + CBC-MAC mode, and its secret key MUST have been already set in
+ * the provided context. The parameters are linked in the EAX context.
+ *
+ * After this function has been called, the `br_eax_reset()` function must
+ * be called, to provide the nonce for EAX computation.
+ *
+ * \param ctx EAX context structure.
+ * \param bctx block cipher context (already initialised with secret key).
+ */
+void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx);
+
+/**
+ * \brief Capture pre-AAD state.
+ *
+ * This function precomputes key-dependent data, and stores it in the
+ * provided `st` structure. This structure should then be used with
+ * `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()`
+ * and then used with `br_eax_reset_post_aad()`.
+ *
+ * The EAX context structure is unmodified by this call.
+ *
+ * \param ctx EAX context structure.
+ * \param st recipient for captured state.
+ */
+void br_eax_capture(const br_eax_context *ctx, br_eax_state *st);
+
+/**
+ * \brief Reset an EAX context.
+ *
+ * This function resets an already initialised EAX context for a new
+ * computation run. Implementations and keys are conserved. This function
+ * can be called at any time; it cancels any ongoing EAX computation that
+ * uses the provided context structure.
+ *
+ * It is critical to EAX security that nonce values are not repeated for
+ * the same encryption key. Nonces can have arbitrary length. If nonces
+ * are randomly generated, then a nonce length of at least 128 bits (16
+ * bytes) is recommended, to make nonce reuse probability sufficiently
+ * low.
+ *
+ * \param ctx EAX context structure.
+ * \param nonce EAX nonce to use.
+ * \param len EAX nonce length (in bytes).
+ */
+void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len);
+
+/**
+ * \brief Reset an EAX context with a pre-AAD captured state.
+ *
+ * This function is an alternative to `br_eax_reset()`, that reuses a
+ * previously captured state structure for lower per-message overhead.
+ * The state should have been populated with `br_eax_capture_state()`
+ * but not updated with `br_eax_get_aad_mac()`.
+ *
+ * After this function is called, additional authenticated data MUST
+ * be injected. At least one byte of additional authenticated data
+ * MUST be provided with `br_eax_aad_inject()`; computation result will
+ * be incorrect if `br_eax_flip()` is called right away.
+ *
+ * After injection of the AAD and call to `br_eax_flip()`, at least
+ * one message byte must be provided. Empty messages are not supported
+ * with this reset mode.
+ *
+ * \param ctx EAX context structure.
+ * \param st pre-AAD captured state.
+ * \param nonce EAX nonce to use.
+ * \param len EAX nonce length (in bytes).
+ */
+void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
+ const void *nonce, size_t len);
+
+/**
+ * \brief Reset an EAX context with a post-AAD captured state.
+ *
+ * This function is an alternative to `br_eax_reset()`, that reuses a
+ * previously captured state structure for lower per-message overhead.
+ * The state should have been populated with `br_eax_capture_state()`
+ * and then updated with `br_eax_get_aad_mac()`.
+ *
+ * After this function is called, message data MUST be injected. The
+ * `br_eax_flip()` function MUST NOT be called. At least one byte of
+ * message data MUST be provided with `br_eax_run()`; empty messages
+ * are not supported with this reset mode.
+ *
+ * \param ctx EAX context structure.
+ * \param st post-AAD captured state.
+ * \param nonce EAX nonce to use.
+ * \param len EAX nonce length (in bytes).
+ */
+void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
+ const void *nonce, size_t len);
+
+/**
+ * \brief Inject additional authenticated data into EAX.
+ *
+ * The provided data is injected into a running EAX computation. Additional
+ * data must be injected _before_ the call to `br_eax_flip()`.
+ * Additional data can be injected in several chunks of arbitrary length;
+ * the total amount of additional authenticated data is unlimited.
+ *
+ * \param ctx EAX context structure.
+ * \param data pointer to additional authenticated data.
+ * \param len length of additional authenticated data (in bytes).
+ */
+void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Finish injection of additional authenticated data into EAX.
+ *
+ * This function MUST be called before beginning the actual encryption
+ * or decryption (with `br_eax_run()`), even if no additional authenticated
+ * data was injected. No additional authenticated data may be injected
+ * after this function call.
+ *
+ * \param ctx EAX context structure.
+ */
+void br_eax_flip(br_eax_context *ctx);
+
+/**
+ * \brief Obtain a copy of the MAC on additional authenticated data.
+ *
+ * This function may be called only after `br_eax_flip()`; it copies the
+ * AAD-specific MAC value into the provided state. The MAC value depends
+ * on the secret key and the additional data itself, but not on the
+ * nonce. The updated state `st` is meant to be used as parameter for a
+ * further `br_eax_reset_post_aad()` call.
+ *
+ * \param ctx EAX context structure.
+ * \param st captured state to update.
+ */
+static inline void
+br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st)
+{
+ memcpy(st->st[1], ctx->head, sizeof ctx->head);
+}
+
+/**
+ * \brief Encrypt or decrypt some data with EAX.
+ *
+ * Data encryption or decryption can be done after `br_eax_flip()`
+ * has been called on the context. If `encrypt` is non-zero, then the
+ * provided data shall be plaintext, and it is encrypted in place.
+ * Otherwise, the data shall be ciphertext, and it is decrypted in place.
+ *
+ * Data may be provided in several chunks of arbitrary length.
+ *
+ * \param ctx EAX context structure.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ */
+void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len);
+
+/**
+ * \brief Compute EAX authentication tag.
+ *
+ * Compute the EAX authentication tag. The tag is a 16-byte value which
+ * is written in the provided `tag` buffer. This call terminates the
+ * EAX run: no data may be processed with that EAX context afterwards,
+ * until `br_eax_reset()` is called to initiate a new EAX run.
+ *
+ * The tag value must normally be sent along with the encrypted data.
+ * When decrypting, the tag value must be recomputed and compared with
+ * the received tag: if the two tag values differ, then either the tag
+ * or the encrypted data was altered in transit. As an alternative to
+ * this function, the `br_eax_check_tag()` function can be used to
+ * compute and check the tag value.
+ *
+ * \param ctx EAX context structure.
+ * \param tag destination buffer for the tag (16 bytes).
+ */
+void br_eax_get_tag(br_eax_context *ctx, void *tag);
+
+/**
+ * \brief Compute and check EAX authentication tag.
+ *
+ * This function is an alternative to `br_eax_get_tag()`, normally used
+ * on the receiving end (i.e. when decrypting value). The tag value is
+ * recomputed and compared with the provided tag value. If they match, 1
+ * is returned; on mismatch, 0 is returned. A returned value of 0 means
+ * that the data or the tag was altered in transit, normally leading to
+ * wholesale rejection of the complete message.
+ *
+ * \param ctx EAX context structure.
+ * \param tag tag value to compare with (16 bytes).
+ * \return 1 on success (exact match of tag value), 0 otherwise.
+ */
+uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag);
+
+/**
+ * \brief Compute EAX authentication tag (with truncation).
+ *
+ * This function is similar to `br_eax_get_tag()`, except that it allows
+ * the tag to be truncated to a smaller length. The intended tag length
+ * is provided as `len` (in bytes); it MUST be no more than 16, but
+ * it may be smaller. Note that decreasing tag length mechanically makes
+ * forgeries easier; NIST SP 800-38D specifies that the tag length shall
+ * lie between 12 and 16 bytes (inclusive), but may be truncated down to
+ * 4 or 8 bytes, for specific applications that can tolerate it. It must
+ * also be noted that successful forgeries leak information on the
+ * authentication key, making subsequent forgeries easier. Therefore,
+ * tag truncation, and in particular truncation to sizes lower than 12
+ * bytes, shall be envisioned only with great care.
+ *
+ * The tag is written in the provided `tag` buffer. This call terminates
+ * the EAX run: no data may be processed with that EAX context
+ * afterwards, until `br_eax_reset()` is called to initiate a new EAX
+ * run.
+ *
+ * The tag value must normally be sent along with the encrypted data.
+ * When decrypting, the tag value must be recomputed and compared with
+ * the received tag: if the two tag values differ, then either the tag
+ * or the encrypted data was altered in transit. As an alternative to
+ * this function, the `br_eax_check_tag_trunc()` function can be used to
+ * compute and check the tag value.
+ *
+ * \param ctx EAX context structure.
+ * \param tag destination buffer for the tag.
+ * \param len tag length (16 bytes or less).
+ */
+void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len);
+
+/**
+ * \brief Compute and check EAX authentication tag (with truncation).
+ *
+ * This function is an alternative to `br_eax_get_tag_trunc()`, normally used
+ * on the receiving end (i.e. when decrypting value). The tag value is
+ * recomputed and compared with the provided tag value. If they match, 1
+ * is returned; on mismatch, 0 is returned. A returned value of 0 means
+ * that the data or the tag was altered in transit, normally leading to
+ * wholesale rejection of the complete message.
+ *
+ * Tag length MUST be 16 bytes or less. The normal EAX tag length is 16
+ * bytes. See `br_check_tag_trunc()` for some discussion on the potential
+ * perils of truncating authentication tags.
+ *
+ * \param ctx EAX context structure.
+ * \param tag tag value to compare with.
+ * \param len tag length (in bytes).
+ * \return 1 on success (exact match of tag value), 0 otherwise.
+ */
+uint32_t br_eax_check_tag_trunc(br_eax_context *ctx,
+ const void *tag, size_t len);
+
+/**
+ * \brief Class instance for EAX.
+ */
+extern const br_aead_class br_eax_vtable;
+
+/**
+ * \brief Context structure for CCM.
+ *
+ * CCM is an AEAD mode that combines a block cipher in CTR mode with
+ * CBC-MAC using the same block cipher and the same key, to provide
+ * authenticated encryption:
+ *
+ * - Any block cipher with 16-byte blocks can be used with CCM
+ * (technically, other block sizes are defined as well, but this
+ * is not implemented by these functions; shorter blocks also
+ * imply numerous security issues).
+ *
+ * - The authentication tag length, and plaintext length, MUST be
+ * known when starting processing data. Plaintext and ciphertext
+ * can still be provided by chunks, but the total size must match
+ * the value provided upon initialisation.
+ *
+ * - The nonce length is constrained between 7 and 13 bytes (inclusive).
+ * Furthermore, the plaintext length, when encoded, must fit over
+ * 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then
+ * the plaintext length cannot exceed 65535 bytes.
+ *
+ * - Additional authenticated data length is practically unlimited
+ * (formal limit is at 2^64 bytes).
+ *
+ * - The authentication tag has length 4 to 16 bytes (even values only).
+ *
+ * The CCM initialisation function receives as parameter an
+ * _initialised_ block cipher implementation context, with the secret
+ * key already set. A pointer to that context will be kept within the
+ * CCM context structure. It is up to the caller to allocate and
+ * initialise that block cipher context.
+ */
+typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
+ const br_block_ctrcbc_class **bctx;
+ unsigned char ctr[16];
+ unsigned char cbcmac[16];
+ unsigned char tagmask[16];
+ unsigned char buf[16];
+ size_t ptr;
+ size_t tag_len;
+#endif
+} br_ccm_context;
+
+/**
+ * \brief Initialize a CCM context.
+ *
+ * A block cipher implementation, with its initialised context
+ * structure, is provided. The block cipher MUST use 16-byte blocks in
+ * CTR + CBC-MAC mode, and its secret key MUST have been already set in
+ * the provided context. The parameters are linked in the CCM context.
+ *
+ * After this function has been called, the `br_ccm_reset()` function must
+ * be called, to provide the nonce for CCM computation.
+ *
+ * \param ctx CCM context structure.
+ * \param bctx block cipher context (already initialised with secret key).
+ */
+void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx);
+
+/**
+ * \brief Reset a CCM context.
+ *
+ * This function resets an already initialised CCM context for a new
+ * computation run. Implementations and keys are conserved. This function
+ * can be called at any time; it cancels any ongoing CCM computation that
+ * uses the provided context structure.
+ *
+ * The `aad_len` parameter contains the total length, in bytes, of the
+ * additional authenticated data. It may be zero. That length MUST be
+ * exact.
+ *
+ * The `data_len` parameter contains the total length, in bytes, of the
+ * data that will be injected (plaintext or ciphertext). That length MUST
+ * be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)).
+ *
+ * The nonce length (`nonce_len`), in bytes, must be in the 7..13 range
+ * (inclusive).
+ *
+ * The tag length (`tag_len`), in bytes, must be in the 4..16 range, and
+ * be an even integer. Short tags mechanically allow for higher forgery
+ * probabilities; hence, tag sizes smaller than 12 bytes shall be used only
+ * with care.
+ *
+ * It is critical to CCM security that nonce values are not repeated for
+ * the same encryption key. Random generation of nonces is not generally
+ * recommended, due to the relatively small maximum nonce value.
+ *
+ * Returned value is 1 on success, 0 on error. An error is reported if
+ * the tag or nonce length is out of range, or if the
+ * plaintext/ciphertext length cannot be encoded with the specified
+ * nonce length.
+ *
+ * \param ctx CCM context structure.
+ * \param nonce CCM nonce to use.
+ * \param nonce_len CCM nonce length (in bytes, 7 to 13).
+ * \param aad_len additional authenticated data length (in bytes).
+ * \param data_len plaintext/ciphertext length (in bytes).
+ * \param tag_len tag length (in bytes).
+ * \return 1 on success, 0 on error.
+ */
+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);
+
+/**
+ * \brief Inject additional authenticated data into CCM.
+ *
+ * The provided data is injected into a running CCM computation. Additional
+ * data must be injected _before_ the call to `br_ccm_flip()`.
+ * Additional data can be injected in several chunks of arbitrary length,
+ * but the total amount MUST exactly match the value which was provided
+ * to `br_ccm_reset()`.
+ *
+ * \param ctx CCM context structure.
+ * \param data pointer to additional authenticated data.
+ * \param len length of additional authenticated data (in bytes).
+ */
+void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Finish injection of additional authenticated data into CCM.
+ *
+ * This function MUST be called before beginning the actual encryption
+ * or decryption (with `br_ccm_run()`), even if no additional authenticated
+ * data was injected. No additional authenticated data may be injected
+ * after this function call.
+ *
+ * \param ctx CCM context structure.
+ */
+void br_ccm_flip(br_ccm_context *ctx);
+
+/**
+ * \brief Encrypt or decrypt some data with CCM.
+ *
+ * Data encryption or decryption can be done after `br_ccm_flip()`
+ * has been called on the context. If `encrypt` is non-zero, then the
+ * provided data shall be plaintext, and it is encrypted in place.
+ * Otherwise, the data shall be ciphertext, and it is decrypted in place.
+ *
+ * Data may be provided in several chunks of arbitrary length, provided
+ * that the total length exactly matches the length provided to the
+ * `br_ccm_reset()` call.
+ *
+ * \param ctx CCM context structure.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ */
+void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len);
+
+/**
+ * \brief Compute CCM authentication tag.
+ *
+ * Compute the CCM authentication tag. This call terminates the CCM
+ * run: all data must have been injected with `br_ccm_run()` (in zero,
+ * one or more successive calls). After this function has been called,
+ * no more data can br processed; a `br_ccm_reset()` call is required
+ * to start a new message.
+ *
+ * The tag length was provided upon context initialisation (last call
+ * to `br_ccm_reset()`); it is returned by this function.
+ *
+ * The tag value must normally be sent along with the encrypted data.
+ * When decrypting, the tag value must be recomputed and compared with
+ * the received tag: if the two tag values differ, then either the tag
+ * or the encrypted data was altered in transit. As an alternative to
+ * this function, the `br_ccm_check_tag()` function can be used to
+ * compute and check the tag value.
+ *
+ * \param ctx CCM context structure.
+ * \param tag destination buffer for the tag (up to 16 bytes).
+ * \return the tag length (in bytes).
+ */
+size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag);
+
+/**
+ * \brief Compute and check CCM authentication tag.
+ *
+ * This function is an alternative to `br_ccm_get_tag()`, normally used
+ * on the receiving end (i.e. when decrypting value). The tag value is
+ * recomputed and compared with the provided tag value. If they match, 1
+ * is returned; on mismatch, 0 is returned. A returned value of 0 means
+ * that the data or the tag was altered in transit, normally leading to
+ * wholesale rejection of the complete message.
+ *
+ * \param ctx CCM context structure.
+ * \param tag tag value to compare with (up to 16 bytes).
+ * \return 1 on success (exact match of tag value), 0 otherwise.
+ */
+uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Property changes on: stable/12/contrib/bearssl/inc/bearssl_aead.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_block.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_block.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_block.h (revision 346145)
@@ -0,0 +1,2618 @@
+/*
+ * 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_BLOCK_H__
+#define BR_BEARSSL_BLOCK_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file bearssl_block.h
+ *
+ * # Block Ciphers and Symmetric Ciphers
+ *
+ * This file documents the API for block ciphers and other symmetric
+ * ciphers.
+ *
+ *
+ * ## Procedural API
+ *
+ * For a block cipher implementation, up to three separate sets of
+ * functions are provided, for CBC encryption, CBC decryption, and CTR
+ * encryption/decryption. Each set has its own context structure,
+ * initialised with the encryption key.
+ *
+ * For CBC encryption and decryption, the data to encrypt or decrypt is
+ * referenced as a sequence of blocks. The implementations assume that
+ * there is no partial block; no padding is applied or removed. The
+ * caller is responsible for handling any kind of padding.
+ *
+ * Function for CTR encryption are defined only for block ciphers with
+ * blocks of 16 bytes or more (i.e. AES, but not DES/3DES).
+ *
+ * Each implemented block cipher is identified by an "internal name"
+ * from which are derived the names of structures and functions that
+ * implement the cipher. For the block cipher of internal name "`xxx`",
+ * the following are defined:
+ *
+ * - `br_xxx_BLOCK_SIZE`
+ *
+ * A macro that evaluates to the block size (in bytes) of the
+ * cipher. For all implemented block ciphers, this value is a
+ * power of two.
+ *
+ * - `br_xxx_cbcenc_keys`
+ *
+ * Context structure that contains the subkeys resulting from the key
+ * expansion. These subkeys are appropriate for CBC encryption. The
+ * structure first field is called `vtable` and points to the
+ * appropriate OOP structure.
+ *
+ * - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)`
+ *
+ * Perform key expansion: subkeys for CBC encryption are computed and
+ * written in the provided context structure. The key length MUST be
+ * adequate for the implemented block cipher. This function also sets
+ * the `vtable` field.
+ *
+ * - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)`
+ *
+ * Perform CBC encryption of `len` bytes, in place. The encrypted data
+ * replaces the cleartext. `len` MUST be a multiple of the block length
+ * (if it is not, the function may loop forever or overflow a buffer).
+ * The IV is provided with the `iv` pointer; it is also updated with
+ * a copy of the last encrypted block.
+ *
+ * - `br_xxx_cbcdec_keys`
+ *
+ * Context structure that contains the subkeys resulting from the key
+ * expansion. These subkeys are appropriate for CBC decryption. The
+ * structure first field is called `vtable` and points to the
+ * appropriate OOP structure.
+ *
+ * - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)`
+ *
+ * Perform key expansion: subkeys for CBC decryption are computed and
+ * written in the provided context structure. The key length MUST be
+ * adequate for the implemented block cipher. This function also sets
+ * the `vtable` field.
+ *
+ * - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)`
+ *
+ * Perform CBC decryption of `len` bytes, in place. The decrypted data
+ * replaces the ciphertext. `len` MUST be a multiple of the block length
+ * (if it is not, the function may loop forever or overflow a buffer).
+ * The IV is provided with the `iv` pointer; it is also updated with
+ * a copy of the last _encrypted_ block.
+ *
+ * - `br_xxx_ctr_keys`
+ *
+ * Context structure that contains the subkeys resulting from the key
+ * expansion. These subkeys are appropriate for CTR encryption and
+ * decryption. The structure first field is called `vtable` and
+ * points to the appropriate OOP structure.
+ *
+ * - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)`
+ *
+ * Perform key expansion: subkeys for CTR encryption and decryption
+ * are computed and written in the provided context structure. The
+ * key length MUST be adequate for the implemented block cipher. This
+ * function also sets the `vtable` field.
+ *
+ * - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`)
+ *
+ * Perform CTR encryption/decryption of some data. Processing is done
+ * "in place" (the output data replaces the input data). This function
+ * implements the "standard incrementing function" from NIST SP800-38A,
+ * annex B: the IV length shall be 4 bytes less than the block size
+ * (i.e. 12 bytes for AES) and the counter is the 32-bit value starting
+ * with `cc`. The data length (`len`) is not necessarily a multiple of
+ * the block size. The new counter value is returned, which supports
+ * chunked processing, provided that each chunk length (except possibly
+ * the last one) is a multiple of the block size.
+ *
+ * - `br_xxx_ctrcbc_keys`
+ *
+ * Context structure that contains the subkeys resulting from the
+ * key expansion. These subkeys are appropriate for doing combined
+ * CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX
+ * authenticated encryption modes. The structure first field is
+ * called `vtable` and points to the appropriate OOP structure.
+ *
+ * - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)`
+ *
+ * Perform key expansion: subkeys for combined CTR
+ * encryption/decryption and CBC-MAC are computed and written in the
+ * provided context structure. The key length MUST be adequate for
+ * the implemented block cipher. This function also sets the
+ * `vtable` field.
+ *
+ * - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)`
+ *
+ * Perform CTR encryption of some data, and CBC-MAC. Processing is
+ * done "in place" (the output data replaces the input data). This
+ * function applies CTR encryption on the data, using a full
+ * block-size counter (i.e. for 128-bit blocks, the counter is
+ * incremented as a 128-bit value). The 'ctr' array contains the
+ * initial value for the counter (used in the first block) and it is
+ * updated with the new value after data processing. The 'cbcmac'
+ * value shall point to a block-sized value which is used as IV for
+ * CBC-MAC, computed over the encrypted data (output of CTR
+ * encryption); the resulting CBC-MAC is written over 'cbcmac' on
+ * output.
+ *
+ * The data length MUST be a multiple of the block size.
+ *
+ * - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)`
+ *
+ * Perform CTR decryption of some data, and CBC-MAC. Processing is
+ * done "in place" (the output data replaces the input data). This
+ * function applies CTR decryption on the data, using a full
+ * block-size counter (i.e. for 128-bit blocks, the counter is
+ * incremented as a 128-bit value). The 'ctr' array contains the
+ * initial value for the counter (used in the first block) and it is
+ * updated with the new value after data processing. The 'cbcmac'
+ * value shall point to a block-sized value which is used as IV for
+ * CBC-MAC, computed over the encrypted data (input of CTR
+ * encryption); the resulting CBC-MAC is written over 'cbcmac' on
+ * output.
+ *
+ * The data length MUST be a multiple of the block size.
+ *
+ * - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)`
+ *
+ * Perform CTR encryption or decryption of the provided data. The
+ * data is processed "in place" (the output data replaces the input
+ * data). A full block-sized counter is applied (i.e. for 128-bit
+ * blocks, the counter is incremented as a 128-bit value). The 'ctr'
+ * array contains the initial value for the counter (used in the
+ * first block), and it is updated with the new value after data
+ * processing.
+ *
+ * The data length MUST be a multiple of the block size.
+ *
+ * - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)`
+ *
+ * Compute CBC-MAC over the provided data. The IV for CBC-MAC is
+ * provided as 'cbcmac'; the output is written over the same array.
+ * The data itself is untouched. The data length MUST be a multiple
+ * of the block size.
+ *
+ *
+ * It shall be noted that the key expansion functions return `void`. If
+ * the provided key length is not allowed, then there will be no error
+ * reporting; implementations need not validate the key length, thus an
+ * invalid key length may result in undefined behaviour (e.g. buffer
+ * overflow).
+ *
+ * Subkey structures contain no interior pointer, and no external
+ * resources are allocated upon key expansion. They can thus be
+ * discarded without any explicit deallocation.
+ *
+ *
+ * ## Object-Oriented API
+ *
+ * Each context structure begins with a field (called `vtable`) that
+ * points to an instance of a structure that references the relevant
+ * functions through pointers. Each such structure contains the
+ * following:
+ *
+ * - `context_size`
+ *
+ * The size (in bytes) of the context structure for subkeys.
+ *
+ * - `block_size`
+ *
+ * The cipher block size (in bytes).
+ *
+ * - `log_block_size`
+ *
+ * The base-2 logarithm of cipher block size (e.g. 4 for blocks
+ * of 16 bytes).
+ *
+ * - `init`
+ *
+ * Pointer to the key expansion function.
+ *
+ * - `run`
+ *
+ * Pointer to the encryption/decryption function.
+ *
+ * For combined CTR/CBC-MAC encryption, the `vtable` has a slightly
+ * different structure:
+ *
+ * - `context_size`
+ *
+ * The size (in bytes) of the context structure for subkeys.
+ *
+ * - `block_size`
+ *
+ * The cipher block size (in bytes).
+ *
+ * - `log_block_size`
+ *
+ * The base-2 logarithm of cipher block size (e.g. 4 for blocks
+ * of 16 bytes).
+ *
+ * - `init`
+ *
+ * Pointer to the key expansion function.
+ *
+ * - `encrypt`
+ *
+ * Pointer to the CTR encryption + CBC-MAC function.
+ *
+ * - `decrypt`
+ *
+ * Pointer to the CTR decryption + CBC-MAC function.
+ *
+ * - `ctr`
+ *
+ * Pointer to the CTR encryption/decryption function.
+ *
+ * - `mac`
+ *
+ * Pointer to the CBC-MAC function.
+ *
+ * For block cipher "`xxx`", static, constant instances of these
+ * structures are defined, under the names:
+ *
+ * - `br_xxx_cbcenc_vtable`
+ * - `br_xxx_cbcdec_vtable`
+ * - `br_xxx_ctr_vtable`
+ * - `br_xxx_ctrcbc_vtable`
+ *
+ *
+ * ## Implemented Block Ciphers
+ *
+ * Provided implementations are:
+ *
+ * | Name | Function | Block Size (bytes) | Key lengths (bytes) |
+ * | :-------- | :------- | :----------------: | :-----------------: |
+ * | aes_big | AES | 16 | 16, 24 and 32 |
+ * | aes_small | AES | 16 | 16, 24 and 32 |
+ * | aes_ct | AES | 16 | 16, 24 and 32 |
+ * | aes_ct64 | AES | 16 | 16, 24 and 32 |
+ * | aes_x86ni | AES | 16 | 16, 24 and 32 |
+ * | aes_pwr8 | AES | 16 | 16, 24 and 32 |
+ * | des_ct | DES/3DES | 8 | 8, 16 and 24 |
+ * | des_tab | DES/3DES | 8 | 8, 16 and 24 |
+ *
+ * **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8,
+ * 16 and 24 bytes), but some of the bits are ignored by the algorithm, so
+ * the _effective_ key lengths, from a security point of view, are 56,
+ * 112 and 168 bits, respectively.
+ *
+ * `aes_big` is a "classical" AES implementation, using tables. It
+ * is fast but not constant-time, since it makes data-dependent array
+ * accesses.
+ *
+ * `aes_small` is an AES implementation optimized for code size. It
+ * is substantially slower than `aes_big`; it is not constant-time
+ * either.
+ *
+ * `aes_ct` is a constant-time implementation of AES; its code is about
+ * as big as that of `aes_big`, while its performance is comparable to
+ * that of `aes_small`. However, it is constant-time. This
+ * implementation should thus be considered to be the "default" AES in
+ * BearSSL, to be used unless the operational context guarantees that a
+ * non-constant-time implementation is safe, or an architecture-specific
+ * constant-time implementation can be used (e.g. using dedicated
+ * hardware opcodes).
+ *
+ * `aes_ct64` is another constant-time implementation of AES. It is
+ * similar to `aes_ct` but uses 64-bit values. On 32-bit machines,
+ * `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has
+ * a larger footprint; however, on 64-bit architectures, `aes_ct64`
+ * is typically twice faster than `aes_ct` for modes that allow parallel
+ * operations (i.e. CTR, and CBC decryption, but not CBC encryption).
+ *
+ * `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It
+ * uses the AES-NI opcodes when available.
+ *
+ * `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and
+ * 64-bit, both little-endian and big-endian). It uses the AES opcodes
+ * present in POWER8 and later.
+ *
+ * `des_tab` is a classic, table-based implementation of DES/3DES. It
+ * is not constant-time.
+ *
+ * `des_ct` is an constant-time implementation of DES/3DES. It is
+ * substantially slower than `des_tab`.
+ *
+ * ## ChaCha20 and Poly1305
+ *
+ * ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They
+ * are described in [RFC 7539](https://tools.ietf.org/html/rfc7539).
+ *
+ * Two function pointer types are defined:
+ *
+ * - `br_chacha20_run` describes a function that implements ChaCha20
+ * only.
+ *
+ * - `br_poly1305_run` describes an implementation of Poly1305,
+ * in the AEAD combination with ChaCha20 specified in RFC 7539
+ * (the ChaCha20 implementation is provided as a function pointer).
+ *
+ * `chacha20_ct` is a straightforward implementation of ChaCha20 in
+ * plain C; it is constant-time, small, and reasonably fast.
+ *
+ * `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that
+ * support these opcodes). It is faster than `chacha20_ct`.
+ *
+ * `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD
+ * construction, where the Poly1305 part is performed with mixed 32-bit
+ * multiplications (operands are 32-bit, result is 64-bit).
+ *
+ * `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit
+ * multiplications (32-bit operands, 32-bit result). It is slower than
+ * `poly1305_ctmul`, except on some specific architectures such as
+ * the ARM Cortex M0+.
+ *
+ * `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit
+ * multiplications (operands are 64-bit, result is 128-bit) on 64-bit
+ * platforms that support such operations.
+ *
+ * `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15"
+ * big integer implementation. It is meant mostly for testing purposes,
+ * although it can help with saving a few hundred bytes of code footprint
+ * on systems where code size is scarce.
+ */
+
+/**
+ * \brief Class type for CBC encryption implementations.
+ *
+ * A `br_block_cbcenc_class` instance points to the functions implementing
+ * a specific block cipher, when used in CBC mode for encrypting data.
+ */
+typedef struct br_block_cbcenc_class_ br_block_cbcenc_class;
+struct br_block_cbcenc_class_ {
+ /**
+ * \brief Size (in bytes) of the context structure appropriate
+ * for containing subkeys.
+ */
+ size_t context_size;
+
+ /**
+ * \brief Size of individual blocks (in bytes).
+ */
+ unsigned block_size;
+
+ /**
+ * \brief Base-2 logarithm of the size of individual blocks,
+ * expressed in bytes.
+ */
+ unsigned log_block_size;
+
+ /**
+ * \brief Initialisation function.
+ *
+ * This function sets the `vtable` field in the context structure.
+ * The key length MUST be one of the key lengths supported by
+ * the implementation.
+ *
+ * \param ctx context structure to initialise.
+ * \param key secret key.
+ * \param key_len key length (in bytes).
+ */
+ void (*init)(const br_block_cbcenc_class **ctx,
+ const void *key, size_t key_len);
+
+ /**
+ * \brief Run the CBC encryption.
+ *
+ * The `iv` parameter points to the IV for this run; it is
+ * updated with a copy of the last encrypted block. The data
+ * is encrypted "in place"; its length (`len`) MUST be a
+ * multiple of the block size.
+ *
+ * \param ctx context structure (already initialised).
+ * \param iv IV for CBC encryption (updated).
+ * \param data data to encrypt.
+ * \param len data length (in bytes, multiple of block size).
+ */
+ void (*run)(const br_block_cbcenc_class *const *ctx,
+ void *iv, void *data, size_t len);
+};
+
+/**
+ * \brief Class type for CBC decryption implementations.
+ *
+ * A `br_block_cbcdec_class` instance points to the functions implementing
+ * a specific block cipher, when used in CBC mode for decrypting data.
+ */
+typedef struct br_block_cbcdec_class_ br_block_cbcdec_class;
+struct br_block_cbcdec_class_ {
+ /**
+ * \brief Size (in bytes) of the context structure appropriate
+ * for containing subkeys.
+ */
+ size_t context_size;
+
+ /**
+ * \brief Size of individual blocks (in bytes).
+ */
+ unsigned block_size;
+
+ /**
+ * \brief Base-2 logarithm of the size of individual blocks,
+ * expressed in bytes.
+ */
+ unsigned log_block_size;
+
+ /**
+ * \brief Initialisation function.
+ *
+ * This function sets the `vtable` field in the context structure.
+ * The key length MUST be one of the key lengths supported by
+ * the implementation.
+ *
+ * \param ctx context structure to initialise.
+ * \param key secret key.
+ * \param key_len key length (in bytes).
+ */
+ void (*init)(const br_block_cbcdec_class **ctx,
+ const void *key, size_t key_len);
+
+ /**
+ * \brief Run the CBC decryption.
+ *
+ * The `iv` parameter points to the IV for this run; it is
+ * updated with a copy of the last encrypted block. The data
+ * is decrypted "in place"; its length (`len`) MUST be a
+ * multiple of the block size.
+ *
+ * \param ctx context structure (already initialised).
+ * \param iv IV for CBC decryption (updated).
+ * \param data data to decrypt.
+ * \param len data length (in bytes, multiple of block size).
+ */
+ void (*run)(const br_block_cbcdec_class *const *ctx,
+ void *iv, void *data, size_t len);
+};
+
+/**
+ * \brief Class type for CTR encryption/decryption implementations.
+ *
+ * A `br_block_ctr_class` instance points to the functions implementing
+ * a specific block cipher, when used in CTR mode for encrypting or
+ * decrypting data.
+ */
+typedef struct br_block_ctr_class_ br_block_ctr_class;
+struct br_block_ctr_class_ {
+ /**
+ * \brief Size (in bytes) of the context structure appropriate
+ * for containing subkeys.
+ */
+ size_t context_size;
+
+ /**
+ * \brief Size of individual blocks (in bytes).
+ */
+ unsigned block_size;
+
+ /**
+ * \brief Base-2 logarithm of the size of individual blocks,
+ * expressed in bytes.
+ */
+ unsigned log_block_size;
+
+ /**
+ * \brief Initialisation function.
+ *
+ * This function sets the `vtable` field in the context structure.
+ * The key length MUST be one of the key lengths supported by
+ * the implementation.
+ *
+ * \param ctx context structure to initialise.
+ * \param key secret key.
+ * \param key_len key length (in bytes).
+ */
+ void (*init)(const br_block_ctr_class **ctx,
+ const void *key, size_t key_len);
+
+ /**
+ * \brief Run the CTR encryption or decryption.
+ *
+ * The `iv` parameter points to the IV for this run; its
+ * length is exactly 4 bytes less than the block size (e.g.
+ * 12 bytes for AES/CTR). The IV is combined with a 32-bit
+ * block counter to produce the block value which is processed
+ * with the block cipher.
+ *
+ * The data to encrypt or decrypt is updated "in place". Its
+ * length (`len` bytes) is not required to be a multiple of
+ * the block size; if the final block is partial, then the
+ * corresponding key stream bits are dropped.
+ *
+ * The resulting counter value is returned.
+ *
+ * \param ctx context structure (already initialised).
+ * \param iv IV for CTR encryption/decryption.
+ * \param cc initial value for the block counter.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ * \return the new block counter value.
+ */
+ uint32_t (*run)(const br_block_ctr_class *const *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len);
+};
+
+/**
+ * \brief Class type for combined CTR and CBC-MAC implementations.
+ *
+ * A `br_block_ctrcbc_class` instance points to the functions implementing
+ * a specific block cipher, when used in CTR mode for encrypting or
+ * decrypting data, along with CBC-MAC.
+ */
+typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class;
+struct br_block_ctrcbc_class_ {
+ /**
+ * \brief Size (in bytes) of the context structure appropriate
+ * for containing subkeys.
+ */
+ size_t context_size;
+
+ /**
+ * \brief Size of individual blocks (in bytes).
+ */
+ unsigned block_size;
+
+ /**
+ * \brief Base-2 logarithm of the size of individual blocks,
+ * expressed in bytes.
+ */
+ unsigned log_block_size;
+
+ /**
+ * \brief Initialisation function.
+ *
+ * This function sets the `vtable` field in the context structure.
+ * The key length MUST be one of the key lengths supported by
+ * the implementation.
+ *
+ * \param ctx context structure to initialise.
+ * \param key secret key.
+ * \param key_len key length (in bytes).
+ */
+ void (*init)(const br_block_ctrcbc_class **ctx,
+ const void *key, size_t key_len);
+
+ /**
+ * \brief Run the CTR encryption + CBC-MAC.
+ *
+ * The `ctr` parameter points to the counter; its length shall
+ * be equal to the block size. It is updated by this function
+ * as encryption proceeds.
+ *
+ * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
+ * is computed over the encrypted data (output of CTR
+ * encryption). Its length shall be equal to the block size. The
+ * computed CBC-MAC value is written over the `cbcmac` array.
+ *
+ * The data to encrypt is updated "in place". Its length (`len`
+ * bytes) MUST be a multiple of the block size.
+ *
+ * \param ctx context structure (already initialised).
+ * \param ctr counter for CTR encryption (initial and final).
+ * \param cbcmac IV and output buffer for CBC-MAC.
+ * \param data data to encrypt.
+ * \param len data length (in bytes).
+ */
+ void (*encrypt)(const br_block_ctrcbc_class *const *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+ /**
+ * \brief Run the CTR decryption + CBC-MAC.
+ *
+ * The `ctr` parameter points to the counter; its length shall
+ * be equal to the block size. It is updated by this function
+ * as decryption proceeds.
+ *
+ * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
+ * is computed over the encrypted data (i.e. before CTR
+ * decryption). Its length shall be equal to the block size. The
+ * computed CBC-MAC value is written over the `cbcmac` array.
+ *
+ * The data to decrypt is updated "in place". Its length (`len`
+ * bytes) MUST be a multiple of the block size.
+ *
+ * \param ctx context structure (already initialised).
+ * \param ctr counter for CTR encryption (initial and final).
+ * \param cbcmac IV and output buffer for CBC-MAC.
+ * \param data data to decrypt.
+ * \param len data length (in bytes).
+ */
+ void (*decrypt)(const br_block_ctrcbc_class *const *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+ /**
+ * \brief Run the CTR encryption/decryption only.
+ *
+ * The `ctr` parameter points to the counter; its length shall
+ * be equal to the block size. It is updated by this function
+ * as decryption proceeds.
+ *
+ * The data to decrypt is updated "in place". Its length (`len`
+ * bytes) MUST be a multiple of the block size.
+ *
+ * \param ctx context structure (already initialised).
+ * \param ctr counter for CTR encryption (initial and final).
+ * \param data data to decrypt.
+ * \param len data length (in bytes).
+ */
+ void (*ctr)(const br_block_ctrcbc_class *const *ctx,
+ void *ctr, void *data, size_t len);
+
+ /**
+ * \brief Run the CBC-MAC only.
+ *
+ * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
+ * is computed over the encrypted data (i.e. before CTR
+ * decryption). Its length shall be equal to the block size. The
+ * computed CBC-MAC value is written over the `cbcmac` array.
+ *
+ * The data is unmodified. Its length (`len` bytes) MUST be a
+ * multiple of the block size.
+ *
+ * \param ctx context structure (already initialised).
+ * \param cbcmac IV and output buffer for CBC-MAC.
+ * \param data data to decrypt.
+ * \param len data length (in bytes).
+ */
+ void (*mac)(const br_block_ctrcbc_class *const *ctx,
+ void *cbcmac, const void *data, size_t len);
+};
+
+/*
+ * Traditional, table-based AES implementation. It is fast, but uses
+ * internal tables (in particular a 1 kB table for encryption, another
+ * 1 kB table for decryption, and a 256-byte table for key schedule),
+ * and it is not constant-time. In contexts where cache-timing attacks
+ * apply, this implementation may leak the secret key.
+ */
+
+/** \brief AES block size (16 bytes). */
+#define br_aes_big_BLOCK_SIZE 16
+
+/**
+ * \brief Context for AES subkeys (`aes_big` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_big_cbcenc_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_big` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_big_cbcdec_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption
+ * and decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctr_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_big_ctr_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption
+ * and decryption + CBC-MAC).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctrcbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_big_ctrcbc_keys;
+
+/**
+ * \brief Class instance for AES CBC encryption (`aes_big` implementation).
+ */
+extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable;
+
+/**
+ * \brief Class instance for AES CBC decryption (`aes_big` implementation).
+ */
+extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption and decryption
+ * (`aes_big` implementation).
+ */
+extern const br_block_ctr_class br_aes_big_ctr_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption/decryption + CBC-MAC
+ * (`aes_big` implementation).
+ */
+extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC encryption
+ * (`aes_big` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC decryption
+ * (`aes_big` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR encryption
+ * and decryption (`aes_big` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
+ * (`aes_big` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with AES (`aes_big` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with AES (`aes_big` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CTR encryption and decryption with AES (`aes_big` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (constant, 12 bytes).
+ * \param cc initial block counter value.
+ * \param data data to encrypt or decrypt (updated).
+ * \param len data length (in bytes).
+ * \return new block counter value.
+ */
+uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR encryption/decryption with AES (`aes_big` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param data data to MAC (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len);
+
+/**
+ * \brief CBC-MAC with AES (`aes_big` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to MAC (unmodified).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len);
+
+/*
+ * AES implementation optimized for size. It is slower than the
+ * traditional table-based AES implementation, but requires much less
+ * code. It still uses data-dependent table accesses (albeit within a
+ * much smaller 256-byte table), which makes it conceptually vulnerable
+ * to cache-timing attacks.
+ */
+
+/** \brief AES block size (16 bytes). */
+#define br_aes_small_BLOCK_SIZE 16
+
+/**
+ * \brief Context for AES subkeys (`aes_small` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_small_cbcenc_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_small` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_small_cbcdec_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption
+ * and decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctr_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_small_ctr_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption
+ * and decryption + CBC-MAC).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctrcbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_small_ctrcbc_keys;
+
+/**
+ * \brief Class instance for AES CBC encryption (`aes_small` implementation).
+ */
+extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable;
+
+/**
+ * \brief Class instance for AES CBC decryption (`aes_small` implementation).
+ */
+extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption and decryption
+ * (`aes_small` implementation).
+ */
+extern const br_block_ctr_class br_aes_small_ctr_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption/decryption + CBC-MAC
+ * (`aes_small` implementation).
+ */
+extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC encryption
+ * (`aes_small` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC decryption
+ * (`aes_small` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR encryption
+ * and decryption (`aes_small` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
+ * (`aes_small` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with AES (`aes_small` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with AES (`aes_small` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CTR encryption and decryption with AES (`aes_small` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (constant, 12 bytes).
+ * \param cc initial block counter value.
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes).
+ * \return new block counter value.
+ */
+uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR encryption/decryption with AES (`aes_small` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param data data to MAC (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len);
+
+/**
+ * \brief CBC-MAC with AES (`aes_small` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to MAC (unmodified).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len);
+
+/*
+ * Constant-time AES implementation. Its size is similar to that of
+ * 'aes_big', and its performance is similar to that of 'aes_small' (faster
+ * decryption, slower encryption). However, it is constant-time, i.e.
+ * immune to cache-timing and similar attacks.
+ */
+
+/** \brief AES block size (16 bytes). */
+#define br_aes_ct_BLOCK_SIZE 16
+
+/**
+ * \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_ct_cbcenc_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_ct_cbcdec_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption
+ * and decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctr_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_ct_ctr_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption
+ * and decryption + CBC-MAC).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctrcbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[60];
+ unsigned num_rounds;
+#endif
+} br_aes_ct_ctrcbc_keys;
+
+/**
+ * \brief Class instance for AES CBC encryption (`aes_ct` implementation).
+ */
+extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable;
+
+/**
+ * \brief Class instance for AES CBC decryption (`aes_ct` implementation).
+ */
+extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption and decryption
+ * (`aes_ct` implementation).
+ */
+extern const br_block_ctr_class br_aes_ct_ctr_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption/decryption + CBC-MAC
+ * (`aes_ct` implementation).
+ */
+extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC encryption
+ * (`aes_ct` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC decryption
+ * (`aes_ct` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR encryption
+ * and decryption (`aes_ct` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
+ * (`aes_ct` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with AES (`aes_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with AES (`aes_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CTR encryption and decryption with AES (`aes_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (constant, 12 bytes).
+ * \param cc initial block counter value.
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes).
+ * \return new block counter value.
+ */
+uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR encryption/decryption with AES (`aes_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param data data to MAC (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len);
+
+/**
+ * \brief CBC-MAC with AES (`aes_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to MAC (unmodified).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len);
+
+/*
+ * 64-bit constant-time AES implementation. It is similar to 'aes_ct'
+ * but uses 64-bit registers, making it about twice faster than 'aes_ct'
+ * on 64-bit platforms, while remaining constant-time and with a similar
+ * code size. (The doubling in performance is only for CBC decryption
+ * and CTR mode; CBC encryption is non-parallel and cannot benefit from
+ * the larger registers.)
+ */
+
+/** \brief AES block size (16 bytes). */
+#define br_aes_ct64_BLOCK_SIZE 16
+
+/**
+ * \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t skey[30];
+ unsigned num_rounds;
+#endif
+} br_aes_ct64_cbcenc_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t skey[30];
+ unsigned num_rounds;
+#endif
+} br_aes_ct64_cbcdec_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption
+ * and decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctr_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t skey[30];
+ unsigned num_rounds;
+#endif
+} br_aes_ct64_ctr_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption
+ * and decryption + CBC-MAC).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctrcbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t skey[30];
+ unsigned num_rounds;
+#endif
+} br_aes_ct64_ctrcbc_keys;
+
+/**
+ * \brief Class instance for AES CBC encryption (`aes_ct64` implementation).
+ */
+extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable;
+
+/**
+ * \brief Class instance for AES CBC decryption (`aes_ct64` implementation).
+ */
+extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption and decryption
+ * (`aes_ct64` implementation).
+ */
+extern const br_block_ctr_class br_aes_ct64_ctr_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption/decryption + CBC-MAC
+ * (`aes_ct64` implementation).
+ */
+extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC encryption
+ * (`aes_ct64` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC decryption
+ * (`aes_ct64` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR encryption
+ * and decryption (`aes_ct64` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
+ * (`aes_ct64` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with AES (`aes_ct64` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with AES (`aes_ct64` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CTR encryption and decryption with AES (`aes_ct64` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (constant, 12 bytes).
+ * \param cc initial block counter value.
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes).
+ * \return new block counter value.
+ */
+uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR encryption/decryption with AES (`aes_ct64` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param data data to MAC (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len);
+
+/**
+ * \brief CBC-MAC with AES (`aes_ct64` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to MAC (unmodified).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len);
+
+/*
+ * AES implementation using AES-NI opcodes (x86 platform).
+ */
+
+/** \brief AES block size (16 bytes). */
+#define br_aes_x86ni_BLOCK_SIZE 16
+
+/**
+ * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_x86ni_cbcenc_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_x86ni_cbcdec_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption
+ * and decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctr_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_x86ni_ctr_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption
+ * and decryption + CBC-MAC).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctrcbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_x86ni_ctrcbc_keys;
+
+/**
+ * \brief Class instance for AES CBC encryption (`aes_x86ni` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`.
+ */
+extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable;
+
+/**
+ * \brief Class instance for AES CBC decryption (`aes_x86ni` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`.
+ */
+extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption and decryption
+ * (`aes_x86ni` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`.
+ */
+extern const br_block_ctr_class br_aes_x86ni_ctr_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption/decryption + CBC-MAC
+ * (`aes_x86ni` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`.
+ */
+extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC encryption
+ * (`aes_x86ni` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC decryption
+ * (`aes_x86ni` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR encryption
+ * and decryption (`aes_x86ni` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
+ * (`aes_x86ni` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with AES (`aes_x86ni` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with AES (`aes_x86ni` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CTR encryption and decryption with AES (`aes_x86ni` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (constant, 12 bytes).
+ * \param cc initial block counter value.
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes).
+ * \return new block counter value.
+ */
+uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR encryption/decryption with AES (`aes_x86ni` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param data data to MAC (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len);
+
+/**
+ * \brief CBC-MAC with AES (`aes_x86ni` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to MAC (unmodified).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len);
+
+/**
+ * \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if
+ * available.
+ *
+ * This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if
+ * that implementation was compiled in the library _and_ the x86 AES
+ * opcodes are available on the currently running CPU. If either of
+ * these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`.
+ */
+const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void);
+
+/**
+ * \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if
+ * available.
+ *
+ * This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if
+ * that implementation was compiled in the library _and_ the x86 AES
+ * opcodes are available on the currently running CPU. If either of
+ * these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`.
+ */
+const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void);
+
+/**
+ * \brief Obtain the `aes_x86ni` AES-CTR implementation, if available.
+ *
+ * This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if
+ * that implementation was compiled in the library _and_ the x86 AES
+ * opcodes are available on the currently running CPU. If either of
+ * these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_x86ni` AES-CTR implementation, or `NULL`.
+ */
+const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void);
+
+/**
+ * \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if
+ * available.
+ *
+ * This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if
+ * that implementation was compiled in the library _and_ the x86 AES
+ * opcodes are available on the currently running CPU. If either of
+ * these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_x86ni` AES-CTR implementation, or `NULL`.
+ */
+const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void);
+
+/*
+ * AES implementation using POWER8 opcodes.
+ */
+
+/** \brief AES block size (16 bytes). */
+#define br_aes_pwr8_BLOCK_SIZE 16
+
+/**
+ * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_pwr8_cbcenc_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_pwr8_cbcdec_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption
+ * and decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctr_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_pwr8_ctr_keys;
+
+/**
+ * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption
+ * and decryption + CBC-MAC).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_ctrcbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ union {
+ unsigned char skni[16 * 15];
+ } skey;
+ unsigned num_rounds;
+#endif
+} br_aes_pwr8_ctrcbc_keys;
+
+/**
+ * \brief Class instance for AES CBC encryption (`aes_pwr8` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`.
+ */
+extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable;
+
+/**
+ * \brief Class instance for AES CBC decryption (`aes_pwr8` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`.
+ */
+extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption and decryption
+ * (`aes_pwr8` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`.
+ */
+extern const br_block_ctr_class br_aes_pwr8_ctr_vtable;
+
+/**
+ * \brief Class instance for AES CTR encryption/decryption + CBC-MAC
+ * (`aes_pwr8` implementation).
+ *
+ * Since this implementation might be omitted from the library, or the
+ * AES opcode unavailable on the current CPU, a pointer to this class
+ * instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`.
+ */
+extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC encryption
+ * (`aes_pwr8` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CBC decryption
+ * (`aes_pwr8` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR encryption
+ * and decryption (`aes_pwr8` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
+ * (`aes_pwr8` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with AES (`aes_pwr8` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with AES (`aes_pwr8` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 16).
+ */
+void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CTR encryption and decryption with AES (`aes_pwr8` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (constant, 12 bytes).
+ * \param cc initial block counter value.
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes).
+ * \return new block counter value.
+ */
+uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len);
+
+/**
+ * \brief CTR encryption/decryption with AES (`aes_pwr8` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param ctr counter for CTR (16 bytes, updated).
+ * \param data data to MAC (updated).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len);
+
+/**
+ * \brief CBC-MAC with AES (`aes_pwr8` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param cbcmac IV for CBC-MAC (updated).
+ * \param data data to MAC (unmodified).
+ * \param len data length (in bytes, MUST be a multiple of 16).
+ */
+void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len);
+
+/**
+ * \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if
+ * available.
+ *
+ * This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if
+ * that implementation was compiled in the library _and_ the POWER8
+ * crypto opcodes are available on the currently running CPU. If either
+ * of these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`.
+ */
+const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void);
+
+/**
+ * \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if
+ * available.
+ *
+ * This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if
+ * that implementation was compiled in the library _and_ the POWER8
+ * crypto opcodes are available on the currently running CPU. If either
+ * of these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`.
+ */
+const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void);
+
+/**
+ * \brief Obtain the `aes_pwr8` AES-CTR implementation, if available.
+ *
+ * This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that
+ * implementation was compiled in the library _and_ the POWER8 crypto
+ * opcodes are available on the currently running CPU. If either of
+ * these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_pwr8` AES-CTR implementation, or `NULL`.
+ */
+const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void);
+
+/**
+ * \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if
+ * available.
+ *
+ * This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if
+ * that implementation was compiled in the library _and_ the POWER8 AES
+ * opcodes are available on the currently running CPU. If either of
+ * these conditions is not met, then this function returns `NULL`.
+ *
+ * \return the `aes_pwr8` AES-CTR implementation, or `NULL`.
+ */
+const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void);
+
+/**
+ * \brief Aggregate structure large enough to be used as context for
+ * subkeys (CBC encryption) for all AES implementations.
+ */
+typedef union {
+ const br_block_cbcenc_class *vtable;
+ br_aes_big_cbcenc_keys c_big;
+ br_aes_small_cbcenc_keys c_small;
+ br_aes_ct_cbcenc_keys c_ct;
+ br_aes_ct64_cbcenc_keys c_ct64;
+ br_aes_x86ni_cbcenc_keys c_x86ni;
+ br_aes_pwr8_cbcenc_keys c_pwr8;
+} br_aes_gen_cbcenc_keys;
+
+/**
+ * \brief Aggregate structure large enough to be used as context for
+ * subkeys (CBC decryption) for all AES implementations.
+ */
+typedef union {
+ const br_block_cbcdec_class *vtable;
+ br_aes_big_cbcdec_keys c_big;
+ br_aes_small_cbcdec_keys c_small;
+ br_aes_ct_cbcdec_keys c_ct;
+ br_aes_ct64_cbcdec_keys c_ct64;
+ br_aes_x86ni_cbcdec_keys c_x86ni;
+ br_aes_pwr8_cbcdec_keys c_pwr8;
+} br_aes_gen_cbcdec_keys;
+
+/**
+ * \brief Aggregate structure large enough to be used as context for
+ * subkeys (CTR encryption and decryption) for all AES implementations.
+ */
+typedef union {
+ const br_block_ctr_class *vtable;
+ br_aes_big_ctr_keys c_big;
+ br_aes_small_ctr_keys c_small;
+ br_aes_ct_ctr_keys c_ct;
+ br_aes_ct64_ctr_keys c_ct64;
+ br_aes_x86ni_ctr_keys c_x86ni;
+ br_aes_pwr8_ctr_keys c_pwr8;
+} br_aes_gen_ctr_keys;
+
+/**
+ * \brief Aggregate structure large enough to be used as context for
+ * subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations.
+ */
+typedef union {
+ const br_block_ctrcbc_class *vtable;
+ br_aes_big_ctrcbc_keys c_big;
+ br_aes_small_ctrcbc_keys c_small;
+ br_aes_ct_ctrcbc_keys c_ct;
+ br_aes_ct64_ctrcbc_keys c_ct64;
+ br_aes_x86ni_ctrcbc_keys c_x86ni;
+ br_aes_pwr8_ctrcbc_keys c_pwr8;
+} br_aes_gen_ctrcbc_keys;
+
+/*
+ * Traditional, table-based implementation for DES/3DES. Since tables are
+ * used, cache-timing attacks are conceptually possible.
+ */
+
+/** \brief DES/3DES block size (8 bytes). */
+#define br_des_tab_BLOCK_SIZE 8
+
+/**
+ * \brief Context for DES subkeys (`des_tab` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[96];
+ unsigned num_rounds;
+#endif
+} br_des_tab_cbcenc_keys;
+
+/**
+ * \brief Context for DES subkeys (`des_tab` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[96];
+ unsigned num_rounds;
+#endif
+} br_des_tab_cbcdec_keys;
+
+/**
+ * \brief Class instance for DES CBC encryption (`des_tab` implementation).
+ */
+extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable;
+
+/**
+ * \brief Class instance for DES CBC decryption (`des_tab` implementation).
+ */
+extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for DES CBC encryption
+ * (`des_tab` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for DES CBC decryption
+ * (`des_tab` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with DES (`des_tab` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 8).
+ */
+void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with DES (`des_tab` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 8).
+ */
+void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/*
+ * Constant-time implementation for DES/3DES. It is substantially slower
+ * (by a factor of about 4x), but also immune to cache-timing attacks.
+ */
+
+/** \brief DES/3DES block size (8 bytes). */
+#define br_des_ct_BLOCK_SIZE 8
+
+/**
+ * \brief Context for DES subkeys (`des_ct` implementation, CBC encryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcenc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[96];
+ unsigned num_rounds;
+#endif
+} br_des_ct_cbcenc_keys;
+
+/**
+ * \brief Context for DES subkeys (`des_ct` implementation, CBC decryption).
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /** \brief Pointer to vtable for this context. */
+ const br_block_cbcdec_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint32_t skey[96];
+ unsigned num_rounds;
+#endif
+} br_des_ct_cbcdec_keys;
+
+/**
+ * \brief Class instance for DES CBC encryption (`des_ct` implementation).
+ */
+extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable;
+
+/**
+ * \brief Class instance for DES CBC decryption (`des_ct` implementation).
+ */
+extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable;
+
+/**
+ * \brief Context initialisation (key schedule) for DES CBC encryption
+ * (`des_ct` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief Context initialisation (key schedule) for DES CBC decryption
+ * (`des_ct` implementation).
+ *
+ * \param ctx context to initialise.
+ * \param key secret key.
+ * \param len secret key length (in bytes).
+ */
+void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx,
+ const void *key, size_t len);
+
+/**
+ * \brief CBC encryption with DES (`des_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to encrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 8).
+ */
+void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/**
+ * \brief CBC decryption with DES (`des_ct` implementation).
+ *
+ * \param ctx context (already initialised).
+ * \param iv IV (updated).
+ * \param data data to decrypt (updated).
+ * \param len data length (in bytes, MUST be multiple of 8).
+ */
+void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv,
+ void *data, size_t len);
+
+/*
+ * These structures are large enough to accommodate subkeys for all
+ * DES/3DES implementations.
+ */
+
+/**
+ * \brief Aggregate structure large enough to be used as context for
+ * subkeys (CBC encryption) for all DES implementations.
+ */
+typedef union {
+ const br_block_cbcenc_class *vtable;
+ br_des_tab_cbcenc_keys tab;
+ br_des_ct_cbcenc_keys ct;
+} br_des_gen_cbcenc_keys;
+
+/**
+ * \brief Aggregate structure large enough to be used as context for
+ * subkeys (CBC decryption) for all DES implementations.
+ */
+typedef union {
+ const br_block_cbcdec_class *vtable;
+ br_des_tab_cbcdec_keys c_tab;
+ br_des_ct_cbcdec_keys c_ct;
+} br_des_gen_cbcdec_keys;
+
+/**
+ * \brief Type for a ChaCha20 implementation.
+ *
+ * An implementation follows the description in RFC 7539:
+ *
+ * - Key is 256 bits (`key` points to exactly 32 bytes).
+ *
+ * - IV is 96 bits (`iv` points to exactly 12 bytes).
+ *
+ * - Block counter is over 32 bits and starts at value `cc`; the
+ * resulting value is returned.
+ *
+ * Data (pointed to by `data`, of length `len`) is encrypted/decrypted
+ * in place. If `len` is not a multiple of 64, then the excess bytes from
+ * the last block processing are dropped (therefore, "chunked" processing
+ * works only as long as each non-final chunk has a length multiple of 64).
+ *
+ * \param key secret key (32 bytes).
+ * \param iv IV (12 bytes).
+ * \param cc initial counter value.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ */
+typedef uint32_t (*br_chacha20_run)(const void *key,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief ChaCha20 implementation (straightforward C code, constant-time).
+ *
+ * \see br_chacha20_run
+ *
+ * \param key secret key (32 bytes).
+ * \param iv IV (12 bytes).
+ * \param cc initial counter value.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ */
+uint32_t br_chacha20_ct_run(const void *key,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief ChaCha20 implementation (SSE2 code, constant-time).
+ *
+ * This implementation is available only on x86 platforms, depending on
+ * compiler support. Moreover, in 32-bit mode, it might not actually run,
+ * if the underlying hardware does not implement the SSE2 opcode (in
+ * 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled
+ * at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain
+ * a pointer to that function.
+ *
+ * \see br_chacha20_run
+ *
+ * \param key secret key (32 bytes).
+ * \param iv IV (12 bytes).
+ * \param cc initial counter value.
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ */
+uint32_t br_chacha20_sse2_run(const void *key,
+ const void *iv, uint32_t cc, void *data, size_t len);
+
+/**
+ * \brief Obtain the `sse2` ChaCha20 implementation, if available.
+ *
+ * This function returns a pointer to `br_chacha20_sse2_run`, if
+ * that implementation was compiled in the library _and_ the SSE2
+ * opcodes are available on the currently running CPU. If either of
+ * these conditions is not met, then this function returns `0`.
+ *
+ * \return the `sse2` ChaCha20 implementation, or `0`.
+ */
+br_chacha20_run br_chacha20_sse2_get(void);
+
+/**
+ * \brief Type for a ChaCha20+Poly1305 AEAD implementation.
+ *
+ * The provided data is encrypted or decrypted with ChaCha20. The
+ * authentication tag is computed on the concatenation of the
+ * additional data and the ciphertext, with the padding and lengths
+ * as described in RFC 7539 (section 2.8).
+ *
+ * After decryption, the caller is responsible for checking that the
+ * computed tag matches the expected value.
+ *
+ * \param key secret key (32 bytes).
+ * \param iv nonce (12 bytes).
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ * \param aad additional authenticated data.
+ * \param aad_len length of additional authenticated data (in bytes).
+ * \param tag output buffer for the authentication tag.
+ * \param ichacha implementation of ChaCha20.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ */
+typedef void (*br_poly1305_run)(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt);
+
+/**
+ * \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications).
+ *
+ * \see br_poly1305_run
+ *
+ * \param key secret key (32 bytes).
+ * \param iv nonce (12 bytes).
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ * \param aad additional authenticated data.
+ * \param aad_len length of additional authenticated data (in bytes).
+ * \param tag output buffer for the authentication tag.
+ * \param ichacha implementation of ChaCha20.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ */
+void br_poly1305_ctmul_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt);
+
+/**
+ * \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications).
+ *
+ * \see br_poly1305_run
+ *
+ * \param key secret key (32 bytes).
+ * \param iv nonce (12 bytes).
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ * \param aad additional authenticated data.
+ * \param aad_len length of additional authenticated data (in bytes).
+ * \param tag output buffer for the authentication tag.
+ * \param ichacha implementation of ChaCha20.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ */
+void br_poly1305_ctmul32_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt);
+
+/**
+ * \brief ChaCha20+Poly1305 AEAD implementation (i15).
+ *
+ * This implementation relies on the generic big integer code "i15"
+ * (which uses pure 32-bit multiplications). As such, it may save a
+ * little code footprint in a context where "i15" is already included
+ * (e.g. for elliptic curves or for RSA); however, it is also
+ * substantially slower than the ctmul and ctmul32 implementations.
+ *
+ * \see br_poly1305_run
+ *
+ * \param key secret key (32 bytes).
+ * \param iv nonce (12 bytes).
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ * \param aad additional authenticated data.
+ * \param aad_len length of additional authenticated data (in bytes).
+ * \param tag output buffer for the authentication tag.
+ * \param ichacha implementation of ChaCha20.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ */
+void br_poly1305_i15_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt);
+
+/**
+ * \brief ChaCha20+Poly1305 AEAD implementation (ctmulq).
+ *
+ * This implementation uses 64-bit multiplications (result over 128 bits).
+ * It is available only on platforms that offer such a primitive (in
+ * practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to
+ * dynamically obtain a pointer to that function, or 0 if not supported.
+ *
+ * \see br_poly1305_run
+ *
+ * \param key secret key (32 bytes).
+ * \param iv nonce (12 bytes).
+ * \param data data to encrypt or decrypt.
+ * \param len data length (in bytes).
+ * \param aad additional authenticated data.
+ * \param aad_len length of additional authenticated data (in bytes).
+ * \param tag output buffer for the authentication tag.
+ * \param ichacha implementation of ChaCha20.
+ * \param encrypt non-zero for encryption, zero for decryption.
+ */
+void br_poly1305_ctmulq_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt);
+
+/**
+ * \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available.
+ *
+ * This function returns a pointer to the `br_poly1305_ctmulq_run()`
+ * function if supported on the current platform; otherwise, it returns 0.
+ *
+ * \return the ctmulq ChaCha20+Poly1305 implementation, or 0.
+ */
+br_poly1305_run br_poly1305_ctmulq_get(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Property changes on: stable/12/contrib/bearssl/inc/bearssl_block.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_ec.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_ec.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_ec.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/inc/bearssl_ec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_hash.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_hash.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_hash.h (revision 346145)
@@ -0,0 +1,1346 @@
+/*
+ * 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_HASH_H__
+#define BR_BEARSSL_HASH_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file bearssl_hash.h
+ *
+ * # Hash Functions
+ *
+ * This file documents the API for hash functions.
+ *
+ *
+ * ## Procedural API
+ *
+ * For each implemented hash function, of name "`xxx`", the following
+ * elements are defined:
+ *
+ * - `br_xxx_vtable`
+ *
+ * An externally defined instance of `br_hash_class`.
+ *
+ * - `br_xxx_SIZE`
+ *
+ * A macro that evaluates to the output size (in bytes) of the
+ * hash function.
+ *
+ * - `br_xxx_ID`
+ *
+ * A macro that evaluates to a symbolic identifier for the hash
+ * function. Such identifiers are used with HMAC and signature
+ * algorithm implementations.
+ *
+ * NOTE: for the "standard" hash functions defined in [the TLS
+ * standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1),
+ * the symbolic identifiers match the constants used in TLS, i.e.
+ * 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512,
+ * respectively.
+ *
+ * - `br_xxx_context`
+ *
+ * Context for an ongoing computation. It is allocated by the
+ * caller, and a pointer to it is passed to all functions. A
+ * context contains no interior pointer, so it can be moved around
+ * and cloned (with a simple `memcpy()` or equivalent) in order to
+ * capture the function state at some point. Computations that use
+ * distinct context structures are independent of each other. The
+ * first field of `br_xxx_context` is always a pointer to the
+ * `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer.
+ *
+ * - `br_xxx_init(br_xxx_context *ctx)`
+ *
+ * Initialise the provided context. Previous contents of the structure
+ * are ignored. This calls resets the context to the start of a new
+ * hash computation; it also sets the first field of the context
+ * structure (called `vtable`) to a pointer to the statically
+ * allocated constant `br_xxx_vtable` structure.
+ *
+ * - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)`
+ *
+ * Add some more bytes to the hash computation represented by the
+ * provided context.
+ *
+ * - `br_xxx_out(const br_xxx_context *ctx, void *out)`
+ *
+ * Complete the hash computation and write the result in the provided
+ * buffer. The output buffer MUST be large enough to accommodate the
+ * result. The context is NOT modified by this operation, so this
+ * function can be used to get a "partial hash" while still keeping
+ * the possibility of adding more bytes to the input.
+ *
+ * - `br_xxx_state(const br_xxx_context *ctx, void *out)`
+ *
+ * Get a copy of the "current state" for the computation so far. For
+ * MD functions (MD5, SHA-1, SHA-2 family), this is the running state
+ * resulting from the processing of the last complete input block.
+ * Returned value is the current input length (in bytes).
+ *
+ * - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)`
+ *
+ * Set the internal state to the provided values. The 'stb' and
+ * 'count' values shall match that which was obtained from
+ * `br_xxx_state()`. This restores the hash state only if the state
+ * values were at an appropriate block boundary. This does NOT set
+ * the `vtable` pointer in the context.
+ *
+ * Context structures can be discarded without any explicit deallocation.
+ * Hash function implementations are purely software and don't reserve
+ * any resources outside of the context structure itself.
+ *
+ *
+ * ## Object-Oriented API
+ *
+ * For each hash function that follows the procedural API described
+ * above, an object-oriented API is also provided. In that API, function
+ * pointers from the vtable (`br_xxx_vtable`) are used. The vtable
+ * incarnates object-oriented programming. An introduction on the OOP
+ * concept used here can be read on the BearSSL Web site:<br />
+ * &nbsp;&nbsp;&nbsp;[https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html)
+ *
+ * The vtable offers functions called `init()`, `update()`, `out()`,
+ * `set()` and `set_state()`, which are in fact the functions from
+ * the procedural API. That vtable also contains two informative fields:
+ *
+ * - `context_size`
+ *
+ * The size of the context structure (`br_xxx_context`), in bytes.
+ * This can be used by generic implementations to perform dynamic
+ * context allocation.
+ *
+ * - `desc`
+ *
+ * A "descriptor" field that encodes some information on the hash
+ * function: symbolic identifier, output size, state size,
+ * internal block size, details on the padding.
+ *
+ * Users of this object-oriented API (in particular generic HMAC
+ * implementations) may make the following assumptions:
+ *
+ * - Hash output size is no more than 64 bytes.
+ * - Hash internal state size is no more than 64 bytes.
+ * - Internal block size is a power of two, no less than 16 and no more
+ * than 256.
+ *
+ *
+ * ## Implemented Hash Functions
+ *
+ * Implemented hash functions are:
+ *
+ * | Function | Name | Output length | State length |
+ * | :-------- | :------ | :-----------: | :----------: |
+ * | MD5 | md5 | 16 | 16 |
+ * | SHA-1 | sha1 | 20 | 20 |
+ * | SHA-224 | sha224 | 28 | 32 |
+ * | SHA-256 | sha256 | 32 | 32 |
+ * | SHA-384 | sha384 | 48 | 64 |
+ * | SHA-512 | sha512 | 64 | 64 |
+ * | MD5+SHA-1 | md5sha1 | 36 | 36 |
+ *
+ * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the
+ * same input; in the implementation, the internal data buffer is
+ * shared, thus making it more memory-efficient than separate MD5 and
+ * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS
+ * 1.1.)
+ *
+ *
+ * ## Multi-Hasher
+ *
+ * An aggregate hasher is provided, that can compute several standard
+ * hash functions in parallel. It uses `br_multihash_context` and a
+ * procedural API. It is configured with the implementations (the vtables)
+ * that it should use; it will then compute all these hash functions in
+ * parallel, on the same input. It is meant to be used in cases when the
+ * hash of an object will be used, but the exact hash function is not
+ * known yet (typically, streamed processing on X.509 certificates).
+ *
+ * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384
+ * and SHA-512) are supported by the multi-hasher.
+ *
+ *
+ * ## GHASH
+ *
+ * GHASH is not a generic hash function; it is a _universal_ hash function,
+ * which, as the name does not say, means that it CANNOT be used in most
+ * places where a hash function is needed. GHASH is used within the GCM
+ * encryption mode, to provide the checked integrity functionality.
+ *
+ * A GHASH implementation is basically a function that uses the type defined
+ * in this file under the name `br_ghash`:
+ *
+ * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len);
+ *
+ * The `y` pointer refers to a 16-byte value which is used as input, and
+ * receives the output of the GHASH invocation. `h` is a 16-byte secret
+ * value (that serves as key). `data` and `len` define the input data.
+ *
+ * Three GHASH implementations are provided, all constant-time, based on
+ * the use of integer multiplications with appropriate masking to cancel
+ * carry propagation.
+ */
+
+/**
+ * \brief Class type for hash function implementations.
+ *
+ * A `br_hash_class` instance references the methods implementing a hash
+ * function. Constant instances of this structure are defined for each
+ * implemented hash function. Such instances are also called "vtables".
+ *
+ * Vtables are used to support object-oriented programming, as
+ * described on [the BearSSL Web site](https://www.bearssl.org/oop.html).
+ */
+typedef struct br_hash_class_ br_hash_class;
+struct br_hash_class_ {
+ /**
+ * \brief Size (in bytes) of the context structure appropriate for
+ * computing this hash function.
+ */
+ size_t context_size;
+
+ /**
+ * \brief Descriptor word that contains information about the hash
+ * function.
+ *
+ * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF`
+ * and `BR_HASHDESC_xxx_MASK` to access the specific value, as
+ * follows:
+ *
+ * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK
+ *
+ * The defined elements are:
+ *
+ * - `ID`: the symbolic identifier for the function, as defined
+ * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1)
+ * (MD5 = 1, SHA-1 = 2,...).
+ *
+ * - `OUT`: hash output size, in bytes.
+ *
+ * - `STATE`: internal running state size, in bytes.
+ *
+ * - `LBLEN`: base-2 logarithm for the internal block size, as
+ * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224
+ * and SHA-256, since these functions use 64-byte blocks; for
+ * SHA-384 and SHA-512, this is 7, corresponding to their
+ * 128-byte blocks).
+ *
+ * The descriptor may contain a few other flags.
+ */
+ uint32_t desc;
+
+ /**
+ * \brief Initialisation method.
+ *
+ * This method takes as parameter a pointer to a context area,
+ * that it initialises. The first field of the context is set
+ * to this vtable; other elements are initialised for a new hash
+ * computation.
+ *
+ * \param ctx pointer to (the first field of) the context.
+ */
+ void (*init)(const br_hash_class **ctx);
+
+ /**
+ * \brief Data injection method.
+ *
+ * The `len` bytes starting at address `data` are injected into
+ * the running hash computation incarnated by the specified
+ * context. The context is updated accordingly. It is allowed
+ * to have `len == 0`, in which case `data` is ignored (and could
+ * be `NULL`), and nothing happens.
+ * on the input data.
+ *
+ * \param ctx pointer to (the first field of) the context.
+ * \param data pointer to the first data byte to inject.
+ * \param len number of bytes to inject.
+ */
+ void (*update)(const br_hash_class **ctx, const void *data, size_t len);
+
+ /**
+ * \brief Produce hash output.
+ *
+ * The hash output corresponding to all data bytes injected in the
+ * context since the last `init()` call is computed, and written
+ * in the buffer pointed to by `dst`. The hash output size depends
+ * on the implemented hash function (e.g. 16 bytes for MD5).
+ * The context is _not_ modified by this call, so further bytes
+ * may be afterwards injected to continue the current computation.
+ *
+ * \param ctx pointer to (the first field of) the context.
+ * \param dst destination buffer for the hash output.
+ */
+ void (*out)(const br_hash_class *const *ctx, void *dst);
+
+ /**
+ * \brief Get running state.
+ *
+ * This method saves the current running state into the `dst`
+ * buffer. What constitutes the "running state" depends on the
+ * hash function; for Merkle-Damgård hash functions (like
+ * MD5 or SHA-1), this is the output obtained after processing
+ * each block. The number of bytes injected so far is returned.
+ * The context is not modified by this call.
+ *
+ * \param ctx pointer to (the first field of) the context.
+ * \param dst destination buffer for the state.
+ * \return the injected total byte length.
+ */
+ uint64_t (*state)(const br_hash_class *const *ctx, void *dst);
+
+ /**
+ * \brief Set running state.
+ *
+ * This methods replaces the running state for the function.
+ *
+ * \param ctx pointer to (the first field of) the context.
+ * \param stb source buffer for the state.
+ * \param count injected total byte length.
+ */
+ void (*set_state)(const br_hash_class **ctx,
+ const void *stb, uint64_t count);
+};
+
+#ifndef BR_DOXYGEN_IGNORE
+#define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF)
+#define BR_HASHDESC_ID_OFF 0
+#define BR_HASHDESC_ID_MASK 0xFF
+
+#define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF)
+#define BR_HASHDESC_OUT_OFF 8
+#define BR_HASHDESC_OUT_MASK 0x7F
+
+#define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF)
+#define BR_HASHDESC_STATE_OFF 15
+#define BR_HASHDESC_STATE_MASK 0xFF
+
+#define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF)
+#define BR_HASHDESC_LBLEN_OFF 23
+#define BR_HASHDESC_LBLEN_MASK 0x0F
+
+#define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28)
+#define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29)
+#define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30)
+#endif
+
+/*
+ * Specific hash functions.
+ *
+ * Rules for contexts:
+ * -- No interior pointer.
+ * -- No pointer to external dynamically allocated resources.
+ * -- First field is called 'vtable' and is a pointer to a
+ * const-qualified br_hash_class instance (pointer is set by init()).
+ * -- SHA-224 and SHA-256 contexts are identical.
+ * -- SHA-384 and SHA-512 contexts are identical.
+ *
+ * Thus, contexts can be moved and cloned to capture the hash function
+ * current state; and there is no need for any explicit "release" function.
+ */
+
+/**
+ * \brief Symbolic identifier for MD5.
+ */
+#define br_md5_ID 1
+
+/**
+ * \brief MD5 output size (in bytes).
+ */
+#define br_md5_SIZE 16
+
+/**
+ * \brief Constant vtable for MD5.
+ */
+extern const br_hash_class br_md5_vtable;
+
+/**
+ * \brief MD5 context.
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /**
+ * \brief Pointer to vtable for this context.
+ */
+ const br_hash_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char buf[64];
+ uint64_t count;
+ uint32_t val[4];
+#endif
+} br_md5_context;
+
+/**
+ * \brief MD5 context initialisation.
+ *
+ * This function initialises or resets a context for a new MD5
+ * computation. It also sets the vtable pointer.
+ *
+ * \param ctx pointer to the context structure.
+ */
+void br_md5_init(br_md5_context *ctx);
+
+/**
+ * \brief Inject some data bytes in a running MD5 computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_md5_update(br_md5_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Compute MD5 output.
+ *
+ * The MD5 output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `out`. The context
+ * itself is not modified, so extra bytes may be injected afterwards
+ * to continue that computation.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the hash output.
+ */
+void br_md5_out(const br_md5_context *ctx, void *out);
+
+/**
+ * \brief Save MD5 running state.
+ *
+ * The running state for MD5 (output of the last internal block
+ * processing) is written in the buffer pointed to by `out`. The
+ * number of bytes injected since the last initialisation or reset
+ * call is returned. The context is not modified.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the running state.
+ * \return the injected total byte length.
+ */
+uint64_t br_md5_state(const br_md5_context *ctx, void *out);
+
+/**
+ * \brief Restore MD5 running state.
+ *
+ * The running state for MD5 is set to the provided values.
+ *
+ * \param ctx pointer to the context structure.
+ * \param stb source buffer for the running state.
+ * \param count the injected total byte length.
+ */
+void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count);
+
+/**
+ * \brief Symbolic identifier for SHA-1.
+ */
+#define br_sha1_ID 2
+
+/**
+ * \brief SHA-1 output size (in bytes).
+ */
+#define br_sha1_SIZE 20
+
+/**
+ * \brief Constant vtable for SHA-1.
+ */
+extern const br_hash_class br_sha1_vtable;
+
+/**
+ * \brief SHA-1 context.
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /**
+ * \brief Pointer to vtable for this context.
+ */
+ const br_hash_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char buf[64];
+ uint64_t count;
+ uint32_t val[5];
+#endif
+} br_sha1_context;
+
+/**
+ * \brief SHA-1 context initialisation.
+ *
+ * This function initialises or resets a context for a new SHA-1
+ * computation. It also sets the vtable pointer.
+ *
+ * \param ctx pointer to the context structure.
+ */
+void br_sha1_init(br_sha1_context *ctx);
+
+/**
+ * \brief Inject some data bytes in a running SHA-1 computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Compute SHA-1 output.
+ *
+ * The SHA-1 output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `out`. The context
+ * itself is not modified, so extra bytes may be injected afterwards
+ * to continue that computation.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the hash output.
+ */
+void br_sha1_out(const br_sha1_context *ctx, void *out);
+
+/**
+ * \brief Save SHA-1 running state.
+ *
+ * The running state for SHA-1 (output of the last internal block
+ * processing) is written in the buffer pointed to by `out`. The
+ * number of bytes injected since the last initialisation or reset
+ * call is returned. The context is not modified.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the running state.
+ * \return the injected total byte length.
+ */
+uint64_t br_sha1_state(const br_sha1_context *ctx, void *out);
+
+/**
+ * \brief Restore SHA-1 running state.
+ *
+ * The running state for SHA-1 is set to the provided values.
+ *
+ * \param ctx pointer to the context structure.
+ * \param stb source buffer for the running state.
+ * \param count the injected total byte length.
+ */
+void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count);
+
+/**
+ * \brief Symbolic identifier for SHA-224.
+ */
+#define br_sha224_ID 3
+
+/**
+ * \brief SHA-224 output size (in bytes).
+ */
+#define br_sha224_SIZE 28
+
+/**
+ * \brief Constant vtable for SHA-224.
+ */
+extern const br_hash_class br_sha224_vtable;
+
+/**
+ * \brief SHA-224 context.
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /**
+ * \brief Pointer to vtable for this context.
+ */
+ const br_hash_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char buf[64];
+ uint64_t count;
+ uint32_t val[8];
+#endif
+} br_sha224_context;
+
+/**
+ * \brief SHA-224 context initialisation.
+ *
+ * This function initialises or resets a context for a new SHA-224
+ * computation. It also sets the vtable pointer.
+ *
+ * \param ctx pointer to the context structure.
+ */
+void br_sha224_init(br_sha224_context *ctx);
+
+/**
+ * \brief Inject some data bytes in a running SHA-224 computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Compute SHA-224 output.
+ *
+ * The SHA-224 output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `out`. The context
+ * itself is not modified, so extra bytes may be injected afterwards
+ * to continue that computation.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the hash output.
+ */
+void br_sha224_out(const br_sha224_context *ctx, void *out);
+
+/**
+ * \brief Save SHA-224 running state.
+ *
+ * The running state for SHA-224 (output of the last internal block
+ * processing) is written in the buffer pointed to by `out`. The
+ * number of bytes injected since the last initialisation or reset
+ * call is returned. The context is not modified.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the running state.
+ * \return the injected total byte length.
+ */
+uint64_t br_sha224_state(const br_sha224_context *ctx, void *out);
+
+/**
+ * \brief Restore SHA-224 running state.
+ *
+ * The running state for SHA-224 is set to the provided values.
+ *
+ * \param ctx pointer to the context structure.
+ * \param stb source buffer for the running state.
+ * \param count the injected total byte length.
+ */
+void br_sha224_set_state(br_sha224_context *ctx,
+ const void *stb, uint64_t count);
+
+/**
+ * \brief Symbolic identifier for SHA-256.
+ */
+#define br_sha256_ID 4
+
+/**
+ * \brief SHA-256 output size (in bytes).
+ */
+#define br_sha256_SIZE 32
+
+/**
+ * \brief Constant vtable for SHA-256.
+ */
+extern const br_hash_class br_sha256_vtable;
+
+#ifdef BR_DOXYGEN_IGNORE
+/**
+ * \brief SHA-256 context.
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /**
+ * \brief Pointer to vtable for this context.
+ */
+ const br_hash_class *vtable;
+} br_sha256_context;
+#else
+typedef br_sha224_context br_sha256_context;
+#endif
+
+/**
+ * \brief SHA-256 context initialisation.
+ *
+ * This function initialises or resets a context for a new SHA-256
+ * computation. It also sets the vtable pointer.
+ *
+ * \param ctx pointer to the context structure.
+ */
+void br_sha256_init(br_sha256_context *ctx);
+
+#ifdef BR_DOXYGEN_IGNORE
+/**
+ * \brief Inject some data bytes in a running SHA-256 computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len);
+#else
+#define br_sha256_update br_sha224_update
+#endif
+
+/**
+ * \brief Compute SHA-256 output.
+ *
+ * The SHA-256 output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `out`. The context
+ * itself is not modified, so extra bytes may be injected afterwards
+ * to continue that computation.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the hash output.
+ */
+void br_sha256_out(const br_sha256_context *ctx, void *out);
+
+#if BR_DOXYGEN_IGNORE
+/**
+ * \brief Save SHA-256 running state.
+ *
+ * The running state for SHA-256 (output of the last internal block
+ * processing) is written in the buffer pointed to by `out`. The
+ * number of bytes injected since the last initialisation or reset
+ * call is returned. The context is not modified.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the running state.
+ * \return the injected total byte length.
+ */
+uint64_t br_sha256_state(const br_sha256_context *ctx, void *out);
+#else
+#define br_sha256_state br_sha224_state
+#endif
+
+#if BR_DOXYGEN_IGNORE
+/**
+ * \brief Restore SHA-256 running state.
+ *
+ * The running state for SHA-256 is set to the provided values.
+ *
+ * \param ctx pointer to the context structure.
+ * \param stb source buffer for the running state.
+ * \param count the injected total byte length.
+ */
+void br_sha256_set_state(br_sha256_context *ctx,
+ const void *stb, uint64_t count);
+#else
+#define br_sha256_set_state br_sha224_set_state
+#endif
+
+/**
+ * \brief Symbolic identifier for SHA-384.
+ */
+#define br_sha384_ID 5
+
+/**
+ * \brief SHA-384 output size (in bytes).
+ */
+#define br_sha384_SIZE 48
+
+/**
+ * \brief Constant vtable for SHA-384.
+ */
+extern const br_hash_class br_sha384_vtable;
+
+/**
+ * \brief SHA-384 context.
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /**
+ * \brief Pointer to vtable for this context.
+ */
+ const br_hash_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char buf[128];
+ uint64_t count;
+ uint64_t val[8];
+#endif
+} br_sha384_context;
+
+/**
+ * \brief SHA-384 context initialisation.
+ *
+ * This function initialises or resets a context for a new SHA-384
+ * computation. It also sets the vtable pointer.
+ *
+ * \param ctx pointer to the context structure.
+ */
+void br_sha384_init(br_sha384_context *ctx);
+
+/**
+ * \brief Inject some data bytes in a running SHA-384 computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Compute SHA-384 output.
+ *
+ * The SHA-384 output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `out`. The context
+ * itself is not modified, so extra bytes may be injected afterwards
+ * to continue that computation.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the hash output.
+ */
+void br_sha384_out(const br_sha384_context *ctx, void *out);
+
+/**
+ * \brief Save SHA-384 running state.
+ *
+ * The running state for SHA-384 (output of the last internal block
+ * processing) is written in the buffer pointed to by `out`. The
+ * number of bytes injected since the last initialisation or reset
+ * call is returned. The context is not modified.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the running state.
+ * \return the injected total byte length.
+ */
+uint64_t br_sha384_state(const br_sha384_context *ctx, void *out);
+
+/**
+ * \brief Restore SHA-384 running state.
+ *
+ * The running state for SHA-384 is set to the provided values.
+ *
+ * \param ctx pointer to the context structure.
+ * \param stb source buffer for the running state.
+ * \param count the injected total byte length.
+ */
+void br_sha384_set_state(br_sha384_context *ctx,
+ const void *stb, uint64_t count);
+
+/**
+ * \brief Symbolic identifier for SHA-512.
+ */
+#define br_sha512_ID 6
+
+/**
+ * \brief SHA-512 output size (in bytes).
+ */
+#define br_sha512_SIZE 64
+
+/**
+ * \brief Constant vtable for SHA-512.
+ */
+extern const br_hash_class br_sha512_vtable;
+
+#ifdef BR_DOXYGEN_IGNORE
+/**
+ * \brief SHA-512 context.
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /**
+ * \brief Pointer to vtable for this context.
+ */
+ const br_hash_class *vtable;
+} br_sha512_context;
+#else
+typedef br_sha384_context br_sha512_context;
+#endif
+
+/**
+ * \brief SHA-512 context initialisation.
+ *
+ * This function initialises or resets a context for a new SHA-512
+ * computation. It also sets the vtable pointer.
+ *
+ * \param ctx pointer to the context structure.
+ */
+void br_sha512_init(br_sha512_context *ctx);
+
+#ifdef BR_DOXYGEN_IGNORE
+/**
+ * \brief Inject some data bytes in a running SHA-512 computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len);
+#else
+#define br_sha512_update br_sha384_update
+#endif
+
+/**
+ * \brief Compute SHA-512 output.
+ *
+ * The SHA-512 output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `out`. The context
+ * itself is not modified, so extra bytes may be injected afterwards
+ * to continue that computation.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the hash output.
+ */
+void br_sha512_out(const br_sha512_context *ctx, void *out);
+
+#ifdef BR_DOXYGEN_IGNORE
+/**
+ * \brief Save SHA-512 running state.
+ *
+ * The running state for SHA-512 (output of the last internal block
+ * processing) is written in the buffer pointed to by `out`. The
+ * number of bytes injected since the last initialisation or reset
+ * call is returned. The context is not modified.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the running state.
+ * \return the injected total byte length.
+ */
+uint64_t br_sha512_state(const br_sha512_context *ctx, void *out);
+#else
+#define br_sha512_state br_sha384_state
+#endif
+
+#ifdef BR_DOXYGEN_IGNORE
+/**
+ * \brief Restore SHA-512 running state.
+ *
+ * The running state for SHA-512 is set to the provided values.
+ *
+ * \param ctx pointer to the context structure.
+ * \param stb source buffer for the running state.
+ * \param count the injected total byte length.
+ */
+void br_sha512_set_state(br_sha512_context *ctx,
+ const void *stb, uint64_t count);
+#else
+#define br_sha512_set_state br_sha384_set_state
+#endif
+
+/*
+ * "md5sha1" is a special hash function that computes both MD5 and SHA-1
+ * on the same input, and produces a 36-byte output (MD5 and SHA-1
+ * concatenation, in that order). State size is also 36 bytes.
+ */
+
+/**
+ * \brief Symbolic identifier for MD5+SHA-1.
+ *
+ * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the
+ * same input. It is not one of the functions identified in TLS, so
+ * we give it a symbolic identifier of value 0.
+ */
+#define br_md5sha1_ID 0
+
+/**
+ * \brief MD5+SHA-1 output size (in bytes).
+ */
+#define br_md5sha1_SIZE 36
+
+/**
+ * \brief Constant vtable for MD5+SHA-1.
+ */
+extern const br_hash_class br_md5sha1_vtable;
+
+/**
+ * \brief MD5+SHA-1 context.
+ *
+ * First field is a pointer to the vtable; it is set by the initialisation
+ * function. Other fields are not supposed to be accessed by user code.
+ */
+typedef struct {
+ /**
+ * \brief Pointer to vtable for this context.
+ */
+ const br_hash_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char buf[64];
+ uint64_t count;
+ uint32_t val_md5[4];
+ uint32_t val_sha1[5];
+#endif
+} br_md5sha1_context;
+
+/**
+ * \brief MD5+SHA-1 context initialisation.
+ *
+ * This function initialises or resets a context for a new SHA-512
+ * computation. It also sets the vtable pointer.
+ *
+ * \param ctx pointer to the context structure.
+ */
+void br_md5sha1_init(br_md5sha1_context *ctx);
+
+/**
+ * \brief Inject some data bytes in a running MD5+SHA-1 computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len);
+
+/**
+ * \brief Compute MD5+SHA-1 output.
+ *
+ * The MD5+SHA-1 output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `out`. The context
+ * itself is not modified, so extra bytes may be injected afterwards
+ * to continue that computation.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the hash output.
+ */
+void br_md5sha1_out(const br_md5sha1_context *ctx, void *out);
+
+/**
+ * \brief Save MD5+SHA-1 running state.
+ *
+ * The running state for MD5+SHA-1 (output of the last internal block
+ * processing) is written in the buffer pointed to by `out`. The
+ * number of bytes injected since the last initialisation or reset
+ * call is returned. The context is not modified.
+ *
+ * \param ctx pointer to the context structure.
+ * \param out destination buffer for the running state.
+ * \return the injected total byte length.
+ */
+uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out);
+
+/**
+ * \brief Restore MD5+SHA-1 running state.
+ *
+ * The running state for MD5+SHA-1 is set to the provided values.
+ *
+ * \param ctx pointer to the context structure.
+ * \param stb source buffer for the running state.
+ * \param count the injected total byte length.
+ */
+void br_md5sha1_set_state(br_md5sha1_context *ctx,
+ const void *stb, uint64_t count);
+
+/**
+ * \brief Aggregate context for configurable hash function support.
+ *
+ * The `br_hash_compat_context` type is a type which is large enough to
+ * serve as context for all standard hash functions defined above.
+ */
+typedef union {
+ const br_hash_class *vtable;
+ br_md5_context md5;
+ br_sha1_context sha1;
+ br_sha224_context sha224;
+ br_sha256_context sha256;
+ br_sha384_context sha384;
+ br_sha512_context sha512;
+ br_md5sha1_context md5sha1;
+} br_hash_compat_context;
+
+/*
+ * The multi-hasher is a construct that handles hashing of the same input
+ * data with several hash functions, with a single shared input buffer.
+ * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512
+ * simultaneously, though which functions are activated depends on
+ * the set implementation pointers.
+ */
+
+/**
+ * \brief Multi-hasher context structure.
+ *
+ * The multi-hasher runs up to six hash functions in the standard TLS list
+ * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over
+ * the same input.
+ *
+ * The multi-hasher does _not_ follow the OOP structure with a vtable.
+ * Instead, it is configured with the vtables of the hash functions it
+ * should run. Structure fields are not supposed to be accessed directly.
+ */
+typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char buf[128];
+ uint64_t count;
+ uint32_t val_32[25];
+ uint64_t val_64[16];
+ const br_hash_class *impl[6];
+#endif
+} br_multihash_context;
+
+/**
+ * \brief Clear a multi-hasher context.
+ *
+ * This should always be called once on a given context, _before_ setting
+ * the implementation pointers.
+ *
+ * \param ctx the multi-hasher context.
+ */
+void br_multihash_zero(br_multihash_context *ctx);
+
+/**
+ * \brief Set a hash function implementation.
+ *
+ * Implementations shall be set _after_ clearing the context (with
+ * `br_multihash_zero()`) but _before_ initialising the computation
+ * (with `br_multihash_init()`). The hash function implementation
+ * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224,
+ * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove
+ * an implementation from the multi-hasher.
+ *
+ * \param ctx the multi-hasher context.
+ * \param id the hash function symbolic identifier.
+ * \param impl the hash function vtable, or `NULL`.
+ */
+static inline void
+br_multihash_setimpl(br_multihash_context *ctx,
+ int id, const br_hash_class *impl)
+{
+ /*
+ * This code relies on hash functions ID being values 1 to 6,
+ * in the MD5 to SHA-512 order.
+ */
+ ctx->impl[id - 1] = impl;
+}
+
+/**
+ * \brief Get a hash function implementation.
+ *
+ * This function returns the currently configured vtable for a given
+ * hash function (by symbolic ID). If no such function was configured in
+ * the provided multi-hasher context, then this function returns `NULL`.
+ *
+ * \param ctx the multi-hasher context.
+ * \param id the hash function symbolic identifier.
+ * \return the hash function vtable, or `NULL`.
+ */
+static inline const br_hash_class *
+br_multihash_getimpl(const br_multihash_context *ctx, int id)
+{
+ return ctx->impl[id - 1];
+}
+
+/**
+ * \brief Reset a multi-hasher context.
+ *
+ * This function prepares the context for a new hashing computation,
+ * for all implementations configured at that point.
+ *
+ * \param ctx the multi-hasher context.
+ */
+void br_multihash_init(br_multihash_context *ctx);
+
+/**
+ * \brief Inject some data bytes in a running multi-hashing computation.
+ *
+ * The provided context is updated with some data bytes. If the number
+ * of bytes (`len`) is zero, then the data pointer (`data`) is ignored
+ * and may be `NULL`, and this function does nothing.
+ *
+ * \param ctx pointer to the context structure.
+ * \param data pointer to the injected data.
+ * \param len injected data length (in bytes).
+ */
+void br_multihash_update(br_multihash_context *ctx,
+ const void *data, size_t len);
+
+/**
+ * \brief Compute a hash output from a multi-hasher.
+ *
+ * The hash output for the concatenation of all bytes injected in the
+ * provided context since the last initialisation or reset call, is
+ * computed and written in the buffer pointed to by `dst`. The hash
+ * function to use is identified by `id` and must be one of the standard
+ * hash functions. If that hash function was indeed configured in the
+ * multi-hasher context, the corresponding hash value is written in
+ * `dst` and its length (in bytes) is returned. If the hash function
+ * was _not_ configured, then nothing is written in `dst` and 0 is
+ * returned.
+ *
+ * The context itself is not modified, so extra bytes may be injected
+ * afterwards to continue the hash computations.
+ *
+ * \param ctx pointer to the context structure.
+ * \param id the hash function symbolic identifier.
+ * \param dst destination buffer for the hash output.
+ * \return the hash output length (in bytes), or 0.
+ */
+size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst);
+
+/**
+ * \brief Type for a GHASH implementation.
+ *
+ * GHASH is a sort of keyed hash meant to be used to implement GCM in
+ * combination with a block cipher (with 16-byte blocks).
+ *
+ * The `y` array has length 16 bytes and is used for input and output; in
+ * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte
+ * value that serves as key (it is derived from the encryption key in GCM,
+ * using the block cipher). The data length (`len`) is expressed in bytes.
+ * The `y` array is updated.
+ *
+ * If the data length is not a multiple of 16, then the data is implicitly
+ * padded with zeros up to the next multiple of 16. Thus, when using GHASH
+ * in GCM, this method may be called twice, for the associated data and
+ * for the ciphertext, respectively; the zero-padding implements exactly
+ * the GCM rules.
+ *
+ * \param y the array to update.
+ * \param h the GHASH key.
+ * \param data the input data (may be `NULL` if `len` is zero).
+ * \param len the input data length (in bytes).
+ */
+typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len);
+
+/**
+ * \brief GHASH implementation using multiplications (mixed 32-bit).
+ *
+ * This implementation uses multiplications of 32-bit values, with a
+ * 64-bit result. It is constant-time (if multiplications are
+ * constant-time).
+ *
+ * \param y the array to update.
+ * \param h the GHASH key.
+ * \param data the input data (may be `NULL` if `len` is zero).
+ * \param len the input data length (in bytes).
+ */
+void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len);
+
+/**
+ * \brief GHASH implementation using multiplications (strict 32-bit).
+ *
+ * This implementation uses multiplications of 32-bit values, with a
+ * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`,
+ * but it is expected to be faster on architectures for which the
+ * 32-bit multiplication opcode does not yield the upper 32 bits of the
+ * product. It is constant-time (if multiplications are constant-time).
+ *
+ * \param y the array to update.
+ * \param h the GHASH key.
+ * \param data the input data (may be `NULL` if `len` is zero).
+ * \param len the input data length (in bytes).
+ */
+void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len);
+
+/**
+ * \brief GHASH implementation using multiplications (64-bit).
+ *
+ * This implementation uses multiplications of 64-bit values, with a
+ * 64-bit result. It is constant-time (if multiplications are
+ * constant-time). It is substantially faster than `br_ghash_ctmul()`
+ * and `br_ghash_ctmul32()` on most 64-bit architectures.
+ *
+ * \param y the array to update.
+ * \param h the GHASH key.
+ * \param data the input data (may be `NULL` if `len` is zero).
+ * \param len the input data length (in bytes).
+ */
+void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len);
+
+/**
+ * \brief GHASH implementation using the `pclmulqdq` opcode (part of the
+ * AES-NI instructions).
+ *
+ * This implementation is available only on x86 platforms where the
+ * compiler supports the relevant intrinsic functions. Even if the
+ * compiler supports these functions, the local CPU might not support
+ * the `pclmulqdq` opcode, meaning that a call will fail with an
+ * illegal instruction exception. To safely obtain a pointer to this
+ * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`.
+ *
+ * \param y the array to update.
+ * \param h the GHASH key.
+ * \param data the input data (may be `NULL` if `len` is zero).
+ * \param len the input data length (in bytes).
+ */
+void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len);
+
+/**
+ * \brief Obtain the `pclmul` GHASH implementation, if available.
+ *
+ * If the `pclmul` implementation was compiled in the library (depending
+ * on the compiler abilities) _and_ the local CPU appears to support the
+ * opcode, then this function will return a pointer to the
+ * `br_ghash_pclmul()` function. Otherwise, it will return `0`.
+ *
+ * \return the `pclmul` GHASH implementation, or `0`.
+ */
+br_ghash br_ghash_pclmul_get(void);
+
+/**
+ * \brief GHASH implementation using the POWER8 opcodes.
+ *
+ * This implementation is available only on POWER8 platforms (and later).
+ * To safely obtain a pointer to this function when supported (or 0
+ * otherwise), use `br_ghash_pwr8_get()`.
+ *
+ * \param y the array to update.
+ * \param h the GHASH key.
+ * \param data the input data (may be `NULL` if `len` is zero).
+ * \param len the input data length (in bytes).
+ */
+void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len);
+
+/**
+ * \brief Obtain the `pwr8` GHASH implementation, if available.
+ *
+ * If the `pwr8` implementation was compiled in the library (depending
+ * on the compiler abilities) _and_ the local CPU appears to support the
+ * opcode, then this function will return a pointer to the
+ * `br_ghash_pwr8()` function. Otherwise, it will return `0`.
+ *
+ * \return the `pwr8` GHASH implementation, or `0`.
+ */
+br_ghash br_ghash_pwr8_get(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Property changes on: stable/12/contrib/bearssl/inc/bearssl_hash.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_hmac.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_hmac.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_hmac.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/inc/bearssl_hmac.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_kdf.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_kdf.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_kdf.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/inc/bearssl_kdf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_pem.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_pem.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_pem.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/inc/bearssl_pem.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_prf.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_prf.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_prf.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/inc/bearssl_prf.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_rand.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_rand.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_rand.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/inc/bearssl_rand.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_rsa.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_rsa.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_rsa.h (revision 346145)
@@ -0,0 +1,1655 @@
+/*
+ * 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_RSA_H__
+#define BR_BEARSSL_RSA_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "bearssl_hash.h"
+#include "bearssl_rand.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file bearssl_rsa.h
+ *
+ * # RSA
+ *
+ * This file documents the RSA implementations provided with BearSSL.
+ * Note that the SSL engine accesses these implementations through a
+ * configurable API, so it is possible to, for instance, run a SSL
+ * server which uses a RSA engine which is not based on this code.
+ *
+ * ## Key Elements
+ *
+ * RSA public and private keys consist in lists of big integers. All
+ * such integers are represented with big-endian unsigned notation:
+ * first byte is the most significant, and the value is positive (so
+ * there is no dedicated "sign bit"). Public and private key structures
+ * thus contain, for each such integer, a pointer to the first value byte
+ * (`unsigned char *`), and a length (`size_t`) which is the number of
+ * relevant bytes. As a general rule, minimal-length encoding is not
+ * enforced: values may have extra leading bytes of value 0.
+ *
+ * RSA public keys consist in two integers:
+ *
+ * - the modulus (`n`);
+ * - the public exponent (`e`).
+ *
+ * RSA private keys, as defined in
+ * [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers:
+ *
+ * - the modulus (`n`);
+ * - the public exponent (`e`);
+ * - the private exponent (`d`);
+ * - the first prime factor (`p`);
+ * - the second prime factor (`q`);
+ * - the first reduced exponent (`dp`, which is `d` modulo `p-1`);
+ * - the second reduced exponent (`dq`, which is `d` modulo `q-1`);
+ * - the CRT coefficient (`iq`, the inverse of `q` modulo `p`).
+ *
+ * However, the implementations defined in BearSSL use only five of
+ * these integers: `p`, `q`, `dp`, `dq` and `iq`.
+ *
+ * ## Security Features and Limitations
+ *
+ * The implementations contained in BearSSL have the following limitations
+ * and features:
+ *
+ * - They are constant-time. This means that the execution time and
+ * memory access pattern may depend on the _lengths_ of the private
+ * key components, but not on their value, nor on the value of
+ * the operand. Note that this property is not achieved through
+ * random masking, but "true" constant-time code.
+ *
+ * - They support only private keys with two prime factors. RSA private
+ * keys with three or more prime factors are nominally supported, but
+ * rarely used; they may offer faster operations, at the expense of
+ * more code and potentially a reduction in security if there are
+ * "too many" prime factors.
+ *
+ * - The public exponent may have arbitrary length. Of course, it is
+ * a good idea to keep public exponents small, so that public key
+ * operations are fast; but, contrary to some widely deployed
+ * implementations, BearSSL has no problem with public exponents
+ * longer than 32 bits.
+ *
+ * - The two prime factors of the modulus need not have the same length
+ * (but severely imbalanced factor lengths might reduce security).
+ * Similarly, there is no requirement that the first factor (`p`)
+ * be greater than the second factor (`q`).
+ *
+ * - Prime factors and modulus must be smaller than a compile-time limit.
+ * This is made necessary by the use of fixed-size stack buffers, and
+ * the limit has been adjusted to keep stack usage under 2 kB for the
+ * RSA operations. Currently, the maximum modulus size is 4096 bits,
+ * and the maximum prime factor size is 2080 bits.
+ *
+ * - The RSA functions themselves do not enforce lower size limits,
+ * except that which is absolutely necessary for the operation to
+ * mathematically make sense (e.g. a PKCS#1 v1.5 signature with
+ * SHA-1 requires a modulus of at least 361 bits). It is up to users
+ * of this code to enforce size limitations when appropriate (e.g.
+ * the X.509 validation engine, by default, rejects RSA keys of
+ * less than 1017 bits).
+ *
+ * - Within the size constraints expressed above, arbitrary bit lengths
+ * are supported. There is no requirement that prime factors or
+ * modulus have a size multiple of 8 or 16.
+ *
+ * - When verifying PKCS#1 v1.5 signatures, both variants of the hash
+ * function identifying header (with and without the ASN.1 NULL) are
+ * supported. When producing such signatures, the variant with the
+ * ASN.1 NULL is used.
+ *
+ * ## Implementations
+ *
+ * Three RSA implementations are included:
+ *
+ * - The **i32** implementation internally represents big integers
+ * as arrays of 32-bit integers. It is perfunctory and portable,
+ * but not very efficient.
+ *
+ * - The **i31** implementation uses 32-bit integers, each containing
+ * 31 bits worth of integer data. The i31 implementation is somewhat
+ * faster than the i32 implementation (the reduced integer size makes
+ * carry propagation easier) for a similar code footprint, but uses
+ * very slightly larger stack buffers (about 4% bigger).
+ *
+ * - The **i62** implementation is similar to the i31 implementation,
+ * except that it internally leverages the 64x64->128 multiplication
+ * opcode. This implementation is available only on architectures
+ * where such an opcode exists. It is much faster than i31.
+ *
+ * - The **i15** implementation uses 16-bit integers, each containing
+ * 15 bits worth of integer data. Multiplication results fit on
+ * 32 bits, so this won't use the "widening" multiplication routine
+ * on ARM Cortex M0/M0+, for much better performance and constant-time
+ * execution.
+ */
+
+/**
+ * \brief RSA public key.
+ *
+ * The structure references the modulus and the public exponent. Both
+ * integers use unsigned big-endian representation; extra leading bytes
+ * of value 0 are allowed.
+ */
+typedef struct {
+ /** \brief Modulus. */
+ unsigned char *n;
+ /** \brief Modulus length (in bytes). */
+ size_t nlen;
+ /** \brief Public exponent. */
+ unsigned char *e;
+ /** \brief Public exponent length (in bytes). */
+ size_t elen;
+} br_rsa_public_key;
+
+/**
+ * \brief RSA private key.
+ *
+ * The structure references the private factors, reduced private
+ * exponents, and CRT coefficient. It also contains the bit length of
+ * the modulus. The big integers use unsigned big-endian representation;
+ * extra leading bytes of value 0 are allowed. However, the modulus bit
+ * length (`n_bitlen`) MUST be exact.
+ */
+typedef struct {
+ /** \brief Modulus bit length (in bits, exact value). */
+ uint32_t n_bitlen;
+ /** \brief First prime factor. */
+ unsigned char *p;
+ /** \brief First prime factor length (in bytes). */
+ size_t plen;
+ /** \brief Second prime factor. */
+ unsigned char *q;
+ /** \brief Second prime factor length (in bytes). */
+ size_t qlen;
+ /** \brief First reduced private exponent. */
+ unsigned char *dp;
+ /** \brief First reduced private exponent length (in bytes). */
+ size_t dplen;
+ /** \brief Second reduced private exponent. */
+ unsigned char *dq;
+ /** \brief Second reduced private exponent length (in bytes). */
+ size_t dqlen;
+ /** \brief CRT coefficient. */
+ unsigned char *iq;
+ /** \brief CRT coefficient length (in bytes). */
+ size_t iqlen;
+} br_rsa_private_key;
+
+/**
+ * \brief Type for a RSA public key engine.
+ *
+ * The public key engine performs the modular exponentiation of the
+ * provided value with the public exponent. The value is modified in
+ * place.
+ *
+ * The value length (`xlen`) is verified to have _exactly_ the same
+ * length as the modulus (actual modulus length, without extra leading
+ * zeros in the modulus representation in memory). If the length does
+ * not match, then this function returns 0 and `x[]` is unmodified.
+ *
+ * It `xlen` is correct, then `x[]` is modified. Returned value is 1
+ * on success, 0 on error. Error conditions include an oversized `x[]`
+ * (the array has the same length as the modulus, but the numerical value
+ * is not lower than the modulus) and an invalid modulus (e.g. an even
+ * integer). If an error is reported, then the new contents of `x[]` are
+ * unspecified.
+ *
+ * \param x operand to exponentiate.
+ * \param xlen length of the operand (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk);
+
+/**
+ * \brief Type for a RSA signature verification engine (PKCS#1 v1.5).
+ *
+ * Parameters are:
+ *
+ * - The signature itself. The provided array is NOT modified.
+ *
+ * - The encoded OID for the hash function. The provided array must begin
+ * with a single byte that contains the length of the OID value (in
+ * bytes), followed by exactly that many bytes. This parameter may
+ * also be `NULL`, in which case the raw hash value should be used
+ * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up
+ * to TLS-1.1, with a 36-byte hash value).
+ *
+ * - The hash output length, in bytes.
+ *
+ * - The public key.
+ *
+ * - An output buffer for the hash value. The caller must still compare
+ * it with the hash of the data over which the signature is computed.
+ *
+ * **Constraints:**
+ *
+ * - Hash length MUST be no more than 64 bytes.
+ *
+ * - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]`
+ * must have a value in the 0..32 range, inclusive).
+ *
+ * This function verifies that the signature length (`xlen`) matches the
+ * modulus length (this function returns 0 on mismatch). If the modulus
+ * size exceeds the maximum supported RSA size, then the function also
+ * returns 0.
+ *
+ * Returned value is 1 on success, 0 on error.
+ *
+ * Implementations of this type need not be constant-time.
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash_len expected hash value length (in bytes).
+ * \param pk RSA public key.
+ * \param hash_out output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out);
+
+/**
+ * \brief Type for a RSA signature verification engine (PSS).
+ *
+ * Parameters are:
+ *
+ * - The signature itself. The provided array is NOT modified.
+ *
+ * - The hash function which was used to hash the message.
+ *
+ * - The hash function to use with MGF1 within the PSS padding. This
+ * is not necessarily the same hash function as the one which was
+ * used to hash the signed message.
+ *
+ * - The hashed message (as an array of bytes).
+ *
+ * - The PSS salt length (in bytes).
+ *
+ * - The public key.
+ *
+ * **Constraints:**
+ *
+ * - Hash message length MUST be no more than 64 bytes.
+ *
+ * Note that, contrary to PKCS#1 v1.5 signature, the hash value of the
+ * signed data cannot be extracted from the signature; it must be
+ * provided to the verification function.
+ *
+ * This function verifies that the signature length (`xlen`) matches the
+ * modulus length (this function returns 0 on mismatch). If the modulus
+ * size exceeds the maximum supported RSA size, then the function also
+ * returns 0.
+ *
+ * Returned value is 1 on success, 0 on error.
+ *
+ * Implementations of this type need not be constant-time.
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hf_data hash function applied on the message.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hash value of the signed message.
+ * \param salt_len PSS salt length (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+typedef uint32_t (*br_rsa_pss_vrfy)(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk);
+
+/**
+ * \brief Type for a RSA encryption engine (OAEP).
+ *
+ * Parameters are:
+ *
+ * - A source of random bytes. The source must be already initialized.
+ *
+ * - A hash function, used internally with the mask generation function
+ * (MGF1).
+ *
+ * - A label. The `label` pointer may be `NULL` if `label_len` is zero
+ * (an empty label, which is the default in PKCS#1 v2.2).
+ *
+ * - The public key.
+ *
+ * - The destination buffer. Its maximum length (in bytes) is provided;
+ * if that length is lower than the public key length, then an error
+ * is reported.
+ *
+ * - The source message.
+ *
+ * The encrypted message output has exactly the same length as the modulus
+ * (mathematical length, in bytes, not counting extra leading zeros in the
+ * modulus representation in the public key).
+ *
+ * The source message (`src`, length `src_len`) may overlap with the
+ * destination buffer (`dst`, length `dst_max_len`).
+ *
+ * This function returns the actual encrypted message length, in bytes;
+ * on error, zero is returned. An error is reported if the output buffer
+ * is not large enough, or the public is invalid, or the public key
+ * modulus exceeds the maximum supported RSA size.
+ *
+ * \param rnd source of random bytes.
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param pk RSA public key.
+ * \param dst destination buffer.
+ * \param dst_max_len destination buffer length (maximum encrypted data size).
+ * \param src message to encrypt.
+ * \param src_len source message length (in bytes).
+ * \return encrypted message length (in bytes), or 0 on error.
+ */
+typedef size_t (*br_rsa_oaep_encrypt)(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len);
+
+/**
+ * \brief Type for a RSA private key engine.
+ *
+ * The `x[]` buffer is modified in place, and its length is inferred from
+ * the modulus length (`x[]` is assumed to have a length of
+ * `(sk->n_bitlen+7)/8` bytes).
+ *
+ * Returned value is 1 on success, 0 on error.
+ *
+ * \param x operand to exponentiate.
+ * \param sk RSA private key.
+ * \return 1 on success, 0 on error.
+ */
+typedef uint32_t (*br_rsa_private)(unsigned char *x,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief Type for a RSA signature generation engine (PKCS#1 v1.5).
+ *
+ * Parameters are:
+ *
+ * - The encoded OID for the hash function. The provided array must begin
+ * with a single byte that contains the length of the OID value (in
+ * bytes), followed by exactly that many bytes. This parameter may
+ * also be `NULL`, in which case the raw hash value should be used
+ * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up
+ * to TLS-1.1, with a 36-byte hash value).
+ *
+ * - The hash value computes over the data to sign (its length is
+ * expressed in bytes).
+ *
+ * - The RSA private key.
+ *
+ * - The output buffer, that receives the signature.
+ *
+ * Returned value is 1 on success, 0 on error. Error conditions include
+ * a too small modulus for the provided hash OID and value, or some
+ * invalid key parameters. The signature length is exactly
+ * `(sk->n_bitlen+7)/8` bytes.
+ *
+ * This function is expected to be constant-time with regards to the
+ * private key bytes (lengths of the modulus and the individual factors
+ * may leak, though) and to the hashed data.
+ *
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash hash value.
+ * \param hash_len hash value length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the signature value.
+ * \return 1 on success, 0 on error.
+ */
+typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief Type for a RSA signature generation engine (PSS).
+ *
+ * Parameters are:
+ *
+ * - An initialized PRNG for salt generation. If the salt length is
+ * zero (`salt_len` parameter), then the PRNG is optional (this is
+ * not the typical case, as the security proof of RSA/PSS is
+ * tighter when a non-empty salt is used).
+ *
+ * - The hash function which was used to hash the message.
+ *
+ * - The hash function to use with MGF1 within the PSS padding. This
+ * is not necessarily the same function as the one used to hash the
+ * message.
+ *
+ * - The hashed message.
+ *
+ * - The salt length, in bytes.
+ *
+ * - The RSA private key.
+ *
+ * - The output buffer, that receives the signature.
+ *
+ * Returned value is 1 on success, 0 on error. Error conditions include
+ * a too small modulus for the provided hash and salt lengths, or some
+ * invalid key parameters. The signature length is exactly
+ * `(sk->n_bitlen+7)/8` bytes.
+ *
+ * This function is expected to be constant-time with regards to the
+ * private key bytes (lengths of the modulus and the individual factors
+ * may leak, though) and to the hashed data.
+ *
+ * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
+ * \param hf_data hash function used to hash the signed data.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hashed message.
+ * \param salt_len salt length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the signature value.
+ * \return 1 on success, 0 on error.
+ */
+typedef uint32_t (*br_rsa_pss_sign)(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash_value, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures).
+ */
+#define BR_HASH_OID_SHA1 \
+ ((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A")
+
+/**
+ * \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures).
+ */
+#define BR_HASH_OID_SHA224 \
+ ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04")
+
+/**
+ * \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures).
+ */
+#define BR_HASH_OID_SHA256 \
+ ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01")
+
+/**
+ * \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures).
+ */
+#define BR_HASH_OID_SHA384 \
+ ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02")
+
+/**
+ * \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures).
+ */
+#define BR_HASH_OID_SHA512 \
+ ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03")
+
+/**
+ * \brief Type for a RSA decryption engine (OAEP).
+ *
+ * Parameters are:
+ *
+ * - A hash function, used internally with the mask generation function
+ * (MGF1).
+ *
+ * - A label. The `label` pointer may be `NULL` if `label_len` is zero
+ * (an empty label, which is the default in PKCS#1 v2.2).
+ *
+ * - The private key.
+ *
+ * - The source and destination buffer. The buffer initially contains
+ * the encrypted message; the buffer contents are altered, and the
+ * decrypted message is written at the start of that buffer
+ * (decrypted message is always shorter than the encrypted message).
+ *
+ * If decryption fails in any way, then `*len` is unmodified, and the
+ * function returns 0. Otherwise, `*len` is set to the decrypted message
+ * length, and 1 is returned. The implementation is responsible for
+ * checking that the input message length matches the key modulus length,
+ * and that the padding is correct.
+ *
+ * Implementations MUST use constant-time check of the validity of the
+ * OAEP padding, at least until the leading byte and hash value have
+ * been checked. Whether overall decryption worked, and the length of
+ * the decrypted message, may leak.
+ *
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param sk RSA private key.
+ * \param data input/output buffer.
+ * \param len encrypted/decrypted message length.
+ * \return 1 on success, 0 on error.
+ */
+typedef uint32_t (*br_rsa_oaep_decrypt)(
+ const br_hash_class *dig, const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len);
+
+/*
+ * RSA "i32" engine. Integers are internally represented as arrays of
+ * 32-bit integers, and the core multiplication primitive is the
+ * 32x32->64 multiplication.
+ */
+
+/**
+ * \brief RSA public key engine "i32".
+ *
+ * \see br_rsa_public
+ *
+ * \param x operand to exponentiate.
+ * \param xlen length of the operand (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA signature verification engine "i32" (PKCS#1 v1.5 signatures).
+ *
+ * \see br_rsa_pkcs1_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash_len expected hash value length (in bytes).
+ * \param pk RSA public key.
+ * \param hash_out output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out);
+
+/**
+ * \brief RSA signature verification engine "i32" (PSS signatures).
+ *
+ * \see br_rsa_pss_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hf_data hash function applied on the message.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hash value of the signed message.
+ * \param salt_len PSS salt length (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA private key engine "i32".
+ *
+ * \see br_rsa_private
+ *
+ * \param x operand to exponentiate.
+ * \param sk RSA private key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i32_private(unsigned char *x,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief RSA signature generation engine "i32" (PKCS#1 v1.5 signatures).
+ *
+ * \see br_rsa_pkcs1_sign
+ *
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash hash value.
+ * \param hash_len hash value length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief RSA signature generation engine "i32" (PSS signatures).
+ *
+ * \see br_rsa_pss_sign
+ *
+ * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
+ * \param hf_data hash function used to hash the signed data.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hashed message.
+ * \param salt_len salt length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the signature value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i32_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash_value, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/*
+ * RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit
+ * word. This uses slightly more stack space (about 4% more) and code
+ * space, but it quite faster.
+ */
+
+/**
+ * \brief RSA public key engine "i31".
+ *
+ * \see br_rsa_public
+ *
+ * \param x operand to exponentiate.
+ * \param xlen length of the operand (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA signature verification engine "i31" (PKCS#1 v1.5 signatures).
+ *
+ * \see br_rsa_pkcs1_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash_len expected hash value length (in bytes).
+ * \param pk RSA public key.
+ * \param hash_out output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out);
+
+/**
+ * \brief RSA signature verification engine "i31" (PSS signatures).
+ *
+ * \see br_rsa_pss_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hf_data hash function applied on the message.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hash value of the signed message.
+ * \param salt_len PSS salt length (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA private key engine "i31".
+ *
+ * \see br_rsa_private
+ *
+ * \param x operand to exponentiate.
+ * \param sk RSA private key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i31_private(unsigned char *x,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief RSA signature generation engine "i31" (PKCS#1 v1.5 signatures).
+ *
+ * \see br_rsa_pkcs1_sign
+ *
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash hash value.
+ * \param hash_len hash value length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief RSA signature generation engine "i31" (PSS signatures).
+ *
+ * \see br_rsa_pss_sign
+ *
+ * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
+ * \param hf_data hash function used to hash the signed data.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hashed message.
+ * \param salt_len salt length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the signature value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i31_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash_value, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/*
+ * RSA "i62" engine. Similar to i31, but internal multiplication use
+ * 64x64->128 multiplications. This is available only on architecture
+ * that offer such an opcode.
+ */
+
+/**
+ * \brief RSA public key engine "i62".
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_public
+ *
+ * \param x operand to exponentiate.
+ * \param xlen length of the operand (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA signature verification engine "i62" (PKCS#1 v1.5 signatures).
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_pkcs1_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash_len expected hash value length (in bytes).
+ * \param pk RSA public key.
+ * \param hash_out output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out);
+
+/**
+ * \brief RSA signature verification engine "i62" (PSS signatures).
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_pss_vrfy_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_pss_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hf_data hash function applied on the message.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hash value of the signed message.
+ * \param salt_len PSS salt length (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA private key engine "i62".
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_private
+ *
+ * \param x operand to exponentiate.
+ * \param sk RSA private key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i62_private(unsigned char *x,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief RSA signature generation engine "i62" (PKCS#1 v1.5 signatures).
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_pkcs1_sign
+ *
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash hash value.
+ * \param hash_len hash value length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief RSA signature generation engine "i62" (PSS signatures).
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_pss_sign_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_pss_sign
+ *
+ * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
+ * \param hf_data hash function used to hash the signed data.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hashed message.
+ * \param salt_len salt length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the signature value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i62_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash_value, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief Get the RSA "i62" implementation (public key operations),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_public br_rsa_i62_public_get(void);
+
+/**
+ * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature verification),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void);
+
+/**
+ * \brief Get the RSA "i62" implementation (PSS signature verification),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_pss_vrfy br_rsa_i62_pss_vrfy_get(void);
+
+/**
+ * \brief Get the RSA "i62" implementation (private key operations),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_private br_rsa_i62_private_get(void);
+
+/**
+ * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature generation),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void);
+
+/**
+ * \brief Get the RSA "i62" implementation (PSS signature generation),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_pss_sign br_rsa_i62_pss_sign_get(void);
+
+/**
+ * \brief Get the RSA "i62" implementation (OAEP encryption),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void);
+
+/**
+ * \brief Get the RSA "i62" implementation (OAEP decryption),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void);
+
+/*
+ * RSA "i15" engine. Integers are represented as 15-bit integers, so
+ * the code uses only 32-bit multiplication (no 64-bit result), which
+ * is vastly faster (and constant-time) on the ARM Cortex M0/M0+.
+ */
+
+/**
+ * \brief RSA public key engine "i15".
+ *
+ * \see br_rsa_public
+ *
+ * \param x operand to exponentiate.
+ * \param xlen length of the operand (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA signature verification engine "i15" (PKCS#1 v1.5 signatures).
+ *
+ * \see br_rsa_pkcs1_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash_len expected hash value length (in bytes).
+ * \param pk RSA public key.
+ * \param hash_out output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out);
+
+/**
+ * \brief RSA signature verification engine "i15" (PSS signatures).
+ *
+ * \see br_rsa_pss_vrfy
+ *
+ * \param x signature buffer.
+ * \param xlen signature length (in bytes).
+ * \param hf_data hash function applied on the message.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hash value of the signed message.
+ * \param salt_len PSS salt length (in bytes).
+ * \param pk RSA public key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk);
+
+/**
+ * \brief RSA private key engine "i15".
+ *
+ * \see br_rsa_private
+ *
+ * \param x operand to exponentiate.
+ * \param sk RSA private key.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i15_private(unsigned char *x,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief RSA signature generation engine "i15" (PKCS#1 v1.5 signatures).
+ *
+ * \see br_rsa_pkcs1_sign
+ *
+ * \param hash_oid encoded hash algorithm OID (or `NULL`).
+ * \param hash hash value.
+ * \param hash_len hash value length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the hash value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief RSA signature generation engine "i15" (PSS signatures).
+ *
+ * \see br_rsa_pss_sign
+ *
+ * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
+ * \param hf_data hash function used to hash the signed data.
+ * \param hf_mgf1 hash function to use with MGF1.
+ * \param hash hashed message.
+ * \param salt_len salt length (in bytes).
+ * \param sk RSA private key.
+ * \param x output buffer for the signature value.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i15_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash_value, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x);
+
+/**
+ * \brief Get "default" RSA implementation (public-key operations).
+ *
+ * This returns the preferred implementation of RSA (public-key operations)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_public br_rsa_public_get_default(void);
+
+/**
+ * \brief Get "default" RSA implementation (private-key operations).
+ *
+ * This returns the preferred implementation of RSA (private-key operations)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_private br_rsa_private_get_default(void);
+
+/**
+ * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature verification).
+ *
+ * This returns the preferred implementation of RSA (signature verification)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void);
+
+/**
+ * \brief Get "default" RSA implementation (PSS signature verification).
+ *
+ * This returns the preferred implementation of RSA (signature verification)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_pss_vrfy br_rsa_pss_vrfy_get_default(void);
+
+/**
+ * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature generation).
+ *
+ * This returns the preferred implementation of RSA (signature generation)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void);
+
+/**
+ * \brief Get "default" RSA implementation (PSS signature generation).
+ *
+ * This returns the preferred implementation of RSA (signature generation)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_pss_sign br_rsa_pss_sign_get_default(void);
+
+/**
+ * \brief Get "default" RSA implementation (OAEP encryption).
+ *
+ * This returns the preferred implementation of RSA (OAEP encryption)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void);
+
+/**
+ * \brief Get "default" RSA implementation (OAEP decryption).
+ *
+ * This returns the preferred implementation of RSA (OAEP decryption)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void);
+
+/**
+ * \brief RSA decryption helper, for SSL/TLS.
+ *
+ * This function performs the RSA decryption for a RSA-based key exchange
+ * in a SSL/TLS server. The provided RSA engine is used. The `data`
+ * parameter points to the value to decrypt, of length `len` bytes. On
+ * success, the 48-byte pre-master secret is copied into `data`, starting
+ * at the first byte of that buffer; on error, the contents of `data`
+ * become indeterminate.
+ *
+ * This function first checks that the provided value length (`len`) is
+ * not lower than 59 bytes, and matches the RSA modulus length; if neither
+ * of this property is met, then this function returns 0 and the buffer
+ * is unmodified.
+ *
+ * Otherwise, decryption and then padding verification are performed, both
+ * in constant-time. A decryption error, or a bad padding, or an
+ * incorrect decrypted value length are reported with a returned value of
+ * 0; on success, 1 is returned. The caller (SSL server engine) is supposed
+ * to proceed with a random pre-master secret in case of error.
+ *
+ * \param core RSA private key engine.
+ * \param sk RSA private key.
+ * \param data input/output buffer.
+ * \param len length (in bytes) of the data to decrypt.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk,
+ unsigned char *data, size_t len);
+
+/**
+ * \brief RSA encryption (OAEP) with the "i15" engine.
+ *
+ * \see br_rsa_oaep_encrypt
+ *
+ * \param rnd source of random bytes.
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param pk RSA public key.
+ * \param dst destination buffer.
+ * \param dst_max_len destination buffer length (maximum encrypted data size).
+ * \param src message to encrypt.
+ * \param src_len source message length (in bytes).
+ * \return encrypted message length (in bytes), or 0 on error.
+ */
+size_t br_rsa_i15_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len);
+
+/**
+ * \brief RSA decryption (OAEP) with the "i15" engine.
+ *
+ * \see br_rsa_oaep_decrypt
+ *
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param sk RSA private key.
+ * \param data input/output buffer.
+ * \param len encrypted/decrypted message length.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i15_oaep_decrypt(
+ const br_hash_class *dig, const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len);
+
+/**
+ * \brief RSA encryption (OAEP) with the "i31" engine.
+ *
+ * \see br_rsa_oaep_encrypt
+ *
+ * \param rnd source of random bytes.
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param pk RSA public key.
+ * \param dst destination buffer.
+ * \param dst_max_len destination buffer length (maximum encrypted data size).
+ * \param src message to encrypt.
+ * \param src_len source message length (in bytes).
+ * \return encrypted message length (in bytes), or 0 on error.
+ */
+size_t br_rsa_i31_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len);
+
+/**
+ * \brief RSA decryption (OAEP) with the "i31" engine.
+ *
+ * \see br_rsa_oaep_decrypt
+ *
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param sk RSA private key.
+ * \param data input/output buffer.
+ * \param len encrypted/decrypted message length.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i31_oaep_decrypt(
+ const br_hash_class *dig, const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len);
+
+/**
+ * \brief RSA encryption (OAEP) with the "i32" engine.
+ *
+ * \see br_rsa_oaep_encrypt
+ *
+ * \param rnd source of random bytes.
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param pk RSA public key.
+ * \param dst destination buffer.
+ * \param dst_max_len destination buffer length (maximum encrypted data size).
+ * \param src message to encrypt.
+ * \param src_len source message length (in bytes).
+ * \return encrypted message length (in bytes), or 0 on error.
+ */
+size_t br_rsa_i32_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len);
+
+/**
+ * \brief RSA decryption (OAEP) with the "i32" engine.
+ *
+ * \see br_rsa_oaep_decrypt
+ *
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param sk RSA private key.
+ * \param data input/output buffer.
+ * \param len encrypted/decrypted message length.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i32_oaep_decrypt(
+ const br_hash_class *dig, const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len);
+
+/**
+ * \brief RSA encryption (OAEP) with the "i62" engine.
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_oaep_encrypt
+ *
+ * \param rnd source of random bytes.
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param pk RSA public key.
+ * \param dst destination buffer.
+ * \param dst_max_len destination buffer length (maximum encrypted data size).
+ * \param src message to encrypt.
+ * \param src_len source message length (in bytes).
+ * \return encrypted message length (in bytes), or 0 on error.
+ */
+size_t br_rsa_i62_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len);
+
+/**
+ * \brief RSA decryption (OAEP) with the "i62" engine.
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_oaep_decrypt
+ *
+ * \param dig hash function to use with MGF1.
+ * \param label label value (may be `NULL` if `label_len` is zero).
+ * \param label_len label length, in bytes.
+ * \param sk RSA private key.
+ * \param data input/output buffer.
+ * \param len encrypted/decrypted message length.
+ * \return 1 on success, 0 on error.
+ */
+uint32_t br_rsa_i62_oaep_decrypt(
+ const br_hash_class *dig, const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len);
+
+/**
+ * \brief Get buffer size to hold RSA private key elements.
+ *
+ * This macro returns the length (in bytes) of the buffer needed to
+ * receive the elements of a RSA private key, as generated by one of
+ * the `br_rsa_*_keygen()` functions. If the provided size is a constant
+ * expression, then the whole macro evaluates to a constant expression.
+ *
+ * \param size target key size (modulus size, in bits)
+ * \return the length of the private key buffer, in bytes.
+ */
+#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4))
+
+/**
+ * \brief Get buffer size to hold RSA public key elements.
+ *
+ * This macro returns the length (in bytes) of the buffer needed to
+ * receive the elements of a RSA public key, as generated by one of
+ * the `br_rsa_*_keygen()` functions. If the provided size is a constant
+ * expression, then the whole macro evaluates to a constant expression.
+ *
+ * \param size target key size (modulus size, in bits)
+ * \return the length of the public key buffer, in bytes.
+ */
+#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3))
+
+/**
+ * \brief Type for RSA key pair generator implementation.
+ *
+ * This function generates a new RSA key pair whose modulus has bit
+ * length `size` bits. The private key elements are written in the
+ * `kbuf_priv` buffer, and pointer values and length fields to these
+ * elements are populated in the provided private key structure `sk`.
+ * Similarly, the public key elements are written in `kbuf_pub`, with
+ * pointers and lengths set in `pk`.
+ *
+ * If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the
+ * private key is set.
+ *
+ * If `pubexp` is not zero, then its value will be used as public
+ * exponent. Valid RSA public exponent values are odd integers
+ * greater than 1. If `pubexp` is zero, then the public exponent will
+ * have value 3.
+ *
+ * The provided PRNG (`rng_ctx`) must have already been initialized
+ * and seeded.
+ *
+ * Returned value is 1 on success, 0 on error. An error is reported
+ * if the requested range is outside of the supported key sizes, or
+ * if an invalid non-zero public exponent value is provided. Supported
+ * range starts at 512 bits, and up to an implementation-defined
+ * maximum (by default 4096 bits). Note that key sizes up to 768 bits
+ * have been broken in practice, and sizes lower than 2048 bits are
+ * usually considered to be weak and should not be used.
+ *
+ * \param rng_ctx source PRNG context (already initialized)
+ * \param sk RSA private key structure (destination)
+ * \param kbuf_priv buffer for private key elements
+ * \param pk RSA public key structure (destination), or `NULL`
+ * \param kbuf_pub buffer for public key elements, or `NULL`
+ * \param size target RSA modulus size (in bits)
+ * \param pubexp public exponent to use, or zero
+ * \return 1 on success, 0 on error (invalid parameters)
+ */
+typedef uint32_t (*br_rsa_keygen)(
+ const br_prng_class **rng_ctx,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp);
+
+/**
+ * \brief RSA key pair generation with the "i15" engine.
+ *
+ * \see br_rsa_keygen
+ *
+ * \param rng_ctx source PRNG context (already initialized)
+ * \param sk RSA private key structure (destination)
+ * \param kbuf_priv buffer for private key elements
+ * \param pk RSA public key structure (destination), or `NULL`
+ * \param kbuf_pub buffer for public key elements, or `NULL`
+ * \param size target RSA modulus size (in bits)
+ * \param pubexp public exponent to use, or zero
+ * \return 1 on success, 0 on error (invalid parameters)
+ */
+uint32_t br_rsa_i15_keygen(
+ const br_prng_class **rng_ctx,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp);
+
+/**
+ * \brief RSA key pair generation with the "i31" engine.
+ *
+ * \see br_rsa_keygen
+ *
+ * \param rng_ctx source PRNG context (already initialized)
+ * \param sk RSA private key structure (destination)
+ * \param kbuf_priv buffer for private key elements
+ * \param pk RSA public key structure (destination), or `NULL`
+ * \param kbuf_pub buffer for public key elements, or `NULL`
+ * \param size target RSA modulus size (in bits)
+ * \param pubexp public exponent to use, or zero
+ * \return 1 on success, 0 on error (invalid parameters)
+ */
+uint32_t br_rsa_i31_keygen(
+ const br_prng_class **rng_ctx,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp);
+
+/**
+ * \brief RSA key pair generation with the "i62" engine.
+ *
+ * This function is defined only on architecture that offer a 64x64->128
+ * opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer
+ * to that function.
+ *
+ * \see br_rsa_keygen
+ *
+ * \param rng_ctx source PRNG context (already initialized)
+ * \param sk RSA private key structure (destination)
+ * \param kbuf_priv buffer for private key elements
+ * \param pk RSA public key structure (destination), or `NULL`
+ * \param kbuf_pub buffer for public key elements, or `NULL`
+ * \param size target RSA modulus size (in bits)
+ * \param pubexp public exponent to use, or zero
+ * \return 1 on success, 0 on error (invalid parameters)
+ */
+uint32_t br_rsa_i62_keygen(
+ const br_prng_class **rng_ctx,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp);
+
+/**
+ * \brief Get the RSA "i62" implementation (key pair generation),
+ * if available.
+ *
+ * \return the implementation, or 0.
+ */
+br_rsa_keygen br_rsa_i62_keygen_get(void);
+
+/**
+ * \brief Get "default" RSA implementation (key pair generation).
+ *
+ * This returns the preferred implementation of RSA (key pair generation)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_keygen br_rsa_keygen_get_default(void);
+
+/**
+ * \brief Type for a modulus computing function.
+ *
+ * Such a function computes the public modulus from the private key. The
+ * encoded modulus (unsigned big-endian) is written on `n`, and the size
+ * (in bytes) is returned. If `n` is `NULL`, then the size is returned but
+ * the modulus itself is not computed.
+ *
+ * If the key size exceeds an internal limit, 0 is returned.
+ *
+ * \param n destination buffer (or `NULL`).
+ * \param sk RSA private key.
+ * \return the modulus length (in bytes), or 0.
+ */
+typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk);
+
+/**
+ * \brief Recompute RSA modulus ("i15" engine).
+ *
+ * \see br_rsa_compute_modulus
+ *
+ * \param n destination buffer (or `NULL`).
+ * \param sk RSA private key.
+ * \return the modulus length (in bytes), or 0.
+ */
+size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk);
+
+/**
+ * \brief Recompute RSA modulus ("i31" engine).
+ *
+ * \see br_rsa_compute_modulus
+ *
+ * \param n destination buffer (or `NULL`).
+ * \param sk RSA private key.
+ * \return the modulus length (in bytes), or 0.
+ */
+size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk);
+
+/**
+ * \brief Get "default" RSA implementation (recompute modulus).
+ *
+ * This returns the preferred implementation of RSA (recompute modulus)
+ * on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void);
+
+/**
+ * \brief Type for a public exponent computing function.
+ *
+ * Such a function recomputes the public exponent from the private key.
+ * 0 is returned if any of the following occurs:
+ *
+ * - Either `p` or `q` is not equal to 3 modulo 4.
+ *
+ * - The public exponent does not fit on 32 bits.
+ *
+ * - An internal limit is exceeded.
+ *
+ * - The private key is invalid in some way.
+ *
+ * For all private keys produced by the key generator functions
+ * (`br_rsa_keygen` type), this function succeeds and returns the true
+ * public exponent. The public exponent is always an odd integer greater
+ * than 1.
+ *
+ * \return the public exponent, or 0.
+ */
+typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk);
+
+/**
+ * \brief Recompute RSA public exponent ("i15" engine).
+ *
+ * \see br_rsa_compute_pubexp
+ *
+ * \return the public exponent, or 0.
+ */
+uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk);
+
+/**
+ * \brief Recompute RSA public exponent ("i31" engine).
+ *
+ * \see br_rsa_compute_pubexp
+ *
+ * \return the public exponent, or 0.
+ */
+uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk);
+
+/**
+ * \brief Get "default" RSA implementation (recompute public exponent).
+ *
+ * This returns the preferred implementation of RSA (recompute public
+ * exponent) on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void);
+
+/**
+ * \brief Type for a private exponent computing function.
+ *
+ * An RSA private key (`br_rsa_private_key`) contains two reduced
+ * private exponents, which are sufficient to perform private key
+ * operations. However, standard encoding formats for RSA private keys
+ * require also a copy of the complete private exponent (non-reduced),
+ * which this function recomputes.
+ *
+ * This function suceeds if all the following conditions hold:
+ *
+ * - Both private factors `p` and `q` are equal to 3 modulo 4.
+ *
+ * - The provided public exponent `pubexp` is correct, and, in particular,
+ * is odd, relatively prime to `p-1` and `q-1`, and greater than 1.
+ *
+ * - No internal storage limit is exceeded.
+ *
+ * For all private keys produced by the key generator functions
+ * (`br_rsa_keygen` type), this function succeeds. Note that the API
+ * restricts the public exponent to a maximum size of 32 bits.
+ *
+ * The encoded private exponent is written in `d` (unsigned big-endian
+ * convention), and the length (in bytes) is returned. If `d` is `NULL`,
+ * then the exponent is not written anywhere, but the length is still
+ * returned. On error, 0 is returned.
+ *
+ * Not all error conditions are detected when `d` is `NULL`; therefore, the
+ * returned value shall be checked also when actually producing the value.
+ *
+ * \param d destination buffer (or `NULL`).
+ * \param sk RSA private key.
+ * \param pubexp the public exponent.
+ * \return the private exponent length (in bytes), or 0.
+ */
+typedef size_t (*br_rsa_compute_privexp)(void *d,
+ const br_rsa_private_key *sk, uint32_t pubexp);
+
+/**
+ * \brief Recompute RSA private exponent ("i15" engine).
+ *
+ * \see br_rsa_compute_privexp
+ *
+ * \param d destination buffer (or `NULL`).
+ * \param sk RSA private key.
+ * \param pubexp the public exponent.
+ * \return the private exponent length (in bytes), or 0.
+ */
+size_t br_rsa_i15_compute_privexp(void *d,
+ const br_rsa_private_key *sk, uint32_t pubexp);
+
+/**
+ * \brief Recompute RSA private exponent ("i31" engine).
+ *
+ * \see br_rsa_compute_privexp
+ *
+ * \param d destination buffer (or `NULL`).
+ * \param sk RSA private key.
+ * \param pubexp the public exponent.
+ * \return the private exponent length (in bytes), or 0.
+ */
+size_t br_rsa_i31_compute_privexp(void *d,
+ const br_rsa_private_key *sk, uint32_t pubexp);
+
+/**
+ * \brief Get "default" RSA implementation (recompute private exponent).
+ *
+ * This returns the preferred implementation of RSA (recompute private
+ * exponent) on the current system.
+ *
+ * \return the default implementation.
+ */
+br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Property changes on: stable/12/contrib/bearssl/inc/bearssl_rsa.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_ssl.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_ssl.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_ssl.h (revision 346145)
@@ -0,0 +1,4296 @@
+/*
+ * 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_SSL_H__
+#define BR_BEARSSL_SSL_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "bearssl_block.h"
+#include "bearssl_hash.h"
+#include "bearssl_hmac.h"
+#include "bearssl_prf.h"
+#include "bearssl_rand.h"
+#include "bearssl_x509.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file bearssl_ssl.h
+ *
+ * # SSL
+ *
+ * For an overview of the SSL/TLS API, see [the BearSSL Web
+ * site](https://www.bearssl.org/api1.html).
+ *
+ * The `BR_TLS_*` constants correspond to the standard cipher suites and
+ * their values in the [IANA
+ * registry](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4).
+ *
+ * The `BR_ALERT_*` constants are for standard TLS alert messages. When
+ * a fatal alert message is sent of received, then the SSL engine context
+ * status is set to the sum of that alert value (an integer in the 0..255
+ * range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert,
+ * `BR_ERR_RECV_FATAL_ALERT` for a received alert).
+ */
+
+/** \brief Optimal input buffer size. */
+#define BR_SSL_BUFSIZE_INPUT (16384 + 325)
+
+/** \brief Optimal output buffer size. */
+#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85)
+
+/** \brief Optimal buffer size for monodirectional engine
+ (shared input/output buffer). */
+#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT
+
+/** \brief Optimal buffer size for bidirectional engine
+ (single buffer split into two separate input/output buffers). */
+#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT)
+
+/*
+ * Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1
+ * and TLS 1.2). Note that though there is a constant for SSL 3.0, that
+ * protocol version is not actually supported.
+ */
+
+/** \brief Protocol version: SSL 3.0 (unsupported). */
+#define BR_SSL30 0x0300
+/** \brief Protocol version: TLS 1.0. */
+#define BR_TLS10 0x0301
+/** \brief Protocol version: TLS 1.1. */
+#define BR_TLS11 0x0302
+/** \brief Protocol version: TLS 1.2. */
+#define BR_TLS12 0x0303
+
+/*
+ * Error constants. They are used to report the reason why a context has
+ * been marked as failed.
+ *
+ * Implementation note: SSL-level error codes should be in the 1..31
+ * range. The 32..63 range is for certificate decoding and validation
+ * errors. Received fatal alerts imply an error code in the 256..511 range.
+ */
+
+/** \brief SSL status: no error so far (0). */
+#define BR_ERR_OK 0
+
+/** \brief SSL status: caller-provided parameter is incorrect. */
+#define BR_ERR_BAD_PARAM 1
+
+/** \brief SSL status: operation requested by the caller cannot be applied
+ with the current context state (e.g. reading data while outgoing data
+ is waiting to be sent). */
+#define BR_ERR_BAD_STATE 2
+
+/** \brief SSL status: incoming protocol or record version is unsupported. */
+#define BR_ERR_UNSUPPORTED_VERSION 3
+
+/** \brief SSL status: incoming record version does not match the expected
+ version. */
+#define BR_ERR_BAD_VERSION 4
+
+/** \brief SSL status: incoming record length is invalid. */
+#define BR_ERR_BAD_LENGTH 5
+
+/** \brief SSL status: incoming record is too large to be processed, or
+ buffer is too small for the handshake message to send. */
+#define BR_ERR_TOO_LARGE 6
+
+/** \brief SSL status: decryption found an invalid padding, or the record
+ MAC is not correct. */
+#define BR_ERR_BAD_MAC 7
+
+/** \brief SSL status: no initial entropy was provided, and none can be
+ obtained from the OS. */
+#define BR_ERR_NO_RANDOM 8
+
+/** \brief SSL status: incoming record type is unknown. */
+#define BR_ERR_UNKNOWN_TYPE 9
+
+/** \brief SSL status: incoming record or message has wrong type with
+ regards to the current engine state. */
+#define BR_ERR_UNEXPECTED 10
+
+/** \brief SSL status: ChangeCipherSpec message from the peer has invalid
+ contents. */
+#define BR_ERR_BAD_CCS 12
+
+/** \brief SSL status: alert message from the peer has invalid contents
+ (odd length). */
+#define BR_ERR_BAD_ALERT 13
+
+/** \brief SSL status: incoming handshake message decoding failed. */
+#define BR_ERR_BAD_HANDSHAKE 14
+
+/** \brief SSL status: ServerHello contains a session ID which is larger
+ than 32 bytes. */
+#define BR_ERR_OVERSIZED_ID 15
+
+/** \brief SSL status: server wants to use a cipher suite that we did
+ not claim to support. This is also reported if we tried to advertise
+ a cipher suite that we do not support. */
+#define BR_ERR_BAD_CIPHER_SUITE 16
+
+/** \brief SSL status: server wants to use a compression that we did not
+ claim to support. */
+#define BR_ERR_BAD_COMPRESSION 17
+
+/** \brief SSL status: server's max fragment length does not match
+ client's. */
+#define BR_ERR_BAD_FRAGLEN 18
+
+/** \brief SSL status: secure renegotiation failed. */
+#define BR_ERR_BAD_SECRENEG 19
+
+/** \brief SSL status: server sent an extension type that we did not
+ announce, or used the same extension type several times in a single
+ ServerHello. */
+#define BR_ERR_EXTRA_EXTENSION 20
+
+/** \brief SSL status: invalid Server Name Indication contents (when
+ used by the server, this extension shall be empty). */
+#define BR_ERR_BAD_SNI 21
+
+/** \brief SSL status: invalid ServerHelloDone from the server (length
+ is not 0). */
+#define BR_ERR_BAD_HELLO_DONE 22
+
+/** \brief SSL status: internal limit exceeded (e.g. server's public key
+ is too large). */
+#define BR_ERR_LIMIT_EXCEEDED 23
+
+/** \brief SSL status: Finished message from peer does not match the
+ expected value. */
+#define BR_ERR_BAD_FINISHED 24
+
+/** \brief SSL status: session resumption attempt with distinct version
+ or cipher suite. */
+#define BR_ERR_RESUME_MISMATCH 25
+
+/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve,
+ signature algorithm, hash function). */
+#define BR_ERR_INVALID_ALGORITHM 26
+
+/** \brief SSL status: invalid signature (on ServerKeyExchange from
+ server, or in CertificateVerify from client). */
+#define BR_ERR_BAD_SIGNATURE 27
+
+/** \brief SSL status: peer's public key does not have the proper type
+ or is not allowed for requested operation. */
+#define BR_ERR_WRONG_KEY_USAGE 28
+
+/** \brief SSL status: client did not send a certificate upon request,
+ or the client certificate could not be validated. */
+#define BR_ERR_NO_CLIENT_AUTH 29
+
+/** \brief SSL status: I/O error or premature close on underlying
+ transport stream. This error code is set only by the simplified
+ I/O API ("br_sslio_*"). */
+#define BR_ERR_IO 31
+
+/** \brief SSL status: base value for a received fatal alert.
+
+ When a fatal alert is received from the peer, the alert value
+ is added to this constant. */
+#define BR_ERR_RECV_FATAL_ALERT 256
+
+/** \brief SSL status: base value for a sent fatal alert.
+
+ When a fatal alert is sent to the peer, the alert value is added
+ to this constant. */
+#define BR_ERR_SEND_FATAL_ALERT 512
+
+/* ===================================================================== */
+
+/**
+ * \brief Decryption engine for SSL.
+ *
+ * When processing incoming records, the SSL engine will use a decryption
+ * engine that uses a specific context structure, and has a set of
+ * methods (a vtable) that follows this template.
+ *
+ * The decryption engine is responsible for applying decryption, verifying
+ * MAC, and keeping track of the record sequence number.
+ */
+typedef struct br_sslrec_in_class_ br_sslrec_in_class;
+struct br_sslrec_in_class_ {
+ /**
+ * \brief Context size (in bytes).
+ */
+ size_t context_size;
+
+ /**
+ * \brief Test validity of the incoming record length.
+ *
+ * This function returns 1 if the announced length for an
+ * incoming record is valid, 0 otherwise,
+ *
+ * \param ctx decryption engine context.
+ * \param record_len incoming record length.
+ * \return 1 of a valid length, 0 otherwise.
+ */
+ int (*check_length)(const br_sslrec_in_class *const *ctx,
+ size_t record_len);
+
+ /**
+ * \brief Decrypt the incoming record.
+ *
+ * This function may assume that the record length is valid
+ * (it has been previously tested with `check_length()`).
+ * Decryption is done in place; `*len` is updated with the
+ * cleartext length, and the address of the first plaintext
+ * byte is returned. If the record is correct but empty, then
+ * `*len` is set to 0 and a non-`NULL` pointer is returned.
+ *
+ * On decryption/MAC error, `NULL` is returned.
+ *
+ * \param ctx decryption engine context.
+ * \param record_type record type (23 for application data, etc).
+ * \param version record version.
+ * \param payload address of encrypted payload.
+ * \param len pointer to payload length (updated).
+ * \return pointer to plaintext, or `NULL` on error.
+ */
+ unsigned char *(*decrypt)(const br_sslrec_in_class **ctx,
+ int record_type, unsigned version,
+ void *payload, size_t *len);
+};
+
+/**
+ * \brief Encryption engine for SSL.
+ *
+ * When building outgoing records, the SSL engine will use an encryption
+ * engine that uses a specific context structure, and has a set of
+ * methods (a vtable) that follows this template.
+ *
+ * The encryption engine is responsible for applying encryption and MAC,
+ * and keeping track of the record sequence number.
+ */
+typedef struct br_sslrec_out_class_ br_sslrec_out_class;
+struct br_sslrec_out_class_ {
+ /**
+ * \brief Context size (in bytes).
+ */
+ size_t context_size;
+
+ /**
+ * \brief Compute maximum plaintext sizes and offsets.
+ *
+ * When this function is called, the `*start` and `*end`
+ * values contain offsets designating the free area in the
+ * outgoing buffer for plaintext data; that free area is
+ * preceded by a 5-byte space which will receive the record
+ * header.
+ *
+ * The `max_plaintext()` function is responsible for adjusting
+ * both `*start` and `*end` to make room for any record-specific
+ * header, MAC, padding, and possible split.
+ *
+ * \param ctx encryption engine context.
+ * \param start pointer to start of plaintext offset (updated).
+ * \param end pointer to start of plaintext offset (updated).
+ */
+ void (*max_plaintext)(const br_sslrec_out_class *const *ctx,
+ size_t *start, size_t *end);
+
+ /**
+ * \brief Perform record encryption.
+ *
+ * This function encrypts the record. The plaintext address and
+ * length are provided. Returned value is the start of the
+ * encrypted record (or sequence of records, if a split was
+ * performed), _including_ the 5-byte header, and `*len` is
+ * adjusted to the total size of the record(s), there again
+ * including the header(s).
+ *
+ * \param ctx decryption engine context.
+ * \param record_type record type (23 for application data, etc).
+ * \param version record version.
+ * \param plaintext address of plaintext.
+ * \param len pointer to plaintext length (updated).
+ * \return pointer to start of built record.
+ */
+ unsigned char *(*encrypt)(const br_sslrec_out_class **ctx,
+ int record_type, unsigned version,
+ void *plaintext, size_t *len);
+};
+
+/**
+ * \brief Context for a no-encryption engine.
+ *
+ * The no-encryption engine processes outgoing records during the initial
+ * handshake, before encryption is applied.
+ */
+typedef struct {
+ /** \brief No-encryption engine vtable. */
+ const br_sslrec_out_class *vtable;
+} br_sslrec_out_clear_context;
+
+/** \brief Static, constant vtable for the no-encryption engine. */
+extern const br_sslrec_out_class br_sslrec_out_clear_vtable;
+
+/* ===================================================================== */
+
+/**
+ * \brief Record decryption engine class, for CBC mode.
+ *
+ * This class type extends the decryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for CBC processing: block cipher implementation, block cipher key,
+ * HMAC parameters (hash function, key, MAC length), and IV. If the
+ * IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
+ */
+typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class;
+struct br_sslrec_in_cbc_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_in_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param bc_impl block cipher implementation (CBC decryption).
+ * \param bc_key block cipher key.
+ * \param bc_key_len block cipher key length (in bytes).
+ * \param dig_impl hash function for HMAC.
+ * \param mac_key HMAC key.
+ * \param mac_key_len HMAC key length (in bytes).
+ * \param mac_out_len HMAC output length (in bytes).
+ * \param iv initial IV (or `NULL`).
+ */
+ void (*init)(const br_sslrec_in_cbc_class **ctx,
+ const br_block_cbcdec_class *bc_impl,
+ const void *bc_key, size_t bc_key_len,
+ const br_hash_class *dig_impl,
+ const void *mac_key, size_t mac_key_len, size_t mac_out_len,
+ const void *iv);
+};
+
+/**
+ * \brief Record encryption engine class, for CBC mode.
+ *
+ * This class type extends the encryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for CBC processing: block cipher implementation, block cipher key,
+ * HMAC parameters (hash function, key, MAC length), and IV. If the
+ * IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
+ */
+typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class;
+struct br_sslrec_out_cbc_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_out_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param bc_impl block cipher implementation (CBC encryption).
+ * \param bc_key block cipher key.
+ * \param bc_key_len block cipher key length (in bytes).
+ * \param dig_impl hash function for HMAC.
+ * \param mac_key HMAC key.
+ * \param mac_key_len HMAC key length (in bytes).
+ * \param mac_out_len HMAC output length (in bytes).
+ * \param iv initial IV (or `NULL`).
+ */
+ void (*init)(const br_sslrec_out_cbc_class **ctx,
+ const br_block_cbcenc_class *bc_impl,
+ const void *bc_key, size_t bc_key_len,
+ const br_hash_class *dig_impl,
+ const void *mac_key, size_t mac_key_len, size_t mac_out_len,
+ const void *iv);
+};
+
+/**
+ * \brief Context structure for decrypting incoming records with
+ * CBC + HMAC.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ const br_sslrec_in_cbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t seq;
+ union {
+ const br_block_cbcdec_class *vtable;
+ br_aes_gen_cbcdec_keys aes;
+ br_des_gen_cbcdec_keys des;
+ } bc;
+ br_hmac_key_context mac;
+ size_t mac_len;
+ unsigned char iv[16];
+ int explicit_IV;
+#endif
+} br_sslrec_in_cbc_context;
+
+/**
+ * \brief Static, constant vtable for record decryption with CBC.
+ */
+extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable;
+
+/**
+ * \brief Context structure for encrypting outgoing records with
+ * CBC + HMAC.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ const br_sslrec_out_cbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t seq;
+ union {
+ const br_block_cbcenc_class *vtable;
+ br_aes_gen_cbcenc_keys aes;
+ br_des_gen_cbcenc_keys des;
+ } bc;
+ br_hmac_key_context mac;
+ size_t mac_len;
+ unsigned char iv[16];
+ int explicit_IV;
+#endif
+} br_sslrec_out_cbc_context;
+
+/**
+ * \brief Static, constant vtable for record encryption with CBC.
+ */
+extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable;
+
+/* ===================================================================== */
+
+/**
+ * \brief Record decryption engine class, for GCM mode.
+ *
+ * This class type extends the decryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for GCM processing: block cipher implementation, block cipher key,
+ * GHASH implementation, and 4-byte IV.
+ */
+typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class;
+struct br_sslrec_in_gcm_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_in_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param bc_impl block cipher implementation (CTR).
+ * \param key block cipher key.
+ * \param key_len block cipher key length (in bytes).
+ * \param gh_impl GHASH implementation.
+ * \param iv static IV (4 bytes).
+ */
+ void (*init)(const br_sslrec_in_gcm_class **ctx,
+ const br_block_ctr_class *bc_impl,
+ const void *key, size_t key_len,
+ br_ghash gh_impl,
+ const void *iv);
+};
+
+/**
+ * \brief Record encryption engine class, for GCM mode.
+ *
+ * This class type extends the encryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for GCM processing: block cipher implementation, block cipher key,
+ * GHASH implementation, and 4-byte IV.
+ */
+typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class;
+struct br_sslrec_out_gcm_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_out_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param bc_impl block cipher implementation (CTR).
+ * \param key block cipher key.
+ * \param key_len block cipher key length (in bytes).
+ * \param gh_impl GHASH implementation.
+ * \param iv static IV (4 bytes).
+ */
+ void (*init)(const br_sslrec_out_gcm_class **ctx,
+ const br_block_ctr_class *bc_impl,
+ const void *key, size_t key_len,
+ br_ghash gh_impl,
+ const void *iv);
+};
+
+/**
+ * \brief Context structure for processing records with GCM.
+ *
+ * The same context structure is used for encrypting and decrypting.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ union {
+ const void *gen;
+ const br_sslrec_in_gcm_class *in;
+ const br_sslrec_out_gcm_class *out;
+ } vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t seq;
+ union {
+ const br_block_ctr_class *vtable;
+ br_aes_gen_ctr_keys aes;
+ } bc;
+ br_ghash gh;
+ unsigned char iv[4];
+ unsigned char h[16];
+#endif
+} br_sslrec_gcm_context;
+
+/**
+ * \brief Static, constant vtable for record decryption with GCM.
+ */
+extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable;
+
+/**
+ * \brief Static, constant vtable for record encryption with GCM.
+ */
+extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable;
+
+/* ===================================================================== */
+
+/**
+ * \brief Record decryption engine class, for ChaCha20+Poly1305.
+ *
+ * This class type extends the decryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for ChaCha20+Poly1305 processing: ChaCha20 implementation,
+ * Poly1305 implementation, key, and 12-byte IV.
+ */
+typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class;
+struct br_sslrec_in_chapol_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_in_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param ichacha ChaCha20 implementation.
+ * \param ipoly Poly1305 implementation.
+ * \param key secret key (32 bytes).
+ * \param iv static IV (12 bytes).
+ */
+ void (*init)(const br_sslrec_in_chapol_class **ctx,
+ br_chacha20_run ichacha,
+ br_poly1305_run ipoly,
+ const void *key, const void *iv);
+};
+
+/**
+ * \brief Record encryption engine class, for ChaCha20+Poly1305.
+ *
+ * This class type extends the encryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for ChaCha20+Poly1305 processing: ChaCha20 implementation,
+ * Poly1305 implementation, key, and 12-byte IV.
+ */
+typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class;
+struct br_sslrec_out_chapol_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_out_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param ichacha ChaCha20 implementation.
+ * \param ipoly Poly1305 implementation.
+ * \param key secret key (32 bytes).
+ * \param iv static IV (12 bytes).
+ */
+ void (*init)(const br_sslrec_out_chapol_class **ctx,
+ br_chacha20_run ichacha,
+ br_poly1305_run ipoly,
+ const void *key, const void *iv);
+};
+
+/**
+ * \brief Context structure for processing records with ChaCha20+Poly1305.
+ *
+ * The same context structure is used for encrypting and decrypting.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ union {
+ const void *gen;
+ const br_sslrec_in_chapol_class *in;
+ const br_sslrec_out_chapol_class *out;
+ } vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t seq;
+ unsigned char key[32];
+ unsigned char iv[12];
+ br_chacha20_run ichacha;
+ br_poly1305_run ipoly;
+#endif
+} br_sslrec_chapol_context;
+
+/**
+ * \brief Static, constant vtable for record decryption with ChaCha20+Poly1305.
+ */
+extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable;
+
+/**
+ * \brief Static, constant vtable for record encryption with ChaCha20+Poly1305.
+ */
+extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable;
+
+/* ===================================================================== */
+
+/**
+ * \brief Record decryption engine class, for CCM mode.
+ *
+ * This class type extends the decryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for CCM processing: block cipher implementation, block cipher key,
+ * and 4-byte IV.
+ */
+typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class;
+struct br_sslrec_in_ccm_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_in_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param bc_impl block cipher implementation (CTR+CBC).
+ * \param key block cipher key.
+ * \param key_len block cipher key length (in bytes).
+ * \param iv static IV (4 bytes).
+ * \param tag_len tag length (in bytes)
+ */
+ void (*init)(const br_sslrec_in_ccm_class **ctx,
+ const br_block_ctrcbc_class *bc_impl,
+ const void *key, size_t key_len,
+ const void *iv, size_t tag_len);
+};
+
+/**
+ * \brief Record encryption engine class, for CCM mode.
+ *
+ * This class type extends the encryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for CCM processing: block cipher implementation, block cipher key,
+ * and 4-byte IV.
+ */
+typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class;
+struct br_sslrec_out_ccm_class_ {
+ /**
+ * \brief Superclass, as first vtable field.
+ */
+ br_sslrec_out_class inner;
+
+ /**
+ * \brief Engine initialisation method.
+ *
+ * This method sets the vtable field in the context.
+ *
+ * \param ctx context to initialise.
+ * \param bc_impl block cipher implementation (CTR+CBC).
+ * \param key block cipher key.
+ * \param key_len block cipher key length (in bytes).
+ * \param iv static IV (4 bytes).
+ * \param tag_len tag length (in bytes)
+ */
+ void (*init)(const br_sslrec_out_ccm_class **ctx,
+ const br_block_ctrcbc_class *bc_impl,
+ const void *key, size_t key_len,
+ const void *iv, size_t tag_len);
+};
+
+/**
+ * \brief Context structure for processing records with CCM.
+ *
+ * The same context structure is used for encrypting and decrypting.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ union {
+ const void *gen;
+ const br_sslrec_in_ccm_class *in;
+ const br_sslrec_out_ccm_class *out;
+ } vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ uint64_t seq;
+ union {
+ const br_block_ctrcbc_class *vtable;
+ br_aes_gen_ctrcbc_keys aes;
+ } bc;
+ unsigned char iv[4];
+ size_t tag_len;
+#endif
+} br_sslrec_ccm_context;
+
+/**
+ * \brief Static, constant vtable for record decryption with CCM.
+ */
+extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable;
+
+/**
+ * \brief Static, constant vtable for record encryption with CCM.
+ */
+extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable;
+
+/* ===================================================================== */
+
+/**
+ * \brief Type for session parameters, to be saved for session resumption.
+ */
+typedef struct {
+ /** \brief Session ID buffer. */
+ unsigned char session_id[32];
+ /** \brief Session ID length (in bytes, at most 32). */
+ unsigned char session_id_len;
+ /** \brief Protocol version. */
+ uint16_t version;
+ /** \brief Cipher suite. */
+ uint16_t cipher_suite;
+ /** \brief Master secret. */
+ unsigned char master_secret[48];
+} br_ssl_session_parameters;
+
+#ifndef BR_DOXYGEN_IGNORE
+/*
+ * Maximum number of cipher suites supported by a client or server.
+ */
+#define BR_MAX_CIPHER_SUITES 48
+#endif
+
+/**
+ * \brief Context structure for SSL engine.
+ *
+ * This strucuture is common to the client and server; both the client
+ * context (`br_ssl_client_context`) and the server context
+ * (`br_ssl_server_context`) include a `br_ssl_engine_context` as their
+ * first field.
+ *
+ * The engine context manages records, including alerts, closures, and
+ * transitions to new encryption/MAC algorithms. Processing of handshake
+ * records is delegated to externally provided code. This structure
+ * should not be used directly.
+ *
+ * Structure contents are opaque and shall not be accessed directly.
+ */
+typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
+ /*
+ * The error code. When non-zero, then the state is "failed" and
+ * no I/O may occur until reset.
+ */
+ int err;
+
+ /*
+ * Configured I/O buffers. They are either disjoint, or identical.
+ */
+ unsigned char *ibuf, *obuf;
+ size_t ibuf_len, obuf_len;
+
+ /*
+ * Maximum fragment length applies to outgoing records; incoming
+ * records can be processed as long as they fit in the input
+ * buffer. It is guaranteed that incoming records at least as big
+ * as max_frag_len can be processed.
+ */
+ uint16_t max_frag_len;
+ unsigned char log_max_frag_len;
+ unsigned char peer_log_max_frag_len;
+
+ /*
+ * Buffering management registers.
+ */
+ size_t ixa, ixb, ixc;
+ size_t oxa, oxb, oxc;
+ unsigned char iomode;
+ unsigned char incrypt;
+
+ /*
+ * Shutdown flag: when set to non-zero, incoming record bytes
+ * will not be accepted anymore. This is used after a close_notify
+ * has been received: afterwards, the engine no longer claims that
+ * it could receive bytes from the transport medium.
+ */
+ unsigned char shutdown_recv;
+
+ /*
+ * 'record_type_in' is set to the incoming record type when the
+ * record header has been received.
+ * 'record_type_out' is used to make the next outgoing record
+ * header when it is ready to go.
+ */
+ unsigned char record_type_in, record_type_out;
+
+ /*
+ * When a record is received, its version is extracted:
+ * -- if 'version_in' is 0, then it is set to the received version;
+ * -- otherwise, if the received version is not identical to
+ * the 'version_in' contents, then a failure is reported.
+ *
+ * This implements the SSL requirement that all records shall
+ * use the negotiated protocol version, once decided (in the
+ * ServerHello). It is up to the handshake handler to adjust this
+ * field when necessary.
+ */
+ uint16_t version_in;
+
+ /*
+ * 'version_out' is used when the next outgoing record is ready
+ * to go.
+ */
+ uint16_t version_out;
+
+ /*
+ * Record handler contexts.
+ */
+ union {
+ const br_sslrec_in_class *vtable;
+ br_sslrec_in_cbc_context cbc;
+ br_sslrec_gcm_context gcm;
+ br_sslrec_chapol_context chapol;
+ br_sslrec_ccm_context ccm;
+ } in;
+ union {
+ const br_sslrec_out_class *vtable;
+ br_sslrec_out_clear_context clear;
+ br_sslrec_out_cbc_context cbc;
+ br_sslrec_gcm_context gcm;
+ br_sslrec_chapol_context chapol;
+ br_sslrec_ccm_context ccm;
+ } out;
+
+ /*
+ * The "application data" flag. Value:
+ * 0 handshake is in process, no application data acceptable
+ * 1 application data can be sent and received
+ * 2 closing, no application data can be sent, but some
+ * can still be received (and discarded)
+ */
+ unsigned char application_data;
+
+ /*
+ * Context RNG.
+ *
+ * rng_init_done is initially 0. It is set to 1 when the
+ * basic structure of the RNG is set, and 2 when some
+ * entropy has been pushed in. The value 2 marks the RNG
+ * as "properly seeded".
+ *
+ * rng_os_rand_done is initially 0. It is set to 1 when
+ * some seeding from the OS or hardware has been attempted.
+ */
+ br_hmac_drbg_context rng;
+ int rng_init_done;
+ int rng_os_rand_done;
+
+ /*
+ * Supported minimum and maximum versions, and cipher suites.
+ */
+ uint16_t version_min;
+ uint16_t version_max;
+ uint16_t suites_buf[BR_MAX_CIPHER_SUITES];
+ unsigned char suites_num;
+
+ /*
+ * For clients, the server name to send as a SNI extension. For
+ * servers, the name received in the SNI extension (if any).
+ */
+ char server_name[256];
+
+ /*
+ * "Security parameters". These are filled by the handshake
+ * handler, and used when switching encryption state.
+ */
+ unsigned char client_random[32];
+ unsigned char server_random[32];
+ br_ssl_session_parameters session;
+
+ /*
+ * ECDHE elements: curve and point from the peer. The server also
+ * uses that buffer for the point to send to the client.
+ */
+ unsigned char ecdhe_curve;
+ unsigned char ecdhe_point[133];
+ unsigned char ecdhe_point_len;
+
+ /*
+ * Secure renegotiation (RFC 5746): 'reneg' can be:
+ * 0 first handshake (server support is not known)
+ * 1 peer does not support secure renegotiation
+ * 2 peer supports secure renegotiation
+ *
+ * The saved_finished buffer contains the client and the
+ * server "Finished" values from the last handshake, in
+ * that order (12 bytes each).
+ */
+ unsigned char reneg;
+ unsigned char saved_finished[24];
+
+ /*
+ * Behavioural flags.
+ */
+ uint32_t flags;
+
+ /*
+ * Context variables for the handshake processor. The 'pad' must
+ * be large enough to accommodate an RSA-encrypted pre-master
+ * secret, or an RSA signature; since we want to support up to
+ * RSA-4096, this means at least 512 bytes. (Other pad usages
+ * require its length to be at least 256.)
+ */
+ struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+ } cpu;
+ uint32_t dp_stack[32];
+ uint32_t rp_stack[32];
+ unsigned char pad[512];
+ unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out;
+ size_t hlen_in, hlen_out;
+ void (*hsrun)(void *ctx);
+
+ /*
+ * The 'action' value communicates OOB information between the
+ * engine and the handshake processor.
+ *
+ * From the engine:
+ * 0 invocation triggered by I/O
+ * 1 invocation triggered by explicit close
+ * 2 invocation triggered by explicit renegotiation
+ */
+ unsigned char action;
+
+ /*
+ * State for alert messages. Value is either 0, or the value of
+ * the alert level byte (level is either 1 for warning, or 2 for
+ * fatal; we convert all other values to 'fatal').
+ */
+ unsigned char alert;
+
+ /*
+ * Closure flags. This flag is set when a close_notify has been
+ * received from the peer.
+ */
+ unsigned char close_received;
+
+ /*
+ * Multi-hasher for the handshake messages. The handshake handler
+ * is responsible for resetting it when appropriate.
+ */
+ br_multihash_context mhash;
+
+ /*
+ * Pointer to the X.509 engine. The engine is supposed to be
+ * already initialized. It is used to validate the peer's
+ * certificate.
+ */
+ const br_x509_class **x509ctx;
+
+ /*
+ * Certificate chain to send. This is used by both client and
+ * server, when they send their respective Certificate messages.
+ * If chain_len is 0, then chain may be NULL.
+ */
+ const br_x509_certificate *chain;
+ size_t chain_len;
+ const unsigned char *cert_cur;
+ size_t cert_len;
+
+ /*
+ * List of supported protocol names (ALPN extension). If unset,
+ * (number of names is 0), then:
+ * - the client sends no ALPN extension;
+ * - the server ignores any incoming ALPN extension.
+ *
+ * Otherwise:
+ * - the client sends an ALPN extension with all the names;
+ * - the server selects the first protocol in its list that
+ * the client also supports, or fails (fatal alert 120)
+ * if the client sends an ALPN extension and there is no
+ * match.
+ *
+ * The 'selected_protocol' field contains 1+n if the matching
+ * name has index n in the list (the value is 0 if no match was
+ * performed, e.g. the peer did not send an ALPN extension).
+ */
+ const char **protocol_names;
+ uint16_t protocol_names_num;
+ uint16_t selected_protocol;
+
+ /*
+ * Pointers to implementations; left to NULL for unsupported
+ * functions. For the raw hash functions, implementations are
+ * referenced from the multihasher (mhash field).
+ */
+ br_tls_prf_impl prf10;
+ br_tls_prf_impl prf_sha256;
+ br_tls_prf_impl prf_sha384;
+ const br_block_cbcenc_class *iaes_cbcenc;
+ const br_block_cbcdec_class *iaes_cbcdec;
+ const br_block_ctr_class *iaes_ctr;
+ const br_block_ctrcbc_class *iaes_ctrcbc;
+ const br_block_cbcenc_class *ides_cbcenc;
+ const br_block_cbcdec_class *ides_cbcdec;
+ br_ghash ighash;
+ br_chacha20_run ichacha;
+ br_poly1305_run ipoly;
+ const br_sslrec_in_cbc_class *icbc_in;
+ const br_sslrec_out_cbc_class *icbc_out;
+ const br_sslrec_in_gcm_class *igcm_in;
+ const br_sslrec_out_gcm_class *igcm_out;
+ const br_sslrec_in_chapol_class *ichapol_in;
+ const br_sslrec_out_chapol_class *ichapol_out;
+ const br_sslrec_in_ccm_class *iccm_in;
+ const br_sslrec_out_ccm_class *iccm_out;
+ const br_ec_impl *iec;
+ br_rsa_pkcs1_vrfy irsavrfy;
+ br_ecdsa_vrfy iecdsa;
+#endif
+} br_ssl_engine_context;
+
+/**
+ * \brief Get currently defined engine behavioural flags.
+ *
+ * \param cc SSL engine context.
+ * \return the flags.
+ */
+static inline uint32_t
+br_ssl_engine_get_flags(br_ssl_engine_context *cc)
+{
+ return cc->flags;
+}
+
+/**
+ * \brief Set all engine behavioural flags.
+ *
+ * \param cc SSL engine context.
+ * \param flags new value for all flags.
+ */
+static inline void
+br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags)
+{
+ cc->flags = flags;
+}
+
+/**
+ * \brief Set some engine behavioural flags.
+ *
+ * The flags set in the `flags` parameter are set in the context; other
+ * flags are untouched.
+ *
+ * \param cc SSL engine context.
+ * \param flags additional set flags.
+ */
+static inline void
+br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags)
+{
+ cc->flags |= flags;
+}
+
+/**
+ * \brief Clear some engine behavioural flags.
+ *
+ * The flags set in the `flags` parameter are cleared from the context; other
+ * flags are untouched.
+ *
+ * \param cc SSL engine context.
+ * \param flags flags to remove.
+ */
+static inline void
+br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
+{
+ cc->flags &= ~flags;
+}
+
+/**
+ * \brief Behavioural flag: enforce server preferences.
+ *
+ * If this flag is set, then the server will enforce its own cipher suite
+ * preference order; otherwise, it follows the client preferences.
+ */
+#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0)
+
+/**
+ * \brief Behavioural flag: disable renegotiation.
+ *
+ * If this flag is set, then renegotiations are rejected unconditionally:
+ * they won't be honoured if asked for programmatically, and requests from
+ * the peer are rejected.
+ */
+#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1)
+
+/**
+ * \brief Behavioural flag: tolerate lack of client authentication.
+ *
+ * If this flag is set in a server and the server requests a client
+ * certificate, but the authentication fails (the client does not send
+ * a certificate, or the client's certificate chain cannot be validated),
+ * then the connection keeps on. Without this flag, a failed client
+ * authentication terminates the connection.
+ *
+ * Notes:
+ *
+ * - If the client's certificate can be validated and its public key is
+ * supported, then a wrong signature value terminates the connection
+ * regardless of that flag.
+ *
+ * - If using full-static ECDH, then a failure to validate the client's
+ * certificate prevents the handshake from succeeding.
+ */
+#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2)
+
+/**
+ * \brief Behavioural flag: fail on application protocol mismatch.
+ *
+ * The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301))
+ * allows the client to send a list of application protocol names, and
+ * the server to select one. A mismatch is one of the following occurrences:
+ *
+ * - On the client: the client sends a list of names, the server
+ * responds with a protocol name which is _not_ part of the list of
+ * names sent by the client.
+ *
+ * - On the server: the client sends a list of names, and the server
+ * is also configured with a list of names, but there is no common
+ * protocol name between the two lists.
+ *
+ * Normal behaviour in case of mismatch is to report no matching name
+ * (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on.
+ * If the flag is set, then a mismatch implies a protocol failure (if
+ * the mismatch is detected by the server, it will send a fatal alert).
+ *
+ * Note: even with this flag, `br_ssl_engine_get_selected_protocol()`
+ * may still return `NULL` if the client or the server does not send an
+ * ALPN extension at all.
+ */
+#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3)
+
+/**
+ * \brief Set the minimum and maximum supported protocol versions.
+ *
+ * The two provided versions MUST be supported by the implementation
+ * (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower
+ * than `version_min`.
+ *
+ * \param cc SSL engine context.
+ * \param version_min minimum supported TLS version.
+ * \param version_max maximum supported TLS version.
+ */
+static inline void
+br_ssl_engine_set_versions(br_ssl_engine_context *cc,
+ unsigned version_min, unsigned version_max)
+{
+ cc->version_min = version_min;
+ cc->version_max = version_max;
+}
+
+/**
+ * \brief Set the list of cipher suites advertised by this context.
+ *
+ * The provided array is copied into the context. It is the caller
+ * responsibility to ensure that all provided suites will be supported
+ * by the context. The engine context has enough room to receive _all_
+ * suites supported by the implementation. The provided array MUST NOT
+ * contain duplicates.
+ *
+ * If the engine is for a client, the "signaling" pseudo-cipher suite
+ * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the
+ * calling application is performing a voluntary downgrade (voluntary
+ * downgrades are not recommended, but if such a downgrade is done, then
+ * adding the fallback pseudo-suite is a good idea).
+ *
+ * \param cc SSL engine context.
+ * \param suites cipher suites.
+ * \param suites_num number of cipher suites.
+ */
+void br_ssl_engine_set_suites(br_ssl_engine_context *cc,
+ const uint16_t *suites, size_t suites_num);
+
+/**
+ * \brief Set the X.509 engine.
+ *
+ * The caller shall ensure that the X.509 engine is properly initialised.
+ *
+ * \param cc SSL engine context.
+ * \param x509ctx X.509 certificate validation context.
+ */
+static inline void
+br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
+{
+ cc->x509ctx = x509ctx;
+}
+
+/**
+ * \brief Set the supported protocol names.
+ *
+ * Protocol names are part of the ALPN extension ([RFC
+ * 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a
+ * character string, containing no more than 255 characters (256 with the
+ * terminating zero). When names are set, then:
+ *
+ * - The client will send an ALPN extension, containing the names. If
+ * the server responds with an ALPN extension, the client will verify
+ * that the response contains one of its name, and report that name
+ * through `br_ssl_engine_get_selected_protocol()`.
+ *
+ * - The server will parse incoming ALPN extension (from clients), and
+ * try to find a common protocol; if none is found, the connection
+ * is aborted with a fatal alert. On match, a response ALPN extension
+ * is sent, and name is reported through
+ * `br_ssl_engine_get_selected_protocol()`.
+ *
+ * The provided array is linked in, and must remain valid while the
+ * connection is live.
+ *
+ * Names MUST NOT be empty. Names MUST NOT be longer than 255 characters
+ * (excluding the terminating 0).
+ *
+ * \param ctx SSL engine context.
+ * \param names list of protocol names (zero-terminated).
+ * \param num number of protocol names (MUST be 1 or more).
+ */
+static inline void
+br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx,
+ const char **names, size_t num)
+{
+ ctx->protocol_names = names;
+ ctx->protocol_names_num = num;
+}
+
+/**
+ * \brief Get the selected protocol.
+ *
+ * If this context was initialised with a non-empty list of protocol
+ * names, and both client and server sent ALPN extensions during the
+ * handshake, and a common name was found, then that name is returned.
+ * Otherwise, `NULL` is returned.
+ *
+ * The returned pointer is one of the pointers provided to the context
+ * with `br_ssl_engine_set_protocol_names()`.
+ *
+ * \return the selected protocol, or `NULL`.
+ */
+static inline const char *
+br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx)
+{
+ unsigned k;
+
+ k = ctx->selected_protocol;
+ return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1];
+}
+
+/**
+ * \brief Set a hash function implementation (by ID).
+ *
+ * Hash functions set with this call will be used for SSL/TLS specific
+ * usages, not X.509 certificate validation. Only "standard" hash functions
+ * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl`
+ * is `NULL`, then the hash function support is removed, not added.
+ *
+ * \param ctx SSL engine context.
+ * \param id hash function identifier.
+ * \param impl hash function implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
+ int id, const br_hash_class *impl)
+{
+ br_multihash_setimpl(&ctx->mhash, id, impl);
+}
+
+/**
+ * \brief Get a hash function implementation (by ID).
+ *
+ * This function retrieves a hash function implementation which was
+ * set with `br_ssl_engine_set_hash()`.
+ *
+ * \param ctx SSL engine context.
+ * \param id hash function identifier.
+ * \return the hash function implementation (or `NULL`).
+ */
+static inline const br_hash_class *
+br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id)
+{
+ return br_multihash_getimpl(&ctx->mhash, id);
+}
+
+/**
+ * \brief Set the PRF implementation (for TLS 1.0 and 1.1).
+ *
+ * This function sets (or removes, if `impl` is `NULL`) the implementation
+ * for the PRF used in TLS 1.0 and 1.1.
+ *
+ * \param cc SSL engine context.
+ * \param impl PRF implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
+{
+ cc->prf10 = impl;
+}
+
+/**
+ * \brief Set the PRF implementation with SHA-256 (for TLS 1.2).
+ *
+ * This function sets (or removes, if `impl` is `NULL`) the implementation
+ * for the SHA-256 variant of the PRF used in TLS 1.2.
+ *
+ * \param cc SSL engine context.
+ * \param impl PRF implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl)
+{
+ cc->prf_sha256 = impl;
+}
+
+/**
+ * \brief Set the PRF implementation with SHA-384 (for TLS 1.2).
+ *
+ * This function sets (or removes, if `impl` is `NULL`) the implementation
+ * for the SHA-384 variant of the PRF used in TLS 1.2.
+ *
+ * \param cc SSL engine context.
+ * \param impl PRF implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl)
+{
+ cc->prf_sha384 = impl;
+}
+
+/**
+ * \brief Set the AES/CBC implementations.
+ *
+ * \param cc SSL engine context.
+ * \param impl_enc AES/CBC encryption implementation (or `NULL`).
+ * \param impl_dec AES/CBC decryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
+ const br_block_cbcenc_class *impl_enc,
+ const br_block_cbcdec_class *impl_dec)
+{
+ cc->iaes_cbcenc = impl_enc;
+ cc->iaes_cbcdec = impl_dec;
+}
+
+/**
+ * \brief Set the "default" AES/CBC implementations.
+ *
+ * This function configures in the engine the AES implementations that
+ * should provide best runtime performance on the local system, while
+ * still being safe (in particular, constant-time). It also sets the
+ * handlers for CBC records.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc);
+
+/**
+ * \brief Set the AES/CTR implementation.
+ *
+ * \param cc SSL engine context.
+ * \param impl AES/CTR encryption/decryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
+ const br_block_ctr_class *impl)
+{
+ cc->iaes_ctr = impl;
+}
+
+/**
+ * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH).
+ *
+ * This function configures in the engine the AES/CTR and GHASH
+ * implementation that should provide best runtime performance on the local
+ * system, while still being safe (in particular, constant-time). It also
+ * sets the handlers for GCM records.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc);
+
+/**
+ * \brief Set the DES/CBC implementations.
+ *
+ * \param cc SSL engine context.
+ * \param impl_enc DES/CBC encryption implementation (or `NULL`).
+ * \param impl_dec DES/CBC decryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
+ const br_block_cbcenc_class *impl_enc,
+ const br_block_cbcdec_class *impl_dec)
+{
+ cc->ides_cbcenc = impl_enc;
+ cc->ides_cbcdec = impl_dec;
+}
+
+/**
+ * \brief Set the "default" DES/CBC implementations.
+ *
+ * This function configures in the engine the DES implementations that
+ * should provide best runtime performance on the local system, while
+ * still being safe (in particular, constant-time). It also sets the
+ * handlers for CBC records.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc);
+
+/**
+ * \brief Set the GHASH implementation (used in GCM mode).
+ *
+ * \param cc SSL engine context.
+ * \param impl GHASH implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
+{
+ cc->ighash = impl;
+}
+
+/**
+ * \brief Set the ChaCha20 implementation.
+ *
+ * \param cc SSL engine context.
+ * \param ichacha ChaCha20 implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_chacha20(br_ssl_engine_context *cc,
+ br_chacha20_run ichacha)
+{
+ cc->ichacha = ichacha;
+}
+
+/**
+ * \brief Set the Poly1305 implementation.
+ *
+ * \param cc SSL engine context.
+ * \param ipoly Poly1305 implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_poly1305(br_ssl_engine_context *cc,
+ br_poly1305_run ipoly)
+{
+ cc->ipoly = ipoly;
+}
+
+/**
+ * \brief Set the "default" ChaCha20 and Poly1305 implementations.
+ *
+ * This function configures in the engine the ChaCha20 and Poly1305
+ * implementations that should provide best runtime performance on the
+ * local system, while still being safe (in particular, constant-time).
+ * It also sets the handlers for ChaCha20+Poly1305 records.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc);
+
+/**
+ * \brief Set the AES/CTR+CBC implementation.
+ *
+ * \param cc SSL engine context.
+ * \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc,
+ const br_block_ctrcbc_class *impl)
+{
+ cc->iaes_ctrcbc = impl;
+}
+
+/**
+ * \brief Set the "default" implementations for AES/CCM.
+ *
+ * This function configures in the engine the AES/CTR+CBC
+ * implementation that should provide best runtime performance on the local
+ * system, while still being safe (in particular, constant-time). It also
+ * sets the handlers for CCM records.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc);
+
+/**
+ * \brief Set the record encryption and decryption engines for CBC + HMAC.
+ *
+ * \param cc SSL engine context.
+ * \param impl_in record CBC decryption implementation (or `NULL`).
+ * \param impl_out record CBC encryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
+ const br_sslrec_in_cbc_class *impl_in,
+ const br_sslrec_out_cbc_class *impl_out)
+{
+ cc->icbc_in = impl_in;
+ cc->icbc_out = impl_out;
+}
+
+/**
+ * \brief Set the record encryption and decryption engines for GCM.
+ *
+ * \param cc SSL engine context.
+ * \param impl_in record GCM decryption implementation (or `NULL`).
+ * \param impl_out record GCM encryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
+ const br_sslrec_in_gcm_class *impl_in,
+ const br_sslrec_out_gcm_class *impl_out)
+{
+ cc->igcm_in = impl_in;
+ cc->igcm_out = impl_out;
+}
+
+/**
+ * \brief Set the record encryption and decryption engines for CCM.
+ *
+ * \param cc SSL engine context.
+ * \param impl_in record CCM decryption implementation (or `NULL`).
+ * \param impl_out record CCM encryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_ccm(br_ssl_engine_context *cc,
+ const br_sslrec_in_ccm_class *impl_in,
+ const br_sslrec_out_ccm_class *impl_out)
+{
+ cc->iccm_in = impl_in;
+ cc->iccm_out = impl_out;
+}
+
+/**
+ * \brief Set the record encryption and decryption engines for
+ * ChaCha20+Poly1305.
+ *
+ * \param cc SSL engine context.
+ * \param impl_in record ChaCha20 decryption implementation (or `NULL`).
+ * \param impl_out record ChaCha20 encryption implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_chapol(br_ssl_engine_context *cc,
+ const br_sslrec_in_chapol_class *impl_in,
+ const br_sslrec_out_chapol_class *impl_out)
+{
+ cc->ichapol_in = impl_in;
+ cc->ichapol_out = impl_out;
+}
+
+/**
+ * \brief Set the EC implementation.
+ *
+ * The elliptic curve implementation will be used for ECDH and ECDHE
+ * cipher suites, and for ECDSA support.
+ *
+ * \param cc SSL engine context.
+ * \param iec EC implementation (or `NULL`).
+ */
+static inline void
+br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)
+{
+ cc->iec = iec;
+}
+
+/**
+ * \brief Set the "default" EC implementation.
+ *
+ * This function sets the elliptic curve implementation for ECDH and
+ * ECDHE cipher suites, and for ECDSA support. It selects the fastest
+ * implementation on the current system.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc);
+
+/**
+ * \brief Get the EC implementation configured in the provided engine.
+ *
+ * \param cc SSL engine context.
+ * \return the EC implementation.
+ */
+static inline const br_ec_impl *
+br_ssl_engine_get_ec(br_ssl_engine_context *cc)
+{
+ return cc->iec;
+}
+
+/**
+ * \brief Set the RSA signature verification implementation.
+ *
+ * On the client, this is used to verify the server's signature on its
+ * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server,
+ * this is used to verify the client's CertificateVerify message (if a
+ * client certificate is requested, and that certificate contains a RSA key).
+ *
+ * \param cc SSL engine context.
+ * \param irsavrfy RSA signature verification implementation.
+ */
+static inline void
+br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
+{
+ cc->irsavrfy = irsavrfy;
+}
+
+/**
+ * \brief Set the "default" RSA implementation (signature verification).
+ *
+ * This function sets the RSA implementation (signature verification)
+ * to the fastest implementation available on the current platform.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc);
+
+/**
+ * \brief Get the RSA implementation (signature verification) configured
+ * in the provided engine.
+ *
+ * \param cc SSL engine context.
+ * \return the RSA signature verification implementation.
+ */
+static inline br_rsa_pkcs1_vrfy
+br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc)
+{
+ return cc->irsavrfy;
+}
+
+/*
+ * \brief Set the ECDSA implementation (signature verification).
+ *
+ * On the client, this is used to verify the server's signature on its
+ * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server,
+ * this is used to verify the client's CertificateVerify message (if a
+ * client certificate is requested, that certificate contains an EC key,
+ * and full-static ECDH is not used).
+ *
+ * The ECDSA implementation will use the EC core implementation configured
+ * in the engine context.
+ *
+ * \param cc client context.
+ * \param iecdsa ECDSA verification implementation.
+ */
+static inline void
+br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa)
+{
+ cc->iecdsa = iecdsa;
+}
+
+/**
+ * \brief Set the "default" ECDSA implementation (signature verification).
+ *
+ * This function sets the ECDSA implementation (signature verification)
+ * to the fastest implementation available on the current platform. This
+ * call also sets the elliptic curve implementation itself, there again
+ * to the fastest EC implementation available.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc);
+
+/**
+ * \brief Get the ECDSA implementation (signature verification) configured
+ * in the provided engine.
+ *
+ * \param cc SSL engine context.
+ * \return the ECDSA signature verification implementation.
+ */
+static inline br_ecdsa_vrfy
+br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc)
+{
+ return cc->iecdsa;
+}
+
+/**
+ * \brief Set the I/O buffer for the SSL engine.
+ *
+ * Once this call has been made, `br_ssl_client_reset()` or
+ * `br_ssl_server_reset()` MUST be called before using the context.
+ *
+ * The provided buffer will be used as long as the engine context is
+ * used. The caller is responsible for keeping it available.
+ *
+ * If `bidi` is 0, then the engine will operate in half-duplex mode
+ * (it won't be able to send data while there is unprocessed incoming
+ * data in the buffer, and it won't be able to receive data while there
+ * is unsent data in the buffer). The optimal buffer size in half-duplex
+ * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra
+ * bytes are ignored. If the buffer is smaller, then this limits the
+ * capacity of the engine to support all allowed record sizes.
+ *
+ * If `bidi` is 1, then the engine will split the buffer into two
+ * parts, for separate handling of outgoing and incoming data. This
+ * enables full-duplex processing, but requires more RAM. The optimal
+ * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the
+ * buffer is larger, then extra bytes are ignored. If the buffer is
+ * smaller, then the split will favour the incoming part, so that
+ * interoperability is maximised.
+ *
+ * \param cc SSL engine context
+ * \param iobuf I/O buffer.
+ * \param iobuf_len I/O buffer length (in bytes).
+ * \param bidi non-zero for full-duplex mode.
+ */
+void br_ssl_engine_set_buffer(br_ssl_engine_context *cc,
+ void *iobuf, size_t iobuf_len, int bidi);
+
+/**
+ * \brief Set the I/O buffers for the SSL engine.
+ *
+ * Once this call has been made, `br_ssl_client_reset()` or
+ * `br_ssl_server_reset()` MUST be called before using the context.
+ *
+ * This function is similar to `br_ssl_engine_set_buffer()`, except
+ * that it enforces full-duplex mode, and the two I/O buffers are
+ * provided as separate chunks.
+ *
+ * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT`
+ * evaluate to the optimal (maximum) sizes for the input and output
+ * buffer, respectively.
+ *
+ * \param cc SSL engine context
+ * \param ibuf input buffer.
+ * \param ibuf_len input buffer length (in bytes).
+ * \param obuf output buffer.
+ * \param obuf_len output buffer length (in bytes).
+ */
+void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc,
+ void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len);
+
+/**
+ * \brief Inject some "initial entropy" in the context.
+ *
+ * This entropy will be added to what can be obtained from the
+ * underlying operating system, if that OS is supported.
+ *
+ * This function may be called several times; all injected entropy chunks
+ * are cumulatively mixed.
+ *
+ * If entropy gathering from the OS is supported and compiled in, then this
+ * step is optional. Otherwise, it is mandatory to inject randomness, and
+ * the caller MUST take care to push (as one or several successive calls)
+ * enough entropy to achieve cryptographic resistance (at least 80 bits,
+ * preferably 128 or more). The engine will report an error if no entropy
+ * was provided and none can be obtained from the OS.
+ *
+ * Take care that this function cannot assess the cryptographic quality of
+ * the provided bytes.
+ *
+ * In all generality, "entropy" must here be considered to mean "that
+ * which the attacker cannot predict". If your OS/architecture does not
+ * have a suitable source of randomness, then you can make do with the
+ * combination of a large enough secret value (possibly a copy of an
+ * asymmetric private key that you also store on the system) AND a
+ * non-repeating value (e.g. current time, provided that the local clock
+ * cannot be reset or altered by the attacker).
+ *
+ * \param cc SSL engine context.
+ * \param data extra entropy to inject.
+ * \param len length of the extra data (in bytes).
+ */
+void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc,
+ const void *data, size_t len);
+
+/**
+ * \brief Get the "server name" in this engine.
+ *
+ * For clients, this is the name provided with `br_ssl_client_reset()`;
+ * for servers, this is the name received from the client as part of the
+ * ClientHello message. If there is no such name (e.g. the client did
+ * not send an SNI extension) then the returned string is empty
+ * (returned pointer points to a byte of value 0).
+ *
+ * The returned pointer refers to a buffer inside the context, which may
+ * be overwritten as part of normal SSL activity (even within the same
+ * connection, if a renegotiation occurs).
+ *
+ * \param cc SSL engine context.
+ * \return the server name (possibly empty).
+ */
+static inline const char *
+br_ssl_engine_get_server_name(const br_ssl_engine_context *cc)
+{
+ return cc->server_name;
+}
+
+/**
+ * \brief Get the protocol version.
+ *
+ * This function returns the protocol version that is used by the
+ * engine. That value is set after sending (for a server) or receiving
+ * (for a client) the ServerHello message.
+ *
+ * \param cc SSL engine context.
+ * \return the protocol version.
+ */
+static inline unsigned
+br_ssl_engine_get_version(const br_ssl_engine_context *cc)
+{
+ return cc->session.version;
+}
+
+/**
+ * \brief Get a copy of the session parameters.
+ *
+ * The session parameters are filled during the handshake, so this
+ * function shall not be called before completion of the handshake.
+ * The initial handshake is completed when the context first allows
+ * application data to be injected.
+ *
+ * This function copies the current session parameters into the provided
+ * structure. Beware that the session parameters include the master
+ * secret, which is sensitive data, to handle with great care.
+ *
+ * \param cc SSL engine context.
+ * \param pp destination structure for the session parameters.
+ */
+static inline void
+br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc,
+ br_ssl_session_parameters *pp)
+{
+ memcpy(pp, &cc->session, sizeof *pp);
+}
+
+/**
+ * \brief Set the session parameters to the provided values.
+ *
+ * This function is meant to be used in the client, before doing a new
+ * handshake; a session resumption will be attempted with these
+ * parameters. In the server, this function has no effect.
+ *
+ * \param cc SSL engine context.
+ * \param pp source structure for the session parameters.
+ */
+static inline void
+br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc,
+ const br_ssl_session_parameters *pp)
+{
+ memcpy(&cc->session, pp, sizeof *pp);
+}
+
+/**
+ * \brief Get identifier for the curve used for key exchange.
+ *
+ * If the cipher suite uses ECDHE, then this function returns the
+ * identifier for the curve used for transient parameters. This is
+ * defined during the course of the handshake, when the ServerKeyExchange
+ * is sent (on the server) or received (on the client). If the
+ * cipher suite does not use ECDHE (e.g. static ECDH, or RSA key
+ * exchange), then this value is indeterminate.
+ *
+ * @param cc SSL engine context.
+ * @return the ECDHE curve identifier.
+ */
+static inline int
+br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc)
+{
+ return cc->ecdhe_curve;
+}
+
+/**
+ * \brief Get the current engine state.
+ *
+ * An SSL engine (client or server) has, at any time, a state which is
+ * the combination of zero, one or more of these flags:
+ *
+ * - `BR_SSL_CLOSED`
+ *
+ * Engine is finished, no more I/O (until next reset).
+ *
+ * - `BR_SSL_SENDREC`
+ *
+ * Engine has some bytes to send to the peer.
+ *
+ * - `BR_SSL_RECVREC`
+ *
+ * Engine expects some bytes from the peer.
+ *
+ * - `BR_SSL_SENDAPP`
+ *
+ * Engine may receive application data to send (or flush).
+ *
+ * - `BR_SSL_RECVAPP`
+ *
+ * Engine has obtained some application data from the peer,
+ * that should be read by the caller.
+ *
+ * If no flag at all is set (state value is 0), then the engine is not
+ * fully initialised yet.
+ *
+ * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag
+ * is set. To distinguish between a normal closure and an error, use
+ * `br_ssl_engine_last_error()`.
+ *
+ * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually
+ * exclusive: the input buffer, at any point, either accumulates
+ * plaintext data, or contains an assembled record that is being sent.
+ * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive.
+ * This may change in a future library version.
+ *
+ * \param cc SSL engine context.
+ * \return the current engine state.
+ */
+unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc);
+
+/** \brief SSL engine state: closed or failed. */
+#define BR_SSL_CLOSED 0x0001
+/** \brief SSL engine state: record data is ready to be sent to the peer. */
+#define BR_SSL_SENDREC 0x0002
+/** \brief SSL engine state: engine may receive records from the peer. */
+#define BR_SSL_RECVREC 0x0004
+/** \brief SSL engine state: engine may accept application data to send. */
+#define BR_SSL_SENDAPP 0x0008
+/** \brief SSL engine state: engine has received application data. */
+#define BR_SSL_RECVAPP 0x0010
+
+/**
+ * \brief Get the engine error indicator.
+ *
+ * The error indicator is `BR_ERR_OK` (0) if no error was encountered
+ * since the last call to `br_ssl_client_reset()` or
+ * `br_ssl_server_reset()`. Other status values are "sticky": they
+ * remain set, and prevent all I/O activity, until cleared. Only the
+ * reset calls clear the error indicator.
+ *
+ * \param cc SSL engine context.
+ * \return 0, or a non-zero error code.
+ */
+static inline int
+br_ssl_engine_last_error(const br_ssl_engine_context *cc)
+{
+ return cc->err;
+}
+
+/*
+ * There are four I/O operations, each identified by a symbolic name:
+ *
+ * sendapp inject application data in the engine
+ * recvapp retrieving application data from the engine
+ * sendrec sending records on the transport medium
+ * recvrec receiving records from the transport medium
+ *
+ * Terminology works thus: in a layered model where the SSL engine sits
+ * between the application and the network, "send" designates operations
+ * where bytes flow from application to network, and "recv" for the
+ * reverse operation. Application data (the plaintext that is to be
+ * conveyed through SSL) is "app", while encrypted records are "rec".
+ * Note that from the SSL engine point of view, "sendapp" and "recvrec"
+ * designate bytes that enter the engine ("inject" operation), while
+ * "recvapp" and "sendrec" designate bytes that exit the engine
+ * ("extract" operation).
+ *
+ * For the operation 'xxx', two functions are defined:
+ *
+ * br_ssl_engine_xxx_buf
+ * Returns a pointer and length to the buffer to use for that
+ * operation. '*len' is set to the number of bytes that may be read
+ * from the buffer (extract operation) or written to the buffer
+ * (inject operation). If no byte may be exchanged for that operation
+ * at that point, then '*len' is set to zero, and NULL is returned.
+ * The engine state is unmodified by this call.
+ *
+ * br_ssl_engine_xxx_ack
+ * Informs the engine that 'len' bytes have been read from the buffer
+ * (extract operation) or written to the buffer (inject operation).
+ * The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed
+ * that which was obtained from a preceding br_ssl_engine_xxx_buf()
+ * call.
+ */
+
+/**
+ * \brief Get buffer for application data to send.
+ *
+ * If the engine is ready to accept application data to send to the
+ * peer, then this call returns a pointer to the buffer where such
+ * data shall be written, and its length is written in `*len`.
+ * Otherwise, `*len` is set to 0 and `NULL` is returned.
+ *
+ * \param cc SSL engine context.
+ * \param len receives the application data output buffer length, or 0.
+ * \return the application data output buffer, or `NULL`.
+ */
+unsigned char *br_ssl_engine_sendapp_buf(
+ const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Inform the engine of some new application data.
+ *
+ * After writing `len` bytes in the buffer returned by
+ * `br_ssl_engine_sendapp_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_sendapp_buf()` call.
+ *
+ * \param cc SSL engine context.
+ * \param len number of bytes pushed (not zero).
+ */
+void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len);
+
+/**
+ * \brief Get buffer for received application data.
+ *
+ * If the engine has received application data from the peer, hen this
+ * call returns a pointer to the buffer from where such data shall be
+ * read, and its length is written in `*len`. Otherwise, `*len` is set
+ * to 0 and `NULL` is returned.
+ *
+ * \param cc SSL engine context.
+ * \param len receives the application data input buffer length, or 0.
+ * \return the application data input buffer, or `NULL`.
+ */
+unsigned char *br_ssl_engine_recvapp_buf(
+ const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Acknowledge some received application data.
+ *
+ * After reading `len` bytes from the buffer returned by
+ * `br_ssl_engine_recvapp_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_recvapp_buf()` call.
+ *
+ * \param cc SSL engine context.
+ * \param len number of bytes read (not zero).
+ */
+void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len);
+
+/**
+ * \brief Get buffer for record data to send.
+ *
+ * If the engine has prepared some records to send to the peer, then this
+ * call returns a pointer to the buffer from where such data shall be
+ * read, and its length is written in `*len`. Otherwise, `*len` is set
+ * to 0 and `NULL` is returned.
+ *
+ * \param cc SSL engine context.
+ * \param len receives the record data output buffer length, or 0.
+ * \return the record data output buffer, or `NULL`.
+ */
+unsigned char *br_ssl_engine_sendrec_buf(
+ const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Acknowledge some sent record data.
+ *
+ * After reading `len` bytes from the buffer returned by
+ * `br_ssl_engine_sendrec_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_sendrec_buf()` call.
+ *
+ * \param cc SSL engine context.
+ * \param len number of bytes read (not zero).
+ */
+void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len);
+
+/**
+ * \brief Get buffer for incoming records.
+ *
+ * If the engine is ready to accept records from the peer, then this
+ * call returns a pointer to the buffer where such data shall be
+ * written, and its length is written in `*len`. Otherwise, `*len` is
+ * set to 0 and `NULL` is returned.
+ *
+ * \param cc SSL engine context.
+ * \param len receives the record data input buffer length, or 0.
+ * \return the record data input buffer, or `NULL`.
+ */
+unsigned char *br_ssl_engine_recvrec_buf(
+ const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Inform the engine of some new record data.
+ *
+ * After writing `len` bytes in the buffer returned by
+ * `br_ssl_engine_recvrec_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_recvrec_buf()` call.
+ *
+ * \param cc SSL engine context.
+ * \param len number of bytes pushed (not zero).
+ */
+void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len);
+
+/**
+ * \brief Flush buffered application data.
+ *
+ * If some application data has been buffered in the engine, then wrap
+ * it into a record and mark it for sending. If no application data has
+ * been buffered but the engine would be ready to accept some, AND the
+ * `force` parameter is non-zero, then an empty record is assembled and
+ * marked for sending. In all other cases, this function does nothing.
+ *
+ * Empty records are technically legal, but not all existing SSL/TLS
+ * implementations support them. Empty records can be useful as a
+ * transparent "keep-alive" mechanism to maintain some low-level
+ * network activity.
+ *
+ * \param cc SSL engine context.
+ * \param force non-zero to force sending an empty record.
+ */
+void br_ssl_engine_flush(br_ssl_engine_context *cc, int force);
+
+/**
+ * \brief Initiate a closure.
+ *
+ * If, at that point, the context is open and in ready state, then a
+ * `close_notify` alert is assembled and marked for sending; this
+ * triggers the closure protocol. Otherwise, no such alert is assembled.
+ *
+ * \param cc SSL engine context.
+ */
+void br_ssl_engine_close(br_ssl_engine_context *cc);
+
+/**
+ * \brief Initiate a renegotiation.
+ *
+ * If the engine is failed or closed, or if the peer is known not to
+ * support secure renegotiation (RFC 5746), or if renegotiations have
+ * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there
+ * is buffered incoming application data, then this function returns 0
+ * and nothing else happens.
+ *
+ * Otherwise, this function returns 1, and a renegotiation attempt is
+ * triggered (if a handshake is already ongoing at that point, then
+ * no new handshake is triggered).
+ *
+ * \param cc SSL engine context.
+ * \return 1 on success, 0 on error.
+ */
+int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
+
+/**
+ * \brief Export key material from a connected SSL engine (RFC 5705).
+ *
+ * This calls compute a secret key of arbitrary length from the master
+ * secret of a connected SSL engine. If the provided context is not
+ * currently in "application data" state (initial handshake is not
+ * finished, another handshake is ongoing, or the connection failed or
+ * was closed), then this function returns 0. Otherwise, a secret key of
+ * length `len` bytes is computed and written in the buffer pointed to
+ * by `dst`, and 1 is returned.
+ *
+ * The computed key follows the specification described in RFC 5705.
+ * That RFC includes two key computations, with and without a "context
+ * value". If `context` is `NULL`, then the variant without context is
+ * used; otherwise, the `context_len` bytes located at the address
+ * pointed to by `context` are used in the computation. Note that it
+ * is possible to have a "with context" key with a context length of
+ * zero bytes, by setting `context` to a non-`NULL` value but
+ * `context_len` to 0.
+ *
+ * When context bytes are used, the context length MUST NOT exceed
+ * 65535 bytes.
+ *
+ * \param cc SSL engine context.
+ * \param dst destination buffer for exported key.
+ * \param len exported key length (in bytes).
+ * \param label disambiguation label.
+ * \param context context value (or `NULL`).
+ * \param context_len context length (in bytes).
+ * \return 1 on success, 0 on error.
+ */
+int br_ssl_key_export(br_ssl_engine_context *cc,
+ void *dst, size_t len, const char *label,
+ const void *context, size_t context_len);
+
+/*
+ * Pre-declaration for the SSL client context.
+ */
+typedef struct br_ssl_client_context_ br_ssl_client_context;
+
+/**
+ * \brief Type for the client certificate, if requested by the server.
+ */
+typedef struct {
+ /**
+ * \brief Authentication type.
+ *
+ * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA`
+ * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange).
+ */
+ int auth_type;
+
+ /**
+ * \brief Hash function for computing the CertificateVerify.
+ *
+ * This is the symbolic identifier for the hash function that
+ * will be used to produce the hash of handshake messages, to
+ * be signed into the CertificateVerify. For full static ECDH
+ * (client and server certificates are both EC in the same
+ * curve, and static ECDH is used), this value is set to -1.
+ *
+ * Take care that with TLS 1.0 and 1.1, that value MUST match
+ * the protocol requirements: value must be 0 (MD5+SHA-1) for
+ * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only
+ * TLS 1.2 allows for other hash functions.
+ */
+ int hash_id;
+
+ /**
+ * \brief Certificate chain to send to the server.
+ *
+ * This is an array of `br_x509_certificate` objects, each
+ * normally containing a DER-encoded certificate. The client
+ * code does not try to decode these elements. If there is no
+ * chain to send to the server, then this pointer shall be
+ * set to `NULL`.
+ */
+ const br_x509_certificate *chain;
+
+ /**
+ * \brief Certificate chain length (number of certificates).
+ *
+ * If there is no chain to send to the server, then this value
+ * shall be set to 0.
+ */
+ size_t chain_len;
+
+} br_ssl_client_certificate;
+
+/*
+ * Note: the constants below for signatures match the TLS constants.
+ */
+
+/** \brief Client authentication type: static ECDH. */
+#define BR_AUTH_ECDH 0
+/** \brief Client authentication type: RSA signature. */
+#define BR_AUTH_RSA 1
+/** \brief Client authentication type: ECDSA signature. */
+#define BR_AUTH_ECDSA 3
+
+/**
+ * \brief Class type for a certificate handler (client side).
+ *
+ * A certificate handler selects a client certificate chain to send to
+ * the server, upon explicit request from that server. It receives
+ * the list of trust anchor DN from the server, and supported types
+ * of certificates and signatures, and returns the chain to use. It
+ * is also invoked to perform the corresponding private key operation
+ * (a signature, or an ECDH computation).
+ *
+ * The SSL client engine will first push the trust anchor DN with
+ * `start_name_list()`, `start_name()`, `append_name()`, `end_name()`
+ * and `end_name_list()`. Then it will call `choose()`, to select the
+ * actual chain (and signature/hash algorithms). Finally, it will call
+ * either `do_sign()` or `do_keyx()`, depending on the algorithm choices.
+ */
+typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class;
+struct br_ssl_client_certificate_class_ {
+ /**
+ * \brief Context size (in bytes).
+ */
+ size_t context_size;
+
+ /**
+ * \brief Begin reception of a list of trust anchor names. This
+ * is called while parsing the incoming CertificateRequest.
+ *
+ * \param pctx certificate handler context.
+ */
+ void (*start_name_list)(const br_ssl_client_certificate_class **pctx);
+
+ /**
+ * \brief Begin reception of a new trust anchor name.
+ *
+ * The total encoded name length is provided; it is less than
+ * 65535 bytes.
+ *
+ * \param pctx certificate handler context.
+ * \param len encoded name length (in bytes).
+ */
+ void (*start_name)(const br_ssl_client_certificate_class **pctx,
+ size_t len);
+
+ /**
+ * \brief Receive some more bytes for the current trust anchor name.
+ *
+ * The provided reference (`data`) points to a transient buffer
+ * they may be reused as soon as this function returns. The chunk
+ * length (`len`) is never zero.
+ *
+ * \param pctx certificate handler context.
+ * \param data anchor name chunk.
+ * \param len anchor name chunk length (in bytes).
+ */
+ void (*append_name)(const br_ssl_client_certificate_class **pctx,
+ const unsigned char *data, size_t len);
+
+ /**
+ * \brief End current trust anchor name.
+ *
+ * This function is called when all the encoded anchor name data
+ * has been provided.
+ *
+ * \param pctx certificate handler context.
+ */
+ void (*end_name)(const br_ssl_client_certificate_class **pctx);
+
+ /**
+ * \brief End list of trust anchor names.
+ *
+ * This function is called when all the anchor names in the
+ * CertificateRequest message have been obtained.
+ *
+ * \param pctx certificate handler context.
+ */
+ void (*end_name_list)(const br_ssl_client_certificate_class **pctx);
+
+ /**
+ * \brief Select client certificate and algorithms.
+ *
+ * This callback function shall fill the provided `choices`
+ * structure with the selected algorithms and certificate chain.
+ * The `hash_id`, `chain` and `chain_len` fields must be set. If
+ * the client cannot or does not wish to send a certificate,
+ * then it shall set `chain` to `NULL` and `chain_len` to 0.
+ *
+ * The `auth_types` parameter describes the authentication types,
+ * signature algorithms and hash functions that are supported by
+ * both the client context and the server, and compatible with
+ * the current protocol version. This is a bit field with the
+ * following contents:
+ *
+ * - If RSA signatures with hash function x are supported, then
+ * bit x is set.
+ *
+ * - If ECDSA signatures with hash function x are supported,
+ * then bit 8+x is set.
+ *
+ * - If static ECDH is supported, with a RSA-signed certificate,
+ * then bit 16 is set.
+ *
+ * - If static ECDH is supported, with an ECDSA-signed certificate,
+ * then bit 17 is set.
+ *
+ * Notes:
+ *
+ * - When using TLS 1.0 or 1.1, the hash function for RSA
+ * signatures is always the special MD5+SHA-1 (id 0), and the
+ * hash function for ECDSA signatures is always SHA-1 (id 2).
+ *
+ * - When using TLS 1.2, the list of hash functions is trimmed
+ * down to include only hash functions that the client context
+ * can support. The actual server list can be obtained with
+ * `br_ssl_client_get_server_hashes()`; that list may be used
+ * to select the certificate chain to send to the server.
+ *
+ * \param pctx certificate handler context.
+ * \param cc SSL client context.
+ * \param auth_types supported authentication types and algorithms.
+ * \param choices destination structure for the policy choices.
+ */
+ void (*choose)(const br_ssl_client_certificate_class **pctx,
+ const br_ssl_client_context *cc, uint32_t auth_types,
+ br_ssl_client_certificate *choices);
+
+ /**
+ * \brief Perform key exchange (client part).
+ *
+ * This callback is invoked in case of a full static ECDH key
+ * exchange:
+ *
+ * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`;
+ *
+ * - the server requests a client certificate;
+ *
+ * - the client has, and sends, a client certificate that
+ * uses an EC key in the same curve as the server's key,
+ * and chooses static ECDH (the `hash_id` field in the choice
+ * structure was set to -1).
+ *
+ * In that situation, this callback is invoked to compute the
+ * client-side ECDH: the provided `data` (of length `*len` bytes)
+ * is the server's public key point (as decoded from its
+ * certificate), and the client shall multiply that point with
+ * its own private key, and write back the X coordinate of the
+ * resulting point in the same buffer, starting at offset 0.
+ * The `*len` value shall be modified to designate the actual
+ * length of the X coordinate.
+ *
+ * The callback must uphold the following:
+ *
+ * - If the input array does not have the proper length for
+ * an encoded curve point, then an error (0) shall be reported.
+ *
+ * - If the input array has the proper length, then processing
+ * MUST be constant-time, even if the data is not a valid
+ * encoded point.
+ *
+ * - This callback MUST check that the input point is valid.
+ *
+ * Returned value is 1 on success, 0 on error.
+ *
+ * \param pctx certificate handler context.
+ * \param data server public key point.
+ * \param len public key point length / X coordinate length.
+ * \return 1 on success, 0 on error.
+ */
+ uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx,
+ unsigned char *data, size_t *len);
+
+ /**
+ * \brief Perform a signature (client authentication).
+ *
+ * This callback is invoked when a client certificate was sent,
+ * and static ECDH is not used. It shall compute a signature,
+ * using the client's private key, over the provided hash value
+ * (which is the hash of all previous handshake messages).
+ *
+ * On input, the hash value to sign is in `data`, of size
+ * `hv_len`; the involved hash function is identified by
+ * `hash_id`. The signature shall be computed and written
+ * back into `data`; the total size of that buffer is `len`
+ * bytes.
+ *
+ * This callback shall verify that the signature length does not
+ * exceed `len` bytes, and abstain from writing the signature if
+ * it does not fit.
+ *
+ * For RSA signatures, the `hash_id` may be 0, in which case
+ * this is the special header-less signature specified in TLS 1.0
+ * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1
+ * v1.5 signatures shall be computed.
+ *
+ * For ECDSA signatures, the signature value shall use the ASN.1
+ * based encoding.
+ *
+ * Returned value is the signature length (in bytes), or 0 on error.
+ *
+ * \param pctx certificate handler context.
+ * \param hash_id hash function identifier.
+ * \param hv_len hash value length (in bytes).
+ * \param data input/output buffer (hash value, then signature).
+ * \param len total buffer length (in bytes).
+ * \return signature length (in bytes) on success, or 0 on error.
+ */
+ size_t (*do_sign)(const br_ssl_client_certificate_class **pctx,
+ int hash_id, size_t hv_len, unsigned char *data, size_t len);
+};
+
+/**
+ * \brief A single-chain RSA client certificate handler.
+ *
+ * This handler uses a single certificate chain, with a RSA
+ * signature. The list of trust anchor DN is ignored.
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ const br_ssl_client_certificate_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ const br_x509_certificate *chain;
+ size_t chain_len;
+ const br_rsa_private_key *sk;
+ br_rsa_pkcs1_sign irsasign;
+#endif
+} br_ssl_client_certificate_rsa_context;
+
+/**
+ * \brief A single-chain EC client certificate handler.
+ *
+ * This handler uses a single certificate chain, with a RSA
+ * signature. The list of trust anchor DN is ignored.
+ *
+ * This handler may support both static ECDH, and ECDSA signatures
+ * (either usage may be selectively disabled).
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ const br_ssl_client_certificate_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ const br_x509_certificate *chain;
+ size_t chain_len;
+ const br_ec_private_key *sk;
+ unsigned allowed_usages;
+ unsigned issuer_key_type;
+ const br_multihash_context *mhash;
+ const br_ec_impl *iec;
+ br_ecdsa_sign iecdsa;
+#endif
+} br_ssl_client_certificate_ec_context;
+
+/**
+ * \brief Context structure for a SSL client.
+ *
+ * The first field (called `eng`) is the SSL engine; all functions that
+ * work on a `br_ssl_engine_context` structure shall take as parameter
+ * a pointer to that field. The other structure fields are opaque and
+ * must not be accessed directly.
+ */
+struct br_ssl_client_context_ {
+ /**
+ * \brief The encapsulated engine context.
+ */
+ br_ssl_engine_context eng;
+
+#ifndef BR_DOXYGEN_IGNORE
+ /*
+ * Minimum ClientHello length; padding with an extension (RFC
+ * 7685) is added if necessary to match at least that length.
+ * Such padding is nominally unnecessary, but it has been used
+ * to work around some server implementation bugs.
+ */
+ uint16_t min_clienthello_len;
+
+ /*
+ * Bit field for algoithms (hash + signature) supported by the
+ * server when requesting a client certificate.
+ */
+ uint32_t hashes;
+
+ /*
+ * Server's public key curve.
+ */
+ int server_curve;
+
+ /*
+ * Context for certificate handler.
+ */
+ const br_ssl_client_certificate_class **client_auth_vtable;
+
+ /*
+ * Client authentication type.
+ */
+ unsigned char auth_type;
+
+ /*
+ * Hash function to use for the client signature. This is 0xFF
+ * if static ECDH is used.
+ */
+ unsigned char hash_id;
+
+ /*
+ * For the core certificate handlers, thus avoiding (in most
+ * cases) the need for an externally provided policy context.
+ */
+ union {
+ const br_ssl_client_certificate_class *vtable;
+ br_ssl_client_certificate_rsa_context single_rsa;
+ br_ssl_client_certificate_ec_context single_ec;
+ } client_auth;
+
+ /*
+ * Implementations.
+ */
+ br_rsa_public irsapub;
+#endif
+};
+
+/**
+ * \brief Get the hash functions and signature algorithms supported by
+ * the server.
+ *
+ * This value is a bit field:
+ *
+ * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`,
+ * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1,
+ * or 2 to 6 for the SHA family).
+ *
+ * - If ECDSA is supported with hash function of ID `x`, then bit `8+x`
+ * is set.
+ *
+ * - Newer algorithms are symbolic 16-bit identifiers that do not
+ * represent signature algorithm and hash function separately. If
+ * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15
+ * range, then bit `16+x` is set.
+ *
+ * "New algorithms" are currently defined only in draft documents, so
+ * this support is subject to possible change. Right now (early 2017),
+ * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA
+ * on Curve448) to bit 24. If the identifiers on the wire change in
+ * future document, then the decoding mechanism in BearSSL will be
+ * amended to keep mapping ed25519 and ed448 on bits 23 and 24,
+ * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not
+ * guaranteed yet.
+ *
+ * \param cc client context.
+ * \return the server-supported hash functions and signature algorithms.
+ */
+static inline uint32_t
+br_ssl_client_get_server_hashes(const br_ssl_client_context *cc)
+{
+ return cc->hashes;
+}
+
+/**
+ * \brief Get the server key curve.
+ *
+ * This function returns the ID for the curve used by the server's public
+ * key. This is set when the server's certificate chain is processed;
+ * this value is 0 if the server's key is not an EC key.
+ *
+ * \return the server's public key curve ID, or 0.
+ */
+static inline int
+br_ssl_client_get_server_curve(const br_ssl_client_context *cc)
+{
+ return cc->server_curve;
+}
+
+/*
+ * Each br_ssl_client_init_xxx() function sets the list of supported
+ * cipher suites and used implementations, as specified by the profile
+ * name 'xxx'. Defined profile names are:
+ *
+ * full all supported versions and suites; constant-time implementations
+ * TODO: add other profiles
+ */
+
+/**
+ * \brief SSL client profile: full.
+ *
+ * This function initialises the provided SSL client context with
+ * all supported algorithms and cipher suites. It also initialises
+ * a companion X.509 validation engine with all supported algorithms,
+ * and the provided trust anchors; the X.509 engine will be used by
+ * the client context to validate the server's certificate.
+ *
+ * \param cc client context to initialise.
+ * \param xc X.509 validation context to initialise.
+ * \param trust_anchors trust anchors to use.
+ * \param trust_anchors_num number of trust anchors.
+ */
+void br_ssl_client_init_full(br_ssl_client_context *cc,
+ br_x509_minimal_context *xc,
+ const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
+
+/**
+ * \brief Clear the complete contents of a SSL client context.
+ *
+ * Everything is cleared, including the reference to the configured buffer,
+ * implementations, cipher suites and state. This is a preparatory step
+ * to assembling a custom profile.
+ *
+ * \param cc client context to clear.
+ */
+void br_ssl_client_zero(br_ssl_client_context *cc);
+
+/**
+ * \brief Set an externally provided client certificate handler context.
+ *
+ * The handler's methods are invoked when the server requests a client
+ * certificate.
+ *
+ * \param cc client context.
+ * \param pctx certificate handler context (pointer to its vtable field).
+ */
+static inline void
+br_ssl_client_set_client_certificate(br_ssl_client_context *cc,
+ const br_ssl_client_certificate_class **pctx)
+{
+ cc->client_auth_vtable = pctx;
+}
+
+/**
+ * \brief Set the RSA public-key operations implementation.
+ *
+ * This will be used to encrypt the pre-master secret with the server's
+ * RSA public key (RSA-encryption cipher suites only).
+ *
+ * \param cc client context.
+ * \param irsapub RSA public-key encryption implementation.
+ */
+static inline void
+br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
+{
+ cc->irsapub = irsapub;
+}
+
+/**
+ * \brief Set the "default" RSA implementation for public-key operations.
+ *
+ * This sets the RSA implementation in the client context (for encrypting
+ * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest
+ * available on the current platform.
+ *
+ * \param cc client context.
+ */
+void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc);
+
+/**
+ * \brief Set the minimum ClientHello length (RFC 7685 padding).
+ *
+ * If this value is set and the ClientHello would be shorter, then
+ * the Pad ClientHello extension will be added with enough padding bytes
+ * to reach the target size. Because of the extension header, the resulting
+ * size will sometimes be slightly more than `len` bytes if the target
+ * size cannot be exactly met.
+ *
+ * The target length relates to the _contents_ of the ClientHello, not
+ * counting its 4-byte header. For instance, if `len` is set to 512,
+ * then the padding will bring the ClientHello size to 516 bytes with its
+ * header, and 521 bytes when counting the 5-byte record header.
+ *
+ * \param cc client context.
+ * \param len minimum ClientHello length (in bytes).
+ */
+static inline void
+br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len)
+{
+ cc->min_clienthello_len = len;
+}
+
+/**
+ * \brief Prepare or reset a client context for a new connection.
+ *
+ * The `server_name` parameter is used to fill the SNI extension; the
+ * X.509 "minimal" engine will also match that name against the server
+ * names included in the server's certificate. If the parameter is
+ * `NULL` then no SNI extension will be sent, and the X.509 "minimal"
+ * engine (if used for server certificate validation) will not check
+ * presence of any specific name in the received certificate.
+ *
+ * Therefore, setting the `server_name` to `NULL` shall be reserved
+ * to cases where alternate or additional methods are used to ascertain
+ * that the right server public key is used (e.g. a "known key" model).
+ *
+ * If `resume_session` is non-zero and the context was previously used
+ * then the session parameters may be reused (depending on whether the
+ * server previously sent a non-empty session ID, and accepts the session
+ * resumption). The session parameters for session resumption can also
+ * be set explicitly with `br_ssl_engine_set_session_parameters()`.
+ *
+ * On failure, the context is marked as failed, and this function
+ * returns 0. A possible failure condition is when no initial entropy
+ * was injected, and none could be obtained from the OS (either OS
+ * randomness gathering is not supported, or it failed).
+ *
+ * \param cc client context.
+ * \param server_name target server name, or `NULL`.
+ * \param resume_session non-zero to try session resumption.
+ * \return 0 on failure, 1 on success.
+ */
+int br_ssl_client_reset(br_ssl_client_context *cc,
+ const char *server_name, int resume_session);
+
+/**
+ * \brief Forget any session in the context.
+ *
+ * This means that the next handshake that uses this context will
+ * necessarily be a full handshake (this applies both to new connections
+ * and to renegotiations).
+ *
+ * \param cc client context.
+ */
+static inline void
+br_ssl_client_forget_session(br_ssl_client_context *cc)
+{
+ cc->eng.session.session_id_len = 0;
+}
+
+/**
+ * \brief Set client certificate chain and key (single RSA case).
+ *
+ * This function sets a client certificate chain, that the client will
+ * send to the server whenever a client certificate is requested. This
+ * certificate uses an RSA public key; the corresponding private key is
+ * invoked for authentication. Trust anchor names sent by the server are
+ * ignored.
+ *
+ * The provided chain and private key are linked in the client context;
+ * they must remain valid as long as they may be used, i.e. normally
+ * for the duration of the connection, since they might be invoked
+ * again upon renegotiations.
+ *
+ * \param cc SSL client context.
+ * \param chain client certificate chain (SSL order: EE comes first).
+ * \param chain_len client chain length (number of certificates).
+ * \param sk client private key.
+ * \param irsasign RSA signature implementation (PKCS#1 v1.5).
+ */
+void br_ssl_client_set_single_rsa(br_ssl_client_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign);
+
+/*
+ * \brief Set the client certificate chain and key (single EC case).
+ *
+ * This function sets a client certificate chain, that the client will
+ * send to the server whenever a client certificate is requested. This
+ * certificate uses an EC public key; the corresponding private key is
+ * invoked for authentication. Trust anchor names sent by the server are
+ * ignored.
+ *
+ * The provided chain and private key are linked in the client context;
+ * they must remain valid as long as they may be used, i.e. normally
+ * for the duration of the connection, since they might be invoked
+ * again upon renegotiations.
+ *
+ * The `allowed_usages` is a combination of usages, namely
+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX`
+ * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value
+ * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA
+ * signature implementation must be provided; otherwise, the `iecdsa`
+ * parameter may be 0.
+ *
+ * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or
+ * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA
+ * that issued (signed) the client certificate. That value is used with
+ * full static ECDH: support of the certificate by the server depends
+ * on how the certificate was signed. (Note: when using TLS 1.2, this
+ * parameter is ignored; but its value matters for TLS 1.0 and 1.1.)
+ *
+ * \param cc server context.
+ * \param chain server certificate chain to send.
+ * \param chain_len chain length (number of certificates).
+ * \param sk server private key (EC).
+ * \param allowed_usages allowed private key usages.
+ * \param cert_issuer_key_type issuing CA's key type.
+ * \param iec EC core implementation.
+ * \param iecdsa ECDSA signature implementation ("asn1" format).
+ */
+void br_ssl_client_set_single_ec(br_ssl_client_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk, unsigned allowed_usages,
+ unsigned cert_issuer_key_type,
+ const br_ec_impl *iec, br_ecdsa_sign iecdsa);
+
+/**
+ * \brief Type for a "translated cipher suite", as an array of two
+ * 16-bit integers.
+ *
+ * The first element is the cipher suite identifier (as used on the wire).
+ * The second element is the concatenation of four 4-bit elements which
+ * characterise the cipher suite contents. In most to least significant
+ * order, these 4-bit elements are:
+ *
+ * - Bits 12 to 15: key exchange + server key type
+ *
+ * | val | symbolic constant | suite type | details |
+ * | :-- | :----------------------- | :---------- | :----------------------------------------------- |
+ * | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) |
+ * | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) |
+ * | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) |
+ * | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA |
+ * | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA |
+ *
+ * - Bits 8 to 11: symmetric encryption algorithm
+ *
+ * | val | symbolic constant | symmetric encryption | key strength (bits) |
+ * | :-- | :--------------------- | :------------------- | :------------------ |
+ * | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 |
+ * | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 |
+ * | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 |
+ * | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 |
+ * | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 |
+ * | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 |
+ *
+ * - Bits 4 to 7: MAC algorithm
+ *
+ * | val | symbolic constant | MAC type | details |
+ * | :-- | :----------------- | :----------- | :------------------------------------ |
+ * | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) |
+ * | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` |
+ * | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` |
+ * | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` |
+ *
+ * - Bits 0 to 3: hash function for PRF when used with TLS-1.2
+ *
+ * | val | symbolic constant | hash function | details |
+ * | :-- | :----------------- | :------------ | :----------------------------------- |
+ * | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` |
+ * | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` |
+ *
+ * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has
+ * standard identifier 0x009C, and is translated to 0x0304, for, in
+ * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0),
+ * SHA-256 in the TLS PRF (4).
+ */
+typedef uint16_t br_suite_translated[2];
+
+#ifndef BR_DOXYGEN_IGNORE
+/*
+ * Constants are already documented in the br_suite_translated type.
+ */
+
+#define BR_SSLKEYX_RSA 0
+#define BR_SSLKEYX_ECDHE_RSA 1
+#define BR_SSLKEYX_ECDHE_ECDSA 2
+#define BR_SSLKEYX_ECDH_RSA 3
+#define BR_SSLKEYX_ECDH_ECDSA 4
+
+#define BR_SSLENC_3DES_CBC 0
+#define BR_SSLENC_AES128_CBC 1
+#define BR_SSLENC_AES256_CBC 2
+#define BR_SSLENC_AES128_GCM 3
+#define BR_SSLENC_AES256_GCM 4
+#define BR_SSLENC_CHACHA20 5
+
+#define BR_SSLMAC_AEAD 0
+#define BR_SSLMAC_SHA1 br_sha1_ID
+#define BR_SSLMAC_SHA256 br_sha256_ID
+#define BR_SSLMAC_SHA384 br_sha384_ID
+
+#define BR_SSLPRF_SHA256 br_sha256_ID
+#define BR_SSLPRF_SHA384 br_sha384_ID
+
+#endif
+
+/*
+ * Pre-declaration for the SSL server context.
+ */
+typedef struct br_ssl_server_context_ br_ssl_server_context;
+
+/**
+ * \brief Type for the server policy choices, taken after analysis of
+ * the client message (ClientHello).
+ */
+typedef struct {
+ /**
+ * \brief Cipher suite to use with that client.
+ */
+ uint16_t cipher_suite;
+
+ /**
+ * \brief Hash function or algorithm for signing the ServerKeyExchange.
+ *
+ * This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*`
+ * cipher suites; it is used only for `TLS_ECDHE_*` suites, in
+ * which the server _signs_ the ephemeral EC Diffie-Hellman
+ * parameters sent to the client.
+ *
+ * This identifier must be one of the following values:
+ *
+ * - `0xFF00 + id`, where `id` is a hash function identifier
+ * (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions);
+ *
+ * - a full 16-bit identifier, lower than `0xFF00`.
+ *
+ * If the first option is used, then the SSL engine will
+ * compute the hash of the data that is to be signed, with the
+ * designated hash function. The `do_sign()` method will be
+ * invoked with that hash value provided in the the `data`
+ * buffer.
+ *
+ * If the second option is used, then the SSL engine will NOT
+ * compute a hash on the data; instead, it will provide the
+ * to-be-signed data itself in `data`, i.e. the concatenation of
+ * the client random, server random, and encoded ECDH
+ * parameters. Furthermore, with TLS-1.2 and later, the 16-bit
+ * identifier will be used "as is" in the protocol, in the
+ * SignatureAndHashAlgorithm; for instance, `0x0401` stands for
+ * RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash
+ * function (the `04`).
+ *
+ * Take care that with TLS 1.0 and 1.1, the hash function is
+ * constrainted by the protocol: RSA signature must use
+ * MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1
+ * (`0xFF02`). Since TLS 1.0 and 1.1 don't include a
+ * SignatureAndHashAlgorithm field in their ServerKeyExchange
+ * messages, any value below `0xFF00` will be usable to send the
+ * raw ServerKeyExchange data to the `do_sign()` callback, but
+ * that callback must still follow the protocol requirements
+ * when generating the signature.
+ */
+ unsigned algo_id;
+
+ /**
+ * \brief Certificate chain to send to the client.
+ *
+ * This is an array of `br_x509_certificate` objects, each
+ * normally containing a DER-encoded certificate. The server
+ * code does not try to decode these elements.
+ */
+ const br_x509_certificate *chain;
+
+ /**
+ * \brief Certificate chain length (number of certificates).
+ */
+ size_t chain_len;
+
+} br_ssl_server_choices;
+
+/**
+ * \brief Class type for a policy handler (server side).
+ *
+ * A policy handler selects the policy parameters for a connection
+ * (cipher suite and other algorithms, and certificate chain to send to
+ * the client); it also performs the server-side computations involving
+ * its permanent private key.
+ *
+ * The SSL server engine will invoke first `choose()`, once the
+ * ClientHello message has been received, then either `do_keyx()`
+ * `do_sign()`, depending on the cipher suite.
+ */
+typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class;
+struct br_ssl_server_policy_class_ {
+ /**
+ * \brief Context size (in bytes).
+ */
+ size_t context_size;
+
+ /**
+ * \brief Select algorithms and certificates for this connection.
+ *
+ * This callback function shall fill the provided `choices`
+ * structure with the policy choices for this connection. This
+ * entails selecting the cipher suite, hash function for signing
+ * the ServerKeyExchange (applicable only to ECDHE cipher suites),
+ * and certificate chain to send.
+ *
+ * The callback receives a pointer to the server context that
+ * contains the relevant data. In particular, the functions
+ * `br_ssl_server_get_client_suites()`,
+ * `br_ssl_server_get_client_hashes()` and
+ * `br_ssl_server_get_client_curves()` can be used to obtain
+ * the cipher suites, hash functions and elliptic curves
+ * supported by both the client and server, respectively. The
+ * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()`
+ * functions yield the protocol version and requested server name
+ * (SNI), respectively.
+ *
+ * This function may modify its context structure (`pctx`) in
+ * arbitrary ways to keep track of its own choices.
+ *
+ * This function shall return 1 if appropriate policy choices
+ * could be made, or 0 if this connection cannot be pursued.
+ *
+ * \param pctx policy context.
+ * \param cc SSL server context.
+ * \param choices destination structure for the policy choices.
+ * \return 1 on success, 0 on error.
+ */
+ int (*choose)(const br_ssl_server_policy_class **pctx,
+ const br_ssl_server_context *cc,
+ br_ssl_server_choices *choices);
+
+ /**
+ * \brief Perform key exchange (server part).
+ *
+ * This callback is invoked to perform the server-side cryptographic
+ * operation for a key exchange that is not ECDHE. This callback
+ * uses the private key.
+ *
+ * **For RSA key exchange**, the provided `data` (of length `*len`
+ * bytes) shall be decrypted with the server's private key, and
+ * the 48-byte premaster secret copied back to the first 48 bytes
+ * of `data`.
+ *
+ * - The caller makes sure that `*len` is at least 59 bytes.
+ *
+ * - This callback MUST check that the provided length matches
+ * that of the key modulus; it shall report an error otherwise.
+ *
+ * - If the length matches that of the RSA key modulus, then
+ * processing MUST be constant-time, even if decryption fails,
+ * or the padding is incorrect, or the plaintext message length
+ * is not exactly 48 bytes.
+ *
+ * - This callback needs not check the two first bytes of the
+ * obtained pre-master secret (the caller will do that).
+ *
+ * - If an error is reported (0), then what the callback put
+ * in the first 48 bytes of `data` is unimportant (the caller
+ * will use random bytes instead).
+ *
+ * **For ECDH key exchange**, the provided `data` (of length `*len`
+ * bytes) is the elliptic curve point from the client. The
+ * callback shall multiply it with its private key, and store
+ * the resulting X coordinate in `data`, starting at offset 0,
+ * and set `*len` to the length of the X coordinate.
+ *
+ * - If the input array does not have the proper length for
+ * an encoded curve point, then an error (0) shall be reported.
+ *
+ * - If the input array has the proper length, then processing
+ * MUST be constant-time, even if the data is not a valid
+ * encoded point.
+ *
+ * - This callback MUST check that the input point is valid.
+ *
+ * Returned value is 1 on success, 0 on error.
+ *
+ * \param pctx policy context.
+ * \param data key exchange data from the client.
+ * \param len key exchange data length (in bytes).
+ * \return 1 on success, 0 on error.
+ */
+ uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx,
+ unsigned char *data, size_t *len);
+
+ /**
+ * \brief Perform a signature (for a ServerKeyExchange message).
+ *
+ * This callback function is invoked for ECDHE cipher suites. On
+ * input, the hash value or message to sign is in `data`, of
+ * size `hv_len`; the involved hash function or algorithm is
+ * identified by `algo_id`. The signature shall be computed and
+ * written back into `data`; the total size of that buffer is
+ * `len` bytes.
+ *
+ * This callback shall verify that the signature length does not
+ * exceed `len` bytes, and abstain from writing the signature if
+ * it does not fit.
+ *
+ * The `algo_id` value matches that which was written in the
+ * `choices` structures by the `choose()` callback. This will be
+ * one of the following:
+ *
+ * - `0xFF00 + id` for a hash function identifier `id`. In
+ * that case, the `data` buffer contains a hash value
+ * already computed over the data that is to be signed,
+ * of length `hv_len`. The `id` may be 0 to designate the
+ * special MD5+SHA-1 concatenation (old-style RSA signing).
+ *
+ * - Another value, lower than `0xFF00`. The `data` buffer
+ * then contains the raw, non-hashed data to be signed
+ * (concatenation of the client and server randoms and
+ * ECDH parameters). The callback is responsible to apply
+ * any relevant hashing as part of the signing process.
+ *
+ * Returned value is the signature length (in bytes), or 0 on error.
+ *
+ * \param pctx policy context.
+ * \param algo_id hash function / algorithm identifier.
+ * \param data input/output buffer (message/hash, then signature).
+ * \param hv_len hash value or message length (in bytes).
+ * \param len total buffer length (in bytes).
+ * \return signature length (in bytes) on success, or 0 on error.
+ */
+ size_t (*do_sign)(const br_ssl_server_policy_class **pctx,
+ unsigned algo_id,
+ unsigned char *data, size_t hv_len, size_t len);
+};
+
+/**
+ * \brief A single-chain RSA policy handler.
+ *
+ * This policy context uses a single certificate chain, and a RSA
+ * private key. The context can be restricted to only signatures or
+ * only key exchange.
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ const br_ssl_server_policy_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ const br_x509_certificate *chain;
+ size_t chain_len;
+ const br_rsa_private_key *sk;
+ unsigned allowed_usages;
+ br_rsa_private irsacore;
+ br_rsa_pkcs1_sign irsasign;
+#endif
+} br_ssl_server_policy_rsa_context;
+
+/**
+ * \brief A single-chain EC policy handler.
+ *
+ * This policy context uses a single certificate chain, and an EC
+ * private key. The context can be restricted to only signatures or
+ * only key exchange.
+ *
+ * Due to how TLS is defined, this context must be made aware whether
+ * the server certificate was itself signed with RSA or ECDSA. The code
+ * does not try to decode the certificate to obtain that information.
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ const br_ssl_server_policy_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ const br_x509_certificate *chain;
+ size_t chain_len;
+ const br_ec_private_key *sk;
+ unsigned allowed_usages;
+ unsigned cert_issuer_key_type;
+ const br_multihash_context *mhash;
+ const br_ec_impl *iec;
+ br_ecdsa_sign iecdsa;
+#endif
+} br_ssl_server_policy_ec_context;
+
+/**
+ * \brief Class type for a session parameter cache.
+ *
+ * Session parameters are saved in the cache with `save()`, and
+ * retrieved with `load()`. The cache implementation can apply any
+ * storage and eviction strategy that it sees fit. The SSL server
+ * context that performs the request is provided, so that its
+ * functionalities may be used by the implementation (e.g. hash
+ * functions or random number generation).
+ */
+typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class;
+struct br_ssl_session_cache_class_ {
+ /**
+ * \brief Context size (in bytes).
+ */
+ size_t context_size;
+
+ /**
+ * \brief Record a session.
+ *
+ * This callback should record the provided session parameters.
+ * The `params` structure is transient, so its contents shall
+ * be copied into the cache. The session ID has been randomly
+ * generated and always has length exactly 32 bytes.
+ *
+ * \param ctx session cache context.
+ * \param server_ctx SSL server context.
+ * \param params session parameters to save.
+ */
+ void (*save)(const br_ssl_session_cache_class **ctx,
+ br_ssl_server_context *server_ctx,
+ const br_ssl_session_parameters *params);
+
+ /**
+ * \brief Lookup a session in the cache.
+ *
+ * The session ID to lookup is in `params` and always has length
+ * exactly 32 bytes. If the session parameters are found in the
+ * cache, then the parameters shall be copied into the `params`
+ * structure. Returned value is 1 on successful lookup, 0
+ * otherwise.
+ *
+ * \param ctx session cache context.
+ * \param server_ctx SSL server context.
+ * \param params destination for session parameters.
+ * \return 1 if found, 0 otherwise.
+ */
+ int (*load)(const br_ssl_session_cache_class **ctx,
+ br_ssl_server_context *server_ctx,
+ br_ssl_session_parameters *params);
+};
+
+/**
+ * \brief Context for a basic cache system.
+ *
+ * The system stores session parameters in a buffer provided at
+ * initialisation time. Each entry uses exactly 100 bytes, and
+ * buffer sizes up to 4294967295 bytes are supported.
+ *
+ * Entries are evicted with a LRU (Least Recently Used) policy. A
+ * search tree is maintained to keep lookups fast even with large
+ * caches.
+ *
+ * Apart from the first field (vtable pointer), the structure
+ * contents are opaque and shall not be accessed directly.
+ */
+typedef struct {
+ /** \brief Pointer to vtable. */
+ const br_ssl_session_cache_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ unsigned char *store;
+ size_t store_len, store_ptr;
+ unsigned char index_key[32];
+ const br_hash_class *hash;
+ int init_done;
+ uint32_t head, tail, root;
+#endif
+} br_ssl_session_cache_lru;
+
+/**
+ * \brief Initialise a LRU session cache with the provided storage space.
+ *
+ * The provided storage space must remain valid as long as the cache
+ * is used. Arbitrary lengths are supported, up to 4294967295 bytes;
+ * each entry uses up exactly 100 bytes.
+ *
+ * \param cc session cache context.
+ * \param store storage space for cached entries.
+ * \param store_len storage space length (in bytes).
+ */
+void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
+ unsigned char *store, size_t store_len);
+
+/**
+ * \brief Forget an entry in an LRU session cache.
+ *
+ * The session cache context must have been initialised. The entry
+ * with the provided session ID (of exactly 32 bytes) is looked for
+ * in the cache; if located, it is disabled.
+ *
+ * \param cc session cache context.
+ * \param id session ID to forget.
+ */
+void br_ssl_session_cache_lru_forget(
+ br_ssl_session_cache_lru *cc, const unsigned char *id);
+
+/**
+ * \brief Context structure for a SSL server.
+ *
+ * The first field (called `eng`) is the SSL engine; all functions that
+ * work on a `br_ssl_engine_context` structure shall take as parameter
+ * a pointer to that field. The other structure fields are opaque and
+ * must not be accessed directly.
+ */
+struct br_ssl_server_context_ {
+ /**
+ * \brief The encapsulated engine context.
+ */
+ br_ssl_engine_context eng;
+
+#ifndef BR_DOXYGEN_IGNORE
+ /*
+ * Maximum version from the client.
+ */
+ uint16_t client_max_version;
+
+ /*
+ * Session cache.
+ */
+ const br_ssl_session_cache_class **cache_vtable;
+
+ /*
+ * Translated cipher suites supported by the client. The list
+ * is trimmed to include only the cipher suites that the
+ * server also supports; they are in the same order as in the
+ * client message.
+ */
+ br_suite_translated client_suites[BR_MAX_CIPHER_SUITES];
+ unsigned char client_suites_num;
+
+ /*
+ * Hash functions supported by the client, with ECDSA and RSA
+ * (bit mask). For hash function with id 'x', set bit index is
+ * x for RSA, x+8 for ECDSA. For newer algorithms, with ID
+ * 0x08**, bit 16+k is set for algorithm 0x0800+k.
+ */
+ uint32_t hashes;
+
+ /*
+ * Curves supported by the client (bit mask, for named curves).
+ */
+ uint32_t curves;
+
+ /*
+ * Context for chain handler.
+ */
+ const br_ssl_server_policy_class **policy_vtable;
+ uint16_t sign_hash_id;
+
+ /*
+ * For the core handlers, thus avoiding (in most cases) the
+ * need for an externally provided policy context.
+ */
+ union {
+ const br_ssl_server_policy_class *vtable;
+ br_ssl_server_policy_rsa_context single_rsa;
+ br_ssl_server_policy_ec_context single_ec;
+ } chain_handler;
+
+ /*
+ * Buffer for the ECDHE private key.
+ */
+ unsigned char ecdhe_key[70];
+ size_t ecdhe_key_len;
+
+ /*
+ * Trust anchor names for client authentication. "ta_names" and
+ * "tas" cannot be both non-NULL.
+ */
+ const br_x500_name *ta_names;
+ const br_x509_trust_anchor *tas;
+ size_t num_tas;
+ size_t cur_dn_index;
+ const unsigned char *cur_dn;
+ size_t cur_dn_len;
+
+ /*
+ * Buffer for the hash value computed over all handshake messages
+ * prior to CertificateVerify, and identifier for the hash function.
+ */
+ unsigned char hash_CV[64];
+ size_t hash_CV_len;
+ int hash_CV_id;
+
+ /*
+ * Server-specific implementations.
+ * (none for now)
+ */
+#endif
+};
+
+/*
+ * Each br_ssl_server_init_xxx() function sets the list of supported
+ * cipher suites and used implementations, as specified by the profile
+ * name 'xxx'. Defined profile names are:
+ *
+ * full_rsa all supported algorithm, server key type is RSA
+ * full_ec all supported algorithm, server key type is EC
+ * TODO: add other profiles
+ *
+ * Naming scheme for "minimal" profiles: min123
+ *
+ * -- character 1: key exchange
+ * r = RSA
+ * e = ECDHE_RSA
+ * f = ECDHE_ECDSA
+ * u = ECDH_RSA
+ * v = ECDH_ECDSA
+ * -- character 2: version / PRF
+ * 0 = TLS 1.0 / 1.1 with MD5+SHA-1
+ * 2 = TLS 1.2 with SHA-256
+ * 3 = TLS 1.2 with SHA-384
+ * -- character 3: encryption
+ * a = AES/CBC
+ * d = 3DES/CBC
+ * g = AES/GCM
+ * c = ChaCha20+Poly1305
+ */
+
+/**
+ * \brief SSL server profile: full_rsa.
+ *
+ * This function initialises the provided SSL server context with
+ * all supported algorithms and cipher suites that rely on a RSA
+ * key pair.
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk RSA private key.
+ */
+void br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief SSL server profile: full_ec.
+ *
+ * This function initialises the provided SSL server context with
+ * all supported algorithms and cipher suites that rely on an EC
+ * key pair.
+ *
+ * The key type of the CA that issued the server's certificate must
+ * be provided, since it matters for ECDH cipher suites (ECDH_RSA
+ * suites require a RSA-powered CA). The key type is either
+ * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`.
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len chain length (number of certificates).
+ * \param cert_issuer_key_type certificate issuer's key type.
+ * \param sk EC private key.
+ */
+void br_ssl_server_init_full_ec(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ unsigned cert_issuer_key_type, const br_ec_private_key *sk);
+
+/**
+ * \brief SSL server profile: minr2g.
+ *
+ * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is
+ * RSA, and RSA key exchange is used (not forward secure, but uses little
+ * CPU in the client).
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk RSA private key.
+ */
+void br_ssl_server_init_minr2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief SSL server profile: mine2g.
+ *
+ * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key
+ * is RSA, and ECDHE key exchange is used. This suite provides forward
+ * security, with a higher CPU expense on the client, and a somewhat
+ * larger code footprint (compared to "minr2g").
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk RSA private key.
+ */
+void br_ssl_server_init_mine2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief SSL server profile: minf2g.
+ *
+ * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
+ * Server key is EC, and ECDHE key exchange is used. This suite provides
+ * forward security, with a higher CPU expense on the client and server
+ * (by a factor of about 3 to 4), and a somewhat larger code footprint
+ * (compared to "minu2g" and "minv2g").
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk EC private key.
+ */
+void br_ssl_server_init_minf2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk);
+
+/**
+ * \brief SSL server profile: minu2g.
+ *
+ * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256.
+ * Server key is EC, and ECDH key exchange is used; the issuing CA used
+ * a RSA key.
+ *
+ * The "minu2g" and "minv2g" profiles do not provide forward secrecy,
+ * but are the lightest on the server (for CPU usage), and are rather
+ * inexpensive on the client as well.
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk EC private key.
+ */
+void br_ssl_server_init_minu2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk);
+
+/**
+ * \brief SSL server profile: minv2g.
+ *
+ * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256.
+ * Server key is EC, and ECDH key exchange is used; the issuing CA used
+ * an EC key.
+ *
+ * The "minu2g" and "minv2g" profiles do not provide forward secrecy,
+ * but are the lightest on the server (for CPU usage), and are rather
+ * inexpensive on the client as well.
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk EC private key.
+ */
+void br_ssl_server_init_minv2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk);
+
+/**
+ * \brief SSL server profile: mine2c.
+ *
+ * This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
+ * Server key is RSA, and ECDHE key exchange is used. This suite
+ * provides forward security.
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk RSA private key.
+ */
+void br_ssl_server_init_mine2c(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk);
+
+/**
+ * \brief SSL server profile: minf2c.
+ *
+ * This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.
+ * Server key is EC, and ECDHE key exchange is used. This suite provides
+ * forward security.
+ *
+ * \param cc server context to initialise.
+ * \param chain server certificate chain.
+ * \param chain_len certificate chain length (number of certificate).
+ * \param sk EC private key.
+ */
+void br_ssl_server_init_minf2c(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk);
+
+/**
+ * \brief Get the supported client suites.
+ *
+ * This function shall be called only after the ClientHello has been
+ * processed, typically from the policy engine. The returned array
+ * contains the cipher suites that are supported by both the client
+ * and the server; these suites are in client preference order, unless
+ * the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case
+ * they are in server preference order.
+ *
+ * The suites are _translated_, which means that each suite is given
+ * as two 16-bit integers: the standard suite identifier, and its
+ * translated version, broken down into its individual components,
+ * as explained with the `br_suite_translated` type.
+ *
+ * The returned array is allocated in the context and will be rewritten
+ * by each handshake.
+ *
+ * \param cc server context.
+ * \param num receives the array size (number of suites).
+ * \return the translated common cipher suites, in preference order.
+ */
+static inline const br_suite_translated *
+br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
+{
+ *num = cc->client_suites_num;
+ return cc->client_suites;
+}
+
+/**
+ * \brief Get the hash functions and signature algorithms supported by
+ * the client.
+ *
+ * This value is a bit field:
+ *
+ * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`,
+ * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1,
+ * or 2 to 6 for the SHA family).
+ *
+ * - If ECDSA is supported with hash function of ID `x`, then bit `8+x`
+ * is set.
+ *
+ * - Newer algorithms are symbolic 16-bit identifiers that do not
+ * represent signature algorithm and hash function separately. If
+ * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15
+ * range, then bit `16+x` is set.
+ *
+ * "New algorithms" are currently defined only in draft documents, so
+ * this support is subject to possible change. Right now (early 2017),
+ * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA
+ * on Curve448) to bit 24. If the identifiers on the wire change in
+ * future document, then the decoding mechanism in BearSSL will be
+ * amended to keep mapping ed25519 and ed448 on bits 23 and 24,
+ * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not
+ * guaranteed yet.
+ *
+ * \param cc server context.
+ * \return the client-supported hash functions and signature algorithms.
+ */
+static inline uint32_t
+br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
+{
+ return cc->hashes;
+}
+
+/**
+ * \brief Get the elliptic curves supported by the client.
+ *
+ * This is a bit field (bit x is set if curve of ID x is supported).
+ *
+ * \param cc server context.
+ * \return the client-supported elliptic curves.
+ */
+static inline uint32_t
+br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
+{
+ return cc->curves;
+}
+
+/**
+ * \brief Clear the complete contents of a SSL server context.
+ *
+ * Everything is cleared, including the reference to the configured buffer,
+ * implementations, cipher suites and state. This is a preparatory step
+ * to assembling a custom profile.
+ *
+ * \param cc server context to clear.
+ */
+void br_ssl_server_zero(br_ssl_server_context *cc);
+
+/**
+ * \brief Set an externally provided policy context.
+ *
+ * The policy context's methods are invoked to decide the cipher suite
+ * and certificate chain, and to perform operations involving the server's
+ * private key.
+ *
+ * \param cc server context.
+ * \param pctx policy context (pointer to its vtable field).
+ */
+static inline void
+br_ssl_server_set_policy(br_ssl_server_context *cc,
+ const br_ssl_server_policy_class **pctx)
+{
+ cc->policy_vtable = pctx;
+}
+
+/**
+ * \brief Set the server certificate chain and key (single RSA case).
+ *
+ * This function uses a policy context included in the server context.
+ * It configures use of a single server certificate chain with a RSA
+ * private key. The `allowed_usages` is a combination of usages, namely
+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
+ * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for
+ * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures).
+ *
+ * \param cc server context.
+ * \param chain server certificate chain to send to the client.
+ * \param chain_len chain length (number of certificates).
+ * \param sk server private key (RSA).
+ * \param allowed_usages allowed private key usages.
+ * \param irsacore RSA core implementation.
+ * \param irsasign RSA signature implementation (PKCS#1 v1.5).
+ */
+void br_ssl_server_set_single_rsa(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk, unsigned allowed_usages,
+ br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign);
+
+/**
+ * \brief Set the server certificate chain and key (single EC case).
+ *
+ * This function uses a policy context included in the server context.
+ * It configures use of a single server certificate chain with an EC
+ * private key. The `allowed_usages` is a combination of usages, namely
+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
+ * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for
+ * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures).
+ *
+ * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH),
+ * the algorithm type of the key used by the issuing CA to sign the
+ * server's certificate must be provided, as `cert_issuer_key_type`
+ * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`).
+ *
+ * \param cc server context.
+ * \param chain server certificate chain to send.
+ * \param chain_len chain length (number of certificates).
+ * \param sk server private key (EC).
+ * \param allowed_usages allowed private key usages.
+ * \param cert_issuer_key_type issuing CA's key type.
+ * \param iec EC core implementation.
+ * \param iecdsa ECDSA signature implementation ("asn1" format).
+ */
+void br_ssl_server_set_single_ec(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk, unsigned allowed_usages,
+ unsigned cert_issuer_key_type,
+ const br_ec_impl *iec, br_ecdsa_sign iecdsa);
+
+/**
+ * \brief Activate client certificate authentication.
+ *
+ * The trust anchor encoded X.500 names (DN) to send to the client are
+ * provided. A client certificate will be requested and validated through
+ * the X.509 validator configured in the SSL engine. If `num` is 0, then
+ * client certificate authentication is disabled.
+ *
+ * If the client does not send a certificate, or on validation failure,
+ * the handshake aborts. Unauthenticated clients can be tolerated by
+ * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag.
+ *
+ * The provided array is linked in, not copied, so that pointer must
+ * remain valid as long as anchor names may be used.
+ *
+ * \param cc server context.
+ * \param ta_names encoded trust anchor names.
+ * \param num number of encoded trust anchor names.
+ */
+static inline void
+br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc,
+ const br_x500_name *ta_names, size_t num)
+{
+ cc->ta_names = ta_names;
+ cc->tas = NULL;
+ cc->num_tas = num;
+}
+
+/**
+ * \brief Activate client certificate authentication.
+ *
+ * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the
+ * trust anchor names are provided not as an array of stand-alone names
+ * (`br_x500_name` structures), but as an array of trust anchors
+ * (`br_x509_trust_anchor` structures). The server engine itself will
+ * only use the `dn` field of each trust anchor. This is meant to allow
+ * defining a single array of trust anchors, to be used here and in the
+ * X.509 validation engine itself.
+ *
+ * The provided array is linked in, not copied, so that pointer must
+ * remain valid as long as anchor names may be used.
+ *
+ * \param cc server context.
+ * \param tas trust anchors (only names are used).
+ * \param num number of trust anchors.
+ */
+static inline void
+br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc,
+ const br_x509_trust_anchor *tas, size_t num)
+{
+ cc->ta_names = NULL;
+ cc->tas = tas;
+ cc->num_tas = num;
+}
+
+/**
+ * \brief Configure the cache for session parameters.
+ *
+ * The cache context is provided as a pointer to its first field (vtable
+ * pointer).
+ *
+ * \param cc server context.
+ * \param vtable session cache context.
+ */
+static inline void
+br_ssl_server_set_cache(br_ssl_server_context *cc,
+ const br_ssl_session_cache_class **vtable)
+{
+ cc->cache_vtable = vtable;
+}
+
+/**
+ * \brief Prepare or reset a server context for handling an incoming client.
+ *
+ * \param cc server context.
+ * \return 1 on success, 0 on error.
+ */
+int br_ssl_server_reset(br_ssl_server_context *cc);
+
+/* ===================================================================== */
+
+/*
+ * Context for the simplified I/O context. The transport medium is accessed
+ * through the low_read() and low_write() callback functions, each with
+ * its own opaque context pointer.
+ *
+ * low_read() read some bytes, at most 'len' bytes, into data[]. The
+ * returned value is the number of read bytes, or -1 on error.
+ * The 'len' parameter is guaranteed never to exceed 20000,
+ * so the length always fits in an 'int' on all platforms.
+ *
+ * low_write() write up to 'len' bytes, to be read from data[]. The
+ * returned value is the number of written bytes, or -1 on
+ * error. The 'len' parameter is guaranteed never to exceed
+ * 20000, so the length always fits in an 'int' on all
+ * parameters.
+ *
+ * A socket closure (if the transport medium is a socket) should be reported
+ * as an error (-1). The callbacks shall endeavour to block until at least
+ * one byte can be read or written; a callback returning 0 at times is
+ * acceptable, but this normally leads to the callback being immediately
+ * called again, so the callback should at least always try to block for
+ * some time if no I/O can take place.
+ *
+ * The SSL engine naturally applies some buffering, so the callbacks need
+ * not apply buffers of their own.
+ */
+/**
+ * \brief Context structure for the simplified SSL I/O wrapper.
+ *
+ * This structure is initialised with `br_sslio_init()`. Its contents
+ * are opaque and shall not be accessed directly.
+ */
+typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
+ br_ssl_engine_context *engine;
+ int (*low_read)(void *read_context,
+ unsigned char *data, size_t len);
+ void *read_context;
+ int (*low_write)(void *write_context,
+ const unsigned char *data, size_t len);
+ void *write_context;
+#endif
+} br_sslio_context;
+
+/**
+ * \brief Initialise a simplified I/O wrapper context.
+ *
+ * The simplified I/O wrapper offers a simpler read/write API for a SSL
+ * engine (client or server), using the provided callback functions for
+ * reading data from, or writing data to, the transport medium.
+ *
+ * The callback functions have the following semantics:
+ *
+ * - Each callback receives an opaque context value (of type `void *`)
+ * that the callback may use arbitrarily (or possibly ignore).
+ *
+ * - `low_read()` reads at least one byte, at most `len` bytes, from
+ * the transport medium. Read bytes shall be written in `data`.
+ *
+ * - `low_write()` writes at least one byte, at most `len` bytes, unto
+ * the transport medium. The bytes to write are read from `data`.
+ *
+ * - The `len` parameter is never zero, and is always lower than 20000.
+ *
+ * - The number of processed bytes (read or written) is returned. Since
+ * that number is less than 20000, it always fits on an `int`.
+ *
+ * - On error, the callbacks return -1. Reaching end-of-stream is an
+ * error. Errors are permanent: the SSL connection is terminated.
+ *
+ * - Callbacks SHOULD NOT return 0. This is tolerated, as long as
+ * callbacks endeavour to block for some non-negligible amount of
+ * time until at least one byte can be sent or received (if a
+ * callback returns 0, then the wrapper invokes it again
+ * immediately).
+ *
+ * - Callbacks MAY return as soon as at least one byte is processed;
+ * they MAY also insist on reading or writing _all_ requested bytes.
+ * Since SSL is a self-terminated protocol (each record has a length
+ * header), this does not change semantics.
+ *
+ * - Callbacks need not apply any buffering (for performance) since SSL
+ * itself uses buffers.
+ *
+ * \param ctx wrapper context to initialise.
+ * \param engine SSL engine to wrap.
+ * \param low_read callback for reading data from the transport.
+ * \param read_context context pointer for `low_read()`.
+ * \param low_write callback for writing data on the transport.
+ * \param write_context context pointer for `low_write()`.
+ */
+void br_sslio_init(br_sslio_context *ctx,
+ br_ssl_engine_context *engine,
+ int (*low_read)(void *read_context,
+ unsigned char *data, size_t len),
+ void *read_context,
+ int (*low_write)(void *write_context,
+ const unsigned char *data, size_t len),
+ void *write_context);
+
+/**
+ * \brief Read some application data from a SSL connection.
+ *
+ * If `len` is zero, then this function returns 0 immediately. In
+ * all other cases, it never returns 0.
+ *
+ * This call returns only when at least one byte has been obtained.
+ * Returned value is the number of bytes read, or -1 on error. The
+ * number of bytes always fits on an 'int' (data from a single SSL/TLS
+ * record is returned).
+ *
+ * On error or SSL closure, this function returns -1. The caller should
+ * inspect the error status on the SSL engine to distinguish between
+ * normal closure and error.
+ *
+ * \param cc SSL wrapper context.
+ * \param dst destination buffer for application data.
+ * \param len maximum number of bytes to obtain.
+ * \return number of bytes obtained, or -1 on error.
+ */
+int br_sslio_read(br_sslio_context *cc, void *dst, size_t len);
+
+/**
+ * \brief Read application data from a SSL connection.
+ *
+ * This calls returns only when _all_ requested `len` bytes are read,
+ * or an error is reached. Returned value is 0 on success, -1 on error.
+ * A normal (verified) SSL closure before that many bytes are obtained
+ * is reported as an error by this function.
+ *
+ * \param cc SSL wrapper context.
+ * \param dst destination buffer for application data.
+ * \param len number of bytes to obtain.
+ * \return 0 on success, or -1 on error.
+ */
+int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len);
+
+/**
+ * \brief Write some application data unto a SSL connection.
+ *
+ * If `len` is zero, then this function returns 0 immediately. In
+ * all other cases, it never returns 0.
+ *
+ * This call returns only when at least one byte has been written.
+ * Returned value is the number of bytes written, or -1 on error. The
+ * number of bytes always fits on an 'int' (less than 20000).
+ *
+ * On error or SSL closure, this function returns -1. The caller should
+ * inspect the error status on the SSL engine to distinguish between
+ * normal closure and error.
+ *
+ * **Important:** SSL is buffered; a "written" byte is a byte that was
+ * injected into the wrapped SSL engine, but this does not necessarily mean
+ * that it has been scheduled for sending. Use `br_sslio_flush()` to
+ * ensure that all pending data has been sent to the transport medium.
+ *
+ * \param cc SSL wrapper context.
+ * \param src source buffer for application data.
+ * \param len maximum number of bytes to write.
+ * \return number of bytes written, or -1 on error.
+ */
+int br_sslio_write(br_sslio_context *cc, const void *src, size_t len);
+
+/**
+ * \brief Write application data unto a SSL connection.
+ *
+ * This calls returns only when _all_ requested `len` bytes have been
+ * written, or an error is reached. Returned value is 0 on success, -1
+ * on error. A normal (verified) SSL closure before that many bytes are
+ * written is reported as an error by this function.
+ *
+ * **Important:** SSL is buffered; a "written" byte is a byte that was
+ * injected into the wrapped SSL engine, but this does not necessarily mean
+ * that it has been scheduled for sending. Use `br_sslio_flush()` to
+ * ensure that all pending data has been sent to the transport medium.
+ *
+ * \param cc SSL wrapper context.
+ * \param src source buffer for application data.
+ * \param len number of bytes to write.
+ * \return 0 on success, or -1 on error.
+ */
+int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len);
+
+/**
+ * \brief Flush pending data.
+ *
+ * This call makes sure that any buffered application data in the
+ * provided context (including the wrapped SSL engine) has been sent
+ * to the transport medium (i.e. accepted by the `low_write()` callback
+ * method). If there is no such pending data, then this function does
+ * nothing (and returns a success, i.e. 0).
+ *
+ * If the underlying transport medium has its own buffers, then it is
+ * up to the caller to ensure the corresponding flushing.
+ *
+ * Returned value is 0 on success, -1 on error.
+ *
+ * \param cc SSL wrapper context.
+ * \return 0 on success, or -1 on error.
+ */
+int br_sslio_flush(br_sslio_context *cc);
+
+/**
+ * \brief Close the SSL connection.
+ *
+ * This call runs the SSL closure protocol (sending a `close_notify`,
+ * receiving the response `close_notify`). When it returns, the SSL
+ * connection is finished. It is still up to the caller to manage the
+ * possible transport-level termination, if applicable (alternatively,
+ * the underlying transport stream may be reused for non-SSL messages).
+ *
+ * Returned value is 0 on success, -1 on error. A failure by the peer
+ * to process the complete closure protocol (i.e. sending back the
+ * `close_notify`) is an error.
+ *
+ * \param cc SSL wrapper context.
+ * \return 0 on success, or -1 on error.
+ */
+int br_sslio_close(br_sslio_context *cc);
+
+/* ===================================================================== */
+
+/*
+ * Symbolic constants for cipher suites.
+ */
+
+/* From RFC 5246 */
+#define BR_TLS_NULL_WITH_NULL_NULL 0x0000
+#define BR_TLS_RSA_WITH_NULL_MD5 0x0001
+#define BR_TLS_RSA_WITH_NULL_SHA 0x0002
+#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B
+#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004
+#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005
+#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A
+#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
+#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
+#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
+#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
+#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D
+#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010
+#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013
+#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016
+#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030
+#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031
+#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032
+#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
+#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036
+#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037
+#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038
+#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
+#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E
+#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F
+#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040
+#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067
+#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068
+#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069
+#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A
+#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B
+#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018
+#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B
+#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034
+#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A
+#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C
+#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D
+
+/* From RFC 4492 */
+#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001
+#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002
+#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003
+#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004
+#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005
+#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006
+#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007
+#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A
+#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B
+#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C
+#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D
+#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E
+#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F
+#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010
+#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011
+#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012
+#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013
+#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014
+#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015
+#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016
+#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017
+#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018
+#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019
+
+/* From RFC 5288 */
+#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
+#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D
+#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
+#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F
+#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0
+#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1
+#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2
+#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3
+#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4
+#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5
+#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6
+#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7
+
+/* From RFC 5289 */
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024
+#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025
+#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026
+#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
+#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028
+#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029
+#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C
+#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D
+#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E
+#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
+#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030
+#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
+#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032
+
+/* From RFC 6655 and 7251 */
+#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C
+#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D
+#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0
+#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
+#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF
+
+/* From RFC 7905 */
+#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8
+#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
+#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA
+#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB
+#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC
+#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD
+#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE
+
+/* From RFC 7507 */
+#define BR_TLS_FALLBACK_SCSV 0x5600
+
+/*
+ * Symbolic constants for alerts.
+ */
+#define BR_ALERT_CLOSE_NOTIFY 0
+#define BR_ALERT_UNEXPECTED_MESSAGE 10
+#define BR_ALERT_BAD_RECORD_MAC 20
+#define BR_ALERT_RECORD_OVERFLOW 22
+#define BR_ALERT_DECOMPRESSION_FAILURE 30
+#define BR_ALERT_HANDSHAKE_FAILURE 40
+#define BR_ALERT_BAD_CERTIFICATE 42
+#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43
+#define BR_ALERT_CERTIFICATE_REVOKED 44
+#define BR_ALERT_CERTIFICATE_EXPIRED 45
+#define BR_ALERT_CERTIFICATE_UNKNOWN 46
+#define BR_ALERT_ILLEGAL_PARAMETER 47
+#define BR_ALERT_UNKNOWN_CA 48
+#define BR_ALERT_ACCESS_DENIED 49
+#define BR_ALERT_DECODE_ERROR 50
+#define BR_ALERT_DECRYPT_ERROR 51
+#define BR_ALERT_PROTOCOL_VERSION 70
+#define BR_ALERT_INSUFFICIENT_SECURITY 71
+#define BR_ALERT_INTERNAL_ERROR 80
+#define BR_ALERT_USER_CANCELED 90
+#define BR_ALERT_NO_RENEGOTIATION 100
+#define BR_ALERT_UNSUPPORTED_EXTENSION 110
+#define BR_ALERT_NO_APPLICATION_PROTOCOL 120
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Property changes on: stable/12/contrib/bearssl/inc/bearssl_ssl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/inc/bearssl_x509.h
===================================================================
--- stable/12/contrib/bearssl/inc/bearssl_x509.h (nonexistent)
+++ stable/12/contrib/bearssl/inc/bearssl_x509.h (revision 346145)
@@ -0,0 +1,1397 @@
+/*
+ * 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_X509_H__
+#define BR_BEARSSL_X509_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "bearssl_ec.h"
+#include "bearssl_hash.h"
+#include "bearssl_rsa.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file bearssl_x509.h
+ *
+ * # X.509 Certificate Chain Processing
+ *
+ * An X.509 processing engine receives an X.509 chain, chunk by chunk,
+ * as received from a SSL/TLS client or server (the client receives the
+ * server's certificate chain, and the server receives the client's
+ * certificate chain if it requested a client certificate). The chain
+ * is thus injected in the engine in SSL order (end-entity first).
+ *
+ * The engine's job is to return the public key to use for SSL/TLS.
+ * How exactly that key is obtained and verified is entirely up to the
+ * engine.
+ *
+ * **The "known key" engine** returns a public key which is already known
+ * from out-of-band information (e.g. the client _remembers_ the key from
+ * a previous connection, as in the usual SSH model). This is the simplest
+ * engine since it simply ignores the chain, thereby avoiding the need
+ * for any decoding logic.
+ *
+ * **The "minimal" engine** implements minimal X.509 decoding and chain
+ * validation:
+ *
+ * - The provided chain should validate "as is". There is no attempt
+ * at reordering, skipping or downloading extra certificates.
+ *
+ * - X.509 v1, v2 and v3 certificates are supported.
+ *
+ * - Trust anchors are a DN and a public key. Each anchor is either a
+ * "CA" anchor, or a non-CA.
+ *
+ * - If the end-entity certificate matches a non-CA anchor (subject DN
+ * is equal to the non-CA name, and public key is also identical to
+ * the anchor key), then this is a _direct trust_ case and the
+ * remaining certificates are ignored.
+ *
+ * - Unless direct trust is applied, the chain must be verifiable up to
+ * a certificate whose issuer DN matches the DN from a "CA" trust anchor,
+ * and whose signature is verifiable against that anchor's public key.
+ * Subsequent certificates in the chain are ignored.
+ *
+ * - The engine verifies subject/issuer DN matching, and enforces
+ * processing of Basic Constraints and Key Usage extensions. The
+ * Authority Key Identifier, Subject Key Identifier, Issuer Alt Name,
+ * Subject Directory Attribute, CRL Distribution Points, Freshest CRL,
+ * Authority Info Access and Subject Info Access extensions are
+ * ignored. The Subject Alt Name is decoded for the end-entity
+ * certificate under some conditions (see below). Other extensions
+ * are ignored if non-critical, or imply chain rejection if critical.
+ *
+ * - The Subject Alt Name extension is parsed for names of type `dNSName`
+ * when decoding the end-entity certificate, and only if there is a
+ * server name to match. If there is no SAN extension, then the
+ * Common Name from the subjectDN is used. That name matching is
+ * case-insensitive and honours a single starting wildcard (i.e. if
+ * the name in the certificate starts with "`*.`" then this matches
+ * any word as first element). Note: this name matching is performed
+ * also in the "direct trust" model.
+ *
+ * - DN matching is byte-to-byte equality (a future version might
+ * include some limited processing for case-insensitive matching and
+ * whitespace normalisation).
+ *
+ * - Successful validation produces a public key type but also a set
+ * of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
+ * The caller is responsible for checking that the key type and
+ * usages are compatible with the expected values (e.g. with the
+ * selected cipher suite, when the client validates the server's
+ * certificate).
+ *
+ * **Important caveats:**
+ *
+ * - The "minimal" engine does not check revocation status. The relevant
+ * extensions are ignored, and CRL or OCSP responses are not gathered
+ * or checked.
+ *
+ * - The "minimal" engine does not currently support Name Constraints
+ * (some basic functionality to handle sub-domains may be added in a
+ * later version).
+ *
+ * - The decoder is not "validating" in the sense that it won't reject
+ * some certificates with invalid field values when these fields are
+ * not actually processed.
+ */
+
+/*
+ * X.509 error codes are in the 32..63 range.
+ */
+
+/** \brief X.509 status: validation was successful; this is not actually
+ an error. */
+#define BR_ERR_X509_OK 32
+
+/** \brief X.509 status: invalid value in an ASN.1 structure. */
+#define BR_ERR_X509_INVALID_VALUE 33
+
+/** \brief X.509 status: truncated certificate. */
+#define BR_ERR_X509_TRUNCATED 34
+
+/** \brief X.509 status: empty certificate chain (no certificate at all). */
+#define BR_ERR_X509_EMPTY_CHAIN 35
+
+/** \brief X.509 status: decoding error: inner element extends beyond
+ outer element size. */
+#define BR_ERR_X509_INNER_TRUNC 36
+
+/** \brief X.509 status: decoding error: unsupported tag class (application
+ or private). */
+#define BR_ERR_X509_BAD_TAG_CLASS 37
+
+/** \brief X.509 status: decoding error: unsupported tag value. */
+#define BR_ERR_X509_BAD_TAG_VALUE 38
+
+/** \brief X.509 status: decoding error: indefinite length. */
+#define BR_ERR_X509_INDEFINITE_LENGTH 39
+
+/** \brief X.509 status: decoding error: extraneous element. */
+#define BR_ERR_X509_EXTRA_ELEMENT 40
+
+/** \brief X.509 status: decoding error: unexpected element. */
+#define BR_ERR_X509_UNEXPECTED 41
+
+/** \brief X.509 status: decoding error: expected constructed element, but
+ is primitive. */
+#define BR_ERR_X509_NOT_CONSTRUCTED 42
+
+/** \brief X.509 status: decoding error: expected primitive element, but
+ is constructed. */
+#define BR_ERR_X509_NOT_PRIMITIVE 43
+
+/** \brief X.509 status: decoding error: BIT STRING length is not multiple
+ of 8. */
+#define BR_ERR_X509_PARTIAL_BYTE 44
+
+/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */
+#define BR_ERR_X509_BAD_BOOLEAN 45
+
+/** \brief X.509 status: decoding error: value is off-limits. */
+#define BR_ERR_X509_OVERFLOW 46
+
+/** \brief X.509 status: invalid distinguished name. */
+#define BR_ERR_X509_BAD_DN 47
+
+/** \brief X.509 status: invalid date/time representation. */
+#define BR_ERR_X509_BAD_TIME 48
+
+/** \brief X.509 status: certificate contains unsupported features that
+ cannot be ignored. */
+#define BR_ERR_X509_UNSUPPORTED 49
+
+/** \brief X.509 status: key or signature size exceeds internal limits. */
+#define BR_ERR_X509_LIMIT_EXCEEDED 50
+
+/** \brief X.509 status: key type does not match that which was expected. */
+#define BR_ERR_X509_WRONG_KEY_TYPE 51
+
+/** \brief X.509 status: signature is invalid. */
+#define BR_ERR_X509_BAD_SIGNATURE 52
+
+/** \brief X.509 status: validation time is unknown. */
+#define BR_ERR_X509_TIME_UNKNOWN 53
+
+/** \brief X.509 status: certificate is expired or not yet valid. */
+#define BR_ERR_X509_EXPIRED 54
+
+/** \brief X.509 status: issuer/subject DN mismatch in the chain. */
+#define BR_ERR_X509_DN_MISMATCH 55
+
+/** \brief X.509 status: expected server name was not found in the chain. */
+#define BR_ERR_X509_BAD_SERVER_NAME 56
+
+/** \brief X.509 status: unknown critical extension in certificate. */
+#define BR_ERR_X509_CRITICAL_EXTENSION 57
+
+/** \brief X.509 status: not a CA, or path length constraint violation */
+#define BR_ERR_X509_NOT_CA 58
+
+/** \brief X.509 status: Key Usage extension prohibits intended usage. */
+#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59
+
+/** \brief X.509 status: public key found in certificate is too small. */
+#define BR_ERR_X509_WEAK_PUBLIC_KEY 60
+
+/** \brief X.509 status: chain could not be linked to a trust anchor. */
+#define BR_ERR_X509_NOT_TRUSTED 62
+
+/**
+ * \brief Aggregate structure for public keys.
+ */
+typedef struct {
+ /** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */
+ unsigned char key_type;
+ /** \brief Actual public key. */
+ union {
+ /** \brief RSA public key. */
+ br_rsa_public_key rsa;
+ /** \brief EC public key. */
+ br_ec_public_key ec;
+ } key;
+} br_x509_pkey;
+
+/**
+ * \brief Distinguished Name (X.500) structure.
+ *
+ * The DN is DER-encoded.
+ */
+typedef struct {
+ /** \brief Encoded DN data. */
+ unsigned char *data;
+ /** \brief Encoded DN length (in bytes). */
+ size_t len;
+} br_x500_name;
+
+/**
+ * \brief Trust anchor structure.
+ */
+typedef struct {
+ /** \brief Encoded DN (X.500 name). */
+ br_x500_name dn;
+ /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */
+ unsigned flags;
+ /** \brief Anchor public key. */
+ br_x509_pkey pkey;
+} br_x509_trust_anchor;
+
+/**
+ * \brief Trust anchor flag: CA.
+ *
+ * A "CA" anchor is deemed fit to verify signatures on certificates.
+ * A "non-CA" anchor is accepted only for direct trust (server's
+ * certificate name and key match the anchor).
+ */
+#define BR_X509_TA_CA 0x0001
+
+/*
+ * Key type: combination of a basic key type (low 4 bits) and some
+ * optional flags.
+ *
+ * For a public key, the basic key type only is set.
+ *
+ * For an expected key type, the flags indicate the intended purpose(s)
+ * for the key; the basic key type may be set to 0 to indicate that any
+ * key type compatible with the indicated purpose is acceptable.
+ */
+/** \brief Key type: algorithm is RSA. */
+#define BR_KEYTYPE_RSA 1
+/** \brief Key type: algorithm is EC. */
+#define BR_KEYTYPE_EC 2
+
+/**
+ * \brief Key type: usage is "key exchange".
+ *
+ * This value is combined (with bitwise OR) with the algorithm
+ * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509
+ * validation engine that it should find a public key of that type,
+ * fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher
+ * suites).
+ */
+#define BR_KEYTYPE_KEYX 0x10
+
+/**
+ * \brief Key type: usage is "signature".
+ *
+ * This value is combined (with bitwise OR) with the algorithm
+ * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509
+ * validation engine that it should find a public key of that type,
+ * fit for signatures (e.g. `TLS_ECDHE_*` cipher suites).
+ */
+#define BR_KEYTYPE_SIGN 0x20
+
+/*
+ * start_chain Called when a new chain is started. If 'server_name'
+ * is not NULL and non-empty, then it is a name that
+ * should be looked for in the EE certificate (in the
+ * SAN extension as dNSName, or in the subjectDN's CN
+ * if there is no SAN extension).
+ * The caller ensures that the provided 'server_name'
+ * pointer remains valid throughout validation.
+ *
+ * start_cert Begins a new certificate in the chain. The provided
+ * length is in bytes; this is the total certificate length.
+ *
+ * append Get some additional bytes for the current certificate.
+ *
+ * end_cert Ends the current certificate.
+ *
+ * end_chain Called at the end of the chain. Returned value is
+ * 0 on success, or a non-zero error code.
+ *
+ * get_pkey Returns the EE certificate public key.
+ *
+ * For a complete chain, start_chain() and end_chain() are always
+ * called. For each certificate, start_cert(), some append() calls, then
+ * end_cert() are called, in that order. There may be no append() call
+ * at all if the certificate is empty (which is not valid but may happen
+ * if the peer sends exactly that).
+ *
+ * get_pkey() shall return a pointer to a structure that is valid as
+ * long as a new chain is not started. This may be a sub-structure
+ * within the context for the engine. This function MAY return a valid
+ * pointer to a public key even in some cases of validation failure,
+ * depending on the validation engine.
+ */
+
+/**
+ * \brief Class type for an X.509 engine.
+ *
+ * A certificate chain validation uses a caller-allocated context, which
+ * contains the running state for that validation. Methods are called
+ * in due order:
+ *
+ * - `start_chain()` is called at the start of the validation.
+ * - Certificates are processed one by one, in SSL order (end-entity
+ * comes first). For each certificate, the following methods are
+ * called:
+ *
+ * - `start_cert()` at the beginning of the certificate.
+ * - `append()` is called zero, one or more times, to provide
+ * the certificate (possibly in chunks).
+ * - `end_cert()` at the end of the certificate.
+ *
+ * - `end_chain()` is called when the last certificate in the chain
+ * was processed.
+ * - `get_pkey()` is called after chain processing, if the chain
+ * validation was successful.
+ *
+ * A context structure may be reused; the `start_chain()` method shall
+ * ensure (re)initialisation.
+ */
+typedef struct br_x509_class_ br_x509_class;
+struct br_x509_class_ {
+ /**
+ * \brief X.509 context size, in bytes.
+ */
+ size_t context_size;
+
+ /**
+ * \brief Start a new chain.
+ *
+ * This method shall set the vtable (first field) of the context
+ * structure.
+ *
+ * The `server_name`, if not `NULL`, will be considered as a
+ * fully qualified domain name, to be matched against the `dNSName`
+ * elements of the end-entity certificate's SAN extension (if there
+ * is no SAN, then the Common Name from the subjectDN will be used).
+ * If `server_name` is `NULL` then no such matching is performed.
+ *
+ * \param ctx validation context.
+ * \param server_name server name to match (or `NULL`).
+ */
+ void (*start_chain)(const br_x509_class **ctx,
+ const char *server_name);
+
+ /**
+ * \brief Start a new certificate.
+ *
+ * \param ctx validation context.
+ * \param length new certificate length (in bytes).
+ */
+ void (*start_cert)(const br_x509_class **ctx, uint32_t length);
+
+ /**
+ * \brief Receive some bytes for the current certificate.
+ *
+ * This function may be called several times in succession for
+ * a given certificate. The caller guarantees that for each
+ * call, `len` is not zero, and the sum of all chunk lengths
+ * for a certificate matches the total certificate length which
+ * was provided in the previous `start_cert()` call.
+ *
+ * If the new certificate is empty (no byte at all) then this
+ * function won't be called at all.
+ *
+ * \param ctx validation context.
+ * \param buf certificate data chunk.
+ * \param len certificate data chunk length (in bytes).
+ */
+ void (*append)(const br_x509_class **ctx,
+ const unsigned char *buf, size_t len);
+
+ /**
+ * \brief Finish the current certificate.
+ *
+ * This function is called when the end of the current certificate
+ * is reached.
+ *
+ * \param ctx validation context.
+ */
+ void (*end_cert)(const br_x509_class **ctx);
+
+ /**
+ * \brief Finish the chain.
+ *
+ * This function is called at the end of the chain. It shall
+ * return either 0 if the validation was successful, or a
+ * non-zero error code. The `BR_ERR_X509_*` constants are
+ * error codes, though other values may be possible.
+ *
+ * \param ctx validation context.
+ * \return 0 on success, or a non-zero error code.
+ */
+ unsigned (*end_chain)(const br_x509_class **ctx);
+
+ /**
+ * \brief Get the resulting end-entity public key.
+ *
+ * The decoded public key is returned. The returned pointer
+ * may be valid only as long as the context structure is
+ * unmodified, i.e. it may cease to be valid if the context
+ * is released or reused.
+ *
+ * This function _may_ return `NULL` if the validation failed.
+ * However, returning a public key does not mean that the
+ * validation was wholly successful; some engines may return
+ * a decoded public key even if the chain did not end on a
+ * trusted anchor.
+ *
+ * If validation succeeded and `usage` is not `NULL`, then
+ * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN`
+ * and/or `BR_KEYTYPE_KEYX` that specifies the validated key
+ * usage types. It is the caller's responsibility to check
+ * that value against the intended use of the public key.
+ *
+ * \param ctx validation context.
+ * \return the end-entity public key, or `NULL`.
+ */
+ const br_x509_pkey *(*get_pkey)(
+ const br_x509_class *const *ctx, unsigned *usages);
+};
+
+/**
+ * \brief The "known key" X.509 engine structure.
+ *
+ * The structure contents are opaque (they shall not be accessed directly),
+ * except for the first field (the vtable).
+ *
+ * The "known key" engine returns an externally configured public key,
+ * and totally ignores the certificate contents.
+ */
+typedef struct {
+ /** \brief Reference to the context vtable. */
+ const br_x509_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
+ br_x509_pkey pkey;
+ unsigned usages;
+#endif
+} br_x509_knownkey_context;
+
+/**
+ * \brief Class instance for the "known key" X.509 engine.
+ */
+extern const br_x509_class br_x509_knownkey_vtable;
+
+/**
+ * \brief Initialize a "known key" X.509 engine with a known RSA public key.
+ *
+ * The `usages` parameter indicates the allowed key usages for that key
+ * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
+ *
+ * The provided pointers are linked in, not copied, so they must remain
+ * valid while the public key may be in usage.
+ *
+ * \param ctx context to initialise.
+ * \param pk known public key.
+ * \param usages allowed key usages.
+ */
+void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
+ const br_rsa_public_key *pk, unsigned usages);
+
+/**
+ * \brief Initialize a "known key" X.509 engine with a known EC public key.
+ *
+ * The `usages` parameter indicates the allowed key usages for that key
+ * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
+ *
+ * The provided pointers are linked in, not copied, so they must remain
+ * valid while the public key may be in usage.
+ *
+ * \param ctx context to initialise.
+ * \param pk known public key.
+ * \param usages allowed key usages.
+ */
+void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
+ const br_ec_public_key *pk, unsigned usages);
+
+#ifndef BR_DOXYGEN_IGNORE
+/*
+ * The minimal X.509 engine has some state buffers which must be large
+ * enough to simultaneously accommodate:
+ * -- the public key extracted from the current certificate;
+ * -- the signature on the current certificate or on the previous
+ * certificate;
+ * -- the public key extracted from the EE certificate.
+ *
+ * We store public key elements in their raw unsigned big-endian
+ * encoding. We want to support up to RSA-4096 with a short (up to 64
+ * bits) public exponent, thus a buffer for a public key must have
+ * length at least 520 bytes. Similarly, a RSA-4096 signature has length
+ * 512 bytes.
+ *
+ * Though RSA public exponents can formally be as large as the modulus
+ * (mathematically, even larger exponents would work, but PKCS#1 forbids
+ * them), exponents that do not fit on 32 bits are extremely rare,
+ * notably because some widespread implementations (e.g. Microsoft's
+ * CryptoAPI) don't support them. Moreover, large public exponent do not
+ * seem to imply any tangible security benefit, and they increase the
+ * cost of public key operations. The X.509 "minimal" engine will tolerate
+ * public exponents of arbitrary size as long as the modulus and the
+ * exponent can fit together in the dedicated buffer.
+ *
+ * EC public keys are shorter than RSA public keys; even with curve
+ * NIST P-521 (the largest curve we care to support), a public key is
+ * encoded over 133 bytes only.
+ */
+#define BR_X509_BUFSIZE_KEY 520
+#define BR_X509_BUFSIZE_SIG 512
+#endif
+
+/**
+ * \brief Type for receiving a name element.
+ *
+ * An array of such structures can be provided to the X.509 decoding
+ * engines. If the specified elements are found in the certificate
+ * subject DN or the SAN extension, then the name contents are copied
+ * as zero-terminated strings into the buffer.
+ *
+ * The decoder converts TeletexString and BMPString to UTF8String, and
+ * ensures that the resulting string is zero-terminated. If the string
+ * does not fit in the provided buffer, then the copy is aborted and an
+ * error is reported.
+ */
+typedef struct {
+ /**
+ * \brief Element OID.
+ *
+ * For X.500 name elements (to be extracted from the subject DN),
+ * this is the encoded OID for the requested name element; the
+ * first byte shall contain the length of the DER-encoded OID
+ * value, followed by the OID value (for instance, OID 2.5.4.3,
+ * for id-at-commonName, will be `03 55 04 03`). This is
+ * equivalent to full DER encoding with the length but without
+ * the tag.
+ *
+ * For SAN name elements, the first byte (`oid[0]`) has value 0,
+ * followed by another byte that matches the expected GeneralName
+ * tag. Allowed second byte values are then:
+ *
+ * - 1: `rfc822Name`
+ *
+ * - 2: `dNSName`
+ *
+ * - 6: `uniformResourceIdentifier`
+ *
+ * - 0: `otherName`
+ *
+ * If first and second byte are 0, then this is a SAN element of
+ * type `otherName`; the `oid[]` array should then contain, right
+ * after the two bytes of value 0, an encoded OID (with the same
+ * conventions as for X.500 name elements). If a match is found
+ * for that OID, then the corresponding name element will be
+ * extracted, as long as it is a supported string type.
+ */
+ const unsigned char *oid;
+
+ /**
+ * \brief Destination buffer.
+ */
+ char *buf;
+
+ /**
+ * \brief Length (in bytes) of the destination buffer.
+ *
+ * The buffer MUST NOT be smaller than 1 byte.
+ */
+ size_t len;
+
+ /**
+ * \brief Decoding status.
+ *
+ * Status is 0 if the name element was not found, 1 if it was
+ * found and decoded, or -1 on error. Error conditions include
+ * an unrecognised encoding, an invalid encoding, or a string
+ * too large for the destination buffer.
+ */
+ int status;
+
+} br_name_element;
+
+/**
+ * \brief The "minimal" X.509 engine structure.
+ *
+ * The structure contents are opaque (they shall not be accessed directly),
+ * except for the first field (the vtable).
+ *
+ * The "minimal" engine performs a rudimentary but serviceable X.509 path
+ * validation.
+ */
+typedef struct {
+ const br_x509_class *vtable;
+
+#ifndef BR_DOXYGEN_IGNORE
+ /* Structure for returning the EE public key. */
+ br_x509_pkey pkey;
+
+ /* 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;
+
+ /* Server name to match with the SAN / CN of the EE certificate. */
+ const char *server_name;
+
+ /* Validated key usages. */
+ unsigned char key_usages;
+
+ /* Explicitly set date and time. */
+ uint32_t days, seconds;
+
+ /* Current certificate length (in bytes). Set to 0 when the
+ certificate has been fully processed. */
+ uint32_t cert_length;
+
+ /* Number of certificates processed so far in the current chain.
+ It is incremented at the end of the processing of a certificate,
+ so it is 0 for the EE. */
+ uint32_t num_certs;
+
+ /* Certificate data chunk. */
+ const unsigned char *hbuf;
+ size_t hlen;
+
+ /* The pad serves as destination for various operations. */
+ unsigned char pad[256];
+
+ /* Buffer for EE public key data. */
+ unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY];
+
+ /* Buffer for currently decoded public key. */
+ unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
+
+ /* Signature type: signer key type, offset to the hash
+ function OID (in the T0 data block) and hash function
+ output length (TBS hash length). */
+ unsigned char cert_signer_key_type;
+ uint16_t cert_sig_hash_oid;
+ unsigned char cert_sig_hash_len;
+
+ /* Current/last certificate signature. */
+ unsigned char cert_sig[BR_X509_BUFSIZE_SIG];
+ uint16_t cert_sig_len;
+
+ /* Minimum RSA key length (difference in bytes from 128). */
+ int16_t min_rsa_size;
+
+ /* Configured trust anchors. */
+ const br_x509_trust_anchor *trust_anchors;
+ size_t trust_anchors_num;
+
+ /*
+ * Multi-hasher for the TBS.
+ */
+ unsigned char do_mhash;
+ br_multihash_context mhash;
+ unsigned char tbs_hash[64];
+
+ /*
+ * Simple hasher for the subject/issuer DN.
+ */
+ unsigned char do_dn_hash;
+ const br_hash_class *dn_hash_impl;
+ br_hash_compat_context dn_hash;
+ unsigned char current_dn_hash[64];
+ unsigned char next_dn_hash[64];
+ unsigned char saved_dn_hash[64];
+
+ /*
+ * Name elements to gather.
+ */
+ br_name_element *name_elts;
+ size_t num_name_elts;
+
+ /*
+ * Public key cryptography implementations (signature verification).
+ */
+ br_rsa_pkcs1_vrfy irsa;
+ br_ecdsa_vrfy iecdsa;
+ const br_ec_impl *iec;
+#endif
+
+} br_x509_minimal_context;
+
+/**
+ * \brief Class instance for the "minimal" X.509 engine.
+ */
+extern const br_x509_class br_x509_minimal_vtable;
+
+/**
+ * \brief Initialise a "minimal" X.509 engine.
+ *
+ * The `dn_hash_impl` parameter shall be a hash function internally used
+ * to match X.500 names (subject/issuer DN, and anchor names). Any standard
+ * hash function may be used, but a collision-resistant hash function is
+ * advised.
+ *
+ * After initialization, some implementations for signature verification
+ * (hash functions and signature algorithms) MUST be added.
+ *
+ * \param ctx context to initialise.
+ * \param dn_hash_impl hash function for DN comparisons.
+ * \param trust_anchors trust anchors.
+ * \param trust_anchors_num number of trust anchors.
+ */
+void br_x509_minimal_init(br_x509_minimal_context *ctx,
+ const br_hash_class *dn_hash_impl,
+ const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
+
+/**
+ * \brief Set a supported hash function in an X.509 "minimal" engine.
+ *
+ * Hash functions are used with signature verification algorithms.
+ * Once initialised (with `br_x509_minimal_init()`), the context must
+ * be configured with the hash functions it shall support for that
+ * purpose. The hash function identifier MUST be one of the standard
+ * hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256,
+ * SHA-384 and SHA-512).
+ *
+ * If `impl` is `NULL`, this _removes_ support for the designated
+ * hash function.
+ *
+ * \param ctx validation context.
+ * \param id hash function identifier (from 1 to 6).
+ * \param impl hash function implementation (or `NULL`).
+ */
+static inline void
+br_x509_minimal_set_hash(br_x509_minimal_context *ctx,
+ int id, const br_hash_class *impl)
+{
+ br_multihash_setimpl(&ctx->mhash, id, impl);
+}
+
+/**
+ * \brief Set a RSA signature verification implementation in the X.509
+ * "minimal" engine.
+ *
+ * Once initialised (with `br_x509_minimal_init()`), the context must
+ * be configured with the signature verification implementations that
+ * it is supposed to support. If `irsa` is `0`, then the RSA support
+ * is disabled.
+ *
+ * \param ctx validation context.
+ * \param irsa RSA signature verification implementation (or `0`).
+ */
+static inline void
+br_x509_minimal_set_rsa(br_x509_minimal_context *ctx,
+ br_rsa_pkcs1_vrfy irsa)
+{
+ ctx->irsa = irsa;
+}
+
+/**
+ * \brief Set a ECDSA signature verification implementation in the X.509
+ * "minimal" engine.
+ *
+ * Once initialised (with `br_x509_minimal_init()`), the context must
+ * be configured with the signature verification implementations that
+ * it is supposed to support.
+ *
+ * If `iecdsa` is `0`, then this call disables ECDSA support; in that
+ * case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function
+ * that verifies ECDSA signatures with format "asn1", and it will use
+ * `iec` as underlying elliptic curve support.
+ *
+ * \param ctx validation context.
+ * \param iec elliptic curve implementation (or `NULL`).
+ * \param iecdsa ECDSA implementation (or `0`).
+ */
+static inline void
+br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx,
+ const br_ec_impl *iec, br_ecdsa_vrfy iecdsa)
+{
+ ctx->iecdsa = iecdsa;
+ ctx->iec = iec;
+}
+
+/**
+ * \brief Initialise a "minimal" X.509 engine with default algorithms.
+ *
+ * This function performs the same job as `br_x509_minimal_init()`, but
+ * also sets implementations for RSA, ECDSA, and the standard hash
+ * functions.
+ *
+ * \param ctx context to initialise.
+ * \param trust_anchors trust anchors.
+ * \param trust_anchors_num number of trust anchors.
+ */
+void br_x509_minimal_init_full(br_x509_minimal_context *ctx,
+ const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
+
+/**
+ * \brief Set the validation time for the X.509 "minimal" engine.
+ *
+ * The validation time is set as two 32-bit integers, for days and
+ * seconds since a fixed epoch:
+ *
+ * - Days are counted in a proleptic Gregorian calendar since
+ * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD";
+ * it is also traditionally known as "1 BC".
+ *
+ * - Seconds are counted since midnight, from 0 to 86400 (a count of
+ * 86400 is possible only if a leap second happened).
+ *
+ * The validation date and time is understood in the UTC time zone.
+ *
+ * If the validation date and time are not explicitly set, but BearSSL
+ * was compiled with support for the system clock on the underlying
+ * platform, then the current time will automatically be used. Otherwise,
+ * not setting the validation date and time implies a validation
+ * failure (except in case of direct trust of the EE key).
+ *
+ * \param ctx validation context.
+ * \param days days since January 1st, 0 AD (Gregorian calendar).
+ * \param seconds seconds since midnight (0 to 86400).
+ */
+static inline void
+br_x509_minimal_set_time(br_x509_minimal_context *ctx,
+ uint32_t days, uint32_t seconds)
+{
+ ctx->days = days;
+ ctx->seconds = seconds;
+}
+
+/**
+ * \brief Set the minimal acceptable length for RSA keys (X.509 "minimal"
+ * engine).
+ *
+ * The RSA key length is expressed in bytes. The default minimum key
+ * length is 128 bytes, corresponding to 1017 bits. RSA keys shorter
+ * than the configured length will be rejected, implying validation
+ * failure. This setting applies to keys extracted from certificates
+ * (both end-entity, and intermediate CA) but not to "CA" trust anchors.
+ *
+ * \param ctx validation context.
+ * \param byte_length minimum RSA key length, **in bytes** (not bits).
+ */
+static inline void
+br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length)
+{
+ ctx->min_rsa_size = (int16_t)(byte_length - 128);
+}
+
+/**
+ * \brief Set the name elements to gather.
+ *
+ * The provided array is linked in the context. The elements are
+ * gathered from the EE certificate. If the same element type is
+ * requested several times, then the relevant structures will be filled
+ * in the order the matching values are encountered in the certificate.
+ *
+ * \param ctx validation context.
+ * \param elts array of name element structures to fill.
+ * \param num_elts number of name element structures to fill.
+ */
+static inline void
+br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx,
+ br_name_element *elts, size_t num_elts)
+{
+ ctx->name_elts = elts;
+ ctx->num_name_elts = num_elts;
+}
+
+/**
+ * \brief X.509 decoder context.
+ *
+ * This structure is _not_ for X.509 validation, but for extracting
+ * names and public keys from encoded certificates. Intended usage is
+ * to use (self-signed) certificates as trust anchors.
+ *
+ * Contents are opaque and shall not be accessed directly.
+ */
+typedef struct {
+
+#ifndef BR_DOXYGEN_IGNORE
+ /* Structure for returning the public key. */
+ br_x509_pkey pkey;
+
+ /* 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;
+
+ /* The pad serves as destination for various operations. */
+ unsigned char pad[256];
+
+ /* Flag set when decoding succeeds. */
+ unsigned char decoded;
+
+ /* Validity dates. */
+ uint32_t notbefore_days, notbefore_seconds;
+ uint32_t notafter_days, notafter_seconds;
+
+ /* The "CA" flag. This is set to true if the certificate contains
+ a Basic Constraints extension that asserts CA status. */
+ unsigned char isCA;
+
+ /* DN processing: the subject DN is extracted and pushed to the
+ provided callback. */
+ unsigned char copy_dn;
+ void *append_dn_ctx;
+ void (*append_dn)(void *ctx, const void *buf, size_t len);
+
+ /* Certificate data chunk. */
+ const unsigned char *hbuf;
+ size_t hlen;
+
+ /* Buffer for decoded public key. */
+ unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
+
+ /* Type of key and hash function used in the certificate signature. */
+ unsigned char signer_key_type;
+ unsigned char signer_hash_id;
+#endif
+
+} br_x509_decoder_context;
+
+/**
+ * \brief Initialise an X.509 decoder context for processing a new
+ * certificate.
+ *
+ * The `append_dn()` callback (with opaque context `append_dn_ctx`)
+ * will be invoked to receive, chunk by chunk, the certificate's
+ * subject DN. If `append_dn` is `0` then the subject DN will be
+ * ignored.
+ *
+ * \param ctx X.509 decoder context to initialise.
+ * \param append_dn DN receiver callback (or `0`).
+ * \param append_dn_ctx context for the DN receiver callback.
+ */
+void br_x509_decoder_init(br_x509_decoder_context *ctx,
+ void (*append_dn)(void *ctx, const void *buf, size_t len),
+ void *append_dn_ctx);
+
+/**
+ * \brief Push some certificate bytes into a decoder context.
+ *
+ * If `len` is non-zero, then that many bytes are pushed, from address
+ * `data`, into the provided decoder context.
+ *
+ * \param ctx X.509 decoder context.
+ * \param data certificate data chunk.
+ * \param len certificate data chunk length (in bytes).
+ */
+void br_x509_decoder_push(br_x509_decoder_context *ctx,
+ const void *data, size_t len);
+
+/**
+ * \brief Obtain the decoded public key.
+ *
+ * Returned value is a pointer to a structure internal to the decoder
+ * context; releasing or reusing the decoder context invalidates that
+ * structure.
+ *
+ * If decoding was not finished, or failed, then `NULL` is returned.
+ *
+ * \param ctx X.509 decoder context.
+ * \return the public key, or `NULL` on unfinished/error.
+ */
+static inline br_x509_pkey *
+br_x509_decoder_get_pkey(br_x509_decoder_context *ctx)
+{
+ if (ctx->decoded && ctx->err == 0) {
+ return &ctx->pkey;
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * \brief Get decoder error status.
+ *
+ * If no error was reported yet but the certificate decoding is not
+ * finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding
+ * was successful, then 0 is returned.
+ *
+ * \param ctx X.509 decoder context.
+ * \return 0 on successful decoding, or a non-zero error code.
+ */
+static inline int
+br_x509_decoder_last_error(br_x509_decoder_context *ctx)
+{
+ if (ctx->err != 0) {
+ return ctx->err;
+ }
+ if (!ctx->decoded) {
+ return BR_ERR_X509_TRUNCATED;
+ }
+ return 0;
+}
+
+/**
+ * \brief Get the "isCA" flag from an X.509 decoder context.
+ *
+ * This flag is set if the decoded certificate claims to be a CA through
+ * a Basic Constraints extension. This flag should not be read before
+ * decoding completed successfully.
+ *
+ * \param ctx X.509 decoder context.
+ * \return the "isCA" flag.
+ */
+static inline int
+br_x509_decoder_isCA(br_x509_decoder_context *ctx)
+{
+ return ctx->isCA;
+}
+
+/**
+ * \brief Get the issuing CA key type (type of algorithm used to sign the
+ * decoded certificate).
+ *
+ * This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned
+ * if the signature type was not recognised.
+ *
+ * \param ctx X.509 decoder context.
+ * \return the issuing CA key type.
+ */
+static inline int
+br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx)
+{
+ return ctx->signer_key_type;
+}
+
+/**
+ * \brief Get the identifier for the hash function used to sign the decoded
+ * certificate.
+ *
+ * This is 0 if the hash function was not recognised.
+ *
+ * \param ctx X.509 decoder context.
+ * \return the signature hash function identifier.
+ */
+static inline int
+br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx)
+{
+ return ctx->signer_hash_id;
+}
+
+/**
+ * \brief Type for an X.509 certificate (DER-encoded).
+ */
+typedef struct {
+ /** \brief The DER-encoded certificate data. */
+ unsigned char *data;
+ /** \brief The DER-encoded certificate length (in bytes). */
+ size_t data_len;
+} br_x509_certificate;
+
+/**
+ * \brief Private key decoder context.
+ *
+ * The private key decoder recognises RSA and EC private keys, either in
+ * their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8
+ * archive (again DER-encoded).
+ *
+ * Structure contents are opaque and shall not be accessed directly.
+ */
+typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
+ /* Structure for returning the private key. */
+ union {
+ br_rsa_private_key rsa;
+ br_ec_private_key ec;
+ } key;
+
+ /* 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;
+
+ /* Private key data chunk. */
+ const unsigned char *hbuf;
+ size_t hlen;
+
+ /* The pad serves as destination for various operations. */
+ unsigned char pad[256];
+
+ /* Decoded key type; 0 until decoding is complete. */
+ unsigned char key_type;
+
+ /* Buffer for the private key elements. It shall be large enough
+ to accommodate all elements for a RSA-4096 private key (roughly
+ five 2048-bit integers, possibly a bit more). */
+ unsigned char key_data[3 * BR_X509_BUFSIZE_SIG];
+#endif
+} br_skey_decoder_context;
+
+/**
+ * \brief Initialise a private key decoder context.
+ *
+ * \param ctx key decoder context to initialise.
+ */
+void br_skey_decoder_init(br_skey_decoder_context *ctx);
+
+/**
+ * \brief Push some data bytes into a private key decoder context.
+ *
+ * If `len` is non-zero, then that many data bytes, starting at address
+ * `data`, are pushed into the decoder.
+ *
+ * \param ctx key decoder context.
+ * \param data private key data chunk.
+ * \param len private key data chunk length (in bytes).
+ */
+void br_skey_decoder_push(br_skey_decoder_context *ctx,
+ const void *data, size_t len);
+
+/**
+ * \brief Get the decoding status for a private key.
+ *
+ * Decoding status is 0 on success, or a non-zero error code. If the
+ * decoding is unfinished when this function is called, then the
+ * status code `BR_ERR_X509_TRUNCATED` is returned.
+ *
+ * \param ctx key decoder context.
+ * \return 0 on successful decoding, or a non-zero error code.
+ */
+static inline int
+br_skey_decoder_last_error(const br_skey_decoder_context *ctx)
+{
+ if (ctx->err != 0) {
+ return ctx->err;
+ }
+ if (ctx->key_type == 0) {
+ return BR_ERR_X509_TRUNCATED;
+ }
+ return 0;
+}
+
+/**
+ * \brief Get the decoded private key type.
+ *
+ * Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is
+ * not finished or failed, then 0 is returned.
+ *
+ * \param ctx key decoder context.
+ * \return decoded private key type, or 0.
+ */
+static inline int
+br_skey_decoder_key_type(const br_skey_decoder_context *ctx)
+{
+ if (ctx->err == 0) {
+ return ctx->key_type;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * \brief Get the decoded RSA private key.
+ *
+ * This function returns `NULL` if the decoding failed, or is not
+ * finished, or the key is not RSA. The returned pointer references
+ * structures within the context that can become invalid if the context
+ * is reused or released.
+ *
+ * \param ctx key decoder context.
+ * \return decoded RSA private key, or `NULL`.
+ */
+static inline const br_rsa_private_key *
+br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx)
+{
+ if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) {
+ return &ctx->key.rsa;
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * \brief Get the decoded EC private key.
+ *
+ * This function returns `NULL` if the decoding failed, or is not
+ * finished, or the key is not EC. The returned pointer references
+ * structures within the context that can become invalid if the context
+ * is reused or released.
+ *
+ * \param ctx key decoder context.
+ * \return decoded EC private key, or `NULL`.
+ */
+static inline const br_ec_private_key *
+br_skey_decoder_get_ec(const br_skey_decoder_context *ctx)
+{
+ if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) {
+ return &ctx->key.ec;
+ } else {
+ return NULL;
+ }
+}
+
+/**
+ * \brief Encode an RSA private key (raw DER format).
+ *
+ * This function encodes the provided key into the "raw" format specified
+ * in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER
+ * encoding rules.
+ *
+ * The key elements are:
+ *
+ * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`)
+ *
+ * - `pk`: the public key (`n` and `e`)
+ *
+ * - `d` (size: `dlen` bytes): the private exponent
+ *
+ * The public key elements, and the private exponent `d`, can be
+ * recomputed from the private key (see `br_rsa_compute_modulus()`,
+ * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`).
+ *
+ * If `dest` is not `NULL`, then the encoded key is written at that
+ * address, and the encoded length (in bytes) is returned. If `dest` is
+ * `NULL`, then nothing is written, but the encoded length is still
+ * computed and returned.
+ *
+ * \param dest the destination buffer (or `NULL`).
+ * \param sk the RSA private key.
+ * \param pk the RSA public key.
+ * \param d the RSA private exponent.
+ * \param dlen the RSA private exponent length (in bytes).
+ * \return the encoded key length (in bytes).
+ */
+size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk,
+ const br_rsa_public_key *pk, const void *d, size_t dlen);
+
+/**
+ * \brief Encode an RSA private key (PKCS#8 DER format).
+ *
+ * This function encodes the provided key into the PKCS#8 format
+ * (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER"
+ * format for the RSA key, as implemented by `br_encode_rsa_raw_der()`.
+ *
+ * The key elements are:
+ *
+ * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`)
+ *
+ * - `pk`: the public key (`n` and `e`)
+ *
+ * - `d` (size: `dlen` bytes): the private exponent
+ *
+ * The public key elements, and the private exponent `d`, can be
+ * recomputed from the private key (see `br_rsa_compute_modulus()`,
+ * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`).
+ *
+ * If `dest` is not `NULL`, then the encoded key is written at that
+ * address, and the encoded length (in bytes) is returned. If `dest` is
+ * `NULL`, then nothing is written, but the encoded length is still
+ * computed and returned.
+ *
+ * \param dest the destination buffer (or `NULL`).
+ * \param sk the RSA private key.
+ * \param pk the RSA public key.
+ * \param d the RSA private exponent.
+ * \param dlen the RSA private exponent length (in bytes).
+ * \return the encoded key length (in bytes).
+ */
+size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk,
+ const br_rsa_public_key *pk, const void *d, size_t dlen);
+
+/**
+ * \brief Encode an EC private key (raw DER format).
+ *
+ * This function encodes the provided key into the "raw" format specified
+ * in RFC 5915 (type `ECPrivateKey`), with DER encoding rules.
+ *
+ * The private key is provided in `sk`, the public key being `pk`. If
+ * `pk` is `NULL`, then the encoded key will not include the public key
+ * in its `publicKey` field (which is nominally optional).
+ *
+ * If `dest` is not `NULL`, then the encoded key is written at that
+ * address, and the encoded length (in bytes) is returned. If `dest` is
+ * `NULL`, then nothing is written, but the encoded length is still
+ * computed and returned.
+ *
+ * If the key cannot be encoded (e.g. because there is no known OBJECT
+ * IDENTIFIER for the used curve), then 0 is returned.
+ *
+ * \param dest the destination buffer (or `NULL`).
+ * \param sk the EC private key.
+ * \param pk the EC public key (or `NULL`).
+ * \return the encoded key length (in bytes), or 0.
+ */
+size_t br_encode_ec_raw_der(void *dest,
+ const br_ec_private_key *sk, const br_ec_public_key *pk);
+
+/**
+ * \brief Encode an EC private key (PKCS#8 DER format).
+ *
+ * This function encodes the provided key into the PKCS#8 format
+ * (RFC 5958, type `OneAsymmetricKey`). The curve is identified
+ * by an OID provided as parameters to the `privateKeyAlgorithm`
+ * field. The private key value (contents of the `privateKey` field)
+ * contains the DER encoding of the `ECPrivateKey` type defined in
+ * RFC 5915, without the `parameters` field (since they would be
+ * redundant with the information in `privateKeyAlgorithm`).
+ *
+ * The private key is provided in `sk`, the public key being `pk`. If
+ * `pk` is not `NULL`, then the encoded public key is included in the
+ * `publicKey` field of the private key value (but not in the `publicKey`
+ * field of the PKCS#8 `OneAsymmetricKey` wrapper).
+ *
+ * If `dest` is not `NULL`, then the encoded key is written at that
+ * address, and the encoded length (in bytes) is returned. If `dest` is
+ * `NULL`, then nothing is written, but the encoded length is still
+ * computed and returned.
+ *
+ * If the key cannot be encoded (e.g. because there is no known OBJECT
+ * IDENTIFIER for the used curve), then 0 is returned.
+ *
+ * \param dest the destination buffer (or `NULL`).
+ * \param sk the EC private key.
+ * \param pk the EC public key (or `NULL`).
+ * \return the encoded key length (in bytes), or 0.
+ */
+size_t br_encode_ec_pkcs8_der(void *dest,
+ const br_ec_private_key *sk, const br_ec_public_key *pk);
+
+/**
+ * \brief PEM banner for RSA private key (raw).
+ */
+#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY"
+
+/**
+ * \brief PEM banner for EC private key (raw).
+ */
+#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY"
+
+/**
+ * \brief PEM banner for an RSA or EC private key in PKCS#8 format.
+ */
+#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Property changes on: stable/12/contrib/bearssl/inc/bearssl_x509.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/mk/Defaults.mk
===================================================================
--- stable/12/contrib/bearssl/mk/Defaults.mk (nonexistent)
+++ stable/12/contrib/bearssl/mk/Defaults.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/mk/Defaults.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/mk/NMake.mk
===================================================================
--- stable/12/contrib/bearssl/mk/NMake.mk (nonexistent)
+++ stable/12/contrib/bearssl/mk/NMake.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/mk/NMake.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/mk/Rules.mk
===================================================================
--- stable/12/contrib/bearssl/mk/Rules.mk (nonexistent)
+++ stable/12/contrib/bearssl/mk/Rules.mk (revision 346145)
@@ -0,0 +1,1318 @@
+# Automatically generated rules. Use 'mkrules.sh' to modify/regenerate.
+
+OBJ = \
+ $(OBJDIR)$Psettings$O \
+ $(OBJDIR)$Pccm$O \
+ $(OBJDIR)$Peax$O \
+ $(OBJDIR)$Pgcm$O \
+ $(OBJDIR)$Pccopy$O \
+ $(OBJDIR)$Pdec16be$O \
+ $(OBJDIR)$Pdec16le$O \
+ $(OBJDIR)$Pdec32be$O \
+ $(OBJDIR)$Pdec32le$O \
+ $(OBJDIR)$Pdec64be$O \
+ $(OBJDIR)$Pdec64le$O \
+ $(OBJDIR)$Penc16be$O \
+ $(OBJDIR)$Penc16le$O \
+ $(OBJDIR)$Penc32be$O \
+ $(OBJDIR)$Penc32le$O \
+ $(OBJDIR)$Penc64be$O \
+ $(OBJDIR)$Penc64le$O \
+ $(OBJDIR)$Ppemdec$O \
+ $(OBJDIR)$Ppemenc$O \
+ $(OBJDIR)$Pec_all_m15$O \
+ $(OBJDIR)$Pec_all_m31$O \
+ $(OBJDIR)$Pec_c25519_i15$O \
+ $(OBJDIR)$Pec_c25519_i31$O \
+ $(OBJDIR)$Pec_c25519_m15$O \
+ $(OBJDIR)$Pec_c25519_m31$O \
+ $(OBJDIR)$Pec_c25519_m62$O \
+ $(OBJDIR)$Pec_c25519_m64$O \
+ $(OBJDIR)$Pec_curve25519$O \
+ $(OBJDIR)$Pec_default$O \
+ $(OBJDIR)$Pec_keygen$O \
+ $(OBJDIR)$Pec_p256_m15$O \
+ $(OBJDIR)$Pec_p256_m31$O \
+ $(OBJDIR)$Pec_p256_m62$O \
+ $(OBJDIR)$Pec_p256_m64$O \
+ $(OBJDIR)$Pec_prime_i15$O \
+ $(OBJDIR)$Pec_prime_i31$O \
+ $(OBJDIR)$Pec_pubkey$O \
+ $(OBJDIR)$Pec_secp256r1$O \
+ $(OBJDIR)$Pec_secp384r1$O \
+ $(OBJDIR)$Pec_secp521r1$O \
+ $(OBJDIR)$Pecdsa_atr$O \
+ $(OBJDIR)$Pecdsa_default_sign_asn1$O \
+ $(OBJDIR)$Pecdsa_default_sign_raw$O \
+ $(OBJDIR)$Pecdsa_default_vrfy_asn1$O \
+ $(OBJDIR)$Pecdsa_default_vrfy_raw$O \
+ $(OBJDIR)$Pecdsa_i15_bits$O \
+ $(OBJDIR)$Pecdsa_i15_sign_asn1$O \
+ $(OBJDIR)$Pecdsa_i15_sign_raw$O \
+ $(OBJDIR)$Pecdsa_i15_vrfy_asn1$O \
+ $(OBJDIR)$Pecdsa_i15_vrfy_raw$O \
+ $(OBJDIR)$Pecdsa_i31_bits$O \
+ $(OBJDIR)$Pecdsa_i31_sign_asn1$O \
+ $(OBJDIR)$Pecdsa_i31_sign_raw$O \
+ $(OBJDIR)$Pecdsa_i31_vrfy_asn1$O \
+ $(OBJDIR)$Pecdsa_i31_vrfy_raw$O \
+ $(OBJDIR)$Pecdsa_rta$O \
+ $(OBJDIR)$Pdig_oid$O \
+ $(OBJDIR)$Pdig_size$O \
+ $(OBJDIR)$Pghash_ctmul$O \
+ $(OBJDIR)$Pghash_ctmul32$O \
+ $(OBJDIR)$Pghash_ctmul64$O \
+ $(OBJDIR)$Pghash_pclmul$O \
+ $(OBJDIR)$Pghash_pwr8$O \
+ $(OBJDIR)$Pmd5$O \
+ $(OBJDIR)$Pmd5sha1$O \
+ $(OBJDIR)$Pmgf1$O \
+ $(OBJDIR)$Pmultihash$O \
+ $(OBJDIR)$Psha1$O \
+ $(OBJDIR)$Psha2big$O \
+ $(OBJDIR)$Psha2small$O \
+ $(OBJDIR)$Pi15_add$O \
+ $(OBJDIR)$Pi15_bitlen$O \
+ $(OBJDIR)$Pi15_decmod$O \
+ $(OBJDIR)$Pi15_decode$O \
+ $(OBJDIR)$Pi15_decred$O \
+ $(OBJDIR)$Pi15_encode$O \
+ $(OBJDIR)$Pi15_fmont$O \
+ $(OBJDIR)$Pi15_iszero$O \
+ $(OBJDIR)$Pi15_moddiv$O \
+ $(OBJDIR)$Pi15_modpow$O \
+ $(OBJDIR)$Pi15_modpow2$O \
+ $(OBJDIR)$Pi15_montmul$O \
+ $(OBJDIR)$Pi15_mulacc$O \
+ $(OBJDIR)$Pi15_muladd$O \
+ $(OBJDIR)$Pi15_ninv15$O \
+ $(OBJDIR)$Pi15_reduce$O \
+ $(OBJDIR)$Pi15_rshift$O \
+ $(OBJDIR)$Pi15_sub$O \
+ $(OBJDIR)$Pi15_tmont$O \
+ $(OBJDIR)$Pi31_add$O \
+ $(OBJDIR)$Pi31_bitlen$O \
+ $(OBJDIR)$Pi31_decmod$O \
+ $(OBJDIR)$Pi31_decode$O \
+ $(OBJDIR)$Pi31_decred$O \
+ $(OBJDIR)$Pi31_encode$O \
+ $(OBJDIR)$Pi31_fmont$O \
+ $(OBJDIR)$Pi31_iszero$O \
+ $(OBJDIR)$Pi31_moddiv$O \
+ $(OBJDIR)$Pi31_modpow$O \
+ $(OBJDIR)$Pi31_modpow2$O \
+ $(OBJDIR)$Pi31_montmul$O \
+ $(OBJDIR)$Pi31_mulacc$O \
+ $(OBJDIR)$Pi31_muladd$O \
+ $(OBJDIR)$Pi31_ninv31$O \
+ $(OBJDIR)$Pi31_reduce$O \
+ $(OBJDIR)$Pi31_rshift$O \
+ $(OBJDIR)$Pi31_sub$O \
+ $(OBJDIR)$Pi31_tmont$O \
+ $(OBJDIR)$Pi32_add$O \
+ $(OBJDIR)$Pi32_bitlen$O \
+ $(OBJDIR)$Pi32_decmod$O \
+ $(OBJDIR)$Pi32_decode$O \
+ $(OBJDIR)$Pi32_decred$O \
+ $(OBJDIR)$Pi32_div32$O \
+ $(OBJDIR)$Pi32_encode$O \
+ $(OBJDIR)$Pi32_fmont$O \
+ $(OBJDIR)$Pi32_iszero$O \
+ $(OBJDIR)$Pi32_modpow$O \
+ $(OBJDIR)$Pi32_montmul$O \
+ $(OBJDIR)$Pi32_mulacc$O \
+ $(OBJDIR)$Pi32_muladd$O \
+ $(OBJDIR)$Pi32_ninv32$O \
+ $(OBJDIR)$Pi32_reduce$O \
+ $(OBJDIR)$Pi32_sub$O \
+ $(OBJDIR)$Pi32_tmont$O \
+ $(OBJDIR)$Pi62_modpow2$O \
+ $(OBJDIR)$Phkdf$O \
+ $(OBJDIR)$Pshake$O \
+ $(OBJDIR)$Phmac$O \
+ $(OBJDIR)$Phmac_ct$O \
+ $(OBJDIR)$Paesctr_drbg$O \
+ $(OBJDIR)$Phmac_drbg$O \
+ $(OBJDIR)$Psysrng$O \
+ $(OBJDIR)$Prsa_default_keygen$O \
+ $(OBJDIR)$Prsa_default_modulus$O \
+ $(OBJDIR)$Prsa_default_oaep_decrypt$O \
+ $(OBJDIR)$Prsa_default_oaep_encrypt$O \
+ $(OBJDIR)$Prsa_default_pkcs1_sign$O \
+ $(OBJDIR)$Prsa_default_pkcs1_vrfy$O \
+ $(OBJDIR)$Prsa_default_priv$O \
+ $(OBJDIR)$Prsa_default_privexp$O \
+ $(OBJDIR)$Prsa_default_pss_sign$O \
+ $(OBJDIR)$Prsa_default_pss_vrfy$O \
+ $(OBJDIR)$Prsa_default_pub$O \
+ $(OBJDIR)$Prsa_default_pubexp$O \
+ $(OBJDIR)$Prsa_i15_keygen$O \
+ $(OBJDIR)$Prsa_i15_modulus$O \
+ $(OBJDIR)$Prsa_i15_oaep_decrypt$O \
+ $(OBJDIR)$Prsa_i15_oaep_encrypt$O \
+ $(OBJDIR)$Prsa_i15_pkcs1_sign$O \
+ $(OBJDIR)$Prsa_i15_pkcs1_vrfy$O \
+ $(OBJDIR)$Prsa_i15_priv$O \
+ $(OBJDIR)$Prsa_i15_privexp$O \
+ $(OBJDIR)$Prsa_i15_pss_sign$O \
+ $(OBJDIR)$Prsa_i15_pss_vrfy$O \
+ $(OBJDIR)$Prsa_i15_pub$O \
+ $(OBJDIR)$Prsa_i15_pubexp$O \
+ $(OBJDIR)$Prsa_i31_keygen$O \
+ $(OBJDIR)$Prsa_i31_keygen_inner$O \
+ $(OBJDIR)$Prsa_i31_modulus$O \
+ $(OBJDIR)$Prsa_i31_oaep_decrypt$O \
+ $(OBJDIR)$Prsa_i31_oaep_encrypt$O \
+ $(OBJDIR)$Prsa_i31_pkcs1_sign$O \
+ $(OBJDIR)$Prsa_i31_pkcs1_vrfy$O \
+ $(OBJDIR)$Prsa_i31_priv$O \
+ $(OBJDIR)$Prsa_i31_privexp$O \
+ $(OBJDIR)$Prsa_i31_pss_sign$O \
+ $(OBJDIR)$Prsa_i31_pss_vrfy$O \
+ $(OBJDIR)$Prsa_i31_pub$O \
+ $(OBJDIR)$Prsa_i31_pubexp$O \
+ $(OBJDIR)$Prsa_i32_oaep_decrypt$O \
+ $(OBJDIR)$Prsa_i32_oaep_encrypt$O \
+ $(OBJDIR)$Prsa_i32_pkcs1_sign$O \
+ $(OBJDIR)$Prsa_i32_pkcs1_vrfy$O \
+ $(OBJDIR)$Prsa_i32_priv$O \
+ $(OBJDIR)$Prsa_i32_pss_sign$O \
+ $(OBJDIR)$Prsa_i32_pss_vrfy$O \
+ $(OBJDIR)$Prsa_i32_pub$O \
+ $(OBJDIR)$Prsa_i62_keygen$O \
+ $(OBJDIR)$Prsa_i62_oaep_decrypt$O \
+ $(OBJDIR)$Prsa_i62_oaep_encrypt$O \
+ $(OBJDIR)$Prsa_i62_pkcs1_sign$O \
+ $(OBJDIR)$Prsa_i62_pkcs1_vrfy$O \
+ $(OBJDIR)$Prsa_i62_priv$O \
+ $(OBJDIR)$Prsa_i62_pss_sign$O \
+ $(OBJDIR)$Prsa_i62_pss_vrfy$O \
+ $(OBJDIR)$Prsa_i62_pub$O \
+ $(OBJDIR)$Prsa_oaep_pad$O \
+ $(OBJDIR)$Prsa_oaep_unpad$O \
+ $(OBJDIR)$Prsa_pkcs1_sig_pad$O \
+ $(OBJDIR)$Prsa_pkcs1_sig_unpad$O \
+ $(OBJDIR)$Prsa_pss_sig_pad$O \
+ $(OBJDIR)$Prsa_pss_sig_unpad$O \
+ $(OBJDIR)$Prsa_ssl_decrypt$O \
+ $(OBJDIR)$Pprf$O \
+ $(OBJDIR)$Pprf_md5sha1$O \
+ $(OBJDIR)$Pprf_sha256$O \
+ $(OBJDIR)$Pprf_sha384$O \
+ $(OBJDIR)$Pssl_ccert_single_ec$O \
+ $(OBJDIR)$Pssl_ccert_single_rsa$O \
+ $(OBJDIR)$Pssl_client$O \
+ $(OBJDIR)$Pssl_client_default_rsapub$O \
+ $(OBJDIR)$Pssl_client_full$O \
+ $(OBJDIR)$Pssl_engine$O \
+ $(OBJDIR)$Pssl_engine_default_aescbc$O \
+ $(OBJDIR)$Pssl_engine_default_aesccm$O \
+ $(OBJDIR)$Pssl_engine_default_aesgcm$O \
+ $(OBJDIR)$Pssl_engine_default_chapol$O \
+ $(OBJDIR)$Pssl_engine_default_descbc$O \
+ $(OBJDIR)$Pssl_engine_default_ec$O \
+ $(OBJDIR)$Pssl_engine_default_ecdsa$O \
+ $(OBJDIR)$Pssl_engine_default_rsavrfy$O \
+ $(OBJDIR)$Pssl_hashes$O \
+ $(OBJDIR)$Pssl_hs_client$O \
+ $(OBJDIR)$Pssl_hs_server$O \
+ $(OBJDIR)$Pssl_io$O \
+ $(OBJDIR)$Pssl_keyexport$O \
+ $(OBJDIR)$Pssl_lru$O \
+ $(OBJDIR)$Pssl_rec_cbc$O \
+ $(OBJDIR)$Pssl_rec_ccm$O \
+ $(OBJDIR)$Pssl_rec_chapol$O \
+ $(OBJDIR)$Pssl_rec_gcm$O \
+ $(OBJDIR)$Pssl_scert_single_ec$O \
+ $(OBJDIR)$Pssl_scert_single_rsa$O \
+ $(OBJDIR)$Pssl_server$O \
+ $(OBJDIR)$Pssl_server_full_ec$O \
+ $(OBJDIR)$Pssl_server_full_rsa$O \
+ $(OBJDIR)$Pssl_server_mine2c$O \
+ $(OBJDIR)$Pssl_server_mine2g$O \
+ $(OBJDIR)$Pssl_server_minf2c$O \
+ $(OBJDIR)$Pssl_server_minf2g$O \
+ $(OBJDIR)$Pssl_server_minr2g$O \
+ $(OBJDIR)$Pssl_server_minu2g$O \
+ $(OBJDIR)$Pssl_server_minv2g$O \
+ $(OBJDIR)$Paes_big_cbcdec$O \
+ $(OBJDIR)$Paes_big_cbcenc$O \
+ $(OBJDIR)$Paes_big_ctr$O \
+ $(OBJDIR)$Paes_big_ctrcbc$O \
+ $(OBJDIR)$Paes_big_dec$O \
+ $(OBJDIR)$Paes_big_enc$O \
+ $(OBJDIR)$Paes_common$O \
+ $(OBJDIR)$Paes_ct$O \
+ $(OBJDIR)$Paes_ct64$O \
+ $(OBJDIR)$Paes_ct64_cbcdec$O \
+ $(OBJDIR)$Paes_ct64_cbcenc$O \
+ $(OBJDIR)$Paes_ct64_ctr$O \
+ $(OBJDIR)$Paes_ct64_ctrcbc$O \
+ $(OBJDIR)$Paes_ct64_dec$O \
+ $(OBJDIR)$Paes_ct64_enc$O \
+ $(OBJDIR)$Paes_ct_cbcdec$O \
+ $(OBJDIR)$Paes_ct_cbcenc$O \
+ $(OBJDIR)$Paes_ct_ctr$O \
+ $(OBJDIR)$Paes_ct_ctrcbc$O \
+ $(OBJDIR)$Paes_ct_dec$O \
+ $(OBJDIR)$Paes_ct_enc$O \
+ $(OBJDIR)$Paes_pwr8$O \
+ $(OBJDIR)$Paes_pwr8_cbcdec$O \
+ $(OBJDIR)$Paes_pwr8_cbcenc$O \
+ $(OBJDIR)$Paes_pwr8_ctr$O \
+ $(OBJDIR)$Paes_pwr8_ctrcbc$O \
+ $(OBJDIR)$Paes_small_cbcdec$O \
+ $(OBJDIR)$Paes_small_cbcenc$O \
+ $(OBJDIR)$Paes_small_ctr$O \
+ $(OBJDIR)$Paes_small_ctrcbc$O \
+ $(OBJDIR)$Paes_small_dec$O \
+ $(OBJDIR)$Paes_small_enc$O \
+ $(OBJDIR)$Paes_x86ni$O \
+ $(OBJDIR)$Paes_x86ni_cbcdec$O \
+ $(OBJDIR)$Paes_x86ni_cbcenc$O \
+ $(OBJDIR)$Paes_x86ni_ctr$O \
+ $(OBJDIR)$Paes_x86ni_ctrcbc$O \
+ $(OBJDIR)$Pchacha20_ct$O \
+ $(OBJDIR)$Pchacha20_sse2$O \
+ $(OBJDIR)$Pdes_ct$O \
+ $(OBJDIR)$Pdes_ct_cbcdec$O \
+ $(OBJDIR)$Pdes_ct_cbcenc$O \
+ $(OBJDIR)$Pdes_support$O \
+ $(OBJDIR)$Pdes_tab$O \
+ $(OBJDIR)$Pdes_tab_cbcdec$O \
+ $(OBJDIR)$Pdes_tab_cbcenc$O \
+ $(OBJDIR)$Ppoly1305_ctmul$O \
+ $(OBJDIR)$Ppoly1305_ctmul32$O \
+ $(OBJDIR)$Ppoly1305_ctmulq$O \
+ $(OBJDIR)$Ppoly1305_i15$O \
+ $(OBJDIR)$Pasn1enc$O \
+ $(OBJDIR)$Pencode_ec_pk8der$O \
+ $(OBJDIR)$Pencode_ec_rawder$O \
+ $(OBJDIR)$Pencode_rsa_pk8der$O \
+ $(OBJDIR)$Pencode_rsa_rawder$O \
+ $(OBJDIR)$Pskey_decoder$O \
+ $(OBJDIR)$Px509_decoder$O \
+ $(OBJDIR)$Px509_knownkey$O \
+ $(OBJDIR)$Px509_minimal$O \
+ $(OBJDIR)$Px509_minimal_full$O
+OBJBRSSL = \
+ $(OBJDIR)$Pbrssl$O \
+ $(OBJDIR)$Pcerts$O \
+ $(OBJDIR)$Pchain$O \
+ $(OBJDIR)$Pclient$O \
+ $(OBJDIR)$Perrors$O \
+ $(OBJDIR)$Pfiles$O \
+ $(OBJDIR)$Pimpl$O \
+ $(OBJDIR)$Pkeys$O \
+ $(OBJDIR)$Pnames$O \
+ $(OBJDIR)$Pserver$O \
+ $(OBJDIR)$Pskey$O \
+ $(OBJDIR)$Psslio$O \
+ $(OBJDIR)$Pta$O \
+ $(OBJDIR)$Ptwrch$O \
+ $(OBJDIR)$Pvector$O \
+ $(OBJDIR)$Pverify$O \
+ $(OBJDIR)$Pxmem$O
+OBJTESTCRYPTO = \
+ $(OBJDIR)$Ptest_crypto$O
+OBJTESTSPEED = \
+ $(OBJDIR)$Ptest_speed$O
+OBJTESTX509 = \
+ $(OBJDIR)$Ptest_x509$O
+HEADERSPUB = inc$Pbearssl.h inc$Pbearssl_aead.h inc$Pbearssl_block.h inc$Pbearssl_ec.h inc$Pbearssl_hash.h inc$Pbearssl_hmac.h inc$Pbearssl_kdf.h inc$Pbearssl_pem.h inc$Pbearssl_prf.h inc$Pbearssl_rand.h inc$Pbearssl_rsa.h inc$Pbearssl_ssl.h inc$Pbearssl_x509.h
+HEADERSPRIV = $(HEADERSPUB) src$Pconfig.h src$Pinner.h
+HEADERSTOOLS = $(HEADERSPUB) tools$Pbrssl.h
+T0SRC = T0$PBlobWriter.cs T0$PCPU.cs T0$PCodeElement.cs T0$PCodeElementJump.cs T0$PCodeElementUInt.cs T0$PCodeElementUIntExpr.cs T0$PCodeElementUIntInt.cs T0$PCodeElementUIntUInt.cs T0$PConstData.cs T0$POpcode.cs T0$POpcodeCall.cs T0$POpcodeConst.cs T0$POpcodeGetLocal.cs T0$POpcodeJump.cs T0$POpcodeJumpIf.cs T0$POpcodeJumpIfNot.cs T0$POpcodeJumpUncond.cs T0$POpcodePutLocal.cs T0$POpcodeRet.cs T0$PSType.cs T0$PT0Comp.cs T0$PTPointerBase.cs T0$PTPointerBlob.cs T0$PTPointerExpr.cs T0$PTPointerNull.cs T0$PTPointerXT.cs T0$PTValue.cs T0$PWord.cs T0$PWordBuilder.cs T0$PWordData.cs T0$PWordInterpreted.cs T0$PWordNative.cs
+T0KERN =
+
+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)
+
+$(OBJDIR)$Psettings$O: src$Psettings.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Psettings$O src$Psettings.c
+
+$(OBJDIR)$Pccm$O: src$Paead$Pccm.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pccm$O src$Paead$Pccm.c
+
+$(OBJDIR)$Peax$O: src$Paead$Peax.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Peax$O src$Paead$Peax.c
+
+$(OBJDIR)$Pgcm$O: src$Paead$Pgcm.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pgcm$O src$Paead$Pgcm.c
+
+$(OBJDIR)$Pccopy$O: src$Pcodec$Pccopy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pccopy$O src$Pcodec$Pccopy.c
+
+$(OBJDIR)$Pdec16be$O: src$Pcodec$Pdec16be.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdec16be$O src$Pcodec$Pdec16be.c
+
+$(OBJDIR)$Pdec16le$O: src$Pcodec$Pdec16le.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdec16le$O src$Pcodec$Pdec16le.c
+
+$(OBJDIR)$Pdec32be$O: src$Pcodec$Pdec32be.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdec32be$O src$Pcodec$Pdec32be.c
+
+$(OBJDIR)$Pdec32le$O: src$Pcodec$Pdec32le.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdec32le$O src$Pcodec$Pdec32le.c
+
+$(OBJDIR)$Pdec64be$O: src$Pcodec$Pdec64be.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdec64be$O src$Pcodec$Pdec64be.c
+
+$(OBJDIR)$Pdec64le$O: src$Pcodec$Pdec64le.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdec64le$O src$Pcodec$Pdec64le.c
+
+$(OBJDIR)$Penc16be$O: src$Pcodec$Penc16be.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Penc16be$O src$Pcodec$Penc16be.c
+
+$(OBJDIR)$Penc16le$O: src$Pcodec$Penc16le.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Penc16le$O src$Pcodec$Penc16le.c
+
+$(OBJDIR)$Penc32be$O: src$Pcodec$Penc32be.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Penc32be$O src$Pcodec$Penc32be.c
+
+$(OBJDIR)$Penc32le$O: src$Pcodec$Penc32le.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Penc32le$O src$Pcodec$Penc32le.c
+
+$(OBJDIR)$Penc64be$O: src$Pcodec$Penc64be.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Penc64be$O src$Pcodec$Penc64be.c
+
+$(OBJDIR)$Penc64le$O: src$Pcodec$Penc64le.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Penc64le$O src$Pcodec$Penc64le.c
+
+$(OBJDIR)$Ppemdec$O: src$Pcodec$Ppemdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ppemdec$O src$Pcodec$Ppemdec.c
+
+$(OBJDIR)$Ppemenc$O: src$Pcodec$Ppemenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ppemenc$O src$Pcodec$Ppemenc.c
+
+$(OBJDIR)$Pec_all_m15$O: src$Pec$Pec_all_m15.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_all_m15$O src$Pec$Pec_all_m15.c
+
+$(OBJDIR)$Pec_all_m31$O: src$Pec$Pec_all_m31.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_all_m31$O src$Pec$Pec_all_m31.c
+
+$(OBJDIR)$Pec_c25519_i15$O: src$Pec$Pec_c25519_i15.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_c25519_i15$O src$Pec$Pec_c25519_i15.c
+
+$(OBJDIR)$Pec_c25519_i31$O: src$Pec$Pec_c25519_i31.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_c25519_i31$O src$Pec$Pec_c25519_i31.c
+
+$(OBJDIR)$Pec_c25519_m15$O: src$Pec$Pec_c25519_m15.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_c25519_m15$O src$Pec$Pec_c25519_m15.c
+
+$(OBJDIR)$Pec_c25519_m31$O: src$Pec$Pec_c25519_m31.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_c25519_m31$O src$Pec$Pec_c25519_m31.c
+
+$(OBJDIR)$Pec_c25519_m62$O: src$Pec$Pec_c25519_m62.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_c25519_m62$O src$Pec$Pec_c25519_m62.c
+
+$(OBJDIR)$Pec_c25519_m64$O: src$Pec$Pec_c25519_m64.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_c25519_m64$O src$Pec$Pec_c25519_m64.c
+
+$(OBJDIR)$Pec_curve25519$O: src$Pec$Pec_curve25519.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_curve25519$O src$Pec$Pec_curve25519.c
+
+$(OBJDIR)$Pec_default$O: src$Pec$Pec_default.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_default$O src$Pec$Pec_default.c
+
+$(OBJDIR)$Pec_keygen$O: src$Pec$Pec_keygen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_keygen$O src$Pec$Pec_keygen.c
+
+$(OBJDIR)$Pec_p256_m15$O: src$Pec$Pec_p256_m15.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_p256_m15$O src$Pec$Pec_p256_m15.c
+
+$(OBJDIR)$Pec_p256_m31$O: src$Pec$Pec_p256_m31.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_p256_m31$O src$Pec$Pec_p256_m31.c
+
+$(OBJDIR)$Pec_p256_m62$O: src$Pec$Pec_p256_m62.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_p256_m62$O src$Pec$Pec_p256_m62.c
+
+$(OBJDIR)$Pec_p256_m64$O: src$Pec$Pec_p256_m64.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_p256_m64$O src$Pec$Pec_p256_m64.c
+
+$(OBJDIR)$Pec_prime_i15$O: src$Pec$Pec_prime_i15.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_prime_i15$O src$Pec$Pec_prime_i15.c
+
+$(OBJDIR)$Pec_prime_i31$O: src$Pec$Pec_prime_i31.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_prime_i31$O src$Pec$Pec_prime_i31.c
+
+$(OBJDIR)$Pec_pubkey$O: src$Pec$Pec_pubkey.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_pubkey$O src$Pec$Pec_pubkey.c
+
+$(OBJDIR)$Pec_secp256r1$O: src$Pec$Pec_secp256r1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_secp256r1$O src$Pec$Pec_secp256r1.c
+
+$(OBJDIR)$Pec_secp384r1$O: src$Pec$Pec_secp384r1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_secp384r1$O src$Pec$Pec_secp384r1.c
+
+$(OBJDIR)$Pec_secp521r1$O: src$Pec$Pec_secp521r1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_secp521r1$O src$Pec$Pec_secp521r1.c
+
+$(OBJDIR)$Pecdsa_atr$O: src$Pec$Pecdsa_atr.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_atr$O src$Pec$Pecdsa_atr.c
+
+$(OBJDIR)$Pecdsa_default_sign_asn1$O: src$Pec$Pecdsa_default_sign_asn1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_sign_asn1$O src$Pec$Pecdsa_default_sign_asn1.c
+
+$(OBJDIR)$Pecdsa_default_sign_raw$O: src$Pec$Pecdsa_default_sign_raw.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_sign_raw$O src$Pec$Pecdsa_default_sign_raw.c
+
+$(OBJDIR)$Pecdsa_default_vrfy_asn1$O: src$Pec$Pecdsa_default_vrfy_asn1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_vrfy_asn1$O src$Pec$Pecdsa_default_vrfy_asn1.c
+
+$(OBJDIR)$Pecdsa_default_vrfy_raw$O: src$Pec$Pecdsa_default_vrfy_raw.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_vrfy_raw$O src$Pec$Pecdsa_default_vrfy_raw.c
+
+$(OBJDIR)$Pecdsa_i15_bits$O: src$Pec$Pecdsa_i15_bits.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i15_bits$O src$Pec$Pecdsa_i15_bits.c
+
+$(OBJDIR)$Pecdsa_i15_sign_asn1$O: src$Pec$Pecdsa_i15_sign_asn1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i15_sign_asn1$O src$Pec$Pecdsa_i15_sign_asn1.c
+
+$(OBJDIR)$Pecdsa_i15_sign_raw$O: src$Pec$Pecdsa_i15_sign_raw.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i15_sign_raw$O src$Pec$Pecdsa_i15_sign_raw.c
+
+$(OBJDIR)$Pecdsa_i15_vrfy_asn1$O: src$Pec$Pecdsa_i15_vrfy_asn1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i15_vrfy_asn1$O src$Pec$Pecdsa_i15_vrfy_asn1.c
+
+$(OBJDIR)$Pecdsa_i15_vrfy_raw$O: src$Pec$Pecdsa_i15_vrfy_raw.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i15_vrfy_raw$O src$Pec$Pecdsa_i15_vrfy_raw.c
+
+$(OBJDIR)$Pecdsa_i31_bits$O: src$Pec$Pecdsa_i31_bits.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i31_bits$O src$Pec$Pecdsa_i31_bits.c
+
+$(OBJDIR)$Pecdsa_i31_sign_asn1$O: src$Pec$Pecdsa_i31_sign_asn1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i31_sign_asn1$O src$Pec$Pecdsa_i31_sign_asn1.c
+
+$(OBJDIR)$Pecdsa_i31_sign_raw$O: src$Pec$Pecdsa_i31_sign_raw.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i31_sign_raw$O src$Pec$Pecdsa_i31_sign_raw.c
+
+$(OBJDIR)$Pecdsa_i31_vrfy_asn1$O: src$Pec$Pecdsa_i31_vrfy_asn1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i31_vrfy_asn1$O src$Pec$Pecdsa_i31_vrfy_asn1.c
+
+$(OBJDIR)$Pecdsa_i31_vrfy_raw$O: src$Pec$Pecdsa_i31_vrfy_raw.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i31_vrfy_raw$O src$Pec$Pecdsa_i31_vrfy_raw.c
+
+$(OBJDIR)$Pecdsa_rta$O: src$Pec$Pecdsa_rta.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_rta$O src$Pec$Pecdsa_rta.c
+
+$(OBJDIR)$Pdig_oid$O: src$Phash$Pdig_oid.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdig_oid$O src$Phash$Pdig_oid.c
+
+$(OBJDIR)$Pdig_size$O: src$Phash$Pdig_size.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdig_size$O src$Phash$Pdig_size.c
+
+$(OBJDIR)$Pghash_ctmul$O: src$Phash$Pghash_ctmul.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pghash_ctmul$O src$Phash$Pghash_ctmul.c
+
+$(OBJDIR)$Pghash_ctmul32$O: src$Phash$Pghash_ctmul32.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pghash_ctmul32$O src$Phash$Pghash_ctmul32.c
+
+$(OBJDIR)$Pghash_ctmul64$O: src$Phash$Pghash_ctmul64.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pghash_ctmul64$O src$Phash$Pghash_ctmul64.c
+
+$(OBJDIR)$Pghash_pclmul$O: src$Phash$Pghash_pclmul.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pghash_pclmul$O src$Phash$Pghash_pclmul.c
+
+$(OBJDIR)$Pghash_pwr8$O: src$Phash$Pghash_pwr8.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pghash_pwr8$O src$Phash$Pghash_pwr8.c
+
+$(OBJDIR)$Pmd5$O: src$Phash$Pmd5.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pmd5$O src$Phash$Pmd5.c
+
+$(OBJDIR)$Pmd5sha1$O: src$Phash$Pmd5sha1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pmd5sha1$O src$Phash$Pmd5sha1.c
+
+$(OBJDIR)$Pmgf1$O: src$Phash$Pmgf1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pmgf1$O src$Phash$Pmgf1.c
+
+$(OBJDIR)$Pmultihash$O: src$Phash$Pmultihash.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pmultihash$O src$Phash$Pmultihash.c
+
+$(OBJDIR)$Psha1$O: src$Phash$Psha1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Psha1$O src$Phash$Psha1.c
+
+$(OBJDIR)$Psha2big$O: src$Phash$Psha2big.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Psha2big$O src$Phash$Psha2big.c
+
+$(OBJDIR)$Psha2small$O: src$Phash$Psha2small.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Psha2small$O src$Phash$Psha2small.c
+
+$(OBJDIR)$Pi15_add$O: src$Pint$Pi15_add.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_add$O src$Pint$Pi15_add.c
+
+$(OBJDIR)$Pi15_bitlen$O: src$Pint$Pi15_bitlen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_bitlen$O src$Pint$Pi15_bitlen.c
+
+$(OBJDIR)$Pi15_decmod$O: src$Pint$Pi15_decmod.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_decmod$O src$Pint$Pi15_decmod.c
+
+$(OBJDIR)$Pi15_decode$O: src$Pint$Pi15_decode.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_decode$O src$Pint$Pi15_decode.c
+
+$(OBJDIR)$Pi15_decred$O: src$Pint$Pi15_decred.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_decred$O src$Pint$Pi15_decred.c
+
+$(OBJDIR)$Pi15_encode$O: src$Pint$Pi15_encode.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_encode$O src$Pint$Pi15_encode.c
+
+$(OBJDIR)$Pi15_fmont$O: src$Pint$Pi15_fmont.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_fmont$O src$Pint$Pi15_fmont.c
+
+$(OBJDIR)$Pi15_iszero$O: src$Pint$Pi15_iszero.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_iszero$O src$Pint$Pi15_iszero.c
+
+$(OBJDIR)$Pi15_moddiv$O: src$Pint$Pi15_moddiv.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_moddiv$O src$Pint$Pi15_moddiv.c
+
+$(OBJDIR)$Pi15_modpow$O: src$Pint$Pi15_modpow.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_modpow$O src$Pint$Pi15_modpow.c
+
+$(OBJDIR)$Pi15_modpow2$O: src$Pint$Pi15_modpow2.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_modpow2$O src$Pint$Pi15_modpow2.c
+
+$(OBJDIR)$Pi15_montmul$O: src$Pint$Pi15_montmul.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_montmul$O src$Pint$Pi15_montmul.c
+
+$(OBJDIR)$Pi15_mulacc$O: src$Pint$Pi15_mulacc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_mulacc$O src$Pint$Pi15_mulacc.c
+
+$(OBJDIR)$Pi15_muladd$O: src$Pint$Pi15_muladd.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_muladd$O src$Pint$Pi15_muladd.c
+
+$(OBJDIR)$Pi15_ninv15$O: src$Pint$Pi15_ninv15.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_ninv15$O src$Pint$Pi15_ninv15.c
+
+$(OBJDIR)$Pi15_reduce$O: src$Pint$Pi15_reduce.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_reduce$O src$Pint$Pi15_reduce.c
+
+$(OBJDIR)$Pi15_rshift$O: src$Pint$Pi15_rshift.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_rshift$O src$Pint$Pi15_rshift.c
+
+$(OBJDIR)$Pi15_sub$O: src$Pint$Pi15_sub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_sub$O src$Pint$Pi15_sub.c
+
+$(OBJDIR)$Pi15_tmont$O: src$Pint$Pi15_tmont.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi15_tmont$O src$Pint$Pi15_tmont.c
+
+$(OBJDIR)$Pi31_add$O: src$Pint$Pi31_add.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_add$O src$Pint$Pi31_add.c
+
+$(OBJDIR)$Pi31_bitlen$O: src$Pint$Pi31_bitlen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_bitlen$O src$Pint$Pi31_bitlen.c
+
+$(OBJDIR)$Pi31_decmod$O: src$Pint$Pi31_decmod.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_decmod$O src$Pint$Pi31_decmod.c
+
+$(OBJDIR)$Pi31_decode$O: src$Pint$Pi31_decode.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_decode$O src$Pint$Pi31_decode.c
+
+$(OBJDIR)$Pi31_decred$O: src$Pint$Pi31_decred.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_decred$O src$Pint$Pi31_decred.c
+
+$(OBJDIR)$Pi31_encode$O: src$Pint$Pi31_encode.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_encode$O src$Pint$Pi31_encode.c
+
+$(OBJDIR)$Pi31_fmont$O: src$Pint$Pi31_fmont.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_fmont$O src$Pint$Pi31_fmont.c
+
+$(OBJDIR)$Pi31_iszero$O: src$Pint$Pi31_iszero.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_iszero$O src$Pint$Pi31_iszero.c
+
+$(OBJDIR)$Pi31_moddiv$O: src$Pint$Pi31_moddiv.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_moddiv$O src$Pint$Pi31_moddiv.c
+
+$(OBJDIR)$Pi31_modpow$O: src$Pint$Pi31_modpow.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_modpow$O src$Pint$Pi31_modpow.c
+
+$(OBJDIR)$Pi31_modpow2$O: src$Pint$Pi31_modpow2.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_modpow2$O src$Pint$Pi31_modpow2.c
+
+$(OBJDIR)$Pi31_montmul$O: src$Pint$Pi31_montmul.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_montmul$O src$Pint$Pi31_montmul.c
+
+$(OBJDIR)$Pi31_mulacc$O: src$Pint$Pi31_mulacc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_mulacc$O src$Pint$Pi31_mulacc.c
+
+$(OBJDIR)$Pi31_muladd$O: src$Pint$Pi31_muladd.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_muladd$O src$Pint$Pi31_muladd.c
+
+$(OBJDIR)$Pi31_ninv31$O: src$Pint$Pi31_ninv31.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_ninv31$O src$Pint$Pi31_ninv31.c
+
+$(OBJDIR)$Pi31_reduce$O: src$Pint$Pi31_reduce.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_reduce$O src$Pint$Pi31_reduce.c
+
+$(OBJDIR)$Pi31_rshift$O: src$Pint$Pi31_rshift.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_rshift$O src$Pint$Pi31_rshift.c
+
+$(OBJDIR)$Pi31_sub$O: src$Pint$Pi31_sub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_sub$O src$Pint$Pi31_sub.c
+
+$(OBJDIR)$Pi31_tmont$O: src$Pint$Pi31_tmont.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi31_tmont$O src$Pint$Pi31_tmont.c
+
+$(OBJDIR)$Pi32_add$O: src$Pint$Pi32_add.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_add$O src$Pint$Pi32_add.c
+
+$(OBJDIR)$Pi32_bitlen$O: src$Pint$Pi32_bitlen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_bitlen$O src$Pint$Pi32_bitlen.c
+
+$(OBJDIR)$Pi32_decmod$O: src$Pint$Pi32_decmod.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_decmod$O src$Pint$Pi32_decmod.c
+
+$(OBJDIR)$Pi32_decode$O: src$Pint$Pi32_decode.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_decode$O src$Pint$Pi32_decode.c
+
+$(OBJDIR)$Pi32_decred$O: src$Pint$Pi32_decred.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_decred$O src$Pint$Pi32_decred.c
+
+$(OBJDIR)$Pi32_div32$O: src$Pint$Pi32_div32.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_div32$O src$Pint$Pi32_div32.c
+
+$(OBJDIR)$Pi32_encode$O: src$Pint$Pi32_encode.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_encode$O src$Pint$Pi32_encode.c
+
+$(OBJDIR)$Pi32_fmont$O: src$Pint$Pi32_fmont.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_fmont$O src$Pint$Pi32_fmont.c
+
+$(OBJDIR)$Pi32_iszero$O: src$Pint$Pi32_iszero.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_iszero$O src$Pint$Pi32_iszero.c
+
+$(OBJDIR)$Pi32_modpow$O: src$Pint$Pi32_modpow.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_modpow$O src$Pint$Pi32_modpow.c
+
+$(OBJDIR)$Pi32_montmul$O: src$Pint$Pi32_montmul.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_montmul$O src$Pint$Pi32_montmul.c
+
+$(OBJDIR)$Pi32_mulacc$O: src$Pint$Pi32_mulacc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_mulacc$O src$Pint$Pi32_mulacc.c
+
+$(OBJDIR)$Pi32_muladd$O: src$Pint$Pi32_muladd.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_muladd$O src$Pint$Pi32_muladd.c
+
+$(OBJDIR)$Pi32_ninv32$O: src$Pint$Pi32_ninv32.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_ninv32$O src$Pint$Pi32_ninv32.c
+
+$(OBJDIR)$Pi32_reduce$O: src$Pint$Pi32_reduce.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_reduce$O src$Pint$Pi32_reduce.c
+
+$(OBJDIR)$Pi32_sub$O: src$Pint$Pi32_sub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_sub$O src$Pint$Pi32_sub.c
+
+$(OBJDIR)$Pi32_tmont$O: src$Pint$Pi32_tmont.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi32_tmont$O src$Pint$Pi32_tmont.c
+
+$(OBJDIR)$Pi62_modpow2$O: src$Pint$Pi62_modpow2.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pi62_modpow2$O src$Pint$Pi62_modpow2.c
+
+$(OBJDIR)$Phkdf$O: src$Pkdf$Phkdf.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Phkdf$O src$Pkdf$Phkdf.c
+
+$(OBJDIR)$Pshake$O: src$Pkdf$Pshake.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pshake$O src$Pkdf$Pshake.c
+
+$(OBJDIR)$Phmac$O: src$Pmac$Phmac.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Phmac$O src$Pmac$Phmac.c
+
+$(OBJDIR)$Phmac_ct$O: src$Pmac$Phmac_ct.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Phmac_ct$O src$Pmac$Phmac_ct.c
+
+$(OBJDIR)$Paesctr_drbg$O: src$Prand$Paesctr_drbg.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paesctr_drbg$O src$Prand$Paesctr_drbg.c
+
+$(OBJDIR)$Phmac_drbg$O: src$Prand$Phmac_drbg.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Phmac_drbg$O src$Prand$Phmac_drbg.c
+
+$(OBJDIR)$Psysrng$O: src$Prand$Psysrng.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Psysrng$O src$Prand$Psysrng.c
+
+$(OBJDIR)$Prsa_default_keygen$O: src$Prsa$Prsa_default_keygen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_keygen$O src$Prsa$Prsa_default_keygen.c
+
+$(OBJDIR)$Prsa_default_modulus$O: src$Prsa$Prsa_default_modulus.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_modulus$O src$Prsa$Prsa_default_modulus.c
+
+$(OBJDIR)$Prsa_default_oaep_decrypt$O: src$Prsa$Prsa_default_oaep_decrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_oaep_decrypt$O src$Prsa$Prsa_default_oaep_decrypt.c
+
+$(OBJDIR)$Prsa_default_oaep_encrypt$O: src$Prsa$Prsa_default_oaep_encrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_oaep_encrypt$O src$Prsa$Prsa_default_oaep_encrypt.c
+
+$(OBJDIR)$Prsa_default_pkcs1_sign$O: src$Prsa$Prsa_default_pkcs1_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pkcs1_sign$O src$Prsa$Prsa_default_pkcs1_sign.c
+
+$(OBJDIR)$Prsa_default_pkcs1_vrfy$O: src$Prsa$Prsa_default_pkcs1_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pkcs1_vrfy$O src$Prsa$Prsa_default_pkcs1_vrfy.c
+
+$(OBJDIR)$Prsa_default_priv$O: src$Prsa$Prsa_default_priv.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_priv$O src$Prsa$Prsa_default_priv.c
+
+$(OBJDIR)$Prsa_default_privexp$O: src$Prsa$Prsa_default_privexp.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_privexp$O src$Prsa$Prsa_default_privexp.c
+
+$(OBJDIR)$Prsa_default_pss_sign$O: src$Prsa$Prsa_default_pss_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pss_sign$O src$Prsa$Prsa_default_pss_sign.c
+
+$(OBJDIR)$Prsa_default_pss_vrfy$O: src$Prsa$Prsa_default_pss_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pss_vrfy$O src$Prsa$Prsa_default_pss_vrfy.c
+
+$(OBJDIR)$Prsa_default_pub$O: src$Prsa$Prsa_default_pub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pub$O src$Prsa$Prsa_default_pub.c
+
+$(OBJDIR)$Prsa_default_pubexp$O: src$Prsa$Prsa_default_pubexp.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pubexp$O src$Prsa$Prsa_default_pubexp.c
+
+$(OBJDIR)$Prsa_i15_keygen$O: src$Prsa$Prsa_i15_keygen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_keygen$O src$Prsa$Prsa_i15_keygen.c
+
+$(OBJDIR)$Prsa_i15_modulus$O: src$Prsa$Prsa_i15_modulus.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_modulus$O src$Prsa$Prsa_i15_modulus.c
+
+$(OBJDIR)$Prsa_i15_oaep_decrypt$O: src$Prsa$Prsa_i15_oaep_decrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_oaep_decrypt$O src$Prsa$Prsa_i15_oaep_decrypt.c
+
+$(OBJDIR)$Prsa_i15_oaep_encrypt$O: src$Prsa$Prsa_i15_oaep_encrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_oaep_encrypt$O src$Prsa$Prsa_i15_oaep_encrypt.c
+
+$(OBJDIR)$Prsa_i15_pkcs1_sign$O: src$Prsa$Prsa_i15_pkcs1_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_pkcs1_sign$O src$Prsa$Prsa_i15_pkcs1_sign.c
+
+$(OBJDIR)$Prsa_i15_pkcs1_vrfy$O: src$Prsa$Prsa_i15_pkcs1_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_pkcs1_vrfy$O src$Prsa$Prsa_i15_pkcs1_vrfy.c
+
+$(OBJDIR)$Prsa_i15_priv$O: src$Prsa$Prsa_i15_priv.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_priv$O src$Prsa$Prsa_i15_priv.c
+
+$(OBJDIR)$Prsa_i15_privexp$O: src$Prsa$Prsa_i15_privexp.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_privexp$O src$Prsa$Prsa_i15_privexp.c
+
+$(OBJDIR)$Prsa_i15_pss_sign$O: src$Prsa$Prsa_i15_pss_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_pss_sign$O src$Prsa$Prsa_i15_pss_sign.c
+
+$(OBJDIR)$Prsa_i15_pss_vrfy$O: src$Prsa$Prsa_i15_pss_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_pss_vrfy$O src$Prsa$Prsa_i15_pss_vrfy.c
+
+$(OBJDIR)$Prsa_i15_pub$O: src$Prsa$Prsa_i15_pub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_pub$O src$Prsa$Prsa_i15_pub.c
+
+$(OBJDIR)$Prsa_i15_pubexp$O: src$Prsa$Prsa_i15_pubexp.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_pubexp$O src$Prsa$Prsa_i15_pubexp.c
+
+$(OBJDIR)$Prsa_i31_keygen$O: src$Prsa$Prsa_i31_keygen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_keygen$O src$Prsa$Prsa_i31_keygen.c
+
+$(OBJDIR)$Prsa_i31_keygen_inner$O: src$Prsa$Prsa_i31_keygen_inner.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_keygen_inner$O src$Prsa$Prsa_i31_keygen_inner.c
+
+$(OBJDIR)$Prsa_i31_modulus$O: src$Prsa$Prsa_i31_modulus.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_modulus$O src$Prsa$Prsa_i31_modulus.c
+
+$(OBJDIR)$Prsa_i31_oaep_decrypt$O: src$Prsa$Prsa_i31_oaep_decrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_oaep_decrypt$O src$Prsa$Prsa_i31_oaep_decrypt.c
+
+$(OBJDIR)$Prsa_i31_oaep_encrypt$O: src$Prsa$Prsa_i31_oaep_encrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_oaep_encrypt$O src$Prsa$Prsa_i31_oaep_encrypt.c
+
+$(OBJDIR)$Prsa_i31_pkcs1_sign$O: src$Prsa$Prsa_i31_pkcs1_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_pkcs1_sign$O src$Prsa$Prsa_i31_pkcs1_sign.c
+
+$(OBJDIR)$Prsa_i31_pkcs1_vrfy$O: src$Prsa$Prsa_i31_pkcs1_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_pkcs1_vrfy$O src$Prsa$Prsa_i31_pkcs1_vrfy.c
+
+$(OBJDIR)$Prsa_i31_priv$O: src$Prsa$Prsa_i31_priv.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_priv$O src$Prsa$Prsa_i31_priv.c
+
+$(OBJDIR)$Prsa_i31_privexp$O: src$Prsa$Prsa_i31_privexp.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_privexp$O src$Prsa$Prsa_i31_privexp.c
+
+$(OBJDIR)$Prsa_i31_pss_sign$O: src$Prsa$Prsa_i31_pss_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_pss_sign$O src$Prsa$Prsa_i31_pss_sign.c
+
+$(OBJDIR)$Prsa_i31_pss_vrfy$O: src$Prsa$Prsa_i31_pss_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_pss_vrfy$O src$Prsa$Prsa_i31_pss_vrfy.c
+
+$(OBJDIR)$Prsa_i31_pub$O: src$Prsa$Prsa_i31_pub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_pub$O src$Prsa$Prsa_i31_pub.c
+
+$(OBJDIR)$Prsa_i31_pubexp$O: src$Prsa$Prsa_i31_pubexp.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i31_pubexp$O src$Prsa$Prsa_i31_pubexp.c
+
+$(OBJDIR)$Prsa_i32_oaep_decrypt$O: src$Prsa$Prsa_i32_oaep_decrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_oaep_decrypt$O src$Prsa$Prsa_i32_oaep_decrypt.c
+
+$(OBJDIR)$Prsa_i32_oaep_encrypt$O: src$Prsa$Prsa_i32_oaep_encrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_oaep_encrypt$O src$Prsa$Prsa_i32_oaep_encrypt.c
+
+$(OBJDIR)$Prsa_i32_pkcs1_sign$O: src$Prsa$Prsa_i32_pkcs1_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_pkcs1_sign$O src$Prsa$Prsa_i32_pkcs1_sign.c
+
+$(OBJDIR)$Prsa_i32_pkcs1_vrfy$O: src$Prsa$Prsa_i32_pkcs1_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_pkcs1_vrfy$O src$Prsa$Prsa_i32_pkcs1_vrfy.c
+
+$(OBJDIR)$Prsa_i32_priv$O: src$Prsa$Prsa_i32_priv.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_priv$O src$Prsa$Prsa_i32_priv.c
+
+$(OBJDIR)$Prsa_i32_pss_sign$O: src$Prsa$Prsa_i32_pss_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_pss_sign$O src$Prsa$Prsa_i32_pss_sign.c
+
+$(OBJDIR)$Prsa_i32_pss_vrfy$O: src$Prsa$Prsa_i32_pss_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_pss_vrfy$O src$Prsa$Prsa_i32_pss_vrfy.c
+
+$(OBJDIR)$Prsa_i32_pub$O: src$Prsa$Prsa_i32_pub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i32_pub$O src$Prsa$Prsa_i32_pub.c
+
+$(OBJDIR)$Prsa_i62_keygen$O: src$Prsa$Prsa_i62_keygen.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_keygen$O src$Prsa$Prsa_i62_keygen.c
+
+$(OBJDIR)$Prsa_i62_oaep_decrypt$O: src$Prsa$Prsa_i62_oaep_decrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_oaep_decrypt$O src$Prsa$Prsa_i62_oaep_decrypt.c
+
+$(OBJDIR)$Prsa_i62_oaep_encrypt$O: src$Prsa$Prsa_i62_oaep_encrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_oaep_encrypt$O src$Prsa$Prsa_i62_oaep_encrypt.c
+
+$(OBJDIR)$Prsa_i62_pkcs1_sign$O: src$Prsa$Prsa_i62_pkcs1_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_pkcs1_sign$O src$Prsa$Prsa_i62_pkcs1_sign.c
+
+$(OBJDIR)$Prsa_i62_pkcs1_vrfy$O: src$Prsa$Prsa_i62_pkcs1_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_pkcs1_vrfy$O src$Prsa$Prsa_i62_pkcs1_vrfy.c
+
+$(OBJDIR)$Prsa_i62_priv$O: src$Prsa$Prsa_i62_priv.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_priv$O src$Prsa$Prsa_i62_priv.c
+
+$(OBJDIR)$Prsa_i62_pss_sign$O: src$Prsa$Prsa_i62_pss_sign.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_pss_sign$O src$Prsa$Prsa_i62_pss_sign.c
+
+$(OBJDIR)$Prsa_i62_pss_vrfy$O: src$Prsa$Prsa_i62_pss_vrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_pss_vrfy$O src$Prsa$Prsa_i62_pss_vrfy.c
+
+$(OBJDIR)$Prsa_i62_pub$O: src$Prsa$Prsa_i62_pub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i62_pub$O src$Prsa$Prsa_i62_pub.c
+
+$(OBJDIR)$Prsa_oaep_pad$O: src$Prsa$Prsa_oaep_pad.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_oaep_pad$O src$Prsa$Prsa_oaep_pad.c
+
+$(OBJDIR)$Prsa_oaep_unpad$O: src$Prsa$Prsa_oaep_unpad.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_oaep_unpad$O src$Prsa$Prsa_oaep_unpad.c
+
+$(OBJDIR)$Prsa_pkcs1_sig_pad$O: src$Prsa$Prsa_pkcs1_sig_pad.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_pkcs1_sig_pad$O src$Prsa$Prsa_pkcs1_sig_pad.c
+
+$(OBJDIR)$Prsa_pkcs1_sig_unpad$O: src$Prsa$Prsa_pkcs1_sig_unpad.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_pkcs1_sig_unpad$O src$Prsa$Prsa_pkcs1_sig_unpad.c
+
+$(OBJDIR)$Prsa_pss_sig_pad$O: src$Prsa$Prsa_pss_sig_pad.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_pss_sig_pad$O src$Prsa$Prsa_pss_sig_pad.c
+
+$(OBJDIR)$Prsa_pss_sig_unpad$O: src$Prsa$Prsa_pss_sig_unpad.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_pss_sig_unpad$O src$Prsa$Prsa_pss_sig_unpad.c
+
+$(OBJDIR)$Prsa_ssl_decrypt$O: src$Prsa$Prsa_ssl_decrypt.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_ssl_decrypt$O src$Prsa$Prsa_ssl_decrypt.c
+
+$(OBJDIR)$Pprf$O: src$Pssl$Pprf.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pprf$O src$Pssl$Pprf.c
+
+$(OBJDIR)$Pprf_md5sha1$O: src$Pssl$Pprf_md5sha1.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pprf_md5sha1$O src$Pssl$Pprf_md5sha1.c
+
+$(OBJDIR)$Pprf_sha256$O: src$Pssl$Pprf_sha256.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pprf_sha256$O src$Pssl$Pprf_sha256.c
+
+$(OBJDIR)$Pprf_sha384$O: src$Pssl$Pprf_sha384.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pprf_sha384$O src$Pssl$Pprf_sha384.c
+
+$(OBJDIR)$Pssl_ccert_single_ec$O: src$Pssl$Pssl_ccert_single_ec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_ccert_single_ec$O src$Pssl$Pssl_ccert_single_ec.c
+
+$(OBJDIR)$Pssl_ccert_single_rsa$O: src$Pssl$Pssl_ccert_single_rsa.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_ccert_single_rsa$O src$Pssl$Pssl_ccert_single_rsa.c
+
+$(OBJDIR)$Pssl_client$O: src$Pssl$Pssl_client.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_client$O src$Pssl$Pssl_client.c
+
+$(OBJDIR)$Pssl_client_default_rsapub$O: src$Pssl$Pssl_client_default_rsapub.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_client_default_rsapub$O src$Pssl$Pssl_client_default_rsapub.c
+
+$(OBJDIR)$Pssl_client_full$O: src$Pssl$Pssl_client_full.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_client_full$O src$Pssl$Pssl_client_full.c
+
+$(OBJDIR)$Pssl_engine$O: src$Pssl$Pssl_engine.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine$O src$Pssl$Pssl_engine.c
+
+$(OBJDIR)$Pssl_engine_default_aescbc$O: src$Pssl$Pssl_engine_default_aescbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_aescbc$O src$Pssl$Pssl_engine_default_aescbc.c
+
+$(OBJDIR)$Pssl_engine_default_aesccm$O: src$Pssl$Pssl_engine_default_aesccm.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_aesccm$O src$Pssl$Pssl_engine_default_aesccm.c
+
+$(OBJDIR)$Pssl_engine_default_aesgcm$O: src$Pssl$Pssl_engine_default_aesgcm.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_aesgcm$O src$Pssl$Pssl_engine_default_aesgcm.c
+
+$(OBJDIR)$Pssl_engine_default_chapol$O: src$Pssl$Pssl_engine_default_chapol.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_chapol$O src$Pssl$Pssl_engine_default_chapol.c
+
+$(OBJDIR)$Pssl_engine_default_descbc$O: src$Pssl$Pssl_engine_default_descbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_descbc$O src$Pssl$Pssl_engine_default_descbc.c
+
+$(OBJDIR)$Pssl_engine_default_ec$O: src$Pssl$Pssl_engine_default_ec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_ec$O src$Pssl$Pssl_engine_default_ec.c
+
+$(OBJDIR)$Pssl_engine_default_ecdsa$O: src$Pssl$Pssl_engine_default_ecdsa.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_ecdsa$O src$Pssl$Pssl_engine_default_ecdsa.c
+
+$(OBJDIR)$Pssl_engine_default_rsavrfy$O: src$Pssl$Pssl_engine_default_rsavrfy.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_rsavrfy$O src$Pssl$Pssl_engine_default_rsavrfy.c
+
+$(OBJDIR)$Pssl_hashes$O: src$Pssl$Pssl_hashes.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_hashes$O src$Pssl$Pssl_hashes.c
+
+$(OBJDIR)$Pssl_hs_client$O: src$Pssl$Pssl_hs_client.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_hs_client$O src$Pssl$Pssl_hs_client.c
+
+$(OBJDIR)$Pssl_hs_server$O: src$Pssl$Pssl_hs_server.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_hs_server$O src$Pssl$Pssl_hs_server.c
+
+$(OBJDIR)$Pssl_io$O: src$Pssl$Pssl_io.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_io$O src$Pssl$Pssl_io.c
+
+$(OBJDIR)$Pssl_keyexport$O: src$Pssl$Pssl_keyexport.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_keyexport$O src$Pssl$Pssl_keyexport.c
+
+$(OBJDIR)$Pssl_lru$O: src$Pssl$Pssl_lru.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_lru$O src$Pssl$Pssl_lru.c
+
+$(OBJDIR)$Pssl_rec_cbc$O: src$Pssl$Pssl_rec_cbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_rec_cbc$O src$Pssl$Pssl_rec_cbc.c
+
+$(OBJDIR)$Pssl_rec_ccm$O: src$Pssl$Pssl_rec_ccm.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_rec_ccm$O src$Pssl$Pssl_rec_ccm.c
+
+$(OBJDIR)$Pssl_rec_chapol$O: src$Pssl$Pssl_rec_chapol.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_rec_chapol$O src$Pssl$Pssl_rec_chapol.c
+
+$(OBJDIR)$Pssl_rec_gcm$O: src$Pssl$Pssl_rec_gcm.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_rec_gcm$O src$Pssl$Pssl_rec_gcm.c
+
+$(OBJDIR)$Pssl_scert_single_ec$O: src$Pssl$Pssl_scert_single_ec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_scert_single_ec$O src$Pssl$Pssl_scert_single_ec.c
+
+$(OBJDIR)$Pssl_scert_single_rsa$O: src$Pssl$Pssl_scert_single_rsa.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_scert_single_rsa$O src$Pssl$Pssl_scert_single_rsa.c
+
+$(OBJDIR)$Pssl_server$O: src$Pssl$Pssl_server.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server$O src$Pssl$Pssl_server.c
+
+$(OBJDIR)$Pssl_server_full_ec$O: src$Pssl$Pssl_server_full_ec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_full_ec$O src$Pssl$Pssl_server_full_ec.c
+
+$(OBJDIR)$Pssl_server_full_rsa$O: src$Pssl$Pssl_server_full_rsa.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_full_rsa$O src$Pssl$Pssl_server_full_rsa.c
+
+$(OBJDIR)$Pssl_server_mine2c$O: src$Pssl$Pssl_server_mine2c.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_mine2c$O src$Pssl$Pssl_server_mine2c.c
+
+$(OBJDIR)$Pssl_server_mine2g$O: src$Pssl$Pssl_server_mine2g.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_mine2g$O src$Pssl$Pssl_server_mine2g.c
+
+$(OBJDIR)$Pssl_server_minf2c$O: src$Pssl$Pssl_server_minf2c.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_minf2c$O src$Pssl$Pssl_server_minf2c.c
+
+$(OBJDIR)$Pssl_server_minf2g$O: src$Pssl$Pssl_server_minf2g.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_minf2g$O src$Pssl$Pssl_server_minf2g.c
+
+$(OBJDIR)$Pssl_server_minr2g$O: src$Pssl$Pssl_server_minr2g.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_minr2g$O src$Pssl$Pssl_server_minr2g.c
+
+$(OBJDIR)$Pssl_server_minu2g$O: src$Pssl$Pssl_server_minu2g.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_minu2g$O src$Pssl$Pssl_server_minu2g.c
+
+$(OBJDIR)$Pssl_server_minv2g$O: src$Pssl$Pssl_server_minv2g.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_server_minv2g$O src$Pssl$Pssl_server_minv2g.c
+
+$(OBJDIR)$Paes_big_cbcdec$O: src$Psymcipher$Paes_big_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_big_cbcdec$O src$Psymcipher$Paes_big_cbcdec.c
+
+$(OBJDIR)$Paes_big_cbcenc$O: src$Psymcipher$Paes_big_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_big_cbcenc$O src$Psymcipher$Paes_big_cbcenc.c
+
+$(OBJDIR)$Paes_big_ctr$O: src$Psymcipher$Paes_big_ctr.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_big_ctr$O src$Psymcipher$Paes_big_ctr.c
+
+$(OBJDIR)$Paes_big_ctrcbc$O: src$Psymcipher$Paes_big_ctrcbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_big_ctrcbc$O src$Psymcipher$Paes_big_ctrcbc.c
+
+$(OBJDIR)$Paes_big_dec$O: src$Psymcipher$Paes_big_dec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_big_dec$O src$Psymcipher$Paes_big_dec.c
+
+$(OBJDIR)$Paes_big_enc$O: src$Psymcipher$Paes_big_enc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_big_enc$O src$Psymcipher$Paes_big_enc.c
+
+$(OBJDIR)$Paes_common$O: src$Psymcipher$Paes_common.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_common$O src$Psymcipher$Paes_common.c
+
+$(OBJDIR)$Paes_ct$O: src$Psymcipher$Paes_ct.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct$O src$Psymcipher$Paes_ct.c
+
+$(OBJDIR)$Paes_ct64$O: src$Psymcipher$Paes_ct64.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct64$O src$Psymcipher$Paes_ct64.c
+
+$(OBJDIR)$Paes_ct64_cbcdec$O: src$Psymcipher$Paes_ct64_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct64_cbcdec$O src$Psymcipher$Paes_ct64_cbcdec.c
+
+$(OBJDIR)$Paes_ct64_cbcenc$O: src$Psymcipher$Paes_ct64_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct64_cbcenc$O src$Psymcipher$Paes_ct64_cbcenc.c
+
+$(OBJDIR)$Paes_ct64_ctr$O: src$Psymcipher$Paes_ct64_ctr.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct64_ctr$O src$Psymcipher$Paes_ct64_ctr.c
+
+$(OBJDIR)$Paes_ct64_ctrcbc$O: src$Psymcipher$Paes_ct64_ctrcbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct64_ctrcbc$O src$Psymcipher$Paes_ct64_ctrcbc.c
+
+$(OBJDIR)$Paes_ct64_dec$O: src$Psymcipher$Paes_ct64_dec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct64_dec$O src$Psymcipher$Paes_ct64_dec.c
+
+$(OBJDIR)$Paes_ct64_enc$O: src$Psymcipher$Paes_ct64_enc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct64_enc$O src$Psymcipher$Paes_ct64_enc.c
+
+$(OBJDIR)$Paes_ct_cbcdec$O: src$Psymcipher$Paes_ct_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct_cbcdec$O src$Psymcipher$Paes_ct_cbcdec.c
+
+$(OBJDIR)$Paes_ct_cbcenc$O: src$Psymcipher$Paes_ct_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct_cbcenc$O src$Psymcipher$Paes_ct_cbcenc.c
+
+$(OBJDIR)$Paes_ct_ctr$O: src$Psymcipher$Paes_ct_ctr.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct_ctr$O src$Psymcipher$Paes_ct_ctr.c
+
+$(OBJDIR)$Paes_ct_ctrcbc$O: src$Psymcipher$Paes_ct_ctrcbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct_ctrcbc$O src$Psymcipher$Paes_ct_ctrcbc.c
+
+$(OBJDIR)$Paes_ct_dec$O: src$Psymcipher$Paes_ct_dec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct_dec$O src$Psymcipher$Paes_ct_dec.c
+
+$(OBJDIR)$Paes_ct_enc$O: src$Psymcipher$Paes_ct_enc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_ct_enc$O src$Psymcipher$Paes_ct_enc.c
+
+$(OBJDIR)$Paes_pwr8$O: src$Psymcipher$Paes_pwr8.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_pwr8$O src$Psymcipher$Paes_pwr8.c
+
+$(OBJDIR)$Paes_pwr8_cbcdec$O: src$Psymcipher$Paes_pwr8_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_pwr8_cbcdec$O src$Psymcipher$Paes_pwr8_cbcdec.c
+
+$(OBJDIR)$Paes_pwr8_cbcenc$O: src$Psymcipher$Paes_pwr8_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_pwr8_cbcenc$O src$Psymcipher$Paes_pwr8_cbcenc.c
+
+$(OBJDIR)$Paes_pwr8_ctr$O: src$Psymcipher$Paes_pwr8_ctr.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_pwr8_ctr$O src$Psymcipher$Paes_pwr8_ctr.c
+
+$(OBJDIR)$Paes_pwr8_ctrcbc$O: src$Psymcipher$Paes_pwr8_ctrcbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_pwr8_ctrcbc$O src$Psymcipher$Paes_pwr8_ctrcbc.c
+
+$(OBJDIR)$Paes_small_cbcdec$O: src$Psymcipher$Paes_small_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_small_cbcdec$O src$Psymcipher$Paes_small_cbcdec.c
+
+$(OBJDIR)$Paes_small_cbcenc$O: src$Psymcipher$Paes_small_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_small_cbcenc$O src$Psymcipher$Paes_small_cbcenc.c
+
+$(OBJDIR)$Paes_small_ctr$O: src$Psymcipher$Paes_small_ctr.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_small_ctr$O src$Psymcipher$Paes_small_ctr.c
+
+$(OBJDIR)$Paes_small_ctrcbc$O: src$Psymcipher$Paes_small_ctrcbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_small_ctrcbc$O src$Psymcipher$Paes_small_ctrcbc.c
+
+$(OBJDIR)$Paes_small_dec$O: src$Psymcipher$Paes_small_dec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_small_dec$O src$Psymcipher$Paes_small_dec.c
+
+$(OBJDIR)$Paes_small_enc$O: src$Psymcipher$Paes_small_enc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_small_enc$O src$Psymcipher$Paes_small_enc.c
+
+$(OBJDIR)$Paes_x86ni$O: src$Psymcipher$Paes_x86ni.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni$O src$Psymcipher$Paes_x86ni.c
+
+$(OBJDIR)$Paes_x86ni_cbcdec$O: src$Psymcipher$Paes_x86ni_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni_cbcdec$O src$Psymcipher$Paes_x86ni_cbcdec.c
+
+$(OBJDIR)$Paes_x86ni_cbcenc$O: src$Psymcipher$Paes_x86ni_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni_cbcenc$O src$Psymcipher$Paes_x86ni_cbcenc.c
+
+$(OBJDIR)$Paes_x86ni_ctr$O: src$Psymcipher$Paes_x86ni_ctr.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni_ctr$O src$Psymcipher$Paes_x86ni_ctr.c
+
+$(OBJDIR)$Paes_x86ni_ctrcbc$O: src$Psymcipher$Paes_x86ni_ctrcbc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni_ctrcbc$O src$Psymcipher$Paes_x86ni_ctrcbc.c
+
+$(OBJDIR)$Pchacha20_ct$O: src$Psymcipher$Pchacha20_ct.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pchacha20_ct$O src$Psymcipher$Pchacha20_ct.c
+
+$(OBJDIR)$Pchacha20_sse2$O: src$Psymcipher$Pchacha20_sse2.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pchacha20_sse2$O src$Psymcipher$Pchacha20_sse2.c
+
+$(OBJDIR)$Pdes_ct$O: src$Psymcipher$Pdes_ct.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdes_ct$O src$Psymcipher$Pdes_ct.c
+
+$(OBJDIR)$Pdes_ct_cbcdec$O: src$Psymcipher$Pdes_ct_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdes_ct_cbcdec$O src$Psymcipher$Pdes_ct_cbcdec.c
+
+$(OBJDIR)$Pdes_ct_cbcenc$O: src$Psymcipher$Pdes_ct_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdes_ct_cbcenc$O src$Psymcipher$Pdes_ct_cbcenc.c
+
+$(OBJDIR)$Pdes_support$O: src$Psymcipher$Pdes_support.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdes_support$O src$Psymcipher$Pdes_support.c
+
+$(OBJDIR)$Pdes_tab$O: src$Psymcipher$Pdes_tab.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdes_tab$O src$Psymcipher$Pdes_tab.c
+
+$(OBJDIR)$Pdes_tab_cbcdec$O: src$Psymcipher$Pdes_tab_cbcdec.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdes_tab_cbcdec$O src$Psymcipher$Pdes_tab_cbcdec.c
+
+$(OBJDIR)$Pdes_tab_cbcenc$O: src$Psymcipher$Pdes_tab_cbcenc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pdes_tab_cbcenc$O src$Psymcipher$Pdes_tab_cbcenc.c
+
+$(OBJDIR)$Ppoly1305_ctmul$O: src$Psymcipher$Ppoly1305_ctmul.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ppoly1305_ctmul$O src$Psymcipher$Ppoly1305_ctmul.c
+
+$(OBJDIR)$Ppoly1305_ctmul32$O: src$Psymcipher$Ppoly1305_ctmul32.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ppoly1305_ctmul32$O src$Psymcipher$Ppoly1305_ctmul32.c
+
+$(OBJDIR)$Ppoly1305_ctmulq$O: src$Psymcipher$Ppoly1305_ctmulq.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ppoly1305_ctmulq$O src$Psymcipher$Ppoly1305_ctmulq.c
+
+$(OBJDIR)$Ppoly1305_i15$O: src$Psymcipher$Ppoly1305_i15.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ppoly1305_i15$O src$Psymcipher$Ppoly1305_i15.c
+
+$(OBJDIR)$Pasn1enc$O: src$Px509$Pasn1enc.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pasn1enc$O src$Px509$Pasn1enc.c
+
+$(OBJDIR)$Pencode_ec_pk8der$O: src$Px509$Pencode_ec_pk8der.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pencode_ec_pk8der$O src$Px509$Pencode_ec_pk8der.c
+
+$(OBJDIR)$Pencode_ec_rawder$O: src$Px509$Pencode_ec_rawder.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pencode_ec_rawder$O src$Px509$Pencode_ec_rawder.c
+
+$(OBJDIR)$Pencode_rsa_pk8der$O: src$Px509$Pencode_rsa_pk8der.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pencode_rsa_pk8der$O src$Px509$Pencode_rsa_pk8der.c
+
+$(OBJDIR)$Pencode_rsa_rawder$O: src$Px509$Pencode_rsa_rawder.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pencode_rsa_rawder$O src$Px509$Pencode_rsa_rawder.c
+
+$(OBJDIR)$Pskey_decoder$O: src$Px509$Pskey_decoder.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pskey_decoder$O src$Px509$Pskey_decoder.c
+
+$(OBJDIR)$Px509_decoder$O: src$Px509$Px509_decoder.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Px509_decoder$O src$Px509$Px509_decoder.c
+
+$(OBJDIR)$Px509_knownkey$O: src$Px509$Px509_knownkey.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Px509_knownkey$O src$Px509$Px509_knownkey.c
+
+$(OBJDIR)$Px509_minimal$O: src$Px509$Px509_minimal.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Px509_minimal$O src$Px509$Px509_minimal.c
+
+$(OBJDIR)$Px509_minimal_full$O: src$Px509$Px509_minimal_full.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Px509_minimal_full$O src$Px509$Px509_minimal_full.c
+
+$(OBJDIR)$Pbrssl$O: tools$Pbrssl.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pbrssl$O tools$Pbrssl.c
+
+$(OBJDIR)$Pcerts$O: tools$Pcerts.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pcerts$O tools$Pcerts.c
+
+$(OBJDIR)$Pchain$O: tools$Pchain.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pchain$O tools$Pchain.c
+
+$(OBJDIR)$Pclient$O: tools$Pclient.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pclient$O tools$Pclient.c
+
+$(OBJDIR)$Perrors$O: tools$Perrors.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Perrors$O tools$Perrors.c
+
+$(OBJDIR)$Pfiles$O: tools$Pfiles.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pfiles$O tools$Pfiles.c
+
+$(OBJDIR)$Pimpl$O: tools$Pimpl.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pimpl$O tools$Pimpl.c
+
+$(OBJDIR)$Pkeys$O: tools$Pkeys.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pkeys$O tools$Pkeys.c
+
+$(OBJDIR)$Pnames$O: tools$Pnames.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pnames$O tools$Pnames.c
+
+$(OBJDIR)$Pserver$O: tools$Pserver.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pserver$O tools$Pserver.c
+
+$(OBJDIR)$Pskey$O: tools$Pskey.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pskey$O tools$Pskey.c
+
+$(OBJDIR)$Psslio$O: tools$Psslio.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Psslio$O tools$Psslio.c
+
+$(OBJDIR)$Pta$O: tools$Pta.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pta$O tools$Pta.c
+
+$(OBJDIR)$Ptwrch$O: tools$Ptwrch.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ptwrch$O tools$Ptwrch.c
+
+$(OBJDIR)$Pvector$O: tools$Pvector.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pvector$O tools$Pvector.c
+
+$(OBJDIR)$Pverify$O: tools$Pverify.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pverify$O tools$Pverify.c
+
+$(OBJDIR)$Pxmem$O: tools$Pxmem.c $(HEADERSTOOLS)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pxmem$O tools$Pxmem.c
+
+$(OBJDIR)$Ptest_crypto$O: test$Ptest_crypto.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ptest_crypto$O test$Ptest_crypto.c
+
+$(OBJDIR)$Ptest_speed$O: test$Ptest_speed.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Ptest_speed$O test$Ptest_speed.c
+
+$(OBJDIR)$Ptest_x509$O: test$Ptest_x509.c $(HEADERSPRIV)
+ $(CC) $(CFLAGS) $(INCFLAGS) -DSRCDIRNAME=".." $(CCOUT)$(OBJDIR)$Ptest_x509$O test$Ptest_x509.c
Property changes on: stable/12/contrib/bearssl/mk/Rules.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/mk/SingleUnix.mk
===================================================================
--- stable/12/contrib/bearssl/mk/SingleUnix.mk (nonexistent)
+++ stable/12/contrib/bearssl/mk/SingleUnix.mk (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/mk/SingleUnix.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/mk/mkT0.cmd
===================================================================
--- stable/12/contrib/bearssl/mk/mkT0.cmd (nonexistent)
+++ stable/12/contrib/bearssl/mk/mkT0.cmd (revision 346145)
@@ -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%
Index: stable/12/contrib/bearssl/mk/mkT0.sh
===================================================================
--- stable/12/contrib/bearssl/mk/mkT0.sh (nonexistent)
+++ stable/12/contrib/bearssl/mk/mkT0.sh (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/mk/mkT0.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/mk/mkrules.sh
===================================================================
--- stable/12/contrib/bearssl/mk/mkrules.sh (nonexistent)
+++ stable/12/contrib/bearssl/mk/mkrules.sh (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/mk/mkrules.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/README.txt
===================================================================
--- stable/12/contrib/bearssl/samples/README.txt (nonexistent)
+++ stable/12/contrib/bearssl/samples/README.txt (revision 346145)
@@ -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.
Property changes on: stable/12/contrib/bearssl/samples/README.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/cert-ee-ec+rsa.pem
===================================================================
--- stable/12/contrib/bearssl/samples/cert-ee-ec+rsa.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/cert-ee-ec+rsa.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/cert-ee-ec.pem
===================================================================
--- stable/12/contrib/bearssl/samples/cert-ee-ec.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/cert-ee-ec.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/cert-ee-rsa.pem
===================================================================
--- stable/12/contrib/bearssl/samples/cert-ee-rsa.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/cert-ee-rsa.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/cert-ica-ec.pem
===================================================================
--- stable/12/contrib/bearssl/samples/cert-ica-ec.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/cert-ica-ec.pem (revision 346145)
@@ -0,0 +1,10 @@
+-----BEGIN CERTIFICATE-----
+MIIBqTCCAU6gAwIBAgIUINPr4oz+2uajLF478mY6KzZ7sMowCgYIKoZIzj0EAwIwHDELMAkGA1UE
+BhMCQ0ExDTALBgNVBAMTBFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMzcxMjMxMjM1OTU5WjAnMQsw
+CQYDVQQGEwJDQTEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0D
+AQcDQgAEcC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDN
+SZ4Hv9CunebQsycWoaNjMGEwHwYDVR0jBBgwFoAUlUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0O
+BBYEFPDQ8SL5ekgXBns9vbj1zVWcXD5wMA4GA1UdDwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/
+MAoGCCqGSM49BAMCA0kAMEYCIQCF40ZomdYCellmHLdPNS0INjhhfgVI2GlDH+tW6a0GDgIhAIJw
+tGIDSUbIVFkF2XjbUxzgbmb1DxQ7yS04EnCRVvmp
+-----END CERTIFICATE-----
Index: stable/12/contrib/bearssl/samples/cert-ica-rsa.pem
===================================================================
--- stable/12/contrib/bearssl/samples/cert-ica-rsa.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/cert-ica-rsa.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/cert-root-ec.pem
===================================================================
--- stable/12/contrib/bearssl/samples/cert-root-ec.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/cert-root-ec.pem (revision 346145)
@@ -0,0 +1,9 @@
+-----BEGIN CERTIFICATE-----
+MIIBijCCATCgAwIBAgIBCTAKBggqhkjOPQQDAjAcMQswCQYDVQQGEwJDQTENMAsGA1UEAxMEUm9v
+dDAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEyMzU5NTlaMBwxCzAJBgNVBAYTAkNBMQ0wCwYDVQQD
+EwRSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t
+6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eHwuXYxfN/jaNjMGEwHwYDVR0jBBgwFoAU
+lUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0OBBYEFJVBtOJnqvF/vI9582gUWmuSFqJAMA4GA1Ud
+DwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQCz1GCIAoRtqU2h
+x62hec7E+/XxnUGDORWnkliiGrcmxQIgNPq9NHD7ts0xYjTwZsd0bN62+iY93lM4LHbkNV9q/gA=
+-----END CERTIFICATE-----
Index: stable/12/contrib/bearssl/samples/cert-root-rsa.pem
===================================================================
--- stable/12/contrib/bearssl/samples/cert-root-rsa.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/cert-root-rsa.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/chain-ec+rsa.h
===================================================================
--- stable/12/contrib/bearssl/samples/chain-ec+rsa.h (nonexistent)
+++ stable/12/contrib/bearssl/samples/chain-ec+rsa.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/samples/chain-ec+rsa.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/chain-ec.h
===================================================================
--- stable/12/contrib/bearssl/samples/chain-ec.h (nonexistent)
+++ stable/12/contrib/bearssl/samples/chain-ec.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/samples/chain-ec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/chain-rsa.h
===================================================================
--- stable/12/contrib/bearssl/samples/chain-rsa.h (nonexistent)
+++ stable/12/contrib/bearssl/samples/chain-rsa.h (revision 346145)
@@ -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
Property changes on: stable/12/contrib/bearssl/samples/chain-rsa.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/client_basic.c
===================================================================
--- stable/12/contrib/bearssl/samples/client_basic.c (nonexistent)
+++ stable/12/contrib/bearssl/samples/client_basic.c (revision 346145)
@@ -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;
+ }
+}
Property changes on: stable/12/contrib/bearssl/samples/client_basic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/custom_profile.c
===================================================================
--- stable/12/contrib/bearssl/samples/custom_profile.c (nonexistent)
+++ stable/12/contrib/bearssl/samples/custom_profile.c (revision 346145)
@@ -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);
+ */
+}
Property changes on: stable/12/contrib/bearssl/samples/custom_profile.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/key-ec.h
===================================================================
--- stable/12/contrib/bearssl/samples/key-ec.h (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-ec.h (revision 346145)
@@ -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
+};
Property changes on: stable/12/contrib/bearssl/samples/key-ec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/key-ee-ec.pem
===================================================================
--- stable/12/contrib/bearssl/samples/key-ee-ec.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-ee-ec.pem (revision 346145)
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIAORW0IGkHORG0jvCPu1rXVl+eb3IUdiSPo/l3twnYaloAoGCCqGSM49AwEHoUQDQgAE
+Xzidp/9Niq/2NDlGGvw63/Qjqqnq+8UI3gCOvnmlN1hMbd0ByqtH34m2xxcfOPwdIBTdRcDgj5NO
+OAv86ZmhSQ==
+-----END EC PRIVATE KEY-----
Index: stable/12/contrib/bearssl/samples/key-ee-rsa.pem
===================================================================
--- stable/12/contrib/bearssl/samples/key-ee-rsa.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-ee-rsa.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/key-ica-ec.pem
===================================================================
--- stable/12/contrib/bearssl/samples/key-ica-ec.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-ica-ec.pem (revision 346145)
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIEJOkvo4MZ9N+wlTodEzmWor1RauybudPe92K15viDbzoAoGCCqGSM49AwEHoUQDQgAE
+cC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDNSZ4Hv9Cu
+nebQsycWoQ==
+-----END EC PRIVATE KEY-----
Index: stable/12/contrib/bearssl/samples/key-ica-rsa.pem
===================================================================
--- stable/12/contrib/bearssl/samples/key-ica-rsa.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-ica-rsa.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/key-root-ec.pem
===================================================================
--- stable/12/contrib/bearssl/samples/key-root-ec.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-root-ec.pem (revision 346145)
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEINx41f6h/utlj52XNFbIGJdkF3qZy1/g9hH2/yV4t/tnoAoGCCqGSM49AwEHoUQDQgAE
+cXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eH
+wuXYxfN/jQ==
+-----END EC PRIVATE KEY-----
Index: stable/12/contrib/bearssl/samples/key-root-rsa.pem
===================================================================
--- stable/12/contrib/bearssl/samples/key-root-rsa.pem (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-root-rsa.pem (revision 346145)
@@ -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-----
Index: stable/12/contrib/bearssl/samples/key-rsa.h
===================================================================
--- stable/12/contrib/bearssl/samples/key-rsa.h (nonexistent)
+++ stable/12/contrib/bearssl/samples/key-rsa.h (revision 346145)
@@ -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
+};
Property changes on: stable/12/contrib/bearssl/samples/key-rsa.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/samples/server_basic.c
===================================================================
--- stable/12/contrib/bearssl/samples/server_basic.c (nonexistent)
+++ stable/12/contrib/bearssl/samples/server_basic.c (revision 346145)
@@ -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);
+ }
+}
Property changes on: stable/12/contrib/bearssl/samples/server_basic.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/aead/ccm.c
===================================================================
--- stable/12/contrib/bearssl/src/aead/ccm.c (nonexistent)
+++ stable/12/contrib/bearssl/src/aead/ccm.c (revision 346145)
@@ -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);
+}
Property changes on: stable/12/contrib/bearssl/src/aead/ccm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/aead/eax.c
===================================================================
--- stable/12/contrib/bearssl/src/aead/eax.c (nonexistent)
+++ stable/12/contrib/bearssl/src/aead/eax.c (revision 346145)
@@ -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
+};
Property changes on: stable/12/contrib/bearssl/src/aead/eax.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/aead/gcm.c
===================================================================
--- stable/12/contrib/bearssl/src/aead/gcm.c (nonexistent)
+++ stable/12/contrib/bearssl/src/aead/gcm.c (revision 346145)
@@ -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
+};
Property changes on: stable/12/contrib/bearssl/src/aead/gcm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/ccopy.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/ccopy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/ccopy.c (revision 346145)
@@ -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 ++;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/ccopy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/dec16be.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/dec16be.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/dec16be.c (revision 346145)
@@ -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;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/dec16be.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/dec16le.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/dec16le.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/dec16le.c (revision 346145)
@@ -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_dec16le(uint16_t *v, size_t num, const void *src)
+{
+ const unsigned char *buf;
+
+ buf = src;
+ while (num -- > 0) {
+ *v ++ = br_dec16le(buf);
+ buf += 2;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/dec16le.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/dec32be.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/dec32be.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/dec32be.c (revision 346145)
@@ -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_dec32be(uint32_t *v, size_t num, const void *src)
+{
+ const unsigned char *buf;
+
+ buf = src;
+ while (num -- > 0) {
+ *v ++ = br_dec32be(buf);
+ buf += 4;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/dec32be.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/dec32le.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/dec32le.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/dec32le.c (revision 346145)
@@ -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_dec32le(uint32_t *v, size_t num, const void *src)
+{
+ const unsigned char *buf;
+
+ buf = src;
+ while (num -- > 0) {
+ *v ++ = br_dec32le(buf);
+ buf += 4;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/dec32le.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/dec64be.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/dec64be.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/dec64be.c (revision 346145)
@@ -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_dec64be(uint64_t *v, size_t num, const void *src)
+{
+ const unsigned char *buf;
+
+ buf = src;
+ while (num -- > 0) {
+ *v ++ = br_dec64be(buf);
+ buf += 8;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/dec64be.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/dec64le.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/dec64le.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/dec64le.c (revision 346145)
@@ -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_dec64le(uint64_t *v, size_t num, const void *src)
+{
+ const unsigned char *buf;
+
+ buf = src;
+ while (num -- > 0) {
+ *v ++ = br_dec64le(buf);
+ buf += 8;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/dec64le.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/enc16be.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/enc16be.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/enc16be.c (revision 346145)
@@ -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_enc16be(void *dst, const uint16_t *v, size_t num)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ while (num -- > 0) {
+ br_enc16be(buf, *v ++);
+ buf += 2;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/enc16be.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/enc16le.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/enc16le.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/enc16le.c (revision 346145)
@@ -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_enc16le(void *dst, const uint16_t *v, size_t num)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ while (num -- > 0) {
+ br_enc16le(buf, *v ++);
+ buf += 2;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/enc16le.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/enc32be.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/enc32be.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/enc32be.c (revision 346145)
@@ -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_enc32be(void *dst, const uint32_t *v, size_t num)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ while (num -- > 0) {
+ br_enc32be(buf, *v ++);
+ buf += 4;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/enc32be.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/enc32le.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/enc32le.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/enc32le.c (revision 346145)
@@ -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_enc32le(void *dst, const uint32_t *v, size_t num)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ while (num -- > 0) {
+ br_enc32le(buf, *v ++);
+ buf += 4;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/enc32le.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/enc64be.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/enc64be.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/enc64be.c (revision 346145)
@@ -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_enc64be(void *dst, const uint64_t *v, size_t num)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ while (num -- > 0) {
+ br_enc64be(buf, *v ++);
+ buf += 8;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/enc64be.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/enc64le.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/enc64le.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/enc64le.c (revision 346145)
@@ -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_enc64le(void *dst, const uint64_t *v, size_t num)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ while (num -- > 0) {
+ br_enc64le(buf, *v ++);
+ buf += 8;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/codec/enc64le.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/pemdec.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/pemdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/pemdec.c (revision 346145)
@@ -0,0 +1,526 @@
+/* Automatically generated code; do not modify directly. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+} t0_context;
+
+static uint32_t
+t0_parse7E_unsigned(const unsigned char **p)
+{
+ uint32_t x;
+
+ x = 0;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ return x;
+ }
+ }
+}
+
+static int32_t
+t0_parse7E_signed(const unsigned char **p)
+{
+ int neg;
+ uint32_t x;
+
+ neg = ((**p) >> 6) & 1;
+ x = (uint32_t)-neg;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ if (neg) {
+ return -(int32_t)~x - 1;
+ } else {
+ return (int32_t)x;
+ }
+ }
+ }
+}
+
+#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
+#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
+#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
+#define T0_INT1(x) T0_FBYTE(x, 0)
+#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+
+/* static const unsigned char t0_datablock[]; */
+
+
+void br_pem_decoder_init_main(void *t0ctx);
+
+void br_pem_decoder_run(void *t0ctx);
+
+
+
+#include "inner.h"
+
+#define CTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
+
+/* see bearssl_pem.h */
+void
+br_pem_decoder_init(br_pem_decoder_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->cpu.dp = &ctx->dp_stack[0];
+ ctx->cpu.rp = &ctx->rp_stack[0];
+ br_pem_decoder_init_main(&ctx->cpu);
+ br_pem_decoder_run(&ctx->cpu);
+}
+
+/* see bearssl_pem.h */
+size_t
+br_pem_decoder_push(br_pem_decoder_context *ctx,
+ const void *data, size_t len)
+{
+ if (ctx->event) {
+ return 0;
+ }
+ ctx->hbuf = data;
+ ctx->hlen = len;
+ br_pem_decoder_run(&ctx->cpu);
+ return len - ctx->hlen;
+}
+
+/* see bearssl_pem.h */
+int
+br_pem_decoder_event(br_pem_decoder_context *ctx)
+{
+ int event;
+
+ event = ctx->event;
+ ctx->event = 0;
+ return event;
+}
+
+
+
+static const unsigned char t0_datablock[] = {
+ 0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20,
+ 0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x00
+};
+
+static const unsigned char t0_codeblock[] = {
+ 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01,
+ 0x01, 0x08, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_pem_decoder_context, event)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_pem_decoder_context, name)), 0x00, 0x00, 0x05,
+ 0x14, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x03, 0x13, 0x04, 0x76, 0x01,
+ 0x2D, 0x0C, 0x06, 0x05, 0x2E, 0x01, 0x03, 0x2D, 0x00, 0x01, 0x0D, 0x27,
+ 0x05, 0x04, 0x01, 0x03, 0x2D, 0x00, 0x15, 0x2E, 0x01, 0x02, 0x2D, 0x00,
+ 0x01, 0x01, 0x7F, 0x03, 0x00, 0x25, 0x01, 0x00, 0x18, 0x0D, 0x06, 0x03,
+ 0x13, 0x04, 0x3C, 0x01, 0x7F, 0x18, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00,
+ 0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x23, 0x01,
+ 0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x18, 0x0D, 0x06, 0x09, 0x13, 0x01,
+ 0x00, 0x23, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x18, 0x0D, 0x06,
+ 0x06, 0x13, 0x01, 0x7F, 0x00, 0x04, 0x08, 0x13, 0x01, 0x03, 0x2D, 0x01,
+ 0x00, 0x00, 0x13, 0x01, 0x00, 0x03, 0x00, 0x04, 0xFF, 0x33, 0x01, 0x2C,
+ 0x14, 0x01, 0x2D, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x7F, 0x00, 0x14, 0x31,
+ 0x06, 0x02, 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01,
+ 0x02, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00,
+ 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03,
+ 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02,
+ 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D,
+ 0x06, 0x04, 0x13, 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x2E,
+ 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, 0x00,
+ 0x2F, 0x05, 0x04, 0x13, 0x01, 0x03, 0x00, 0x01, 0x3D, 0x0C, 0x06, 0x03,
+ 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x0F, 0x10, 0x06, 0x03, 0x01, 0x03,
+ 0x00, 0x02, 0x00, 0x01, 0x04, 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14,
+ 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06,
+ 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13,
+ 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x20, 0x13, 0x2F, 0x05,
+ 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x03, 0x10, 0x06, 0x03, 0x01,
+ 0x03, 0x00, 0x02, 0x00, 0x01, 0x0A, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x02,
+ 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E,
+ 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02,
+ 0x00, 0x01, 0x10, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1C, 0x02,
+ 0x00, 0x1C, 0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x24, 0x06,
+ 0x02, 0x04, 0x7B, 0x04, 0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04,
+ 0x20, 0x01, 0x7F, 0x00, 0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05,
+ 0x13, 0x20, 0x01, 0x00, 0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00,
+ 0x00, 0x1E, 0x04, 0x5E, 0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x22, 0x01,
+ 0x80, 0x7F, 0x2B, 0x14, 0x06, 0x02, 0x30, 0x00, 0x13, 0x04, 0x6E, 0x00,
+ 0x2C, 0x14, 0x31, 0x05, 0x01, 0x00, 0x13, 0x04, 0x77, 0x00, 0x14, 0x14,
+ 0x01, 0x80, 0x61, 0x0E, 0x1B, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03,
+ 0x01, 0x20, 0x08, 0x00, 0x01, 0x14, 0x03, 0x00, 0x1B, 0x18, 0x05, 0x05,
+ 0x20, 0x2E, 0x01, 0x00, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06,
+ 0x20, 0x02, 0x00, 0x1B, 0x08, 0x00, 0x14, 0x01, 0x0D, 0x0D, 0x06, 0x03,
+ 0x13, 0x04, 0x03, 0x2A, 0x18, 0x1A, 0x1E, 0x1B, 0x1F, 0x1B, 0x04, 0x59,
+ 0x00, 0x19, 0x14, 0x1D, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00,
+ 0x21, 0x1A, 0x11, 0x00, 0x00, 0x2C, 0x01, 0x0A, 0x0C, 0x06, 0x02, 0x04,
+ 0x78, 0x00, 0x01, 0x01, 0x7F, 0x03, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0C,
+ 0x06, 0x09, 0x31, 0x05, 0x04, 0x01, 0x00, 0x03, 0x00, 0x04, 0x70, 0x13,
+ 0x02, 0x00, 0x00, 0x00, 0x14, 0x06, 0x14, 0x1F, 0x14, 0x22, 0x07, 0x17,
+ 0x01, 0x2D, 0x0C, 0x06, 0x08, 0x22, 0x07, 0x1E, 0x01, 0x00, 0x1B, 0x1A,
+ 0x00, 0x04, 0x69, 0x22, 0x1A, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1B,
+ 0x01, 0x20, 0x0B, 0x10, 0x00
+};
+
+static const uint16_t t0_caddr[] = {
+ 0,
+ 5,
+ 10,
+ 15,
+ 19,
+ 24,
+ 29,
+ 67,
+ 149,
+ 384,
+ 396,
+ 431,
+ 450,
+ 460,
+ 479,
+ 523,
+ 534,
+ 539,
+ 549,
+ 574,
+ 601
+};
+
+#define T0_INTERPRETED 29
+
+#define T0_ENTER(ip, rp, slot) do { \
+ const unsigned char *t0_newip; \
+ uint32_t t0_lnum; \
+ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
+ t0_lnum = t0_parse7E_unsigned(&t0_newip); \
+ (rp) += t0_lnum; \
+ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
+ (ip) = t0_newip; \
+ } while (0)
+
+#define T0_DEFENTRY(name, slot) \
+void \
+name(void *ctx) \
+{ \
+ t0_context *t0ctx = ctx; \
+ t0ctx->ip = &t0_codeblock[0]; \
+ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
+}
+
+T0_DEFENTRY(br_pem_decoder_init_main, 38)
+
+#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
+
+void
+br_pem_decoder_run(void *t0ctx)
+{
+ uint32_t *dp, *rp;
+ const unsigned char *ip;
+
+#define T0_LOCAL(x) (*(rp - 2 - (x)))
+#define T0_POP() (*-- dp)
+#define T0_POPi() (*(int32_t *)(-- dp))
+#define T0_PEEK(x) (*(dp - 1 - (x)))
+#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
+#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
+#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
+#define T0_RPOP() (*-- rp)
+#define T0_RPOPi() (*(int32_t *)(-- rp))
+#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
+#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
+#define T0_ROLL(x) do { \
+ size_t t0len = (size_t)(x); \
+ uint32_t t0tmp = *(dp - 1 - t0len); \
+ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_SWAP() do { \
+ uint32_t t0tmp = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_ROT() do { \
+ uint32_t t0tmp = *(dp - 3); \
+ *(dp - 3) = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_NROT() do { \
+ uint32_t t0tmp = *(dp - 1); \
+ *(dp - 1) = *(dp - 2); \
+ *(dp - 2) = *(dp - 3); \
+ *(dp - 3) = t0tmp; \
+} while (0)
+#define T0_PICK(x) do { \
+ uint32_t t0depth = (x); \
+ T0_PUSH(T0_PEEK(t0depth)); \
+} while (0)
+#define T0_CO() do { \
+ goto t0_exit; \
+} while (0)
+#define T0_RET() goto t0_next
+
+ dp = ((t0_context *)t0ctx)->dp;
+ rp = ((t0_context *)t0ctx)->rp;
+ ip = ((t0_context *)t0ctx)->ip;
+ goto t0_next;
+ for (;;) {
+ uint32_t t0x;
+
+ t0_next:
+ t0x = T0_NEXT(&ip);
+ if (t0x < T0_INTERPRETED) {
+ switch (t0x) {
+ int32_t t0off;
+
+ case 0: /* ret */
+ t0x = T0_RPOP();
+ rp -= (t0x >> 16);
+ t0x &= 0xFFFF;
+ if (t0x == 0) {
+ ip = NULL;
+ goto t0_exit;
+ }
+ ip = &t0_codeblock[t0x];
+ break;
+ case 1: /* literal constant */
+ T0_PUSHi(t0_parse7E_signed(&ip));
+ break;
+ case 2: /* read local */
+ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
+ break;
+ case 3: /* write local */
+ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
+ break;
+ case 4: /* jump */
+ t0off = t0_parse7E_signed(&ip);
+ ip += t0off;
+ break;
+ case 5: /* jump if */
+ t0off = t0_parse7E_signed(&ip);
+ if (T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 6: /* jump if not */
+ t0off = t0_parse7E_signed(&ip);
+ if (!T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 7: {
+ /* + */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a + b);
+
+ }
+ break;
+ case 8: {
+ /* - */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a - b);
+
+ }
+ break;
+ case 9: {
+ /* < */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a < b));
+
+ }
+ break;
+ case 10: {
+ /* << */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x << c);
+
+ }
+ break;
+ case 11: {
+ /* <= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a <= b));
+
+ }
+ break;
+ case 12: {
+ /* <> */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a != b));
+
+ }
+ break;
+ case 13: {
+ /* = */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a == b));
+
+ }
+ break;
+ case 14: {
+ /* >= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a >= b));
+
+ }
+ break;
+ case 15: {
+ /* >> */
+
+ int c = (int)T0_POPi();
+ int32_t x = T0_POPi();
+ T0_PUSHi(x >> c);
+
+ }
+ break;
+ case 16: {
+ /* and */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a & b);
+
+ }
+ break;
+ case 17: {
+ /* co */
+ T0_CO();
+ }
+ break;
+ case 18: {
+ /* data-get8 */
+
+ size_t addr = T0_POP();
+ T0_PUSH(t0_datablock[addr]);
+
+ }
+ break;
+ case 19: {
+ /* drop */
+ (void)T0_POP();
+ }
+ break;
+ case 20: {
+ /* dup */
+ T0_PUSH(T0_PEEK(0));
+ }
+ break;
+ case 21: {
+ /* flush-buf */
+
+ if (CTX->ptr > 0) {
+ if (CTX->dest) {
+ CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
+ }
+ CTX->ptr = 0;
+ }
+
+ }
+ break;
+ case 22: {
+ /* from-base64 */
+
+ uint32_t c = T0_POP();
+ uint32_t p, q, r, z;
+ p = c - 0x41;
+ q = c - 0x61;
+ r = c - 0x30;
+
+ z = ((p + 2) & -LT(p, 26))
+ | ((q + 28) & -LT(q, 26))
+ | ((r + 54) & -LT(r, 10))
+ | (64 & -EQ(c, 0x2B))
+ | (65 & -EQ(c, 0x2F))
+ | EQ(c, 0x3D);
+ T0_PUSHi((int32_t)z - 2);
+
+ }
+ break;
+ case 23: {
+ /* get8 */
+
+ size_t addr = T0_POP();
+ T0_PUSH(*((unsigned char *)CTX + addr));
+
+ }
+ break;
+ case 24: {
+ /* over */
+ T0_PUSH(T0_PEEK(1));
+ }
+ break;
+ case 25: {
+ /* read8-native */
+
+ if (CTX->hlen > 0) {
+ T0_PUSH(*CTX->hbuf ++);
+ CTX->hlen --;
+ } else {
+ T0_PUSHi(-1);
+ }
+
+ }
+ break;
+ case 26: {
+ /* set8 */
+
+ size_t addr = T0_POP();
+ unsigned x = T0_POP();
+ *((unsigned char *)CTX + addr) = x;
+
+ }
+ break;
+ case 27: {
+ /* swap */
+ T0_SWAP();
+ }
+ break;
+ case 28: {
+ /* write8 */
+
+ unsigned char x = (unsigned char)T0_POP();
+ CTX->buf[CTX->ptr ++] = x;
+ if (CTX->ptr == sizeof CTX->buf) {
+ if (CTX->dest) {
+ CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
+ }
+ CTX->ptr = 0;
+ }
+
+ }
+ break;
+ }
+
+ } else {
+ T0_ENTER(ip, rp, t0x);
+ }
+ }
+t0_exit:
+ ((t0_context *)t0ctx)->dp = dp;
+ ((t0_context *)t0ctx)->rp = rp;
+ ((t0_context *)t0ctx)->ip = ip;
+}
Property changes on: stable/12/contrib/bearssl/src/codec/pemdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/codec/pemdec.t0
===================================================================
--- stable/12/contrib/bearssl/src/codec/pemdec.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/pemdec.t0 (revision 346145)
@@ -0,0 +1,314 @@
+\ 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.
+
+preamble {
+
+#include "inner.h"
+
+#define CTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
+
+/* see bearssl_pem.h */
+void
+br_pem_decoder_init(br_pem_decoder_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->cpu.dp = &ctx->dp_stack[0];
+ ctx->cpu.rp = &ctx->rp_stack[0];
+ br_pem_decoder_init_main(&ctx->cpu);
+ br_pem_decoder_run(&ctx->cpu);
+}
+
+/* see bearssl_pem.h */
+size_t
+br_pem_decoder_push(br_pem_decoder_context *ctx,
+ const void *data, size_t len)
+{
+ if (ctx->event) {
+ return 0;
+ }
+ ctx->hbuf = data;
+ ctx->hlen = len;
+ br_pem_decoder_run(&ctx->cpu);
+ return len - ctx->hlen;
+}
+
+/* see bearssl_pem.h */
+int
+br_pem_decoder_event(br_pem_decoder_context *ctx)
+{
+ int event;
+
+ event = ctx->event;
+ ctx->event = 0;
+ return event;
+}
+
+}
+
+\ Define a word that evaluates to the address of a field within the
+\ decoder context.
+: addr:
+ next-word { field }
+ "addr-" field + 0 1 define-word
+ 0 8191 "offsetof(br_pem_decoder_context, " field + ")" + make-CX
+ postpone literal postpone ; ;
+
+addr: event
+addr: name
+addr: buf
+addr: ptr
+
+\ Set a byte at a specific address (offset within the context).
+cc: set8 ( value addr -- ) {
+ size_t addr = T0_POP();
+ unsigned x = T0_POP();
+ *((unsigned char *)CTX + addr) = x;
+}
+
+\ Get a byte at a specific address (offset within the context).
+cc: get8 ( addr -- value ) {
+ size_t addr = T0_POP();
+ T0_PUSH(*((unsigned char *)CTX + addr));
+}
+
+\ Send an event.
+: send-event ( event -- )
+ addr-event set8 co ;
+
+\ Low-level function to read a single byte. Returned value is the byte
+\ (0 to 255), or -1 if there is no available data.
+cc: read8-native ( -- x ) {
+ if (CTX->hlen > 0) {
+ T0_PUSH(*CTX->hbuf ++);
+ CTX->hlen --;
+ } else {
+ T0_PUSHi(-1);
+ }
+}
+
+\ Read next byte. Block until the next byte is available.
+: read8 ( -- x )
+ begin read8-native dup 0< ifnot ret then drop co again ;
+
+\ Read bytes until next end-of-line.
+: skip-newline ( -- )
+ begin read8 `\n <> while repeat ;
+
+\ Read bytes until next end-of-line; verify that they are all whitespace.
+\ This returns -1 if they were all whitespace, 0 otherwise.
+: skip-newline-ws ( -- bool )
+ -1 { r }
+ begin read8 dup `\n <> while ws? ifnot 0 >r then repeat
+ drop r ;
+
+\ Normalise a byte to uppercase (ASCII only).
+: norm-upper ( x -- x )
+ dup dup `a >= swap `z <= and if 32 - then ;
+
+\ Read bytes and compare with the provided string. On mismatch, the
+\ rest of the line is consumed. Matching is not case sensitive.
+: match-string ( str -- bool )
+ begin
+ dup data-get8 norm-upper dup ifnot 2drop -1 ret then
+ read8 norm-upper dup `\n = if drop 2drop 0 ret then
+ = ifnot drop skip-newline 0 ret then
+ 1+
+ again ;
+
+\ Read bytes into the provided buffer, but no more than the provided
+\ count. Reading stops when end-of-line is reached. Returned value
+\ is the count of bytes written to the buffer, or 0 if the buffer size
+\ was exceeded. All bytes are normalised to uppercase (ASCII only).
+: read-bytes ( addr len -- len )
+ dup { orig-len }
+ swap
+ begin
+ over ifnot 2drop skip-newline 0 ret then
+ read8 dup `\n = if 2drop orig-len swap - ret then
+ dup `\r = if drop else norm-upper over set8 then
+ 1+ swap 1- swap
+ again ;
+
+\ Remove trailing dashes from the name buffer.
+: trim-dashes ( len -- )
+ begin dup while
+ 1-
+ dup addr-name + get8 `- <> if
+ addr-name + 1+ 0 swap set8 ret
+ then
+ repeat
+ addr-name set8 ;
+
+\ Scan input for next "begin" banner.
+: next-banner-begin ( -- )
+ begin
+ "-----BEGIN " match-string if
+ addr-name 127 read-bytes
+ dup if trim-dashes ret then
+ drop
+ then
+ again ;
+
+\ Convert a Base64 character to its numerical value. Returned value is
+\ 0 to 63 for Base64 characters, -1 for '=', and -2 for all other characters.
+cc: from-base64 ( char -- x ) {
+ uint32_t c = T0_POP();
+ uint32_t p, q, r, z;
+ p = c - 0x41;
+ q = c - 0x61;
+ r = c - 0x30;
+
+ z = ((p + 2) & -LT(p, 26))
+ | ((q + 28) & -LT(q, 26))
+ | ((r + 54) & -LT(r, 10))
+ | (64 & -EQ(c, 0x2B))
+ | (65 & -EQ(c, 0x2F))
+ | EQ(c, 0x3D);
+ T0_PUSHi((int32_t)z - 2);
+}
+
+\ Test whether a character is whitespace (but not a newline).
+: ws? ( x -- bool )
+ dup `\n <> swap 32 <= and ;
+
+\ Read next character, skipping whitespace (except newline).
+: next-nonws ( -- x )
+ begin
+ read8 dup ws? ifnot ret then
+ drop
+ again ;
+
+\ Write one byte in the output buffer.
+cc: write8 ( x -- ) {
+ unsigned char x = (unsigned char)T0_POP();
+ CTX->buf[CTX->ptr ++] = x;
+ if (CTX->ptr == sizeof CTX->buf) {
+ if (CTX->dest) {
+ CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
+ }
+ CTX->ptr = 0;
+ }
+}
+
+\ Flush the output buffer.
+cc: flush-buf ( -- ) {
+ if (CTX->ptr > 0) {
+ if (CTX->dest) {
+ CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
+ }
+ CTX->ptr = 0;
+ }
+}
+
+\ Decode the four next Base64 characters. Returned value is:
+\ 0 quartet processed, three bytes produced.
+\ -1 dash encountered as first character (no leading whitespace).
+\ 1 quartet processed, one or two bytes produced, terminator reached.
+\ 2 end-of-line reached.
+\ 3 error.
+\ For all positive return values, the remaining of the current line has been
+\ consumed.
+: decode-next-quartet ( -- r )
+ \ Process first character. It may be a dash.
+ read8 dup `- = if drop -1 ret then
+ dup ws? if drop next-nonws then
+ dup `\n = if drop 2 ret then
+ from-base64 dup 0< if drop skip-newline 3 ret then
+ { acc }
+
+ \ Second character.
+ next-nonws dup `\n = if drop 3 ret then
+ from-base64 dup 0< if drop skip-newline 3 ret then
+ acc 6 << + >acc
+
+ \ Third character: may be an equal sign.
+ next-nonws dup `\n = if drop 3 ret then
+ dup `= = if
+ \ Fourth character must be an equal sign.
+ drop
+ next-nonws dup `\n = if drop 3 ret then
+ skip-newline-ws ifnot drop 3 ret then
+ `= <> if 3 ret then
+ acc 0x0F and if 3 ret then
+ acc 4 >> write8
+ 1 ret
+ then
+ from-base64 dup 0< if drop skip-newline 3 ret then
+ acc 6 << + >acc
+
+ \ Fourth character: may be an equal sign.
+ next-nonws dup `\n = if drop 3 ret then
+ dup `= = if
+ drop skip-newline-ws ifnot 3 ret then
+ acc 0x03 and if 3 ret then
+ acc 10 >> write8
+ acc 2 >> write8
+ 1 ret
+ then
+ from-base64 dup 0< if drop skip-newline 3 ret then
+ acc 6 << + >acc
+ acc 16 >> write8
+ acc 8 >> write8
+ acc write8
+ 0 ;
+
+\ Check trailer line (possibly, the leading dash has been read). This
+\ sends the appropriate event.
+: check-trailer ( bool -- )
+ ifnot
+ begin read8 dup `\n = while drop repeat
+ `- <> if skip-newline 3 send-event ret then
+ then
+ "----END " match-string ifnot 3 send-event ret then
+ flush-buf
+ skip-newline 2 send-event ;
+
+\ Decode one line worth of characters. Returned value is 0 if the end of the
+\ object is reached, -1 otherwise. The end of object or error event is sent.
+: decode-line ( -- bool )
+ -1 { first }
+ begin
+ decode-next-quartet
+ case
+ 0 of endof
+ -1 of
+ first ifnot
+ skip-newline 3 send-event
+ else
+ -1 check-trailer
+ then
+ 0 ret
+ endof
+ 1 of 0 check-trailer 0 ret endof
+ 2 of -1 ret endof
+
+ \ On decoding error
+ drop 3 send-event 0 ret
+ endcase
+ 0 >first
+ again ;
+
+: main ( -- ! )
+ begin
+ next-banner-begin 1 send-event
+ begin decode-line while repeat
+ again ;
Index: stable/12/contrib/bearssl/src/codec/pemenc.c
===================================================================
--- stable/12/contrib/bearssl/src/codec/pemenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/codec/pemenc.c (revision 346145)
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Get the appropriate Base64 character for a numeric value in the
+ * 0..63 range. This is constant-time.
+ */
+static char
+b64char(uint32_t x)
+{
+ /*
+ * Values 0 to 25 map to 0x41..0x5A ('A' to 'Z')
+ * Values 26 to 51 map to 0x61..0x7A ('a' to 'z')
+ * Values 52 to 61 map to 0x30..0x39 ('0' to '9')
+ * Value 62 maps to 0x2B ('+')
+ * Value 63 maps to 0x2F ('/')
+ */
+ uint32_t a, b, c;
+
+ a = x - 26;
+ b = x - 52;
+ c = x - 62;
+
+ /*
+ * Looking at bits 8..15 of values a, b and c:
+ *
+ * x a b c
+ * ---------------------
+ * 0..25 FF FF FF
+ * 26..51 00 FF FF
+ * 52..61 00 00 FF
+ * 62..63 00 00 00
+ */
+ return (char)(((x + 0x41) & ((a & b & c) >> 8))
+ | ((x + (0x61 - 26)) & ((~a & b & c) >> 8))
+ | ((x - (52 - 0x30)) & ((~a & ~b & c) >> 8))
+ | ((0x2B + ((x & 1) << 2)) & (~(a | b | c) >> 8)));
+}
+
+/* see bearssl_pem.h */
+size_t
+br_pem_encode(void *dest, const void *data, size_t len,
+ const char *banner, unsigned flags)
+{
+ size_t dlen, banner_len, lines;
+ char *d;
+ unsigned char *buf;
+ size_t u;
+ int off, lim;
+
+ banner_len = strlen(banner);
+ /* FIXME: try to avoid divisions here, as they may pull
+ an extra libc function. */
+ if ((flags & BR_PEM_LINE64) != 0) {
+ lines = (len + 47) / 48;
+ } else {
+ lines = (len + 56) / 57;
+ }
+ dlen = (banner_len << 1) + 30 + (((len + 2) / 3) << 2)
+ + lines + 2;
+ if ((flags & BR_PEM_CRLF) != 0) {
+ dlen += lines + 2;
+ }
+
+ if (dest == NULL) {
+ return dlen;
+ }
+
+ d = dest;
+
+ /*
+ * We always move the source data to the end of output buffer;
+ * the encoding process never "catches up" except at the very
+ * end. This also handles all conditions of partial or total
+ * overlap.
+ */
+ buf = (unsigned char *)d + dlen - len;
+ memmove(buf, data, len);
+
+ memcpy(d, "-----BEGIN ", 11);
+ d += 11;
+ memcpy(d, banner, banner_len);
+ d += banner_len;
+ memcpy(d, "-----", 5);
+ d += 5;
+ if ((flags & BR_PEM_CRLF) != 0) {
+ *d ++ = 0x0D;
+ }
+ *d ++ = 0x0A;
+
+ off = 0;
+ lim = (flags & BR_PEM_LINE64) != 0 ? 16 : 19;
+ for (u = 0; (u + 2) < len; u += 3) {
+ uint32_t w;
+
+ w = ((uint32_t)buf[u] << 16)
+ | ((uint32_t)buf[u + 1] << 8)
+ | (uint32_t)buf[u + 2];
+ *d ++ = b64char(w >> 18);
+ *d ++ = b64char((w >> 12) & 0x3F);
+ *d ++ = b64char((w >> 6) & 0x3F);
+ *d ++ = b64char(w & 0x3F);
+ if (++ off == lim) {
+ off = 0;
+ if ((flags & BR_PEM_CRLF) != 0) {
+ *d ++ = 0x0D;
+ }
+ *d ++ = 0x0A;
+ }
+ }
+ if (u < len) {
+ uint32_t w;
+
+ w = (uint32_t)buf[u] << 16;
+ if (u + 1 < len) {
+ w |= (uint32_t)buf[u + 1] << 8;
+ }
+ *d ++ = b64char(w >> 18);
+ *d ++ = b64char((w >> 12) & 0x3F);
+ if (u + 1 < len) {
+ *d ++ = b64char((w >> 6) & 0x3F);
+ } else {
+ *d ++ = 0x3D;
+ }
+ *d ++ = 0x3D;
+ off ++;
+ }
+ if (off != 0) {
+ if ((flags & BR_PEM_CRLF) != 0) {
+ *d ++ = 0x0D;
+ }
+ *d ++ = 0x0A;
+ }
+
+ memcpy(d, "-----END ", 9);
+ d += 9;
+ memcpy(d, banner, banner_len);
+ d += banner_len;
+ memcpy(d, "-----", 5);
+ d += 5;
+ if ((flags & BR_PEM_CRLF) != 0) {
+ *d ++ = 0x0D;
+ }
+ *d ++ = 0x0A;
+
+ /* Final zero, not counted in returned length. */
+ *d ++ = 0x00;
+
+ return dlen;
+}
Property changes on: stable/12/contrib/bearssl/src/codec/pemenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/config.h
===================================================================
--- stable/12/contrib/bearssl/src/config.h (nonexistent)
+++ stable/12/contrib/bearssl/src/config.h (revision 346145)
@@ -0,0 +1,229 @@
+/*
+ * 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 CONFIG_H__
+#define CONFIG_H__
+
+/*
+ * This file contains compile-time flags that can override the
+ * autodetection performed in relevant files. Each flag is a macro; it
+ * deactivates the feature if defined to 0, activates it if defined to a
+ * non-zero integer (normally 1). If the macro is not defined, then
+ * autodetection applies.
+ */
+
+/*
+ * When BR_64 is enabled, 64-bit integer types are assumed to be
+ * efficient (i.e. the architecture has 64-bit registers and can
+ * do 64-bit operations as fast as 32-bit operations).
+ *
+#define BR_64 1
+ */
+
+/*
+ * When BR_LOMUL is enabled, then multiplications of 32-bit values whose
+ * result are truncated to the low 32 bits are assumed to be
+ * substantially more efficient than 32-bit multiplications that yield
+ * 64-bit results. This is typically the case on low-end ARM Cortex M
+ * systems (M0, M0+, M1, and arguably M3 and M4 as well).
+ *
+#define BR_LOMUL 1
+ */
+
+/*
+ * When BR_SLOW_MUL is enabled, multiplications are assumed to be
+ * substantially slow with regards to other integer operations, thus
+ * making it worth to make more operations for a given task if it allows
+ * using less multiplications.
+ *
+#define BR_SLOW_MUL 1
+ */
+
+/*
+ * When BR_SLOW_MUL15 is enabled, short multplications (on 15-bit words)
+ * are assumed to be substantially slow with regards to other integer
+ * operations, thus making it worth to make more integer operations if
+ * it allows using less multiplications.
+ *
+#define BR_SLOW_MUL15 1
+ */
+
+/*
+ * When BR_CT_MUL31 is enabled, multiplications of 31-bit values (used
+ * in the "i31" big integer implementation) use an alternate implementation
+ * which is slower and larger than the normal multiplication, but should
+ * ensure constant-time multiplications even on architectures where the
+ * multiplication opcode takes a variable number of cycles to complete.
+ *
+#define BR_CT_MUL31 1
+ */
+
+/*
+ * When BR_CT_MUL15 is enabled, multiplications of 15-bit values (held
+ * in 32-bit words) use an alternate implementation which is slower and
+ * larger than the normal multiplication, but should ensure
+ * constant-time multiplications on most/all architectures where the
+ * basic multiplication is not constant-time.
+#define BR_CT_MUL15 1
+ */
+
+/*
+ * When BR_NO_ARITH_SHIFT is enabled, arithmetic right shifts (with sign
+ * extension) are performed with a sequence of operations which is bigger
+ * and slower than a simple right shift on a signed value. This avoids
+ * relying on an implementation-defined behaviour. However, most if not
+ * all C compilers use sign extension for right shifts on signed values,
+ * so this alternate macro is disabled by default.
+#define BR_NO_ARITH_SHIFT 1
+ */
+
+/*
+ * When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode
+ * to automatically obtain quality randomness for seeding its internal
+ * PRNG. Since that opcode is present only in recent x86 CPU, its
+ * support is dynamically tested; if the current CPU does not support
+ * it, then another random source will be used, such as /dev/urandom or
+ * CryptGenRandom().
+ *
+#define BR_RDRAND 1
+ */
+
+/*
+ * When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom
+ * to automatically obtain quality randomness for seedings its internal
+ * PRNG.
+ *
+#define BR_USE_URANDOM 1
+ */
+
+/*
+ * When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32
+ * (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to
+ * automatically obtain quality randomness for seedings its internal PRNG.
+ *
+ * Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the
+ * former takes precedence.
+ *
+#define BR_USE_WIN32_RAND 1
+ */
+
+/*
+ * When BR_USE_UNIX_TIME is enabled, the X.509 validation engine obtains
+ * the current time from the OS by calling time(), and assuming that the
+ * returned value (a 'time_t') is an integer that counts time in seconds
+ * since the Unix Epoch (Jan 1st, 1970, 00:00 UTC).
+ *
+#define BR_USE_UNIX_TIME 1
+ */
+
+/*
+ * When BR_USE_WIN32_TIME is enabled, the X.509 validation engine obtains
+ * the current time from the OS by calling the Win32 function
+ * GetSystemTimeAsFileTime().
+ *
+ * Note: if both BR_USE_UNIX_TIME and BR_USE_WIN32_TIME are defined, the
+ * former takes precedence.
+ *
+#define BR_USE_WIN32_TIME 1
+ */
+
+/*
+ * When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with
+ * inline assembly which is shorter and/or faster. This should be used
+ * only when all of the following are true:
+ * - target architecture is ARM in Thumb mode
+ * - target endianness is little-endian
+ * - compiler is GCC (or GCC-compatible for inline assembly syntax)
+ *
+ * This is meant for the low-end cores (Cortex M0, M0+, M1, M3).
+ * Note: if BR_LOMUL is not explicitly enabled or disabled, then
+ * enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL.
+ *
+#define BR_ARMEL_CORTEXM_GCC 1
+ */
+
+/*
+ * When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI"
+ * instructions (dedicated AES opcodes) will be compiled. If this is not
+ * enabled explicitly, then that AES implementation will be compiled only
+ * if a compatible compiler is detected. If set explicitly to 0, the
+ * implementation will not be compiled at all.
+ *
+#define BR_AES_X86NI 1
+ */
+
+/*
+ * When BR_SSE2 is enabled, SSE2 intrinsics will be used for some
+ * algorithm implementations that use them (e.g. chacha20_sse2). If this
+ * is not enabled explicitly, then support for SSE2 intrinsics will be
+ * automatically detected. If set explicitly to 0, then SSE2 code will
+ * not be compiled at all.
+ *
+#define BR_SSE2 1
+ */
+
+/*
+ * When BR_POWER8 is enabled, the AES implementation using the POWER ISA
+ * 2.07 opcodes (available on POWER8 processors and later) is compiled.
+ * If this is not enabled explicitly, then that implementation will be
+ * compiled only if a compatible compiler is detected, _and_ the target
+ * architecture is POWER8 or later.
+ *
+#define BR_POWER8 1
+ */
+
+/*
+ * When BR_INT128 is enabled, then code using the 'unsigned __int64'
+ * and 'unsigned __int128' types will be used to leverage 64x64->128
+ * unsigned multiplications. This should work with GCC and compatible
+ * compilers on 64-bit architectures.
+ *
+#define BR_INT128 1
+ */
+
+/*
+ * When BR_UMUL128 is enabled, then code using the '_umul128()' and
+ * '_addcarry_u64()' intrinsics will be used to implement 64x64->128
+ * unsigned multiplications. This should work on Visual C on x64 systems.
+ *
+#define BR_UMUL128 1
+ */
+
+/*
+ * When BR_LE_UNALIGNED is enabled, then the current architecture is
+ * assumed to use little-endian encoding for integers, and to tolerate
+ * unaligned accesses with no or minimal time penalty.
+ *
+#define BR_LE_UNALIGNED 1
+ */
+
+/*
+ * When BR_BE_UNALIGNED is enabled, then the current architecture is
+ * assumed to use big-endian encoding for integers, and to tolerate
+ * unaligned accesses with no or minimal time penalty.
+ *
+#define BR_BE_UNALIGNED 1
+ */
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/config.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_all_m15.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_all_m15.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_all_m15.c (revision 346145)
@@ -0,0 +1,121 @@
+/*
+ * 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"
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return br_ec_p256_m15.generator(curve, len);
+ case BR_EC_curve25519:
+ return br_ec_c25519_m15.generator(curve, len);
+ default:
+ return br_ec_prime_i15.generator(curve, len);
+ }
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return br_ec_p256_m15.order(curve, len);
+ case BR_EC_curve25519:
+ return br_ec_c25519_m15.order(curve, len);
+ default:
+ return br_ec_prime_i15.order(curve, len);
+ }
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return br_ec_p256_m15.xoff(curve, len);
+ case BR_EC_curve25519:
+ return br_ec_c25519_m15.xoff(curve, len);
+ default:
+ return br_ec_prime_i15.xoff(curve, len);
+ }
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return br_ec_p256_m15.mul(G, Glen, kb, kblen, curve);
+ case BR_EC_curve25519:
+ return br_ec_c25519_m15.mul(G, Glen, kb, kblen, curve);
+ default:
+ return br_ec_prime_i15.mul(G, Glen, kb, kblen, curve);
+ }
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return br_ec_p256_m15.mulgen(R, x, xlen, curve);
+ case BR_EC_curve25519:
+ return br_ec_c25519_m15.mulgen(R, x, xlen, curve);
+ default:
+ return br_ec_prime_i15.mulgen(R, x, xlen, curve);
+ }
+}
+
+static uint32_t
+api_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)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return br_ec_p256_m15.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+ case BR_EC_curve25519:
+ return br_ec_c25519_m15.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+ default:
+ return br_ec_prime_i15.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+ }
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_all_m15 = {
+ (uint32_t)0x23800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_all_m15.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_all_m31.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_all_m31.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_all_m31.c (revision 346145)
@@ -0,0 +1,171 @@
+/*
+ * 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"
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_p256_m64.generator(curve, len);
+#else
+ return br_ec_p256_m31.generator(curve, len);
+#endif
+ case BR_EC_curve25519:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_c25519_m64.generator(curve, len);
+#else
+ return br_ec_c25519_m31.generator(curve, len);
+#endif
+ default:
+ return br_ec_prime_i31.generator(curve, len);
+ }
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_p256_m64.order(curve, len);
+#else
+ return br_ec_p256_m31.order(curve, len);
+#endif
+ case BR_EC_curve25519:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_c25519_m64.order(curve, len);
+#else
+ return br_ec_c25519_m31.order(curve, len);
+#endif
+ default:
+ return br_ec_prime_i31.order(curve, len);
+ }
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_p256_m64.xoff(curve, len);
+#else
+ return br_ec_p256_m31.xoff(curve, len);
+#endif
+ case BR_EC_curve25519:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_c25519_m64.xoff(curve, len);
+#else
+ return br_ec_c25519_m31.xoff(curve, len);
+#endif
+ default:
+ return br_ec_prime_i31.xoff(curve, len);
+ }
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_p256_m64.mul(G, Glen, kb, kblen, curve);
+#else
+ return br_ec_p256_m31.mul(G, Glen, kb, kblen, curve);
+#endif
+ case BR_EC_curve25519:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_c25519_m64.mul(G, Glen, kb, kblen, curve);
+#else
+ return br_ec_c25519_m31.mul(G, Glen, kb, kblen, curve);
+#endif
+ default:
+ return br_ec_prime_i31.mul(G, Glen, kb, kblen, curve);
+ }
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_p256_m64.mulgen(R, x, xlen, curve);
+#else
+ return br_ec_p256_m31.mulgen(R, x, xlen, curve);
+#endif
+ case BR_EC_curve25519:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_c25519_m64.mulgen(R, x, xlen, curve);
+#else
+ return br_ec_c25519_m31.mulgen(R, x, xlen, curve);
+#endif
+ default:
+ return br_ec_prime_i31.mulgen(R, x, xlen, curve);
+ }
+}
+
+static uint32_t
+api_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)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_p256_m64.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+#else
+ return br_ec_p256_m31.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+#endif
+ case BR_EC_curve25519:
+#if BR_INT128 || BR_UMUL128
+ return br_ec_c25519_m64.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+#else
+ return br_ec_c25519_m31.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+#endif
+ default:
+ return br_ec_prime_i31.muladd(A, B, len,
+ x, xlen, y, ylen, curve);
+ }
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_all_m31 = {
+ (uint32_t)0x23800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_all_m31.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_c25519_i15.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_c25519_i15.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_c25519_i15.c (revision 346145)
@@ -0,0 +1,398 @@
+/*
+ * 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"
+
+/*
+ * Parameters for the field:
+ * - field modulus p = 2^255-19
+ * - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
+ */
+
+static const uint16_t C255_P[] = {
+ 0x0110,
+ 0x7FED, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF
+};
+
+#define P0I 0x4A1B
+
+static const uint16_t C255_R2[] = {
+ 0x0110,
+ 0x0169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000
+};
+
+/* obsolete
+#include <stdio.h>
+#include <stdlib.h>
+static void
+print_int_mont(const char *name, const uint16_t *x)
+{
+ uint16_t y[18];
+ unsigned char tmp[32];
+ size_t u;
+
+ printf("%s = ", name);
+ memcpy(y, x, sizeof y);
+ br_i15_from_monty(y, C255_P, P0I);
+ br_i15_encode(tmp, sizeof tmp, y);
+ for (u = 0; u < sizeof tmp; u ++) {
+ printf("%02X", tmp[u]);
+ }
+ printf("\n");
+}
+*/
+
+static const uint16_t C255_A24[] = {
+ 0x0110,
+ 0x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000
+};
+
+static const unsigned char GEN[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ORDER[] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return GEN;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return ORDER;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 0;
+}
+
+static void
+cswap(uint16_t *a, uint16_t *b, uint32_t ctl)
+{
+ int i;
+
+ ctl = -ctl;
+ for (i = 0; i < 18; i ++) {
+ uint32_t aw, bw, tw;
+
+ aw = a[i];
+ bw = b[i];
+ tw = ctl & (aw ^ bw);
+ a[i] = aw ^ tw;
+ b[i] = bw ^ tw;
+ }
+}
+
+static void
+c255_add(uint16_t *d, const uint16_t *a, const uint16_t *b)
+{
+ uint32_t ctl;
+ uint16_t t[18];
+
+ memcpy(t, a, sizeof t);
+ ctl = br_i15_add(t, b, 1);
+ ctl |= NOT(br_i15_sub(t, C255_P, 0));
+ br_i15_sub(t, C255_P, ctl);
+ memcpy(d, t, sizeof t);
+}
+
+static void
+c255_sub(uint16_t *d, const uint16_t *a, const uint16_t *b)
+{
+ uint16_t t[18];
+
+ memcpy(t, a, sizeof t);
+ br_i15_add(t, C255_P, br_i15_sub(t, b, 1));
+ memcpy(d, t, sizeof t);
+}
+
+static void
+c255_mul(uint16_t *d, const uint16_t *a, const uint16_t *b)
+{
+ uint16_t t[18];
+
+ br_i15_montymul(t, a, b, C255_P, P0I);
+ memcpy(d, t, sizeof t);
+}
+
+static void
+byteswap(unsigned char *G)
+{
+ int i;
+
+ for (i = 0; i < 16; i ++) {
+ unsigned char t;
+
+ t = G[i];
+ G[i] = G[31 - i];
+ G[31 - i] = t;
+ }
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+#define ILEN (18 * sizeof(uint16_t))
+
+ /*
+ * The a[] and b[] arrays have an extra word to allow for
+ * decoding without using br_i15_decode_reduce().
+ */
+ uint16_t x1[18], x2[18], x3[18], z2[18], z3[18];
+ uint16_t a[19], aa[18], b[19], bb[18];
+ uint16_t c[18], d[18], e[18], da[18], cb[18];
+ unsigned char k[32];
+ uint32_t swap;
+ int i;
+
+ (void)curve;
+
+ /*
+ * Points are encoded over exactly 32 bytes. Multipliers must fit
+ * in 32 bytes as well.
+ * RFC 7748 mandates that the high bit of the last point byte must
+ * be ignored/cleared.
+ */
+ if (Glen != 32 || kblen > 32) {
+ return 0;
+ }
+ G[31] &= 0x7F;
+
+ /*
+ * Byteswap the point encoding, because it uses little-endian, and
+ * the generic decoding routine uses big-endian.
+ */
+ byteswap(G);
+
+ /*
+ * Decode the point ('u' coordinate). This should be reduced
+ * modulo p, but we prefer to avoid the dependency on
+ * br_i15_decode_reduce(). Instead, we use br_i15_decode_mod()
+ * with a synthetic modulus of value 2^255 (this must work
+ * since G was truncated to 255 bits), then use a conditional
+ * subtraction. We use br_i15_decode_mod() and not
+ * br_i15_decode(), because the ec_prime_i15 implementation uses
+ * the former but not the latter.
+ * br_i15_decode_reduce(a, G, 32, C255_P);
+ */
+ br_i15_zero(b, 0x111);
+ b[18] = 1;
+ br_i15_decode_mod(a, G, 32, b);
+ a[0] = 0x110;
+ br_i15_sub(a, C255_P, NOT(br_i15_sub(a, C255_P, 0)));
+
+ /*
+ * Initialise variables x1, x2, z2, x3 and z3. We set all of them
+ * into Montgomery representation.
+ */
+ br_i15_montymul(x1, a, C255_R2, C255_P, P0I);
+ memcpy(x3, x1, ILEN);
+ br_i15_zero(z2, C255_P[0]);
+ memcpy(x2, z2, ILEN);
+ x2[1] = 19;
+ memcpy(z3, x2, ILEN);
+
+ memset(k, 0, (sizeof k) - kblen);
+ memcpy(k + (sizeof k) - kblen, kb, kblen);
+ k[31] &= 0xF8;
+ k[0] &= 0x7F;
+ k[0] |= 0x40;
+
+ /* obsolete
+ print_int_mont("x1", x1);
+ */
+
+ swap = 0;
+ for (i = 254; i >= 0; i --) {
+ uint32_t kt;
+
+ kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
+ swap ^= kt;
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+ swap = kt;
+
+ /* obsolete
+ print_int_mont("x2", x2);
+ print_int_mont("z2", z2);
+ print_int_mont("x3", x3);
+ print_int_mont("z3", z3);
+ */
+
+ c255_add(a, x2, z2);
+ c255_mul(aa, a, a);
+ c255_sub(b, x2, z2);
+ c255_mul(bb, b, b);
+ c255_sub(e, aa, bb);
+ c255_add(c, x3, z3);
+ c255_sub(d, x3, z3);
+ c255_mul(da, d, a);
+ c255_mul(cb, c, b);
+
+ /* obsolete
+ print_int_mont("a ", a);
+ print_int_mont("aa", aa);
+ print_int_mont("b ", b);
+ print_int_mont("bb", bb);
+ print_int_mont("e ", e);
+ print_int_mont("c ", c);
+ print_int_mont("d ", d);
+ print_int_mont("da", da);
+ print_int_mont("cb", cb);
+ */
+
+ c255_add(x3, da, cb);
+ c255_mul(x3, x3, x3);
+ c255_sub(z3, da, cb);
+ c255_mul(z3, z3, z3);
+ c255_mul(z3, z3, x1);
+ c255_mul(x2, aa, bb);
+ c255_mul(z2, C255_A24, e);
+ c255_add(z2, z2, aa);
+ c255_mul(z2, e, z2);
+
+ /* obsolete
+ print_int_mont("x2", x2);
+ print_int_mont("z2", z2);
+ print_int_mont("x3", x3);
+ print_int_mont("z3", z3);
+ */
+ }
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+
+ /*
+ * Inverse z2 with a modular exponentiation. This is a simple
+ * square-and-multiply algorithm; we mutualise most non-squarings
+ * since the exponent contains almost only ones.
+ */
+ memcpy(a, z2, ILEN);
+ for (i = 0; i < 15; i ++) {
+ c255_mul(a, a, a);
+ c255_mul(a, a, z2);
+ }
+ memcpy(b, a, ILEN);
+ for (i = 0; i < 14; i ++) {
+ int j;
+
+ for (j = 0; j < 16; j ++) {
+ c255_mul(b, b, b);
+ }
+ c255_mul(b, b, a);
+ }
+ for (i = 14; i >= 0; i --) {
+ c255_mul(b, b, b);
+ if ((0xFFEB >> i) & 1) {
+ c255_mul(b, z2, b);
+ }
+ }
+ c255_mul(b, x2, b);
+
+ /*
+ * To avoid a dependency on br_i15_from_monty(), we use a
+ * Montgomery multiplication with 1.
+ * memcpy(x2, b, ILEN);
+ * br_i15_from_monty(x2, C255_P, P0I);
+ */
+ br_i15_zero(a, C255_P[0]);
+ a[1] = 1;
+ br_i15_montymul(x2, a, b, C255_P, P0I);
+
+ br_i15_encode(G, 32, x2);
+ byteswap(G);
+ return 1;
+
+#undef ILEN
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We don't implement this method, since it is used for ECDSA
+ * only, and there is no ECDSA over Curve25519 (which instead
+ * uses EdDSA).
+ */
+ (void)A;
+ (void)B;
+ (void)len;
+ (void)x;
+ (void)xlen;
+ (void)y;
+ (void)ylen;
+ (void)curve;
+ return 0;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_c25519_i15 = {
+ (uint32_t)0x20000000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_c25519_i15.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_c25519_i31.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_c25519_i31.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_c25519_i31.c (revision 346145)
@@ -0,0 +1,390 @@
+/*
+ * 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"
+
+/*
+ * Parameters for the field:
+ * - field modulus p = 2^255-19
+ * - R^2 mod p (R = 2^(31k) for the smallest k such that R >= p)
+ */
+
+static const uint32_t C255_P[] = {
+ 0x00000107,
+ 0x7FFFFFED, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
+ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0000007F
+};
+
+#define P0I 0x286BCA1B
+
+static const uint32_t C255_R2[] = {
+ 0x00000107,
+ 0x00000000, 0x02D20000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+static const uint32_t C255_A24[] = {
+ 0x00000107,
+ 0x53000000, 0x0000468B, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000
+};
+
+/* obsolete
+#include <stdio.h>
+#include <stdlib.h>
+static void
+print_int_mont(const char *name, const uint32_t *x)
+{
+ uint32_t y[10];
+ unsigned char tmp[32];
+ size_t u;
+
+ printf("%s = ", name);
+ memcpy(y, x, sizeof y);
+ br_i31_from_monty(y, C255_P, P0I);
+ br_i31_encode(tmp, sizeof tmp, y);
+ for (u = 0; u < sizeof tmp; u ++) {
+ printf("%02X", tmp[u]);
+ }
+ printf("\n");
+}
+*/
+
+static const unsigned char GEN[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ORDER[] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return GEN;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return ORDER;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 0;
+}
+
+static void
+cswap(uint32_t *a, uint32_t *b, uint32_t ctl)
+{
+ int i;
+
+ ctl = -ctl;
+ for (i = 0; i < 10; i ++) {
+ uint32_t aw, bw, tw;
+
+ aw = a[i];
+ bw = b[i];
+ tw = ctl & (aw ^ bw);
+ a[i] = aw ^ tw;
+ b[i] = bw ^ tw;
+ }
+}
+
+static void
+c255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t ctl;
+ uint32_t t[10];
+
+ memcpy(t, a, sizeof t);
+ ctl = br_i31_add(t, b, 1);
+ ctl |= NOT(br_i31_sub(t, C255_P, 0));
+ br_i31_sub(t, C255_P, ctl);
+ memcpy(d, t, sizeof t);
+}
+
+static void
+c255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t t[10];
+
+ memcpy(t, a, sizeof t);
+ br_i31_add(t, C255_P, br_i31_sub(t, b, 1));
+ memcpy(d, t, sizeof t);
+}
+
+static void
+c255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t t[10];
+
+ br_i31_montymul(t, a, b, C255_P, P0I);
+ memcpy(d, t, sizeof t);
+}
+
+static void
+byteswap(unsigned char *G)
+{
+ int i;
+
+ for (i = 0; i < 16; i ++) {
+ unsigned char t;
+
+ t = G[i];
+ G[i] = G[31 - i];
+ G[31 - i] = t;
+ }
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+ uint32_t x1[10], x2[10], x3[10], z2[10], z3[10];
+ uint32_t a[10], aa[10], b[10], bb[10];
+ uint32_t c[10], d[10], e[10], da[10], cb[10];
+ unsigned char k[32];
+ uint32_t swap;
+ int i;
+
+ (void)curve;
+
+ /*
+ * Points are encoded over exactly 32 bytes. Multipliers must fit
+ * in 32 bytes as well.
+ * RFC 7748 mandates that the high bit of the last point byte must
+ * be ignored/cleared.
+ */
+ if (Glen != 32 || kblen > 32) {
+ return 0;
+ }
+ G[31] &= 0x7F;
+
+ /*
+ * Byteswap the point encoding, because it uses little-endian, and
+ * the generic decoding routine uses big-endian.
+ */
+ byteswap(G);
+
+ /*
+ * Decode the point ('u' coordinate). This should be reduced
+ * modulo p, but we prefer to avoid the dependency on
+ * br_i31_decode_reduce(). Instead, we use br_i31_decode_mod()
+ * with a synthetic modulus of value 2^255 (this must work
+ * since G was truncated to 255 bits), then use a conditional
+ * subtraction. We use br_i31_decode_mod() and not
+ * br_i31_decode(), because the ec_prime_i31 implementation uses
+ * the former but not the latter.
+ * br_i31_decode_reduce(a, G, 32, C255_P);
+ */
+ br_i31_zero(b, 0x108);
+ b[9] = 0x0080;
+ br_i31_decode_mod(a, G, 32, b);
+ a[0] = 0x107;
+ br_i31_sub(a, C255_P, NOT(br_i31_sub(a, C255_P, 0)));
+
+ /*
+ * Initialise variables x1, x2, z2, x3 and z3. We set all of them
+ * into Montgomery representation.
+ */
+ br_i31_montymul(x1, a, C255_R2, C255_P, P0I);
+ memcpy(x3, x1, sizeof x1);
+ br_i31_zero(z2, C255_P[0]);
+ memcpy(x2, z2, sizeof z2);
+ x2[1] = 0x13000000;
+ memcpy(z3, x2, sizeof x2);
+
+ /*
+ * kb[] is in big-endian notation, but possibly shorter than k[].
+ */
+ memset(k, 0, (sizeof k) - kblen);
+ memcpy(k + (sizeof k) - kblen, kb, kblen);
+ k[31] &= 0xF8;
+ k[0] &= 0x7F;
+ k[0] |= 0x40;
+
+ /* obsolete
+ print_int_mont("x1", x1);
+ */
+
+ swap = 0;
+ for (i = 254; i >= 0; i --) {
+ uint32_t kt;
+
+ kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
+ swap ^= kt;
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+ swap = kt;
+
+ /* obsolete
+ print_int_mont("x2", x2);
+ print_int_mont("z2", z2);
+ print_int_mont("x3", x3);
+ print_int_mont("z3", z3);
+ */
+
+ c255_add(a, x2, z2);
+ c255_mul(aa, a, a);
+ c255_sub(b, x2, z2);
+ c255_mul(bb, b, b);
+ c255_sub(e, aa, bb);
+ c255_add(c, x3, z3);
+ c255_sub(d, x3, z3);
+ c255_mul(da, d, a);
+ c255_mul(cb, c, b);
+
+ /* obsolete
+ print_int_mont("a ", a);
+ print_int_mont("aa", aa);
+ print_int_mont("b ", b);
+ print_int_mont("bb", bb);
+ print_int_mont("e ", e);
+ print_int_mont("c ", c);
+ print_int_mont("d ", d);
+ print_int_mont("da", da);
+ print_int_mont("cb", cb);
+ */
+
+ c255_add(x3, da, cb);
+ c255_mul(x3, x3, x3);
+ c255_sub(z3, da, cb);
+ c255_mul(z3, z3, z3);
+ c255_mul(z3, z3, x1);
+ c255_mul(x2, aa, bb);
+ c255_mul(z2, C255_A24, e);
+ c255_add(z2, z2, aa);
+ c255_mul(z2, e, z2);
+
+ /* obsolete
+ print_int_mont("x2", x2);
+ print_int_mont("z2", z2);
+ print_int_mont("x3", x3);
+ print_int_mont("z3", z3);
+ */
+ }
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+
+ /*
+ * Inverse z2 with a modular exponentiation. This is a simple
+ * square-and-multiply algorithm; we mutualise most non-squarings
+ * since the exponent contains almost only ones.
+ */
+ memcpy(a, z2, sizeof z2);
+ for (i = 0; i < 15; i ++) {
+ c255_mul(a, a, a);
+ c255_mul(a, a, z2);
+ }
+ memcpy(b, a, sizeof a);
+ for (i = 0; i < 14; i ++) {
+ int j;
+
+ for (j = 0; j < 16; j ++) {
+ c255_mul(b, b, b);
+ }
+ c255_mul(b, b, a);
+ }
+ for (i = 14; i >= 0; i --) {
+ c255_mul(b, b, b);
+ if ((0xFFEB >> i) & 1) {
+ c255_mul(b, z2, b);
+ }
+ }
+ c255_mul(b, x2, b);
+
+ /*
+ * To avoid a dependency on br_i31_from_monty(), we use
+ * a Montgomery multiplication with 1.
+ * memcpy(x2, b, sizeof b);
+ * br_i31_from_monty(x2, C255_P, P0I);
+ */
+ br_i31_zero(a, C255_P[0]);
+ a[1] = 1;
+ br_i31_montymul(x2, a, b, C255_P, P0I);
+
+ br_i31_encode(G, 32, x2);
+ byteswap(G);
+ return 1;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We don't implement this method, since it is used for ECDSA
+ * only, and there is no ECDSA over Curve25519 (which instead
+ * uses EdDSA).
+ */
+ (void)A;
+ (void)B;
+ (void)len;
+ (void)x;
+ (void)xlen;
+ (void)y;
+ (void)ylen;
+ (void)curve;
+ return 0;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_c25519_i31 = {
+ (uint32_t)0x20000000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_c25519_i31.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_c25519_m15.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_c25519_m15.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_c25519_m15.c (revision 346145)
@@ -0,0 +1,1478 @@
+/*
+ * 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"
+
+/* obsolete
+#include <stdio.h>
+#include <stdlib.h>
+static void
+print_int(const char *name, const uint32_t *x)
+{
+ size_t u;
+ unsigned char tmp[36];
+
+ printf("%s = ", name);
+ for (u = 0; u < 20; u ++) {
+ if (x[u] > 0x1FFF) {
+ printf("INVALID:");
+ for (u = 0; u < 20; u ++) {
+ printf(" %04X", x[u]);
+ }
+ printf("\n");
+ return;
+ }
+ }
+ memset(tmp, 0, sizeof tmp);
+ for (u = 0; u < 20; u ++) {
+ uint32_t w;
+ int j, k;
+
+ w = x[u];
+ j = 13 * (int)u;
+ k = j & 7;
+ if (k != 0) {
+ w <<= k;
+ j -= k;
+ }
+ k = j >> 3;
+ tmp[35 - k] |= (unsigned char)w;
+ tmp[34 - k] |= (unsigned char)(w >> 8);
+ tmp[33 - k] |= (unsigned char)(w >> 16);
+ tmp[32 - k] |= (unsigned char)(w >> 24);
+ }
+ for (u = 4; u < 36; u ++) {
+ printf("%02X", tmp[u]);
+ }
+ printf("\n");
+}
+*/
+
+/*
+ * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
+ * that right-shifting a signed negative integer copies the sign bit
+ * (arithmetic right-shift). This is "implementation-defined behaviour",
+ * i.e. it is not undefined, but it may differ between compilers. Each
+ * compiler is supposed to document its behaviour in that respect. GCC
+ * explicitly defines that an arithmetic right shift is used. We expect
+ * all other compilers to do the same, because underlying CPU offer an
+ * arithmetic right shift opcode that could not be used otherwise.
+ */
+#if BR_NO_ARITH_SHIFT
+#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
+ | ((-((uint32_t)(x) >> 31)) << (32 - (n))))
+#else
+#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
+#endif
+
+/*
+ * Convert an integer from unsigned little-endian encoding to a sequence of
+ * 13-bit words in little-endian order. The final "partial" word is
+ * returned.
+ */
+static uint32_t
+le8_to_le13(uint32_t *dst, const unsigned char *src, size_t len)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ acc |= (uint32_t)(*src ++) << acc_len;
+ acc_len += 8;
+ if (acc_len >= 13) {
+ *dst ++ = acc & 0x1FFF;
+ acc >>= 13;
+ acc_len -= 13;
+ }
+ }
+ return acc;
+}
+
+/*
+ * Convert an integer (13-bit words, little-endian) to unsigned
+ * little-endian encoding. The total encoding length is provided; all
+ * the destination bytes will be filled.
+ */
+static void
+le13_to_le8(unsigned char *dst, size_t len, const uint32_t *src)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ if (acc_len < 8) {
+ acc |= (*src ++) << acc_len;
+ acc_len += 13;
+ }
+ *dst ++ = (unsigned char)acc;
+ acc >>= 8;
+ acc_len -= 8;
+ }
+}
+
+/*
+ * Normalise an array of words to a strict 13 bits per word. Returned
+ * value is the resulting carry. The source (w) and destination (d)
+ * arrays may be identical, but shall not overlap partially.
+ */
+static inline uint32_t
+norm13(uint32_t *d, const uint32_t *w, size_t len)
+{
+ size_t u;
+ uint32_t cc;
+
+ cc = 0;
+ for (u = 0; u < len; u ++) {
+ int32_t z;
+
+ z = w[u] + cc;
+ d[u] = z & 0x1FFF;
+ cc = ARSH(z, 13);
+ }
+ return cc;
+}
+
+/*
+ * mul20() multiplies two 260-bit integers together. Each word must fit
+ * on 13 bits; source operands use 20 words, destination operand
+ * receives 40 words. All overlaps allowed.
+ *
+ * square20() computes the square of a 260-bit integer. Each word must
+ * fit on 13 bits; source operand uses 20 words, destination operand
+ * receives 40 words. All overlaps allowed.
+ */
+
+#if BR_SLOW_MUL15
+
+static void
+mul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ /*
+ * Two-level Karatsuba: turns a 20x20 multiplication into
+ * nine 5x5 multiplications. We use 13-bit words but do not
+ * propagate carries immediately, so words may expand:
+ *
+ * - First Karatsuba decomposition turns the 20x20 mul on
+ * 13-bit words into three 10x10 muls, two on 13-bit words
+ * and one on 14-bit words.
+ *
+ * - Second Karatsuba decomposition further splits these into:
+ *
+ * * four 5x5 muls on 13-bit words
+ * * four 5x5 muls on 14-bit words
+ * * one 5x5 mul on 15-bit words
+ *
+ * Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit
+ * or 15-bit words, respectively.
+ */
+ uint32_t u[45], v[45], w[90];
+ uint32_t cc;
+ int i;
+
+#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
+ (dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \
+ + (s2w)[5 * (s2_off) + 0]; \
+ (dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \
+ + (s2w)[5 * (s2_off) + 1]; \
+ (dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \
+ + (s2w)[5 * (s2_off) + 2]; \
+ (dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \
+ + (s2w)[5 * (s2_off) + 3]; \
+ (dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \
+ + (s2w)[5 * (s2_off) + 4]; \
+ } while (0)
+
+#define ZADDT(dw, d_off, sw, s_off) do { \
+ (dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \
+ (dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \
+ (dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \
+ (dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \
+ (dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \
+ } while (0)
+
+#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
+ (dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \
+ + (s2w)[5 * (s2_off) + 0]; \
+ (dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \
+ + (s2w)[5 * (s2_off) + 1]; \
+ (dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \
+ + (s2w)[5 * (s2_off) + 2]; \
+ (dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \
+ + (s2w)[5 * (s2_off) + 3]; \
+ (dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \
+ + (s2w)[5 * (s2_off) + 4]; \
+ } while (0)
+
+#define CPR1(w, cprcc) do { \
+ uint32_t cprz = (w) + cprcc; \
+ (w) = cprz & 0x1FFF; \
+ cprcc = cprz >> 13; \
+ } while (0)
+
+#define CPR(dw, d_off) do { \
+ uint32_t cprcc; \
+ cprcc = 0; \
+ CPR1((dw)[(d_off) + 0], cprcc); \
+ CPR1((dw)[(d_off) + 1], cprcc); \
+ CPR1((dw)[(d_off) + 2], cprcc); \
+ CPR1((dw)[(d_off) + 3], cprcc); \
+ CPR1((dw)[(d_off) + 4], cprcc); \
+ CPR1((dw)[(d_off) + 5], cprcc); \
+ CPR1((dw)[(d_off) + 6], cprcc); \
+ CPR1((dw)[(d_off) + 7], cprcc); \
+ CPR1((dw)[(d_off) + 8], cprcc); \
+ (dw)[(d_off) + 9] = cprcc; \
+ } while (0)
+
+ memcpy(u, a, 20 * sizeof *a);
+ ZADD(u, 4, a, 0, a, 1);
+ ZADD(u, 5, a, 2, a, 3);
+ ZADD(u, 6, a, 0, a, 2);
+ ZADD(u, 7, a, 1, a, 3);
+ ZADD(u, 8, u, 6, u, 7);
+
+ memcpy(v, b, 20 * sizeof *b);
+ ZADD(v, 4, b, 0, b, 1);
+ ZADD(v, 5, b, 2, b, 3);
+ ZADD(v, 6, b, 0, b, 2);
+ ZADD(v, 7, b, 1, b, 3);
+ ZADD(v, 8, v, 6, v, 7);
+
+ /*
+ * Do the eight first 8x8 muls. Source words are at most 16382
+ * each, so we can add product results together "as is" in 32-bit
+ * words.
+ */
+ for (i = 0; i < 40; i += 5) {
+ w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]);
+ w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1])
+ + MUL15(u[i + 1], v[i + 0]);
+ w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2])
+ + MUL15(u[i + 1], v[i + 1])
+ + MUL15(u[i + 2], v[i + 0]);
+ w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3])
+ + MUL15(u[i + 1], v[i + 2])
+ + MUL15(u[i + 2], v[i + 1])
+ + MUL15(u[i + 3], v[i + 0]);
+ w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4])
+ + MUL15(u[i + 1], v[i + 3])
+ + MUL15(u[i + 2], v[i + 2])
+ + MUL15(u[i + 3], v[i + 1])
+ + MUL15(u[i + 4], v[i + 0]);
+ w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4])
+ + MUL15(u[i + 2], v[i + 3])
+ + MUL15(u[i + 3], v[i + 2])
+ + MUL15(u[i + 4], v[i + 1]);
+ w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4])
+ + MUL15(u[i + 3], v[i + 3])
+ + MUL15(u[i + 4], v[i + 2]);
+ w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4])
+ + MUL15(u[i + 4], v[i + 3]);
+ w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]);
+ w[(i << 1) + 9] = 0;
+ }
+
+ /*
+ * For the 9th multiplication, source words are up to 32764,
+ * so we must do some carry propagation. If we add up to
+ * 4 products and the carry is no more than 524224, then the
+ * result fits in 32 bits, and the next carry will be no more
+ * than 524224 (because 4*(32764^2)+524224 < 8192*524225).
+ *
+ * We thus just skip one of the products in the middle word,
+ * then do a carry propagation (this reduces words to 13 bits
+ * each, except possibly the last, which may use up to 17 bits
+ * or so), then add the missing product.
+ */
+ w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]);
+ w[80 + 1] = MUL15(u[40 + 0], v[40 + 1])
+ + MUL15(u[40 + 1], v[40 + 0]);
+ w[80 + 2] = MUL15(u[40 + 0], v[40 + 2])
+ + MUL15(u[40 + 1], v[40 + 1])
+ + MUL15(u[40 + 2], v[40 + 0]);
+ w[80 + 3] = MUL15(u[40 + 0], v[40 + 3])
+ + MUL15(u[40 + 1], v[40 + 2])
+ + MUL15(u[40 + 2], v[40 + 1])
+ + MUL15(u[40 + 3], v[40 + 0]);
+ w[80 + 4] = MUL15(u[40 + 0], v[40 + 4])
+ + MUL15(u[40 + 1], v[40 + 3])
+ + MUL15(u[40 + 2], v[40 + 2])
+ + MUL15(u[40 + 3], v[40 + 1]);
+ /* + MUL15(u[40 + 4], v[40 + 0]) */
+ w[80 + 5] = MUL15(u[40 + 1], v[40 + 4])
+ + MUL15(u[40 + 2], v[40 + 3])
+ + MUL15(u[40 + 3], v[40 + 2])
+ + MUL15(u[40 + 4], v[40 + 1]);
+ w[80 + 6] = MUL15(u[40 + 2], v[40 + 4])
+ + MUL15(u[40 + 3], v[40 + 3])
+ + MUL15(u[40 + 4], v[40 + 2]);
+ w[80 + 7] = MUL15(u[40 + 3], v[40 + 4])
+ + MUL15(u[40 + 4], v[40 + 3]);
+ w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]);
+
+ CPR(w, 80);
+
+ w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]);
+
+ /*
+ * The products on 14-bit words in slots 6 and 7 yield values
+ * up to 5*(16382^2) each, and we need to subtract two such
+ * values from the higher word. We need the subtraction to fit
+ * in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit.
+ * However, 10*(16382^2) does not fit. So we must perform a
+ * bit of reduction here.
+ */
+ CPR(w, 60);
+ CPR(w, 70);
+
+ /*
+ * Recompose results.
+ */
+
+ /* 0..1*0..1 into 0..3 */
+ ZSUB2F(w, 8, w, 0, w, 2);
+ ZSUB2F(w, 9, w, 1, w, 3);
+ ZADDT(w, 1, w, 8);
+ ZADDT(w, 2, w, 9);
+
+ /* 2..3*2..3 into 4..7 */
+ ZSUB2F(w, 10, w, 4, w, 6);
+ ZSUB2F(w, 11, w, 5, w, 7);
+ ZADDT(w, 5, w, 10);
+ ZADDT(w, 6, w, 11);
+
+ /* (0..1+2..3)*(0..1+2..3) into 12..15 */
+ ZSUB2F(w, 16, w, 12, w, 14);
+ ZSUB2F(w, 17, w, 13, w, 15);
+ ZADDT(w, 13, w, 16);
+ ZADDT(w, 14, w, 17);
+
+ /* first-level recomposition */
+ ZSUB2F(w, 12, w, 0, w, 4);
+ ZSUB2F(w, 13, w, 1, w, 5);
+ ZSUB2F(w, 14, w, 2, w, 6);
+ ZSUB2F(w, 15, w, 3, w, 7);
+ ZADDT(w, 2, w, 12);
+ ZADDT(w, 3, w, 13);
+ ZADDT(w, 4, w, 14);
+ ZADDT(w, 5, w, 15);
+
+ /*
+ * Perform carry propagation to bring all words down to 13 bits.
+ */
+ cc = norm13(d, w, 40);
+ d[39] += (cc << 13);
+
+#undef ZADD
+#undef ZADDT
+#undef ZSUB2F
+#undef CPR1
+#undef CPR
+}
+
+static inline void
+square20(uint32_t *d, const uint32_t *a)
+{
+ mul20(d, a, a);
+}
+
+#else
+
+static void
+mul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t t[39];
+
+ t[ 0] = MUL15(a[ 0], b[ 0]);
+ t[ 1] = MUL15(a[ 0], b[ 1])
+ + MUL15(a[ 1], b[ 0]);
+ t[ 2] = MUL15(a[ 0], b[ 2])
+ + MUL15(a[ 1], b[ 1])
+ + MUL15(a[ 2], b[ 0]);
+ t[ 3] = MUL15(a[ 0], b[ 3])
+ + MUL15(a[ 1], b[ 2])
+ + MUL15(a[ 2], b[ 1])
+ + MUL15(a[ 3], b[ 0]);
+ t[ 4] = MUL15(a[ 0], b[ 4])
+ + MUL15(a[ 1], b[ 3])
+ + MUL15(a[ 2], b[ 2])
+ + MUL15(a[ 3], b[ 1])
+ + MUL15(a[ 4], b[ 0]);
+ t[ 5] = MUL15(a[ 0], b[ 5])
+ + MUL15(a[ 1], b[ 4])
+ + MUL15(a[ 2], b[ 3])
+ + MUL15(a[ 3], b[ 2])
+ + MUL15(a[ 4], b[ 1])
+ + MUL15(a[ 5], b[ 0]);
+ t[ 6] = MUL15(a[ 0], b[ 6])
+ + MUL15(a[ 1], b[ 5])
+ + MUL15(a[ 2], b[ 4])
+ + MUL15(a[ 3], b[ 3])
+ + MUL15(a[ 4], b[ 2])
+ + MUL15(a[ 5], b[ 1])
+ + MUL15(a[ 6], b[ 0]);
+ t[ 7] = MUL15(a[ 0], b[ 7])
+ + MUL15(a[ 1], b[ 6])
+ + MUL15(a[ 2], b[ 5])
+ + MUL15(a[ 3], b[ 4])
+ + MUL15(a[ 4], b[ 3])
+ + MUL15(a[ 5], b[ 2])
+ + MUL15(a[ 6], b[ 1])
+ + MUL15(a[ 7], b[ 0]);
+ t[ 8] = MUL15(a[ 0], b[ 8])
+ + MUL15(a[ 1], b[ 7])
+ + MUL15(a[ 2], b[ 6])
+ + MUL15(a[ 3], b[ 5])
+ + MUL15(a[ 4], b[ 4])
+ + MUL15(a[ 5], b[ 3])
+ + MUL15(a[ 6], b[ 2])
+ + MUL15(a[ 7], b[ 1])
+ + MUL15(a[ 8], b[ 0]);
+ t[ 9] = MUL15(a[ 0], b[ 9])
+ + MUL15(a[ 1], b[ 8])
+ + MUL15(a[ 2], b[ 7])
+ + MUL15(a[ 3], b[ 6])
+ + MUL15(a[ 4], b[ 5])
+ + MUL15(a[ 5], b[ 4])
+ + MUL15(a[ 6], b[ 3])
+ + MUL15(a[ 7], b[ 2])
+ + MUL15(a[ 8], b[ 1])
+ + MUL15(a[ 9], b[ 0]);
+ t[10] = MUL15(a[ 0], b[10])
+ + MUL15(a[ 1], b[ 9])
+ + MUL15(a[ 2], b[ 8])
+ + MUL15(a[ 3], b[ 7])
+ + MUL15(a[ 4], b[ 6])
+ + MUL15(a[ 5], b[ 5])
+ + MUL15(a[ 6], b[ 4])
+ + MUL15(a[ 7], b[ 3])
+ + MUL15(a[ 8], b[ 2])
+ + MUL15(a[ 9], b[ 1])
+ + MUL15(a[10], b[ 0]);
+ t[11] = MUL15(a[ 0], b[11])
+ + MUL15(a[ 1], b[10])
+ + MUL15(a[ 2], b[ 9])
+ + MUL15(a[ 3], b[ 8])
+ + MUL15(a[ 4], b[ 7])
+ + MUL15(a[ 5], b[ 6])
+ + MUL15(a[ 6], b[ 5])
+ + MUL15(a[ 7], b[ 4])
+ + MUL15(a[ 8], b[ 3])
+ + MUL15(a[ 9], b[ 2])
+ + MUL15(a[10], b[ 1])
+ + MUL15(a[11], b[ 0]);
+ t[12] = MUL15(a[ 0], b[12])
+ + MUL15(a[ 1], b[11])
+ + MUL15(a[ 2], b[10])
+ + MUL15(a[ 3], b[ 9])
+ + MUL15(a[ 4], b[ 8])
+ + MUL15(a[ 5], b[ 7])
+ + MUL15(a[ 6], b[ 6])
+ + MUL15(a[ 7], b[ 5])
+ + MUL15(a[ 8], b[ 4])
+ + MUL15(a[ 9], b[ 3])
+ + MUL15(a[10], b[ 2])
+ + MUL15(a[11], b[ 1])
+ + MUL15(a[12], b[ 0]);
+ t[13] = MUL15(a[ 0], b[13])
+ + MUL15(a[ 1], b[12])
+ + MUL15(a[ 2], b[11])
+ + MUL15(a[ 3], b[10])
+ + MUL15(a[ 4], b[ 9])
+ + MUL15(a[ 5], b[ 8])
+ + MUL15(a[ 6], b[ 7])
+ + MUL15(a[ 7], b[ 6])
+ + MUL15(a[ 8], b[ 5])
+ + MUL15(a[ 9], b[ 4])
+ + MUL15(a[10], b[ 3])
+ + MUL15(a[11], b[ 2])
+ + MUL15(a[12], b[ 1])
+ + MUL15(a[13], b[ 0]);
+ t[14] = MUL15(a[ 0], b[14])
+ + MUL15(a[ 1], b[13])
+ + MUL15(a[ 2], b[12])
+ + MUL15(a[ 3], b[11])
+ + MUL15(a[ 4], b[10])
+ + MUL15(a[ 5], b[ 9])
+ + MUL15(a[ 6], b[ 8])
+ + MUL15(a[ 7], b[ 7])
+ + MUL15(a[ 8], b[ 6])
+ + MUL15(a[ 9], b[ 5])
+ + MUL15(a[10], b[ 4])
+ + MUL15(a[11], b[ 3])
+ + MUL15(a[12], b[ 2])
+ + MUL15(a[13], b[ 1])
+ + MUL15(a[14], b[ 0]);
+ t[15] = MUL15(a[ 0], b[15])
+ + MUL15(a[ 1], b[14])
+ + MUL15(a[ 2], b[13])
+ + MUL15(a[ 3], b[12])
+ + MUL15(a[ 4], b[11])
+ + MUL15(a[ 5], b[10])
+ + MUL15(a[ 6], b[ 9])
+ + MUL15(a[ 7], b[ 8])
+ + MUL15(a[ 8], b[ 7])
+ + MUL15(a[ 9], b[ 6])
+ + MUL15(a[10], b[ 5])
+ + MUL15(a[11], b[ 4])
+ + MUL15(a[12], b[ 3])
+ + MUL15(a[13], b[ 2])
+ + MUL15(a[14], b[ 1])
+ + MUL15(a[15], b[ 0]);
+ t[16] = MUL15(a[ 0], b[16])
+ + MUL15(a[ 1], b[15])
+ + MUL15(a[ 2], b[14])
+ + MUL15(a[ 3], b[13])
+ + MUL15(a[ 4], b[12])
+ + MUL15(a[ 5], b[11])
+ + MUL15(a[ 6], b[10])
+ + MUL15(a[ 7], b[ 9])
+ + MUL15(a[ 8], b[ 8])
+ + MUL15(a[ 9], b[ 7])
+ + MUL15(a[10], b[ 6])
+ + MUL15(a[11], b[ 5])
+ + MUL15(a[12], b[ 4])
+ + MUL15(a[13], b[ 3])
+ + MUL15(a[14], b[ 2])
+ + MUL15(a[15], b[ 1])
+ + MUL15(a[16], b[ 0]);
+ t[17] = MUL15(a[ 0], b[17])
+ + MUL15(a[ 1], b[16])
+ + MUL15(a[ 2], b[15])
+ + MUL15(a[ 3], b[14])
+ + MUL15(a[ 4], b[13])
+ + MUL15(a[ 5], b[12])
+ + MUL15(a[ 6], b[11])
+ + MUL15(a[ 7], b[10])
+ + MUL15(a[ 8], b[ 9])
+ + MUL15(a[ 9], b[ 8])
+ + MUL15(a[10], b[ 7])
+ + MUL15(a[11], b[ 6])
+ + MUL15(a[12], b[ 5])
+ + MUL15(a[13], b[ 4])
+ + MUL15(a[14], b[ 3])
+ + MUL15(a[15], b[ 2])
+ + MUL15(a[16], b[ 1])
+ + MUL15(a[17], b[ 0]);
+ t[18] = MUL15(a[ 0], b[18])
+ + MUL15(a[ 1], b[17])
+ + MUL15(a[ 2], b[16])
+ + MUL15(a[ 3], b[15])
+ + MUL15(a[ 4], b[14])
+ + MUL15(a[ 5], b[13])
+ + MUL15(a[ 6], b[12])
+ + MUL15(a[ 7], b[11])
+ + MUL15(a[ 8], b[10])
+ + MUL15(a[ 9], b[ 9])
+ + MUL15(a[10], b[ 8])
+ + MUL15(a[11], b[ 7])
+ + MUL15(a[12], b[ 6])
+ + MUL15(a[13], b[ 5])
+ + MUL15(a[14], b[ 4])
+ + MUL15(a[15], b[ 3])
+ + MUL15(a[16], b[ 2])
+ + MUL15(a[17], b[ 1])
+ + MUL15(a[18], b[ 0]);
+ t[19] = MUL15(a[ 0], b[19])
+ + MUL15(a[ 1], b[18])
+ + MUL15(a[ 2], b[17])
+ + MUL15(a[ 3], b[16])
+ + MUL15(a[ 4], b[15])
+ + MUL15(a[ 5], b[14])
+ + MUL15(a[ 6], b[13])
+ + MUL15(a[ 7], b[12])
+ + MUL15(a[ 8], b[11])
+ + MUL15(a[ 9], b[10])
+ + MUL15(a[10], b[ 9])
+ + MUL15(a[11], b[ 8])
+ + MUL15(a[12], b[ 7])
+ + MUL15(a[13], b[ 6])
+ + MUL15(a[14], b[ 5])
+ + MUL15(a[15], b[ 4])
+ + MUL15(a[16], b[ 3])
+ + MUL15(a[17], b[ 2])
+ + MUL15(a[18], b[ 1])
+ + MUL15(a[19], b[ 0]);
+ t[20] = MUL15(a[ 1], b[19])
+ + MUL15(a[ 2], b[18])
+ + MUL15(a[ 3], b[17])
+ + MUL15(a[ 4], b[16])
+ + MUL15(a[ 5], b[15])
+ + MUL15(a[ 6], b[14])
+ + MUL15(a[ 7], b[13])
+ + MUL15(a[ 8], b[12])
+ + MUL15(a[ 9], b[11])
+ + MUL15(a[10], b[10])
+ + MUL15(a[11], b[ 9])
+ + MUL15(a[12], b[ 8])
+ + MUL15(a[13], b[ 7])
+ + MUL15(a[14], b[ 6])
+ + MUL15(a[15], b[ 5])
+ + MUL15(a[16], b[ 4])
+ + MUL15(a[17], b[ 3])
+ + MUL15(a[18], b[ 2])
+ + MUL15(a[19], b[ 1]);
+ t[21] = MUL15(a[ 2], b[19])
+ + MUL15(a[ 3], b[18])
+ + MUL15(a[ 4], b[17])
+ + MUL15(a[ 5], b[16])
+ + MUL15(a[ 6], b[15])
+ + MUL15(a[ 7], b[14])
+ + MUL15(a[ 8], b[13])
+ + MUL15(a[ 9], b[12])
+ + MUL15(a[10], b[11])
+ + MUL15(a[11], b[10])
+ + MUL15(a[12], b[ 9])
+ + MUL15(a[13], b[ 8])
+ + MUL15(a[14], b[ 7])
+ + MUL15(a[15], b[ 6])
+ + MUL15(a[16], b[ 5])
+ + MUL15(a[17], b[ 4])
+ + MUL15(a[18], b[ 3])
+ + MUL15(a[19], b[ 2]);
+ t[22] = MUL15(a[ 3], b[19])
+ + MUL15(a[ 4], b[18])
+ + MUL15(a[ 5], b[17])
+ + MUL15(a[ 6], b[16])
+ + MUL15(a[ 7], b[15])
+ + MUL15(a[ 8], b[14])
+ + MUL15(a[ 9], b[13])
+ + MUL15(a[10], b[12])
+ + MUL15(a[11], b[11])
+ + MUL15(a[12], b[10])
+ + MUL15(a[13], b[ 9])
+ + MUL15(a[14], b[ 8])
+ + MUL15(a[15], b[ 7])
+ + MUL15(a[16], b[ 6])
+ + MUL15(a[17], b[ 5])
+ + MUL15(a[18], b[ 4])
+ + MUL15(a[19], b[ 3]);
+ t[23] = MUL15(a[ 4], b[19])
+ + MUL15(a[ 5], b[18])
+ + MUL15(a[ 6], b[17])
+ + MUL15(a[ 7], b[16])
+ + MUL15(a[ 8], b[15])
+ + MUL15(a[ 9], b[14])
+ + MUL15(a[10], b[13])
+ + MUL15(a[11], b[12])
+ + MUL15(a[12], b[11])
+ + MUL15(a[13], b[10])
+ + MUL15(a[14], b[ 9])
+ + MUL15(a[15], b[ 8])
+ + MUL15(a[16], b[ 7])
+ + MUL15(a[17], b[ 6])
+ + MUL15(a[18], b[ 5])
+ + MUL15(a[19], b[ 4]);
+ t[24] = MUL15(a[ 5], b[19])
+ + MUL15(a[ 6], b[18])
+ + MUL15(a[ 7], b[17])
+ + MUL15(a[ 8], b[16])
+ + MUL15(a[ 9], b[15])
+ + MUL15(a[10], b[14])
+ + MUL15(a[11], b[13])
+ + MUL15(a[12], b[12])
+ + MUL15(a[13], b[11])
+ + MUL15(a[14], b[10])
+ + MUL15(a[15], b[ 9])
+ + MUL15(a[16], b[ 8])
+ + MUL15(a[17], b[ 7])
+ + MUL15(a[18], b[ 6])
+ + MUL15(a[19], b[ 5]);
+ t[25] = MUL15(a[ 6], b[19])
+ + MUL15(a[ 7], b[18])
+ + MUL15(a[ 8], b[17])
+ + MUL15(a[ 9], b[16])
+ + MUL15(a[10], b[15])
+ + MUL15(a[11], b[14])
+ + MUL15(a[12], b[13])
+ + MUL15(a[13], b[12])
+ + MUL15(a[14], b[11])
+ + MUL15(a[15], b[10])
+ + MUL15(a[16], b[ 9])
+ + MUL15(a[17], b[ 8])
+ + MUL15(a[18], b[ 7])
+ + MUL15(a[19], b[ 6]);
+ t[26] = MUL15(a[ 7], b[19])
+ + MUL15(a[ 8], b[18])
+ + MUL15(a[ 9], b[17])
+ + MUL15(a[10], b[16])
+ + MUL15(a[11], b[15])
+ + MUL15(a[12], b[14])
+ + MUL15(a[13], b[13])
+ + MUL15(a[14], b[12])
+ + MUL15(a[15], b[11])
+ + MUL15(a[16], b[10])
+ + MUL15(a[17], b[ 9])
+ + MUL15(a[18], b[ 8])
+ + MUL15(a[19], b[ 7]);
+ t[27] = MUL15(a[ 8], b[19])
+ + MUL15(a[ 9], b[18])
+ + MUL15(a[10], b[17])
+ + MUL15(a[11], b[16])
+ + MUL15(a[12], b[15])
+ + MUL15(a[13], b[14])
+ + MUL15(a[14], b[13])
+ + MUL15(a[15], b[12])
+ + MUL15(a[16], b[11])
+ + MUL15(a[17], b[10])
+ + MUL15(a[18], b[ 9])
+ + MUL15(a[19], b[ 8]);
+ t[28] = MUL15(a[ 9], b[19])
+ + MUL15(a[10], b[18])
+ + MUL15(a[11], b[17])
+ + MUL15(a[12], b[16])
+ + MUL15(a[13], b[15])
+ + MUL15(a[14], b[14])
+ + MUL15(a[15], b[13])
+ + MUL15(a[16], b[12])
+ + MUL15(a[17], b[11])
+ + MUL15(a[18], b[10])
+ + MUL15(a[19], b[ 9]);
+ t[29] = MUL15(a[10], b[19])
+ + MUL15(a[11], b[18])
+ + MUL15(a[12], b[17])
+ + MUL15(a[13], b[16])
+ + MUL15(a[14], b[15])
+ + MUL15(a[15], b[14])
+ + MUL15(a[16], b[13])
+ + MUL15(a[17], b[12])
+ + MUL15(a[18], b[11])
+ + MUL15(a[19], b[10]);
+ t[30] = MUL15(a[11], b[19])
+ + MUL15(a[12], b[18])
+ + MUL15(a[13], b[17])
+ + MUL15(a[14], b[16])
+ + MUL15(a[15], b[15])
+ + MUL15(a[16], b[14])
+ + MUL15(a[17], b[13])
+ + MUL15(a[18], b[12])
+ + MUL15(a[19], b[11]);
+ t[31] = MUL15(a[12], b[19])
+ + MUL15(a[13], b[18])
+ + MUL15(a[14], b[17])
+ + MUL15(a[15], b[16])
+ + MUL15(a[16], b[15])
+ + MUL15(a[17], b[14])
+ + MUL15(a[18], b[13])
+ + MUL15(a[19], b[12]);
+ t[32] = MUL15(a[13], b[19])
+ + MUL15(a[14], b[18])
+ + MUL15(a[15], b[17])
+ + MUL15(a[16], b[16])
+ + MUL15(a[17], b[15])
+ + MUL15(a[18], b[14])
+ + MUL15(a[19], b[13]);
+ t[33] = MUL15(a[14], b[19])
+ + MUL15(a[15], b[18])
+ + MUL15(a[16], b[17])
+ + MUL15(a[17], b[16])
+ + MUL15(a[18], b[15])
+ + MUL15(a[19], b[14]);
+ t[34] = MUL15(a[15], b[19])
+ + MUL15(a[16], b[18])
+ + MUL15(a[17], b[17])
+ + MUL15(a[18], b[16])
+ + MUL15(a[19], b[15]);
+ t[35] = MUL15(a[16], b[19])
+ + MUL15(a[17], b[18])
+ + MUL15(a[18], b[17])
+ + MUL15(a[19], b[16]);
+ t[36] = MUL15(a[17], b[19])
+ + MUL15(a[18], b[18])
+ + MUL15(a[19], b[17]);
+ t[37] = MUL15(a[18], b[19])
+ + MUL15(a[19], b[18]);
+ t[38] = MUL15(a[19], b[19]);
+
+ d[39] = norm13(d, t, 39);
+}
+
+static void
+square20(uint32_t *d, const uint32_t *a)
+{
+ uint32_t t[39];
+
+ t[ 0] = MUL15(a[ 0], a[ 0]);
+ t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1);
+ t[ 2] = MUL15(a[ 1], a[ 1])
+ + ((MUL15(a[ 0], a[ 2])) << 1);
+ t[ 3] = ((MUL15(a[ 0], a[ 3])
+ + MUL15(a[ 1], a[ 2])) << 1);
+ t[ 4] = MUL15(a[ 2], a[ 2])
+ + ((MUL15(a[ 0], a[ 4])
+ + MUL15(a[ 1], a[ 3])) << 1);
+ t[ 5] = ((MUL15(a[ 0], a[ 5])
+ + MUL15(a[ 1], a[ 4])
+ + MUL15(a[ 2], a[ 3])) << 1);
+ t[ 6] = MUL15(a[ 3], a[ 3])
+ + ((MUL15(a[ 0], a[ 6])
+ + MUL15(a[ 1], a[ 5])
+ + MUL15(a[ 2], a[ 4])) << 1);
+ t[ 7] = ((MUL15(a[ 0], a[ 7])
+ + MUL15(a[ 1], a[ 6])
+ + MUL15(a[ 2], a[ 5])
+ + MUL15(a[ 3], a[ 4])) << 1);
+ t[ 8] = MUL15(a[ 4], a[ 4])
+ + ((MUL15(a[ 0], a[ 8])
+ + MUL15(a[ 1], a[ 7])
+ + MUL15(a[ 2], a[ 6])
+ + MUL15(a[ 3], a[ 5])) << 1);
+ t[ 9] = ((MUL15(a[ 0], a[ 9])
+ + MUL15(a[ 1], a[ 8])
+ + MUL15(a[ 2], a[ 7])
+ + MUL15(a[ 3], a[ 6])
+ + MUL15(a[ 4], a[ 5])) << 1);
+ t[10] = MUL15(a[ 5], a[ 5])
+ + ((MUL15(a[ 0], a[10])
+ + MUL15(a[ 1], a[ 9])
+ + MUL15(a[ 2], a[ 8])
+ + MUL15(a[ 3], a[ 7])
+ + MUL15(a[ 4], a[ 6])) << 1);
+ t[11] = ((MUL15(a[ 0], a[11])
+ + MUL15(a[ 1], a[10])
+ + MUL15(a[ 2], a[ 9])
+ + MUL15(a[ 3], a[ 8])
+ + MUL15(a[ 4], a[ 7])
+ + MUL15(a[ 5], a[ 6])) << 1);
+ t[12] = MUL15(a[ 6], a[ 6])
+ + ((MUL15(a[ 0], a[12])
+ + MUL15(a[ 1], a[11])
+ + MUL15(a[ 2], a[10])
+ + MUL15(a[ 3], a[ 9])
+ + MUL15(a[ 4], a[ 8])
+ + MUL15(a[ 5], a[ 7])) << 1);
+ t[13] = ((MUL15(a[ 0], a[13])
+ + MUL15(a[ 1], a[12])
+ + MUL15(a[ 2], a[11])
+ + MUL15(a[ 3], a[10])
+ + MUL15(a[ 4], a[ 9])
+ + MUL15(a[ 5], a[ 8])
+ + MUL15(a[ 6], a[ 7])) << 1);
+ t[14] = MUL15(a[ 7], a[ 7])
+ + ((MUL15(a[ 0], a[14])
+ + MUL15(a[ 1], a[13])
+ + MUL15(a[ 2], a[12])
+ + MUL15(a[ 3], a[11])
+ + MUL15(a[ 4], a[10])
+ + MUL15(a[ 5], a[ 9])
+ + MUL15(a[ 6], a[ 8])) << 1);
+ t[15] = ((MUL15(a[ 0], a[15])
+ + MUL15(a[ 1], a[14])
+ + MUL15(a[ 2], a[13])
+ + MUL15(a[ 3], a[12])
+ + MUL15(a[ 4], a[11])
+ + MUL15(a[ 5], a[10])
+ + MUL15(a[ 6], a[ 9])
+ + MUL15(a[ 7], a[ 8])) << 1);
+ t[16] = MUL15(a[ 8], a[ 8])
+ + ((MUL15(a[ 0], a[16])
+ + MUL15(a[ 1], a[15])
+ + MUL15(a[ 2], a[14])
+ + MUL15(a[ 3], a[13])
+ + MUL15(a[ 4], a[12])
+ + MUL15(a[ 5], a[11])
+ + MUL15(a[ 6], a[10])
+ + MUL15(a[ 7], a[ 9])) << 1);
+ t[17] = ((MUL15(a[ 0], a[17])
+ + MUL15(a[ 1], a[16])
+ + MUL15(a[ 2], a[15])
+ + MUL15(a[ 3], a[14])
+ + MUL15(a[ 4], a[13])
+ + MUL15(a[ 5], a[12])
+ + MUL15(a[ 6], a[11])
+ + MUL15(a[ 7], a[10])
+ + MUL15(a[ 8], a[ 9])) << 1);
+ t[18] = MUL15(a[ 9], a[ 9])
+ + ((MUL15(a[ 0], a[18])
+ + MUL15(a[ 1], a[17])
+ + MUL15(a[ 2], a[16])
+ + MUL15(a[ 3], a[15])
+ + MUL15(a[ 4], a[14])
+ + MUL15(a[ 5], a[13])
+ + MUL15(a[ 6], a[12])
+ + MUL15(a[ 7], a[11])
+ + MUL15(a[ 8], a[10])) << 1);
+ t[19] = ((MUL15(a[ 0], a[19])
+ + MUL15(a[ 1], a[18])
+ + MUL15(a[ 2], a[17])
+ + MUL15(a[ 3], a[16])
+ + MUL15(a[ 4], a[15])
+ + MUL15(a[ 5], a[14])
+ + MUL15(a[ 6], a[13])
+ + MUL15(a[ 7], a[12])
+ + MUL15(a[ 8], a[11])
+ + MUL15(a[ 9], a[10])) << 1);
+ t[20] = MUL15(a[10], a[10])
+ + ((MUL15(a[ 1], a[19])
+ + MUL15(a[ 2], a[18])
+ + MUL15(a[ 3], a[17])
+ + MUL15(a[ 4], a[16])
+ + MUL15(a[ 5], a[15])
+ + MUL15(a[ 6], a[14])
+ + MUL15(a[ 7], a[13])
+ + MUL15(a[ 8], a[12])
+ + MUL15(a[ 9], a[11])) << 1);
+ t[21] = ((MUL15(a[ 2], a[19])
+ + MUL15(a[ 3], a[18])
+ + MUL15(a[ 4], a[17])
+ + MUL15(a[ 5], a[16])
+ + MUL15(a[ 6], a[15])
+ + MUL15(a[ 7], a[14])
+ + MUL15(a[ 8], a[13])
+ + MUL15(a[ 9], a[12])
+ + MUL15(a[10], a[11])) << 1);
+ t[22] = MUL15(a[11], a[11])
+ + ((MUL15(a[ 3], a[19])
+ + MUL15(a[ 4], a[18])
+ + MUL15(a[ 5], a[17])
+ + MUL15(a[ 6], a[16])
+ + MUL15(a[ 7], a[15])
+ + MUL15(a[ 8], a[14])
+ + MUL15(a[ 9], a[13])
+ + MUL15(a[10], a[12])) << 1);
+ t[23] = ((MUL15(a[ 4], a[19])
+ + MUL15(a[ 5], a[18])
+ + MUL15(a[ 6], a[17])
+ + MUL15(a[ 7], a[16])
+ + MUL15(a[ 8], a[15])
+ + MUL15(a[ 9], a[14])
+ + MUL15(a[10], a[13])
+ + MUL15(a[11], a[12])) << 1);
+ t[24] = MUL15(a[12], a[12])
+ + ((MUL15(a[ 5], a[19])
+ + MUL15(a[ 6], a[18])
+ + MUL15(a[ 7], a[17])
+ + MUL15(a[ 8], a[16])
+ + MUL15(a[ 9], a[15])
+ + MUL15(a[10], a[14])
+ + MUL15(a[11], a[13])) << 1);
+ t[25] = ((MUL15(a[ 6], a[19])
+ + MUL15(a[ 7], a[18])
+ + MUL15(a[ 8], a[17])
+ + MUL15(a[ 9], a[16])
+ + MUL15(a[10], a[15])
+ + MUL15(a[11], a[14])
+ + MUL15(a[12], a[13])) << 1);
+ t[26] = MUL15(a[13], a[13])
+ + ((MUL15(a[ 7], a[19])
+ + MUL15(a[ 8], a[18])
+ + MUL15(a[ 9], a[17])
+ + MUL15(a[10], a[16])
+ + MUL15(a[11], a[15])
+ + MUL15(a[12], a[14])) << 1);
+ t[27] = ((MUL15(a[ 8], a[19])
+ + MUL15(a[ 9], a[18])
+ + MUL15(a[10], a[17])
+ + MUL15(a[11], a[16])
+ + MUL15(a[12], a[15])
+ + MUL15(a[13], a[14])) << 1);
+ t[28] = MUL15(a[14], a[14])
+ + ((MUL15(a[ 9], a[19])
+ + MUL15(a[10], a[18])
+ + MUL15(a[11], a[17])
+ + MUL15(a[12], a[16])
+ + MUL15(a[13], a[15])) << 1);
+ t[29] = ((MUL15(a[10], a[19])
+ + MUL15(a[11], a[18])
+ + MUL15(a[12], a[17])
+ + MUL15(a[13], a[16])
+ + MUL15(a[14], a[15])) << 1);
+ t[30] = MUL15(a[15], a[15])
+ + ((MUL15(a[11], a[19])
+ + MUL15(a[12], a[18])
+ + MUL15(a[13], a[17])
+ + MUL15(a[14], a[16])) << 1);
+ t[31] = ((MUL15(a[12], a[19])
+ + MUL15(a[13], a[18])
+ + MUL15(a[14], a[17])
+ + MUL15(a[15], a[16])) << 1);
+ t[32] = MUL15(a[16], a[16])
+ + ((MUL15(a[13], a[19])
+ + MUL15(a[14], a[18])
+ + MUL15(a[15], a[17])) << 1);
+ t[33] = ((MUL15(a[14], a[19])
+ + MUL15(a[15], a[18])
+ + MUL15(a[16], a[17])) << 1);
+ t[34] = MUL15(a[17], a[17])
+ + ((MUL15(a[15], a[19])
+ + MUL15(a[16], a[18])) << 1);
+ t[35] = ((MUL15(a[16], a[19])
+ + MUL15(a[17], a[18])) << 1);
+ t[36] = MUL15(a[18], a[18])
+ + ((MUL15(a[17], a[19])) << 1);
+ t[37] = ((MUL15(a[18], a[19])) << 1);
+ t[38] = MUL15(a[19], a[19]);
+
+ d[39] = norm13(d, t, 39);
+}
+
+#endif
+
+/*
+ * Perform a "final reduction" in field F255 (field for Curve25519)
+ * The source value must be less than twice the modulus. If the value
+ * is not lower than the modulus, then the modulus is subtracted and
+ * this function returns 1; otherwise, it leaves it untouched and it
+ * returns 0.
+ */
+static uint32_t
+reduce_final_f255(uint32_t *d)
+{
+ uint32_t t[20];
+ uint32_t cc;
+ int i;
+
+ memcpy(t, d, sizeof t);
+ cc = 19;
+ for (i = 0; i < 20; i ++) {
+ uint32_t w;
+
+ w = t[i] + cc;
+ cc = w >> 13;
+ t[i] = w & 0x1FFF;
+ }
+ cc = t[19] >> 8;
+ t[19] &= 0xFF;
+ CCOPY(cc, d, t, sizeof t);
+ return cc;
+}
+
+static void
+f255_mulgen(uint32_t *d, const uint32_t *a, const uint32_t *b, int square)
+{
+ uint32_t t[40], cc, w;
+
+ /*
+ * Compute raw multiplication. All result words fit in 13 bits
+ * each; upper word (t[39]) must fit on 5 bits, since the product
+ * of two 256-bit integers must fit on 512 bits.
+ */
+ if (square) {
+ square20(t, a);
+ } else {
+ mul20(t, a, b);
+ }
+
+ /*
+ * Modular reduction: each high word is added where necessary.
+ * Since the modulus is 2^255-19 and word 20 corresponds to
+ * offset 20*13 = 260, word 20+k must be added to word k with
+ * a factor of 19*2^5 = 608. The extra bits in word 19 are also
+ * added that way.
+ */
+ cc = MUL15(t[19] >> 8, 19);
+ t[19] &= 0xFF;
+
+#define MM1(x) do { \
+ w = t[x] + cc + MUL15(t[(x) + 20], 608); \
+ t[x] = w & 0x1FFF; \
+ cc = w >> 13; \
+ } while (0)
+
+ MM1( 0);
+ MM1( 1);
+ MM1( 2);
+ MM1( 3);
+ MM1( 4);
+ MM1( 5);
+ MM1( 6);
+ MM1( 7);
+ MM1( 8);
+ MM1( 9);
+ MM1(10);
+ MM1(11);
+ MM1(12);
+ MM1(13);
+ MM1(14);
+ MM1(15);
+ MM1(16);
+ MM1(17);
+ MM1(18);
+ MM1(19);
+
+#undef MM1
+
+ cc = MUL15(w >> 8, 19);
+ t[19] &= 0xFF;
+
+#define MM2(x) do { \
+ w = t[x] + cc; \
+ d[x] = w & 0x1FFF; \
+ cc = w >> 13; \
+ } while (0)
+
+ MM2( 0);
+ MM2( 1);
+ MM2( 2);
+ MM2( 3);
+ MM2( 4);
+ MM2( 5);
+ MM2( 6);
+ MM2( 7);
+ MM2( 8);
+ MM2( 9);
+ MM2(10);
+ MM2(11);
+ MM2(12);
+ MM2(13);
+ MM2(14);
+ MM2(15);
+ MM2(16);
+ MM2(17);
+ MM2(18);
+ MM2(19);
+
+#undef MM2
+}
+
+/*
+ * Perform a multiplication of two integers modulo 2^255-19.
+ * Operands are arrays of 20 words, each containing 13 bits of data, in
+ * little-endian order. Input value may be up to 2^256-1; on output, value
+ * fits on 256 bits and is lower than twice the modulus.
+ *
+ * f255_mul() is the general multiplication, f255_square() is specialised
+ * for squarings.
+ */
+#define f255_mul(d, a, b) f255_mulgen(d, a, b, 0)
+#define f255_square(d, a) f255_mulgen(d, a, a, 1)
+
+/*
+ * Add two values in F255. Partial reduction is performed (down to less
+ * than twice the modulus).
+ */
+static void
+f255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ int i;
+ uint32_t cc, w;
+
+ cc = 0;
+ for (i = 0; i < 20; i ++) {
+ w = a[i] + b[i] + cc;
+ d[i] = w & 0x1FFF;
+ cc = w >> 13;
+ }
+ cc = MUL15(w >> 8, 19);
+ d[19] &= 0xFF;
+ for (i = 0; i < 20; i ++) {
+ w = d[i] + cc;
+ d[i] = w & 0x1FFF;
+ cc = w >> 13;
+ }
+}
+
+/*
+ * Subtract one value from another in F255. Partial reduction is
+ * performed (down to less than twice the modulus).
+ */
+static void
+f255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ /*
+ * We actually compute a - b + 2*p, so that the final value is
+ * necessarily positive.
+ */
+ int i;
+ uint32_t cc, w;
+
+ cc = (uint32_t)-38;
+ for (i = 0; i < 20; i ++) {
+ w = a[i] - b[i] + cc;
+ d[i] = w & 0x1FFF;
+ cc = ARSH(w, 13);
+ }
+ cc = MUL15((w + 0x200) >> 8, 19);
+ d[19] &= 0xFF;
+ for (i = 0; i < 20; i ++) {
+ w = d[i] + cc;
+ d[i] = w & 0x1FFF;
+ cc = w >> 13;
+ }
+}
+
+/*
+ * Multiply an integer by the 'A24' constant (121665). Partial reduction
+ * is performed (down to less than twice the modulus).
+ */
+static void
+f255_mul_a24(uint32_t *d, const uint32_t *a)
+{
+ int i;
+ uint32_t cc, w;
+
+ cc = 0;
+ for (i = 0; i < 20; i ++) {
+ w = MUL15(a[i], 121665) + cc;
+ d[i] = w & 0x1FFF;
+ cc = w >> 13;
+ }
+ cc = MUL15(w >> 8, 19);
+ d[19] &= 0xFF;
+ for (i = 0; i < 20; i ++) {
+ w = d[i] + cc;
+ d[i] = w & 0x1FFF;
+ cc = w >> 13;
+ }
+}
+
+static const unsigned char GEN[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ORDER[] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return GEN;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return ORDER;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 0;
+}
+
+static void
+cswap(uint32_t *a, uint32_t *b, uint32_t ctl)
+{
+ int i;
+
+ ctl = -ctl;
+ for (i = 0; i < 20; i ++) {
+ uint32_t aw, bw, tw;
+
+ aw = a[i];
+ bw = b[i];
+ tw = ctl & (aw ^ bw);
+ a[i] = aw ^ tw;
+ b[i] = bw ^ tw;
+ }
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+ uint32_t x1[20], x2[20], x3[20], z2[20], z3[20];
+ uint32_t a[20], aa[20], b[20], bb[20];
+ uint32_t c[20], d[20], e[20], da[20], cb[20];
+ unsigned char k[32];
+ uint32_t swap;
+ int i;
+
+ (void)curve;
+
+ /*
+ * Points are encoded over exactly 32 bytes. Multipliers must fit
+ * in 32 bytes as well.
+ * RFC 7748 mandates that the high bit of the last point byte must
+ * be ignored/cleared.
+ */
+ if (Glen != 32 || kblen > 32) {
+ return 0;
+ }
+ G[31] &= 0x7F;
+
+ /*
+ * Initialise variables x1, x2, z2, x3 and z3. We set all of them
+ * into Montgomery representation.
+ */
+ x1[19] = le8_to_le13(x1, G, 32);
+ memcpy(x3, x1, sizeof x1);
+ memset(z2, 0, sizeof z2);
+ memset(x2, 0, sizeof x2);
+ x2[0] = 1;
+ memset(z3, 0, sizeof z3);
+ z3[0] = 1;
+
+ memset(k, 0, (sizeof k) - kblen);
+ memcpy(k + (sizeof k) - kblen, kb, kblen);
+ k[31] &= 0xF8;
+ k[0] &= 0x7F;
+ k[0] |= 0x40;
+
+ /* obsolete
+ print_int("x1", x1);
+ */
+
+ swap = 0;
+ for (i = 254; i >= 0; i --) {
+ uint32_t kt;
+
+ kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
+ swap ^= kt;
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+ swap = kt;
+
+ /* obsolete
+ print_int("x2", x2);
+ print_int("z2", z2);
+ print_int("x3", x3);
+ print_int("z3", z3);
+ */
+
+ f255_add(a, x2, z2);
+ f255_square(aa, a);
+ f255_sub(b, x2, z2);
+ f255_square(bb, b);
+ f255_sub(e, aa, bb);
+ f255_add(c, x3, z3);
+ f255_sub(d, x3, z3);
+ f255_mul(da, d, a);
+ f255_mul(cb, c, b);
+
+ /* obsolete
+ print_int("a ", a);
+ print_int("aa", aa);
+ print_int("b ", b);
+ print_int("bb", bb);
+ print_int("e ", e);
+ print_int("c ", c);
+ print_int("d ", d);
+ print_int("da", da);
+ print_int("cb", cb);
+ */
+
+ f255_add(x3, da, cb);
+ f255_square(x3, x3);
+ f255_sub(z3, da, cb);
+ f255_square(z3, z3);
+ f255_mul(z3, z3, x1);
+ f255_mul(x2, aa, bb);
+ f255_mul_a24(z2, e);
+ f255_add(z2, z2, aa);
+ f255_mul(z2, e, z2);
+
+ /* obsolete
+ print_int("x2", x2);
+ print_int("z2", z2);
+ print_int("x3", x3);
+ print_int("z3", z3);
+ */
+ }
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+
+ /*
+ * Inverse z2 with a modular exponentiation. This is a simple
+ * square-and-multiply algorithm; we mutualise most non-squarings
+ * since the exponent contains almost only ones.
+ */
+ memcpy(a, z2, sizeof z2);
+ for (i = 0; i < 15; i ++) {
+ f255_square(a, a);
+ f255_mul(a, a, z2);
+ }
+ memcpy(b, a, sizeof a);
+ for (i = 0; i < 14; i ++) {
+ int j;
+
+ for (j = 0; j < 16; j ++) {
+ f255_square(b, b);
+ }
+ f255_mul(b, b, a);
+ }
+ for (i = 14; i >= 0; i --) {
+ f255_square(b, b);
+ if ((0xFFEB >> i) & 1) {
+ f255_mul(b, z2, b);
+ }
+ }
+ f255_mul(x2, x2, b);
+ reduce_final_f255(x2);
+ le13_to_le8(G, 32, x2);
+ return 1;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We don't implement this method, since it is used for ECDSA
+ * only, and there is no ECDSA over Curve25519 (which instead
+ * uses EdDSA).
+ */
+ (void)A;
+ (void)B;
+ (void)len;
+ (void)x;
+ (void)xlen;
+ (void)y;
+ (void)ylen;
+ (void)curve;
+ return 0;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_c25519_m15 = {
+ (uint32_t)0x20000000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_c25519_m15.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_c25519_m31.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_c25519_m31.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_c25519_m31.c (revision 346145)
@@ -0,0 +1,800 @@
+/*
+ * 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"
+
+/* obsolete
+#include <stdio.h>
+#include <stdlib.h>
+static void
+print_int(const char *name, const uint32_t *x)
+{
+ size_t u;
+ unsigned char tmp[40];
+
+ printf("%s = ", name);
+ for (u = 0; u < 9; u ++) {
+ if (x[u] > 0x3FFFFFFF) {
+ printf("INVALID:");
+ for (u = 0; u < 9; u ++) {
+ printf(" %08X", x[u]);
+ }
+ printf("\n");
+ return;
+ }
+ }
+ memset(tmp, 0, sizeof tmp);
+ for (u = 0; u < 9; u ++) {
+ uint64_t w;
+ int j, k;
+
+ w = x[u];
+ j = 30 * (int)u;
+ k = j & 7;
+ if (k != 0) {
+ w <<= k;
+ j -= k;
+ }
+ k = j >> 3;
+ for (j = 0; j < 8; j ++) {
+ tmp[39 - k - j] |= (unsigned char)w;
+ w >>= 8;
+ }
+ }
+ for (u = 8; u < 40; u ++) {
+ printf("%02X", tmp[u]);
+ }
+ printf("\n");
+}
+*/
+
+/*
+ * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
+ * that right-shifting a signed negative integer copies the sign bit
+ * (arithmetic right-shift). This is "implementation-defined behaviour",
+ * i.e. it is not undefined, but it may differ between compilers. Each
+ * compiler is supposed to document its behaviour in that respect. GCC
+ * explicitly defines that an arithmetic right shift is used. We expect
+ * all other compilers to do the same, because underlying CPU offer an
+ * arithmetic right shift opcode that could not be used otherwise.
+ */
+#if BR_NO_ARITH_SHIFT
+#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
+ | ((-((uint32_t)(x) >> 31)) << (32 - (n))))
+#else
+#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
+#endif
+
+/*
+ * Convert an integer from unsigned little-endian encoding to a sequence of
+ * 30-bit words in little-endian order. The final "partial" word is
+ * returned.
+ */
+static uint32_t
+le8_to_le30(uint32_t *dst, const unsigned char *src, size_t len)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ uint32_t b;
+
+ b = *src ++;
+ if (acc_len < 22) {
+ acc |= b << acc_len;
+ acc_len += 8;
+ } else {
+ *dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF;
+ acc = b >> (30 - acc_len);
+ acc_len -= 22;
+ }
+ }
+ return acc;
+}
+
+/*
+ * Convert an integer (30-bit words, little-endian) to unsigned
+ * little-endian encoding. The total encoding length is provided; all
+ * the destination bytes will be filled.
+ */
+static void
+le30_to_le8(unsigned char *dst, size_t len, const uint32_t *src)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ if (acc_len < 8) {
+ uint32_t w;
+
+ w = *src ++;
+ *dst ++ = (unsigned char)(acc | (w << acc_len));
+ acc = w >> (8 - acc_len);
+ acc_len += 22;
+ } else {
+ *dst ++ = (unsigned char)acc;
+ acc >>= 8;
+ acc_len -= 8;
+ }
+ }
+}
+
+/*
+ * Multiply two integers. Source integers are represented as arrays of
+ * nine 30-bit words, for values up to 2^270-1. Result is encoded over
+ * 18 words of 30 bits each.
+ */
+static void
+mul9(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ /*
+ * Maximum intermediate result is no more than
+ * 10376293531797946367, which fits in 64 bits. Reason:
+ *
+ * 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406
+ * 10376293531797946367 < 9663676407 * 2^30
+ *
+ * Thus, adding together 9 products of 30-bit integers, with
+ * a carry of at most 9663676406, yields an integer that fits
+ * on 64 bits and generates a carry of at most 9663676406.
+ */
+ uint64_t t[17];
+ uint64_t cc;
+ int i;
+
+ t[ 0] = MUL31(a[0], b[0]);
+ t[ 1] = MUL31(a[0], b[1])
+ + MUL31(a[1], b[0]);
+ t[ 2] = MUL31(a[0], b[2])
+ + MUL31(a[1], b[1])
+ + MUL31(a[2], b[0]);
+ t[ 3] = MUL31(a[0], b[3])
+ + MUL31(a[1], b[2])
+ + MUL31(a[2], b[1])
+ + MUL31(a[3], b[0]);
+ t[ 4] = MUL31(a[0], b[4])
+ + MUL31(a[1], b[3])
+ + MUL31(a[2], b[2])
+ + MUL31(a[3], b[1])
+ + MUL31(a[4], b[0]);
+ t[ 5] = MUL31(a[0], b[5])
+ + MUL31(a[1], b[4])
+ + MUL31(a[2], b[3])
+ + MUL31(a[3], b[2])
+ + MUL31(a[4], b[1])
+ + MUL31(a[5], b[0]);
+ t[ 6] = MUL31(a[0], b[6])
+ + MUL31(a[1], b[5])
+ + MUL31(a[2], b[4])
+ + MUL31(a[3], b[3])
+ + MUL31(a[4], b[2])
+ + MUL31(a[5], b[1])
+ + MUL31(a[6], b[0]);
+ t[ 7] = MUL31(a[0], b[7])
+ + MUL31(a[1], b[6])
+ + MUL31(a[2], b[5])
+ + MUL31(a[3], b[4])
+ + MUL31(a[4], b[3])
+ + MUL31(a[5], b[2])
+ + MUL31(a[6], b[1])
+ + MUL31(a[7], b[0]);
+ t[ 8] = MUL31(a[0], b[8])
+ + MUL31(a[1], b[7])
+ + MUL31(a[2], b[6])
+ + MUL31(a[3], b[5])
+ + MUL31(a[4], b[4])
+ + MUL31(a[5], b[3])
+ + MUL31(a[6], b[2])
+ + MUL31(a[7], b[1])
+ + MUL31(a[8], b[0]);
+ t[ 9] = MUL31(a[1], b[8])
+ + MUL31(a[2], b[7])
+ + MUL31(a[3], b[6])
+ + MUL31(a[4], b[5])
+ + MUL31(a[5], b[4])
+ + MUL31(a[6], b[3])
+ + MUL31(a[7], b[2])
+ + MUL31(a[8], b[1]);
+ t[10] = MUL31(a[2], b[8])
+ + MUL31(a[3], b[7])
+ + MUL31(a[4], b[6])
+ + MUL31(a[5], b[5])
+ + MUL31(a[6], b[4])
+ + MUL31(a[7], b[3])
+ + MUL31(a[8], b[2]);
+ t[11] = MUL31(a[3], b[8])
+ + MUL31(a[4], b[7])
+ + MUL31(a[5], b[6])
+ + MUL31(a[6], b[5])
+ + MUL31(a[7], b[4])
+ + MUL31(a[8], b[3]);
+ t[12] = MUL31(a[4], b[8])
+ + MUL31(a[5], b[7])
+ + MUL31(a[6], b[6])
+ + MUL31(a[7], b[5])
+ + MUL31(a[8], b[4]);
+ t[13] = MUL31(a[5], b[8])
+ + MUL31(a[6], b[7])
+ + MUL31(a[7], b[6])
+ + MUL31(a[8], b[5]);
+ t[14] = MUL31(a[6], b[8])
+ + MUL31(a[7], b[7])
+ + MUL31(a[8], b[6]);
+ t[15] = MUL31(a[7], b[8])
+ + MUL31(a[8], b[7]);
+ t[16] = MUL31(a[8], b[8]);
+
+ /*
+ * Propagate carries.
+ */
+ cc = 0;
+ for (i = 0; i < 17; i ++) {
+ uint64_t w;
+
+ w = t[i] + cc;
+ d[i] = (uint32_t)w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+ d[17] = (uint32_t)cc;
+}
+
+/*
+ * Square a 270-bit integer, represented as an array of nine 30-bit words.
+ * Result uses 18 words of 30 bits each.
+ */
+static void
+square9(uint32_t *d, const uint32_t *a)
+{
+ uint64_t t[17];
+ uint64_t cc;
+ int i;
+
+ t[ 0] = MUL31(a[0], a[0]);
+ t[ 1] = ((MUL31(a[0], a[1])) << 1);
+ t[ 2] = MUL31(a[1], a[1])
+ + ((MUL31(a[0], a[2])) << 1);
+ t[ 3] = ((MUL31(a[0], a[3])
+ + MUL31(a[1], a[2])) << 1);
+ t[ 4] = MUL31(a[2], a[2])
+ + ((MUL31(a[0], a[4])
+ + MUL31(a[1], a[3])) << 1);
+ t[ 5] = ((MUL31(a[0], a[5])
+ + MUL31(a[1], a[4])
+ + MUL31(a[2], a[3])) << 1);
+ t[ 6] = MUL31(a[3], a[3])
+ + ((MUL31(a[0], a[6])
+ + MUL31(a[1], a[5])
+ + MUL31(a[2], a[4])) << 1);
+ t[ 7] = ((MUL31(a[0], a[7])
+ + MUL31(a[1], a[6])
+ + MUL31(a[2], a[5])
+ + MUL31(a[3], a[4])) << 1);
+ t[ 8] = MUL31(a[4], a[4])
+ + ((MUL31(a[0], a[8])
+ + MUL31(a[1], a[7])
+ + MUL31(a[2], a[6])
+ + MUL31(a[3], a[5])) << 1);
+ t[ 9] = ((MUL31(a[1], a[8])
+ + MUL31(a[2], a[7])
+ + MUL31(a[3], a[6])
+ + MUL31(a[4], a[5])) << 1);
+ t[10] = MUL31(a[5], a[5])
+ + ((MUL31(a[2], a[8])
+ + MUL31(a[3], a[7])
+ + MUL31(a[4], a[6])) << 1);
+ t[11] = ((MUL31(a[3], a[8])
+ + MUL31(a[4], a[7])
+ + MUL31(a[5], a[6])) << 1);
+ t[12] = MUL31(a[6], a[6])
+ + ((MUL31(a[4], a[8])
+ + MUL31(a[5], a[7])) << 1);
+ t[13] = ((MUL31(a[5], a[8])
+ + MUL31(a[6], a[7])) << 1);
+ t[14] = MUL31(a[7], a[7])
+ + ((MUL31(a[6], a[8])) << 1);
+ t[15] = ((MUL31(a[7], a[8])) << 1);
+ t[16] = MUL31(a[8], a[8]);
+
+ /*
+ * Propagate carries.
+ */
+ cc = 0;
+ for (i = 0; i < 17; i ++) {
+ uint64_t w;
+
+ w = t[i] + cc;
+ d[i] = (uint32_t)w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+ d[17] = (uint32_t)cc;
+}
+
+/*
+ * Perform a "final reduction" in field F255 (field for Curve25519)
+ * The source value must be less than twice the modulus. If the value
+ * is not lower than the modulus, then the modulus is subtracted and
+ * this function returns 1; otherwise, it leaves it untouched and it
+ * returns 0.
+ */
+static uint32_t
+reduce_final_f255(uint32_t *d)
+{
+ uint32_t t[9];
+ uint32_t cc;
+ int i;
+
+ memcpy(t, d, sizeof t);
+ cc = 19;
+ for (i = 0; i < 9; i ++) {
+ uint32_t w;
+
+ w = t[i] + cc;
+ cc = w >> 30;
+ t[i] = w & 0x3FFFFFFF;
+ }
+ cc = t[8] >> 15;
+ t[8] &= 0x7FFF;
+ CCOPY(cc, d, t, sizeof t);
+ return cc;
+}
+
+/*
+ * Perform a multiplication of two integers modulo 2^255-19.
+ * Operands are arrays of 9 words, each containing 30 bits of data, in
+ * little-endian order. Input value may be up to 2^256-1; on output, value
+ * fits on 256 bits and is lower than twice the modulus.
+ */
+static void
+f255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t t[18], cc;
+ int i;
+
+ /*
+ * Compute raw multiplication. All result words fit in 30 bits
+ * each; upper word (t[17]) must fit on 2 bits, since the product
+ * of two 256-bit integers must fit on 512 bits.
+ */
+ mul9(t, a, b);
+
+ /*
+ * Modular reduction: each high word is added where necessary.
+ * Since the modulus is 2^255-19 and word 9 corresponds to
+ * offset 9*30 = 270, word 9+k must be added to word k with
+ * a factor of 19*2^15 = 622592. The extra bits in word 8 are also
+ * added that way.
+ *
+ * Keeping the carry on 32 bits helps with 32-bit architectures,
+ * and does not noticeably impact performance on 64-bit systems.
+ */
+ cc = MUL15(t[8] >> 15, 19); /* at most 19*(2^15-1) = 622573 */
+ t[8] &= 0x7FFF;
+ for (i = 0; i < 9; i ++) {
+ uint64_t w;
+
+ w = (uint64_t)t[i] + (uint64_t)cc + MUL31(t[i + 9], 622592);
+ t[i] = (uint32_t)w & 0x3FFFFFFF;
+ cc = (uint32_t)(w >> 30); /* at most 622592 */
+ }
+
+ /*
+ * Original product was up to (2^256-1)^2, i.e. a 512-bit integer.
+ * This was split into two parts (upper of 257 bits, lower of 255
+ * bits), and the upper was added to the lower with a factor 19,
+ * which means that the intermediate value is less than 77*2^255
+ * (19*2^257 + 2^255). Therefore, the extra bits "t[8] >> 15" are
+ * less than 77, and the initial carry cc is at most 76*19 = 1444.
+ */
+ cc = MUL15(t[8] >> 15, 19);
+ t[8] &= 0x7FFF;
+ for (i = 0; i < 9; i ++) {
+ uint32_t z;
+
+ z = t[i] + cc;
+ d[i] = z & 0x3FFFFFFF;
+ cc = z >> 30;
+ }
+
+ /*
+ * Final result is at most 2^255 + 1443. In particular, the last
+ * carry is necessarily 0, since t[8] was truncated to 15 bits.
+ */
+}
+
+/*
+ * Perform a squaring of an integer modulo 2^255-19.
+ * Operands are arrays of 9 words, each containing 30 bits of data, in
+ * little-endian order. Input value may be up to 2^256-1; on output, value
+ * fits on 256 bits and is lower than twice the modulus.
+ */
+static void
+f255_square(uint32_t *d, const uint32_t *a)
+{
+ uint32_t t[18], cc;
+ int i;
+
+ /*
+ * Compute raw squaring. All result words fit in 30 bits
+ * each; upper word (t[17]) must fit on 2 bits, since the square
+ * of a 256-bit integers must fit on 512 bits.
+ */
+ square9(t, a);
+
+ /*
+ * Modular reduction: each high word is added where necessary.
+ * See f255_mul() for details on the reduction and carry limits.
+ */
+ cc = MUL15(t[8] >> 15, 19);
+ t[8] &= 0x7FFF;
+ for (i = 0; i < 9; i ++) {
+ uint64_t w;
+
+ w = (uint64_t)t[i] + (uint64_t)cc + MUL31(t[i + 9], 622592);
+ t[i] = (uint32_t)w & 0x3FFFFFFF;
+ cc = (uint32_t)(w >> 30);
+ }
+ cc = MUL15(t[8] >> 15, 19);
+ t[8] &= 0x7FFF;
+ for (i = 0; i < 9; i ++) {
+ uint32_t z;
+
+ z = t[i] + cc;
+ d[i] = z & 0x3FFFFFFF;
+ cc = z >> 30;
+ }
+}
+
+/*
+ * Add two values in F255. Partial reduction is performed (down to less
+ * than twice the modulus).
+ */
+static void
+f255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ /*
+ * Since operand words fit on 30 bits, we can use 32-bit
+ * variables throughout.
+ */
+ int i;
+ uint32_t cc, w;
+
+ cc = 0;
+ for (i = 0; i < 9; i ++) {
+ w = a[i] + b[i] + cc;
+ d[i] = w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+ cc = MUL15(w >> 15, 19);
+ d[8] &= 0x7FFF;
+ for (i = 0; i < 9; i ++) {
+ w = d[i] + cc;
+ d[i] = w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+}
+
+/*
+ * Subtract one value from another in F255. Partial reduction is
+ * performed (down to less than twice the modulus).
+ */
+static void
+f255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ /*
+ * We actually compute a - b + 2*p, so that the final value is
+ * necessarily positive.
+ */
+ int i;
+ uint32_t cc, w;
+
+ cc = (uint32_t)-38;
+ for (i = 0; i < 9; i ++) {
+ w = a[i] - b[i] + cc;
+ d[i] = w & 0x3FFFFFFF;
+ cc = ARSH(w, 30);
+ }
+ cc = MUL15((w + 0x10000) >> 15, 19);
+ d[8] &= 0x7FFF;
+ for (i = 0; i < 9; i ++) {
+ w = d[i] + cc;
+ d[i] = w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+}
+
+/*
+ * Multiply an integer by the 'A24' constant (121665). Partial reduction
+ * is performed (down to less than twice the modulus).
+ */
+static void
+f255_mul_a24(uint32_t *d, const uint32_t *a)
+{
+ int i;
+ uint64_t w;
+ uint32_t cc;
+
+ /*
+ * a[] is over 256 bits, thus a[8] has length at most 16 bits.
+ * We single out the processing of the last word: intermediate
+ * value w is up to 121665*2^16, yielding a carry for the next
+ * loop of at most 19*(121665*2^16/2^15) = 4623289.
+ */
+ cc = 0;
+ for (i = 0; i < 8; i ++) {
+ w = MUL31(a[i], 121665) + (uint64_t)cc;
+ d[i] = (uint32_t)w & 0x3FFFFFFF;
+ cc = (uint32_t)(w >> 30);
+ }
+ w = MUL31(a[8], 121665) + (uint64_t)cc;
+ d[8] = (uint32_t)w & 0x7FFF;
+ cc = MUL15((uint32_t)(w >> 15), 19);
+
+ for (i = 0; i < 9; i ++) {
+ uint32_t z;
+
+ z = d[i] + cc;
+ d[i] = z & 0x3FFFFFFF;
+ cc = z >> 30;
+ }
+}
+
+static const unsigned char GEN[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ORDER[] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return GEN;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return ORDER;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 0;
+}
+
+static void
+cswap(uint32_t *a, uint32_t *b, uint32_t ctl)
+{
+ int i;
+
+ ctl = -ctl;
+ for (i = 0; i < 9; i ++) {
+ uint32_t aw, bw, tw;
+
+ aw = a[i];
+ bw = b[i];
+ tw = ctl & (aw ^ bw);
+ a[i] = aw ^ tw;
+ b[i] = bw ^ tw;
+ }
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+ uint32_t x1[9], x2[9], x3[9], z2[9], z3[9];
+ uint32_t a[9], aa[9], b[9], bb[9];
+ uint32_t c[9], d[9], e[9], da[9], cb[9];
+ unsigned char k[32];
+ uint32_t swap;
+ int i;
+
+ (void)curve;
+
+ /*
+ * Points are encoded over exactly 32 bytes. Multipliers must fit
+ * in 32 bytes as well.
+ * RFC 7748 mandates that the high bit of the last point byte must
+ * be ignored/cleared.
+ */
+ if (Glen != 32 || kblen > 32) {
+ return 0;
+ }
+ G[31] &= 0x7F;
+
+ /*
+ * Initialise variables x1, x2, z2, x3 and z3. We set all of them
+ * into Montgomery representation.
+ */
+ x1[8] = le8_to_le30(x1, G, 32);
+ memcpy(x3, x1, sizeof x1);
+ memset(z2, 0, sizeof z2);
+ memset(x2, 0, sizeof x2);
+ x2[0] = 1;
+ memset(z3, 0, sizeof z3);
+ z3[0] = 1;
+
+ memset(k, 0, (sizeof k) - kblen);
+ memcpy(k + (sizeof k) - kblen, kb, kblen);
+ k[31] &= 0xF8;
+ k[0] &= 0x7F;
+ k[0] |= 0x40;
+
+ /* obsolete
+ print_int("x1", x1);
+ */
+
+ swap = 0;
+ for (i = 254; i >= 0; i --) {
+ uint32_t kt;
+
+ kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
+ swap ^= kt;
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+ swap = kt;
+
+ /* obsolete
+ print_int("x2", x2);
+ print_int("z2", z2);
+ print_int("x3", x3);
+ print_int("z3", z3);
+ */
+
+ f255_add(a, x2, z2);
+ f255_square(aa, a);
+ f255_sub(b, x2, z2);
+ f255_square(bb, b);
+ f255_sub(e, aa, bb);
+ f255_add(c, x3, z3);
+ f255_sub(d, x3, z3);
+ f255_mul(da, d, a);
+ f255_mul(cb, c, b);
+
+ /* obsolete
+ print_int("a ", a);
+ print_int("aa", aa);
+ print_int("b ", b);
+ print_int("bb", bb);
+ print_int("e ", e);
+ print_int("c ", c);
+ print_int("d ", d);
+ print_int("da", da);
+ print_int("cb", cb);
+ */
+
+ f255_add(x3, da, cb);
+ f255_square(x3, x3);
+ f255_sub(z3, da, cb);
+ f255_square(z3, z3);
+ f255_mul(z3, z3, x1);
+ f255_mul(x2, aa, bb);
+ f255_mul_a24(z2, e);
+ f255_add(z2, z2, aa);
+ f255_mul(z2, e, z2);
+
+ /* obsolete
+ print_int("x2", x2);
+ print_int("z2", z2);
+ print_int("x3", x3);
+ print_int("z3", z3);
+ */
+ }
+ cswap(x2, x3, swap);
+ cswap(z2, z3, swap);
+
+ /*
+ * Inverse z2 with a modular exponentiation. This is a simple
+ * square-and-multiply algorithm; we mutualise most non-squarings
+ * since the exponent contains almost only ones.
+ */
+ memcpy(a, z2, sizeof z2);
+ for (i = 0; i < 15; i ++) {
+ f255_square(a, a);
+ f255_mul(a, a, z2);
+ }
+ memcpy(b, a, sizeof a);
+ for (i = 0; i < 14; i ++) {
+ int j;
+
+ for (j = 0; j < 16; j ++) {
+ f255_square(b, b);
+ }
+ f255_mul(b, b, a);
+ }
+ for (i = 14; i >= 0; i --) {
+ f255_square(b, b);
+ if ((0xFFEB >> i) & 1) {
+ f255_mul(b, z2, b);
+ }
+ }
+ f255_mul(x2, x2, b);
+ reduce_final_f255(x2);
+ le30_to_le8(G, 32, x2);
+ return 1;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We don't implement this method, since it is used for ECDSA
+ * only, and there is no ECDSA over Curve25519 (which instead
+ * uses EdDSA).
+ */
+ (void)A;
+ (void)B;
+ (void)len;
+ (void)x;
+ (void)xlen;
+ (void)y;
+ (void)ylen;
+ (void)curve;
+ return 0;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_c25519_m31 = {
+ (uint32_t)0x20000000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_c25519_m31.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_c25519_m62.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_c25519_m62.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_c25519_m62.c (revision 346145)
@@ -0,0 +1,605 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+#if BR_UMUL128
+#include <intrin.h>
+#endif
+
+static const unsigned char GEN[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ORDER[] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return GEN;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return ORDER;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 0;
+}
+
+/*
+ * A field element is encoded as five 64-bit integers, in basis 2^51.
+ * Limbs may be occasionally larger than 2^51, to save on carry
+ * propagation costs.
+ */
+
+#define MASK51 (((uint64_t)1 << 51) - (uint64_t)1)
+
+/*
+ * Swap two field elements, conditionally on a flag.
+ */
+static inline void
+f255_cswap(uint64_t *a, uint64_t *b, uint32_t ctl)
+{
+ uint64_t m, w;
+
+ m = -(uint64_t)ctl;
+ w = m & (a[0] ^ b[0]); a[0] ^= w; b[0] ^= w;
+ w = m & (a[1] ^ b[1]); a[1] ^= w; b[1] ^= w;
+ w = m & (a[2] ^ b[2]); a[2] ^= w; b[2] ^= w;
+ w = m & (a[3] ^ b[3]); a[3] ^= w; b[3] ^= w;
+ w = m & (a[4] ^ b[4]); a[4] ^= w; b[4] ^= w;
+}
+
+/*
+ * Addition with no carry propagation. Limbs double in size.
+ */
+static inline void
+f255_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+ d[0] = a[0] + b[0];
+ d[1] = a[1] + b[1];
+ d[2] = a[2] + b[2];
+ d[3] = a[3] + b[3];
+ d[4] = a[4] + b[4];
+}
+
+/*
+ * Subtraction.
+ * On input, limbs must fit on 60 bits each. On output, result is
+ * partially reduced, with max value 2^255+19456; moreover, all
+ * limbs will fit on 51 bits, except the low limb, which may have
+ * value up to 2^51+19455.
+ */
+static inline void
+f255_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+ uint64_t cc, w;
+
+ /*
+ * We compute d = (2^255-19)*1024 + a - b. Since the limbs
+ * fit on 60 bits, the maximum value of operands are slightly
+ * more than 2^264, but much less than 2^265-19456. This
+ * ensures that the result is positive.
+ */
+
+ /*
+ * Initial carry is 19456, since we add 2^265-19456. Each
+ * individual subtraction may yield a carry up to 513.
+ */
+ w = a[0] - b[0] - 19456;
+ d[0] = w & MASK51;
+ cc = -(w >> 51) & 0x3FF;
+ w = a[1] - b[1] - cc;
+ d[1] = w & MASK51;
+ cc = -(w >> 51) & 0x3FF;
+ w = a[2] - b[2] - cc;
+ d[2] = w & MASK51;
+ cc = -(w >> 51) & 0x3FF;
+ w = a[3] - b[3] - cc;
+ d[3] = w & MASK51;
+ cc = -(w >> 51) & 0x3FF;
+ d[4] = ((uint64_t)1 << 61) + a[4] - b[4] - cc;
+
+ /*
+ * Partial reduction. The intermediate result may be up to
+ * slightly above 2^265, but less than 2^265+2^255. When we
+ * truncate to 255 bits, the upper bits will be at most 1024.
+ */
+ d[0] += 19 * (d[4] >> 51);
+ d[4] &= MASK51;
+}
+
+/*
+ * UMUL51(hi, lo, x, y) computes:
+ *
+ * hi = floor((x * y) / (2^51))
+ * lo = x * y mod 2^51
+ *
+ * Note that lo < 2^51, but "hi" may be larger, if the input operands are
+ * larger.
+ */
+#if BR_INT128
+
+#define UMUL51(hi, lo, x, y) do { \
+ unsigned __int128 umul_tmp; \
+ umul_tmp = (unsigned __int128)(x) * (unsigned __int128)(y); \
+ (hi) = (uint64_t)(umul_tmp >> 51); \
+ (lo) = (uint64_t)umul_tmp & MASK51; \
+ } while (0)
+
+#elif BR_UMUL128
+
+#define UMUL51(hi, lo, x, y) do { \
+ uint64_t umul_hi, umul_lo; \
+ umul_lo = _umul128((x), (y), &umul_hi); \
+ (hi) = (umul_hi << 13) | (umul_lo >> 51); \
+ (lo) = umul_lo & MASK51; \
+ } while (0)
+
+#endif
+
+/*
+ * Multiplication.
+ * On input, limbs must fit on 54 bits each.
+ * On output, limb 0 is at most 2^51 + 155647, and other limbs fit
+ * on 51 bits each.
+ */
+static inline void
+f255_mul(uint64_t *d, uint64_t *a, uint64_t *b)
+{
+ uint64_t t[10], hi, lo, w, cc;
+
+ /*
+ * Perform cross products, accumulating values without carry
+ * propagation.
+ *
+ * Since input limbs fit on 54 bits each, each individual
+ * UMUL51 will produce a "hi" of less than 2^57. The maximum
+ * sum will be at most 5*(2^57-1) + 4*(2^51-1) (for t[5]),
+ * i.e. less than 324*2^51.
+ */
+
+ UMUL51(t[1], t[0], a[0], b[0]);
+
+ UMUL51(t[2], lo, a[1], b[0]); t[1] += lo;
+ UMUL51(hi, lo, a[0], b[1]); t[1] += lo; t[2] += hi;
+
+ UMUL51(t[3], lo, a[2], b[0]); t[2] += lo;
+ UMUL51(hi, lo, a[1], b[1]); t[2] += lo; t[3] += hi;
+ UMUL51(hi, lo, a[0], b[2]); t[2] += lo; t[3] += hi;
+
+ UMUL51(t[4], lo, a[3], b[0]); t[3] += lo;
+ UMUL51(hi, lo, a[2], b[1]); t[3] += lo; t[4] += hi;
+ UMUL51(hi, lo, a[1], b[2]); t[3] += lo; t[4] += hi;
+ UMUL51(hi, lo, a[0], b[3]); t[3] += lo; t[4] += hi;
+
+ UMUL51(t[5], lo, a[4], b[0]); t[4] += lo;
+ UMUL51(hi, lo, a[3], b[1]); t[4] += lo; t[5] += hi;
+ UMUL51(hi, lo, a[2], b[2]); t[4] += lo; t[5] += hi;
+ UMUL51(hi, lo, a[1], b[3]); t[4] += lo; t[5] += hi;
+ UMUL51(hi, lo, a[0], b[4]); t[4] += lo; t[5] += hi;
+
+ UMUL51(t[6], lo, a[4], b[1]); t[5] += lo;
+ UMUL51(hi, lo, a[3], b[2]); t[5] += lo; t[6] += hi;
+ UMUL51(hi, lo, a[2], b[3]); t[5] += lo; t[6] += hi;
+ UMUL51(hi, lo, a[1], b[4]); t[5] += lo; t[6] += hi;
+
+ UMUL51(t[7], lo, a[4], b[2]); t[6] += lo;
+ UMUL51(hi, lo, a[3], b[3]); t[6] += lo; t[7] += hi;
+ UMUL51(hi, lo, a[2], b[4]); t[6] += lo; t[7] += hi;
+
+ UMUL51(t[8], lo, a[4], b[3]); t[7] += lo;
+ UMUL51(hi, lo, a[3], b[4]); t[7] += lo; t[8] += hi;
+
+ UMUL51(t[9], lo, a[4], b[4]); t[8] += lo;
+
+ /*
+ * The upper words t[5]..t[9] are folded back into the lower
+ * words, using the rule that 2^255 = 19 in the field.
+ *
+ * Since each t[i] is less than 324*2^51, the additions below
+ * will yield less than 6480*2^51 in each limb; this fits in
+ * 64 bits (6480*2^51 < 8192*2^51 = 2^64), hence there is
+ * no overflow.
+ */
+ t[0] += 19 * t[5];
+ t[1] += 19 * t[6];
+ t[2] += 19 * t[7];
+ t[3] += 19 * t[8];
+ t[4] += 19 * t[9];
+
+ /*
+ * Propagate carries.
+ */
+ w = t[0];
+ d[0] = w & MASK51;
+ cc = w >> 51;
+ w = t[1] + cc;
+ d[1] = w & MASK51;
+ cc = w >> 51;
+ w = t[2] + cc;
+ d[2] = w & MASK51;
+ cc = w >> 51;
+ w = t[3] + cc;
+ d[3] = w & MASK51;
+ cc = w >> 51;
+ w = t[4] + cc;
+ d[4] = w & MASK51;
+ cc = w >> 51;
+
+ /*
+ * Since the limbs were 64-bit values, the top carry is at
+ * most 8192 (in practice, that cannot be reached). We simply
+ * performed a partial reduction.
+ */
+ d[0] += 19 * cc;
+}
+
+/*
+ * Multiplication by A24 = 121665.
+ * Input must have limbs of 60 bits at most.
+ */
+static inline void
+f255_mul_a24(uint64_t *d, const uint64_t *a)
+{
+ uint64_t t[5], cc, w;
+
+ /*
+ * 121665 = 15 * 8111. We first multiply by 15, with carry
+ * propagation and partial reduction.
+ */
+ w = a[0] * 15;
+ t[0] = w & MASK51;
+ cc = w >> 51;
+ w = a[1] * 15 + cc;
+ t[1] = w & MASK51;
+ cc = w >> 51;
+ w = a[2] * 15 + cc;
+ t[2] = w & MASK51;
+ cc = w >> 51;
+ w = a[3] * 15 + cc;
+ t[3] = w & MASK51;
+ cc = w >> 51;
+ w = a[4] * 15 + cc;
+ t[4] = w & MASK51;
+ t[0] += 19 * (w >> 51);
+
+ /*
+ * Then multiplication by 8111. At that point, we known that
+ * t[0] is less than 2^51 + 19*8192, and other limbs are less
+ * than 2^51; thus, there will be no overflow.
+ */
+ w = t[0] * 8111;
+ d[0] = w & MASK51;
+ cc = w >> 51;
+ w = t[1] * 8111 + cc;
+ d[1] = w & MASK51;
+ cc = w >> 51;
+ w = t[2] * 8111 + cc;
+ d[2] = w & MASK51;
+ cc = w >> 51;
+ w = t[3] * 8111 + cc;
+ d[3] = w & MASK51;
+ cc = w >> 51;
+ w = t[4] * 8111 + cc;
+ d[4] = w & MASK51;
+ d[0] += 19 * (w >> 51);
+}
+
+/*
+ * Finalize reduction.
+ * On input, limbs must fit on 51 bits, except possibly the low limb,
+ * which may be slightly above 2^51.
+ */
+static inline void
+f255_final_reduce(uint64_t *a)
+{
+ uint64_t t[5], cc, w;
+
+ /*
+ * We add 19. If the result (in t[]) is below 2^255, then a[]
+ * is already less than 2^255-19, thus already reduced.
+ * Otherwise, we subtract 2^255 from t[], in which case we
+ * have t = a - (2^255-19), and that's our result.
+ */
+ w = a[0] + 19;
+ t[0] = w & MASK51;
+ cc = w >> 51;
+ w = a[1] + cc;
+ t[1] = w & MASK51;
+ cc = w >> 51;
+ w = a[2] + cc;
+ t[2] = w & MASK51;
+ cc = w >> 51;
+ w = a[3] + cc;
+ t[3] = w & MASK51;
+ cc = w >> 51;
+ w = a[4] + cc;
+ t[4] = w & MASK51;
+ cc = w >> 51;
+
+ /*
+ * The bit 255 of t is in cc. If that bit is 0, when a[] must
+ * be unchanged; otherwise, it must be replaced with t[].
+ */
+ cc = -cc;
+ a[0] ^= cc & (a[0] ^ t[0]);
+ a[1] ^= cc & (a[1] ^ t[1]);
+ a[2] ^= cc & (a[2] ^ t[2]);
+ a[3] ^= cc & (a[3] ^ t[3]);
+ a[4] ^= cc & (a[4] ^ t[4]);
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+ unsigned char k[32];
+ uint64_t x1[5], x2[5], z2[5], x3[5], z3[5];
+ uint32_t swap;
+ int i;
+
+ (void)curve;
+
+ /*
+ * Points are encoded over exactly 32 bytes. Multipliers must fit
+ * in 32 bytes as well.
+ */
+ if (Glen != 32 || kblen > 32) {
+ return 0;
+ }
+
+ /*
+ * RFC 7748 mandates that the high bit of the last point byte must
+ * be ignored/cleared; the "& MASK51" in the initialization for
+ * x1[4] clears that bit.
+ */
+ x1[0] = br_dec64le(&G[0]) & MASK51;
+ x1[1] = (br_dec64le(&G[6]) >> 3) & MASK51;
+ x1[2] = (br_dec64le(&G[12]) >> 6) & MASK51;
+ x1[3] = (br_dec64le(&G[19]) >> 1) & MASK51;
+ x1[4] = (br_dec64le(&G[24]) >> 12) & MASK51;
+
+ /*
+ * We can use memset() to clear values, because exact-width types
+ * like uint64_t are guaranteed to have no padding bits or
+ * trap representations.
+ */
+ memset(x2, 0, sizeof x2);
+ x2[0] = 1;
+ memset(z2, 0, sizeof z2);
+ memcpy(x3, x1, sizeof x1);
+ memcpy(z3, x2, sizeof x2);
+
+ /*
+ * The multiplier is provided in big-endian notation, and
+ * possibly shorter than 32 bytes.
+ */
+ memset(k, 0, (sizeof k) - kblen);
+ memcpy(k + (sizeof k) - kblen, kb, kblen);
+ k[31] &= 0xF8;
+ k[0] &= 0x7F;
+ k[0] |= 0x40;
+
+ swap = 0;
+
+ for (i = 254; i >= 0; i --) {
+ uint64_t a[5], aa[5], b[5], bb[5], e[5];
+ uint64_t c[5], d[5], da[5], cb[5];
+ uint32_t kt;
+
+ kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
+ swap ^= kt;
+ f255_cswap(x2, x3, swap);
+ f255_cswap(z2, z3, swap);
+ swap = kt;
+
+ /*
+ * At that point, limbs of x_2 and z_2 are assumed to fit
+ * on at most 52 bits each.
+ *
+ * Each f255_add() adds one bit to the maximum range of
+ * the values, but f255_sub() and f255_mul() bring back
+ * the limbs into 52 bits. All f255_add() outputs are
+ * used only as inputs for f255_mul(), which ensures
+ * that limbs remain in the proper range.
+ */
+
+ /* A = x_2 + z_2 -- limbs fit on 53 bits each */
+ f255_add(a, x2, z2);
+
+ /* AA = A^2 */
+ f255_mul(aa, a, a);
+
+ /* B = x_2 - z_2 */
+ f255_sub(b, x2, z2);
+
+ /* BB = B^2 */
+ f255_mul(bb, b, b);
+
+ /* E = AA - BB */
+ f255_sub(e, aa, bb);
+
+ /* C = x_3 + z_3 -- limbs fit on 53 bits each */
+ f255_add(c, x3, z3);
+
+ /* D = x_3 - z_3 */
+ f255_sub(d, x3, z3);
+
+ /* DA = D * A */
+ f255_mul(da, d, a);
+
+ /* CB = C * B */
+ f255_mul(cb, c, b);
+
+ /* x_3 = (DA + CB)^2 */
+ f255_add(x3, da, cb);
+ f255_mul(x3, x3, x3);
+
+ /* z_3 = x_1 * (DA - CB)^2 */
+ f255_sub(z3, da, cb);
+ f255_mul(z3, z3, z3);
+ f255_mul(z3, x1, z3);
+
+ /* x_2 = AA * BB */
+ f255_mul(x2, aa, bb);
+
+ /* z_2 = E * (AA + a24 * E) */
+ f255_mul_a24(z2, e);
+ f255_add(z2, aa, z2);
+ f255_mul(z2, e, z2);
+ }
+
+ f255_cswap(x2, x3, swap);
+ f255_cswap(z2, z3, swap);
+
+ /*
+ * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize
+ * most non-squarings. We use x1 and x3, now useless, as temporaries.
+ */
+ memcpy(x1, z2, sizeof z2);
+ for (i = 0; i < 15; i ++) {
+ f255_mul(x1, x1, x1);
+ f255_mul(x1, x1, z2);
+ }
+ memcpy(x3, x1, sizeof x1);
+ for (i = 0; i < 14; i ++) {
+ int j;
+
+ for (j = 0; j < 16; j ++) {
+ f255_mul(x3, x3, x3);
+ }
+ f255_mul(x3, x3, x1);
+ }
+ for (i = 14; i >= 0; i --) {
+ f255_mul(x3, x3, x3);
+ if ((0xFFEB >> i) & 1) {
+ f255_mul(x3, z2, x3);
+ }
+ }
+
+ /*
+ * Compute x2/z2. We have 1/z2 in x3.
+ */
+ f255_mul(x2, x2, x3);
+ f255_final_reduce(x2);
+
+ /*
+ * Encode the final x2 value in little-endian. We first assemble
+ * the limbs into 64-bit values.
+ */
+ x2[0] |= x2[1] << 51;
+ x2[1] = (x2[1] >> 13) | (x2[2] << 38);
+ x2[2] = (x2[2] >> 26) | (x2[3] << 25);
+ x2[3] = (x2[3] >> 39) | (x2[4] << 12);
+ br_enc64le(G, x2[0]);
+ br_enc64le(G + 8, x2[1]);
+ br_enc64le(G + 16, x2[2]);
+ br_enc64le(G + 24, x2[3]);
+ return 1;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We don't implement this method, since it is used for ECDSA
+ * only, and there is no ECDSA over Curve25519 (which instead
+ * uses EdDSA).
+ */
+ (void)A;
+ (void)B;
+ (void)len;
+ (void)x;
+ (void)xlen;
+ (void)y;
+ (void)ylen;
+ (void)curve;
+ return 0;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_c25519_m62 = {
+ (uint32_t)0x20000000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_c25519_m62_get(void)
+{
+ return &br_ec_c25519_m62;
+}
+
+#else
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_c25519_m62_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/ec/ec_c25519_m62.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_c25519_m64.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_c25519_m64.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_c25519_m64.c (revision 346145)
@@ -0,0 +1,835 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+#if BR_UMUL128
+#include <intrin.h>
+#endif
+
+static const unsigned char GEN[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ORDER[] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return GEN;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return ORDER;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 0;
+}
+
+/*
+ * A field element is encoded as four 64-bit integers, in basis 2^63.
+ * Operations return partially reduced values, which may range up to
+ * 2^255+37.
+ */
+
+#define MASK63 (((uint64_t)1 << 63) - (uint64_t)1)
+
+/*
+ * Swap two field elements, conditionally on a flag.
+ */
+static inline void
+f255_cswap(uint64_t *a, uint64_t *b, uint32_t ctl)
+{
+ uint64_t m, w;
+
+ m = -(uint64_t)ctl;
+ w = m & (a[0] ^ b[0]); a[0] ^= w; b[0] ^= w;
+ w = m & (a[1] ^ b[1]); a[1] ^= w; b[1] ^= w;
+ w = m & (a[2] ^ b[2]); a[2] ^= w; b[2] ^= w;
+ w = m & (a[3] ^ b[3]); a[3] ^= w; b[3] ^= w;
+}
+
+/*
+ * Addition in the field.
+ */
+static inline void
+f255_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+#if BR_INT128
+
+ uint64_t t0, t1, t2, t3, cc;
+ unsigned __int128 z;
+
+ z = (unsigned __int128)a[0] + (unsigned __int128)b[0];
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)a[1] + (unsigned __int128)b[1] + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)a[2] + (unsigned __int128)b[2] + (z >> 64);
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)a[3] + (unsigned __int128)b[3] + (z >> 64);
+ t3 = (uint64_t)z & MASK63;
+ cc = (uint64_t)(z >> 63);
+
+ /*
+ * Since operands are at most 2^255+37, the sum is at most
+ * 2^256+74; thus, the carry cc is equal to 0, 1 or 2.
+ *
+ * We use: 2^255 = 19 mod p.
+ * Since we add 0, 19 or 38 to a value that fits on 255 bits,
+ * the result is at most 2^255+37.
+ */
+ z = (unsigned __int128)t0 + (unsigned __int128)(19 * cc);
+ d[0] = (uint64_t)z;
+ z = (unsigned __int128)t1 + (z >> 64);
+ d[1] = (uint64_t)z;
+ z = (unsigned __int128)t2 + (z >> 64);
+ d[2] = (uint64_t)z;
+ d[3] = t3 + (uint64_t)(z >> 64);
+
+#elif BR_UMUL128
+
+ uint64_t t0, t1, t2, t3, cc;
+ unsigned char k;
+
+ k = _addcarry_u64(0, a[0], b[0], &t0);
+ k = _addcarry_u64(k, a[1], b[1], &t1);
+ k = _addcarry_u64(k, a[2], b[2], &t2);
+ k = _addcarry_u64(k, a[3], b[3], &t3);
+ cc = (k << 1) + (t3 >> 63);
+ t3 &= MASK63;
+
+ /*
+ * Since operands are at most 2^255+37, the sum is at most
+ * 2^256+74; thus, the carry cc is equal to 0, 1 or 2.
+ *
+ * We use: 2^255 = 19 mod p.
+ * Since we add 0, 19 or 38 to a value that fits on 255 bits,
+ * the result is at most 2^255+37.
+ */
+ k = _addcarry_u64(0, t0, 19 * cc, &d[0]);
+ k = _addcarry_u64(k, t1, 0, &d[1]);
+ k = _addcarry_u64(k, t2, 0, &d[2]);
+ (void)_addcarry_u64(k, t3, 0, &d[3]);
+
+#endif
+}
+
+/*
+ * Subtraction.
+ * On input, limbs must fit on 60 bits each. On output, result is
+ * partially reduced, with max value 2^255+19456; moreover, all
+ * limbs will fit on 51 bits, except the low limb, which may have
+ * value up to 2^51+19455.
+ */
+static inline void
+f255_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+#if BR_INT128
+
+ /*
+ * We compute t = 2^256 - 38 + a - b, which is necessarily
+ * positive but lower than 2^256 + 2^255, since a <= 2^255 + 37
+ * and b <= 2^255 + 37. We then subtract 0, p or 2*p, depending
+ * on the two upper bits of t (bits 255 and 256).
+ */
+
+ uint64_t t0, t1, t2, t3, t4, cc;
+ unsigned __int128 z;
+
+ z = (unsigned __int128)a[0] - (unsigned __int128)b[0] - 38;
+ t0 = (uint64_t)z;
+ cc = -(uint64_t)(z >> 64);
+ z = (unsigned __int128)a[1] - (unsigned __int128)b[1]
+ - (unsigned __int128)cc;
+ t1 = (uint64_t)z;
+ cc = -(uint64_t)(z >> 64);
+ z = (unsigned __int128)a[2] - (unsigned __int128)b[2]
+ - (unsigned __int128)cc;
+ t2 = (uint64_t)z;
+ cc = -(uint64_t)(z >> 64);
+ z = (unsigned __int128)a[3] - (unsigned __int128)b[3]
+ - (unsigned __int128)cc;
+ t3 = (uint64_t)z;
+ t4 = 1 + (uint64_t)(z >> 64);
+
+ /*
+ * We have a 257-bit result. The two top bits can be 00, 01 or 10,
+ * but not 11 (value t <= 2^256 - 38 + 2^255 + 37 = 2^256 + 2^255 - 1).
+ * Therefore, we can truncate to 255 bits, and add 0, 19 or 38.
+ * This guarantees that the result is at most 2^255+37.
+ */
+ cc = (38 & -t4) + (19 & -(t3 >> 63));
+ t3 &= MASK63;
+ z = (unsigned __int128)t0 + (unsigned __int128)cc;
+ d[0] = (uint64_t)z;
+ z = (unsigned __int128)t1 + (z >> 64);
+ d[1] = (uint64_t)z;
+ z = (unsigned __int128)t2 + (z >> 64);
+ d[2] = (uint64_t)z;
+ d[3] = t3 + (uint64_t)(z >> 64);
+
+#elif BR_UMUL128
+
+ /*
+ * We compute t = 2^256 - 38 + a - b, which is necessarily
+ * positive but lower than 2^256 + 2^255, since a <= 2^255 + 37
+ * and b <= 2^255 + 37. We then subtract 0, p or 2*p, depending
+ * on the two upper bits of t (bits 255 and 256).
+ */
+
+ uint64_t t0, t1, t2, t3, t4;
+ unsigned char k;
+
+ k = _subborrow_u64(0, a[0], b[0], &t0);
+ k = _subborrow_u64(k, a[1], b[1], &t1);
+ k = _subborrow_u64(k, a[2], b[2], &t2);
+ k = _subborrow_u64(k, a[3], b[3], &t3);
+ (void)_subborrow_u64(k, 1, 0, &t4);
+
+ k = _subborrow_u64(0, t0, 38, &t0);
+ k = _subborrow_u64(k, t1, 0, &t1);
+ k = _subborrow_u64(k, t2, 0, &t2);
+ k = _subborrow_u64(k, t3, 0, &t3);
+ (void)_subborrow_u64(k, t4, 0, &t4);
+
+ /*
+ * We have a 257-bit result. The two top bits can be 00, 01 or 10,
+ * but not 11 (value t <= 2^256 - 38 + 2^255 + 37 = 2^256 + 2^255 - 1).
+ * Therefore, we can truncate to 255 bits, and add 0, 19 or 38.
+ * This guarantees that the result is at most 2^255+37.
+ */
+ t4 = (38 & -t4) + (19 & -(t3 >> 63));
+ t3 &= MASK63;
+ k = _addcarry_u64(0, t0, t4, &d[0]);
+ k = _addcarry_u64(k, t1, 0, &d[1]);
+ k = _addcarry_u64(k, t2, 0, &d[2]);
+ (void)_addcarry_u64(k, t3, 0, &d[3]);
+
+#endif
+}
+
+/*
+ * Multiplication.
+ */
+static inline void
+f255_mul(uint64_t *d, uint64_t *a, uint64_t *b)
+{
+#if BR_INT128
+
+ unsigned __int128 z;
+ uint64_t t0, t1, t2, t3, t4, t5, t6, t7, th;
+
+ /*
+ * Compute the product a*b over plain integers.
+ */
+ z = (unsigned __int128)a[0] * (unsigned __int128)b[0];
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)a[0] * (unsigned __int128)b[1] + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)a[0] * (unsigned __int128)b[2] + (z >> 64);
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)a[0] * (unsigned __int128)b[3] + (z >> 64);
+ t3 = (uint64_t)z;
+ t4 = (uint64_t)(z >> 64);
+
+ z = (unsigned __int128)a[1] * (unsigned __int128)b[0]
+ + (unsigned __int128)t1;
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)a[1] * (unsigned __int128)b[1]
+ + (unsigned __int128)t2 + (z >> 64);
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)a[1] * (unsigned __int128)b[2]
+ + (unsigned __int128)t3 + (z >> 64);
+ t3 = (uint64_t)z;
+ z = (unsigned __int128)a[1] * (unsigned __int128)b[3]
+ + (unsigned __int128)t4 + (z >> 64);
+ t4 = (uint64_t)z;
+ t5 = (uint64_t)(z >> 64);
+
+ z = (unsigned __int128)a[2] * (unsigned __int128)b[0]
+ + (unsigned __int128)t2;
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)a[2] * (unsigned __int128)b[1]
+ + (unsigned __int128)t3 + (z >> 64);
+ t3 = (uint64_t)z;
+ z = (unsigned __int128)a[2] * (unsigned __int128)b[2]
+ + (unsigned __int128)t4 + (z >> 64);
+ t4 = (uint64_t)z;
+ z = (unsigned __int128)a[2] * (unsigned __int128)b[3]
+ + (unsigned __int128)t5 + (z >> 64);
+ t5 = (uint64_t)z;
+ t6 = (uint64_t)(z >> 64);
+
+ z = (unsigned __int128)a[3] * (unsigned __int128)b[0]
+ + (unsigned __int128)t3;
+ t3 = (uint64_t)z;
+ z = (unsigned __int128)a[3] * (unsigned __int128)b[1]
+ + (unsigned __int128)t4 + (z >> 64);
+ t4 = (uint64_t)z;
+ z = (unsigned __int128)a[3] * (unsigned __int128)b[2]
+ + (unsigned __int128)t5 + (z >> 64);
+ t5 = (uint64_t)z;
+ z = (unsigned __int128)a[3] * (unsigned __int128)b[3]
+ + (unsigned __int128)t6 + (z >> 64);
+ t6 = (uint64_t)z;
+ t7 = (uint64_t)(z >> 64);
+
+ /*
+ * Modulo p, we have:
+ *
+ * 2^255 = 19
+ * 2^510 = 19*19 = 361
+ *
+ * We split the intermediate t into three parts, in basis
+ * 2^255. The low one will be in t0..t3; the middle one in t4..t7.
+ * The upper one can only be a single bit (th), since the
+ * multiplication operands are at most 2^255+37 each.
+ */
+ th = t7 >> 62;
+ t7 = ((t7 << 1) | (t6 >> 63)) & MASK63;
+ t6 = (t6 << 1) | (t5 >> 63);
+ t5 = (t5 << 1) | (t4 >> 63);
+ t4 = (t4 << 1) | (t3 >> 63);
+ t3 &= MASK63;
+
+ /*
+ * Multiply the middle part (t4..t7) by 19. We truncate it to
+ * 255 bits; the extra bits will go along with th.
+ */
+ z = (unsigned __int128)t4 * 19;
+ t4 = (uint64_t)z;
+ z = (unsigned __int128)t5 * 19 + (z >> 64);
+ t5 = (uint64_t)z;
+ z = (unsigned __int128)t6 * 19 + (z >> 64);
+ t6 = (uint64_t)z;
+ z = (unsigned __int128)t7 * 19 + (z >> 64);
+ t7 = (uint64_t)z & MASK63;
+
+ th = (361 & -th) + (19 * (uint64_t)(z >> 63));
+
+ /*
+ * Add elements together.
+ * At this point:
+ * t0..t3 fits on 255 bits.
+ * t4..t7 fits on 255 bits.
+ * th <= 361 + 342 = 703.
+ */
+ z = (unsigned __int128)t0 + (unsigned __int128)t4
+ + (unsigned __int128)th;
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)t1 + (unsigned __int128)t5 + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)t2 + (unsigned __int128)t6 + (z >> 64);
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)t3 + (unsigned __int128)t7 + (z >> 64);
+ t3 = (uint64_t)z & MASK63;
+ th = (uint64_t)(z >> 63);
+
+ /*
+ * Since the sum is at most 2^256 + 703, the two upper bits, in th,
+ * can only have value 0, 1 or 2. We just add th*19, which
+ * guarantees a result of at most 2^255+37.
+ */
+ z = (unsigned __int128)t0 + (19 * th);
+ d[0] = (uint64_t)z;
+ z = (unsigned __int128)t1 + (z >> 64);
+ d[1] = (uint64_t)z;
+ z = (unsigned __int128)t2 + (z >> 64);
+ d[2] = (uint64_t)z;
+ d[3] = t3 + (uint64_t)(z >> 64);
+
+#elif BR_UMUL128
+
+ uint64_t t0, t1, t2, t3, t4, t5, t6, t7, th;
+ uint64_t h0, h1, h2, h3;
+ unsigned char k;
+
+ /*
+ * Compute the product a*b over plain integers.
+ */
+ t0 = _umul128(a[0], b[0], &h0);
+ t1 = _umul128(a[0], b[1], &h1);
+ k = _addcarry_u64(0, t1, h0, &t1);
+ t2 = _umul128(a[0], b[2], &h2);
+ k = _addcarry_u64(k, t2, h1, &t2);
+ t3 = _umul128(a[0], b[3], &h3);
+ k = _addcarry_u64(k, t3, h2, &t3);
+ (void)_addcarry_u64(k, h3, 0, &t4);
+
+ k = _addcarry_u64(0, _umul128(a[1], b[0], &h0), t1, &t1);
+ k = _addcarry_u64(k, _umul128(a[1], b[1], &h1), t2, &t2);
+ k = _addcarry_u64(k, _umul128(a[1], b[2], &h2), t3, &t3);
+ k = _addcarry_u64(k, _umul128(a[1], b[3], &h3), t4, &t4);
+ t5 = k;
+ k = _addcarry_u64(0, t2, h0, &t2);
+ k = _addcarry_u64(k, t3, h1, &t3);
+ k = _addcarry_u64(k, t4, h2, &t4);
+ (void)_addcarry_u64(k, t5, h3, &t5);
+
+ k = _addcarry_u64(0, _umul128(a[2], b[0], &h0), t2, &t2);
+ k = _addcarry_u64(k, _umul128(a[2], b[1], &h1), t3, &t3);
+ k = _addcarry_u64(k, _umul128(a[2], b[2], &h2), t4, &t4);
+ k = _addcarry_u64(k, _umul128(a[2], b[3], &h3), t5, &t5);
+ t6 = k;
+ k = _addcarry_u64(0, t3, h0, &t3);
+ k = _addcarry_u64(k, t4, h1, &t4);
+ k = _addcarry_u64(k, t5, h2, &t5);
+ (void)_addcarry_u64(k, t6, h3, &t6);
+
+ k = _addcarry_u64(0, _umul128(a[3], b[0], &h0), t3, &t3);
+ k = _addcarry_u64(k, _umul128(a[3], b[1], &h1), t4, &t4);
+ k = _addcarry_u64(k, _umul128(a[3], b[2], &h2), t5, &t5);
+ k = _addcarry_u64(k, _umul128(a[3], b[3], &h3), t6, &t6);
+ t7 = k;
+ k = _addcarry_u64(0, t4, h0, &t4);
+ k = _addcarry_u64(k, t5, h1, &t5);
+ k = _addcarry_u64(k, t6, h2, &t6);
+ (void)_addcarry_u64(k, t7, h3, &t7);
+
+ /*
+ * Modulo p, we have:
+ *
+ * 2^255 = 19
+ * 2^510 = 19*19 = 361
+ *
+ * We split the intermediate t into three parts, in basis
+ * 2^255. The low one will be in t0..t3; the middle one in t4..t7.
+ * The upper one can only be a single bit (th), since the
+ * multiplication operands are at most 2^255+37 each.
+ */
+ th = t7 >> 62;
+ t7 = ((t7 << 1) | (t6 >> 63)) & MASK63;
+ t6 = (t6 << 1) | (t5 >> 63);
+ t5 = (t5 << 1) | (t4 >> 63);
+ t4 = (t4 << 1) | (t3 >> 63);
+ t3 &= MASK63;
+
+ /*
+ * Multiply the middle part (t4..t7) by 19. We truncate it to
+ * 255 bits; the extra bits will go along with th.
+ */
+ t4 = _umul128(t4, 19, &h0);
+ t5 = _umul128(t5, 19, &h1);
+ t6 = _umul128(t6, 19, &h2);
+ t7 = _umul128(t7, 19, &h3);
+ k = _addcarry_u64(0, t5, h0, &t5);
+ k = _addcarry_u64(k, t6, h1, &t6);
+ k = _addcarry_u64(k, t7, h2, &t7);
+ (void)_addcarry_u64(k, h3, 0, &h3);
+ th = (361 & -th) + (19 * ((h3 << 1) + (t7 >> 63)));
+ t7 &= MASK63;
+
+ /*
+ * Add elements together.
+ * At this point:
+ * t0..t3 fits on 255 bits.
+ * t4..t7 fits on 255 bits.
+ * th <= 361 + 342 = 703.
+ */
+ k = _addcarry_u64(0, t0, t4, &t0);
+ k = _addcarry_u64(k, t1, t5, &t1);
+ k = _addcarry_u64(k, t2, t6, &t2);
+ k = _addcarry_u64(k, t3, t7, &t3);
+ t4 = k;
+ k = _addcarry_u64(0, t0, th, &t0);
+ k = _addcarry_u64(k, t1, 0, &t1);
+ k = _addcarry_u64(k, t2, 0, &t2);
+ k = _addcarry_u64(k, t3, 0, &t3);
+ (void)_addcarry_u64(k, t4, 0, &t4);
+
+ th = (t4 << 1) + (t3 >> 63);
+ t3 &= MASK63;
+
+ /*
+ * Since the sum is at most 2^256 + 703, the two upper bits, in th,
+ * can only have value 0, 1 or 2. We just add th*19, which
+ * guarantees a result of at most 2^255+37.
+ */
+ k = _addcarry_u64(0, t0, 19 * th, &d[0]);
+ k = _addcarry_u64(k, t1, 0, &d[1]);
+ k = _addcarry_u64(k, t2, 0, &d[2]);
+ (void)_addcarry_u64(k, t3, 0, &d[3]);
+
+#endif
+}
+
+/*
+ * Multiplication by A24 = 121665.
+ */
+static inline void
+f255_mul_a24(uint64_t *d, const uint64_t *a)
+{
+#if BR_INT128
+
+ uint64_t t0, t1, t2, t3;
+ unsigned __int128 z;
+
+ z = (unsigned __int128)a[0] * 121665;
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)a[1] * 121665 + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)a[2] * 121665 + (z >> 64);
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)a[3] * 121665 + (z >> 64);
+ t3 = (uint64_t)z & MASK63;
+
+ z = (unsigned __int128)t0 + (19 * (uint64_t)(z >> 63));
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)t1 + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)t2 + (z >> 64);
+ t2 = (uint64_t)z;
+ t3 = t3 + (uint64_t)(z >> 64);
+
+ z = (unsigned __int128)t0 + (19 & -(t3 >> 63));
+ d[0] = (uint64_t)z;
+ z = (unsigned __int128)t1 + (z >> 64);
+ d[1] = (uint64_t)z;
+ z = (unsigned __int128)t2 + (z >> 64);
+ d[2] = (uint64_t)z;
+ d[3] = (t3 & MASK63) + (uint64_t)(z >> 64);
+
+#elif BR_UMUL128
+
+ uint64_t t0, t1, t2, t3, t4, h0, h1, h2, h3;
+ unsigned char k;
+
+ t0 = _umul128(a[0], 121665, &h0);
+ t1 = _umul128(a[1], 121665, &h1);
+ k = _addcarry_u64(0, t1, h0, &t1);
+ t2 = _umul128(a[2], 121665, &h2);
+ k = _addcarry_u64(k, t2, h1, &t2);
+ t3 = _umul128(a[3], 121665, &h3);
+ k = _addcarry_u64(k, t3, h2, &t3);
+ (void)_addcarry_u64(k, h3, 0, &t4);
+
+ t4 = (t4 << 1) + (t3 >> 63);
+ t3 &= MASK63;
+ k = _addcarry_u64(0, t0, 19 * t4, &t0);
+ k = _addcarry_u64(k, t1, 0, &t1);
+ k = _addcarry_u64(k, t2, 0, &t2);
+ (void)_addcarry_u64(k, t3, 0, &t3);
+
+ t4 = 19 & -(t3 >> 63);
+ t3 &= MASK63;
+ k = _addcarry_u64(0, t0, t4, &d[0]);
+ k = _addcarry_u64(k, t1, 0, &d[1]);
+ k = _addcarry_u64(k, t2, 0, &d[2]);
+ (void)_addcarry_u64(k, t3, 0, &d[3]);
+
+#endif
+}
+
+/*
+ * Finalize reduction.
+ */
+static inline void
+f255_final_reduce(uint64_t *a)
+{
+#if BR_INT128
+
+ uint64_t t0, t1, t2, t3, m;
+ unsigned __int128 z;
+
+ /*
+ * We add 19. If the result (in t) is below 2^255, then a[]
+ * is already less than 2^255-19, thus already reduced.
+ * Otherwise, we subtract 2^255 from t[], in which case we
+ * have t = a - (2^255-19), and that's our result.
+ */
+ z = (unsigned __int128)a[0] + 19;
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)a[1] + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)a[2] + (z >> 64);
+ t2 = (uint64_t)z;
+ t3 = a[3] + (uint64_t)(z >> 64);
+
+ m = -(t3 >> 63);
+ t3 &= MASK63;
+ a[0] ^= m & (a[0] ^ t0);
+ a[1] ^= m & (a[1] ^ t1);
+ a[2] ^= m & (a[2] ^ t2);
+ a[3] ^= m & (a[3] ^ t3);
+
+#elif BR_UMUL128
+
+ uint64_t t0, t1, t2, t3, m;
+ unsigned char k;
+
+ /*
+ * We add 19. If the result (in t) is below 2^255, then a[]
+ * is already less than 2^255-19, thus already reduced.
+ * Otherwise, we subtract 2^255 from t[], in which case we
+ * have t = a - (2^255-19), and that's our result.
+ */
+ k = _addcarry_u64(0, a[0], 19, &t0);
+ k = _addcarry_u64(k, a[1], 0, &t1);
+ k = _addcarry_u64(k, a[2], 0, &t2);
+ (void)_addcarry_u64(k, a[3], 0, &t3);
+
+ m = -(t3 >> 63);
+ t3 &= MASK63;
+ a[0] ^= m & (a[0] ^ t0);
+ a[1] ^= m & (a[1] ^ t1);
+ a[2] ^= m & (a[2] ^ t2);
+ a[3] ^= m & (a[3] ^ t3);
+
+#endif
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *kb, size_t kblen, int curve)
+{
+ unsigned char k[32];
+ uint64_t x1[4], x2[4], z2[4], x3[4], z3[4];
+ uint32_t swap;
+ int i;
+
+ (void)curve;
+
+ /*
+ * Points are encoded over exactly 32 bytes. Multipliers must fit
+ * in 32 bytes as well.
+ */
+ if (Glen != 32 || kblen > 32) {
+ return 0;
+ }
+
+ /*
+ * RFC 7748 mandates that the high bit of the last point byte must
+ * be ignored/cleared.
+ */
+ x1[0] = br_dec64le(&G[ 0]);
+ x1[1] = br_dec64le(&G[ 8]);
+ x1[2] = br_dec64le(&G[16]);
+ x1[3] = br_dec64le(&G[24]) & MASK63;
+
+ /*
+ * We can use memset() to clear values, because exact-width types
+ * like uint64_t are guaranteed to have no padding bits or
+ * trap representations.
+ */
+ memset(x2, 0, sizeof x2);
+ x2[0] = 1;
+ memset(z2, 0, sizeof z2);
+ memcpy(x3, x1, sizeof x1);
+ memcpy(z3, x2, sizeof x2);
+
+ /*
+ * The multiplier is provided in big-endian notation, and
+ * possibly shorter than 32 bytes.
+ */
+ memset(k, 0, (sizeof k) - kblen);
+ memcpy(k + (sizeof k) - kblen, kb, kblen);
+ k[31] &= 0xF8;
+ k[0] &= 0x7F;
+ k[0] |= 0x40;
+
+ swap = 0;
+
+ for (i = 254; i >= 0; i --) {
+ uint64_t a[4], aa[4], b[4], bb[4], e[4];
+ uint64_t c[4], d[4], da[4], cb[4];
+ uint32_t kt;
+
+ kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
+ swap ^= kt;
+ f255_cswap(x2, x3, swap);
+ f255_cswap(z2, z3, swap);
+ swap = kt;
+
+ /* A = x_2 + z_2 */
+ f255_add(a, x2, z2);
+
+ /* AA = A^2 */
+ f255_mul(aa, a, a);
+
+ /* B = x_2 - z_2 */
+ f255_sub(b, x2, z2);
+
+ /* BB = B^2 */
+ f255_mul(bb, b, b);
+
+ /* E = AA - BB */
+ f255_sub(e, aa, bb);
+
+ /* C = x_3 + z_3 */
+ f255_add(c, x3, z3);
+
+ /* D = x_3 - z_3 */
+ f255_sub(d, x3, z3);
+
+ /* DA = D * A */
+ f255_mul(da, d, a);
+
+ /* CB = C * B */
+ f255_mul(cb, c, b);
+
+ /* x_3 = (DA + CB)^2 */
+ f255_add(x3, da, cb);
+ f255_mul(x3, x3, x3);
+
+ /* z_3 = x_1 * (DA - CB)^2 */
+ f255_sub(z3, da, cb);
+ f255_mul(z3, z3, z3);
+ f255_mul(z3, x1, z3);
+
+ /* x_2 = AA * BB */
+ f255_mul(x2, aa, bb);
+
+ /* z_2 = E * (AA + a24 * E) */
+ f255_mul_a24(z2, e);
+ f255_add(z2, aa, z2);
+ f255_mul(z2, e, z2);
+ }
+
+ f255_cswap(x2, x3, swap);
+ f255_cswap(z2, z3, swap);
+
+ /*
+ * Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize
+ * most non-squarings. We use x1 and x3, now useless, as temporaries.
+ */
+ memcpy(x1, z2, sizeof z2);
+ for (i = 0; i < 15; i ++) {
+ f255_mul(x1, x1, x1);
+ f255_mul(x1, x1, z2);
+ }
+ memcpy(x3, x1, sizeof x1);
+ for (i = 0; i < 14; i ++) {
+ int j;
+
+ for (j = 0; j < 16; j ++) {
+ f255_mul(x3, x3, x3);
+ }
+ f255_mul(x3, x3, x1);
+ }
+ for (i = 14; i >= 0; i --) {
+ f255_mul(x3, x3, x3);
+ if ((0xFFEB >> i) & 1) {
+ f255_mul(x3, z2, x3);
+ }
+ }
+
+ /*
+ * Compute x2/z2. We have 1/z2 in x3.
+ */
+ f255_mul(x2, x2, x3);
+ f255_final_reduce(x2);
+
+ /*
+ * Encode the final x2 value in little-endian.
+ */
+ br_enc64le(G, x2[0]);
+ br_enc64le(G + 8, x2[1]);
+ br_enc64le(G + 16, x2[2]);
+ br_enc64le(G + 24, x2[3]);
+ return 1;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We don't implement this method, since it is used for ECDSA
+ * only, and there is no ECDSA over Curve25519 (which instead
+ * uses EdDSA).
+ */
+ (void)A;
+ (void)B;
+ (void)len;
+ (void)x;
+ (void)xlen;
+ (void)y;
+ (void)ylen;
+ (void)curve;
+ return 0;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_c25519_m64 = {
+ (uint32_t)0x20000000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_c25519_m64_get(void)
+{
+ return &br_ec_c25519_m64;
+}
+
+#else
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_c25519_m64_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/ec/ec_c25519_m64.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_curve25519.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_curve25519.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_curve25519.c (revision 346145)
@@ -0,0 +1,46 @@
+/*
+ * 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"
+
+static const unsigned char GEN[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char ORDER[] = {
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* see inner.h */
+const br_ec_curve_def br_curve25519 = {
+ BR_EC_curve25519,
+ ORDER, sizeof ORDER,
+ GEN, sizeof GEN
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_curve25519.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_default.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_default.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_default.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_get_default(void)
+{
+#if BR_LOMUL
+ return &br_ec_all_m15;
+#else
+ return &br_ec_all_m31;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ec_default.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_keygen.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_keygen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_keygen.c (revision 346145)
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_ec.h */
+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)
+{
+ const unsigned char *order;
+ unsigned char *buf;
+ size_t len;
+ unsigned mask;
+
+ if (curve < 0 || curve >= 32
+ || ((impl->supported_curves >> curve) & 1) == 0)
+ {
+ return 0;
+ }
+ order = impl->order(curve, &len);
+ while (len > 0 && *order == 0) {
+ order ++;
+ len --;
+ }
+ if (kbuf == NULL || len == 0) {
+ return len;
+ }
+ mask = order[0];
+ mask |= (mask >> 1);
+ mask |= (mask >> 2);
+ mask |= (mask >> 4);
+
+ /*
+ * We generate sequences of random bits of the right size, until
+ * the value is strictly lower than the curve order (we also
+ * check for all-zero values, which are invalid).
+ */
+ buf = kbuf;
+ for (;;) {
+ size_t u;
+ unsigned cc, zz;
+
+ (*rng_ctx)->generate(rng_ctx, buf, len);
+ buf[0] &= mask;
+ cc = 0;
+ u = len;
+ zz = 0;
+ while (u -- > 0) {
+ cc = ((unsigned)(buf[u] - order[u] - cc) >> 8) & 1;
+ zz |= buf[u];
+ }
+ if (cc != 0 && zz != 0) {
+ break;
+ }
+ }
+
+ if (sk != NULL) {
+ sk->curve = curve;
+ sk->x = buf;
+ sk->xlen = len;
+ }
+ return len;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ec_keygen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_p256_m15.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_p256_m15.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_p256_m15.c (revision 346145)
@@ -0,0 +1,2130 @@
+/*
+ * 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"
+
+/*
+ * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
+ * that right-shifting a signed negative integer copies the sign bit
+ * (arithmetic right-shift). This is "implementation-defined behaviour",
+ * i.e. it is not undefined, but it may differ between compilers. Each
+ * compiler is supposed to document its behaviour in that respect. GCC
+ * explicitly defines that an arithmetic right shift is used. We expect
+ * all other compilers to do the same, because underlying CPU offer an
+ * arithmetic right shift opcode that could not be used otherwise.
+ */
+#if BR_NO_ARITH_SHIFT
+#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
+ | ((-((uint32_t)(x) >> 31)) << (32 - (n))))
+#else
+#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
+#endif
+
+/*
+ * Convert an integer from unsigned big-endian encoding to a sequence of
+ * 13-bit words in little-endian order. The final "partial" word is
+ * returned.
+ */
+static uint32_t
+be8_to_le13(uint32_t *dst, const unsigned char *src, size_t len)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ acc |= (uint32_t)src[len] << acc_len;
+ acc_len += 8;
+ if (acc_len >= 13) {
+ *dst ++ = acc & 0x1FFF;
+ acc >>= 13;
+ acc_len -= 13;
+ }
+ }
+ return acc;
+}
+
+/*
+ * Convert an integer (13-bit words, little-endian) to unsigned
+ * big-endian encoding. The total encoding length is provided; all
+ * the destination bytes will be filled.
+ */
+static void
+le13_to_be8(unsigned char *dst, size_t len, const uint32_t *src)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ if (acc_len < 8) {
+ acc |= (*src ++) << acc_len;
+ acc_len += 13;
+ }
+ dst[len] = (unsigned char)acc;
+ acc >>= 8;
+ acc_len -= 8;
+ }
+}
+
+/*
+ * Normalise an array of words to a strict 13 bits per word. Returned
+ * value is the resulting carry. The source (w) and destination (d)
+ * arrays may be identical, but shall not overlap partially.
+ */
+static inline uint32_t
+norm13(uint32_t *d, const uint32_t *w, size_t len)
+{
+ size_t u;
+ uint32_t cc;
+
+ cc = 0;
+ for (u = 0; u < len; u ++) {
+ int32_t z;
+
+ z = w[u] + cc;
+ d[u] = z & 0x1FFF;
+ cc = ARSH(z, 13);
+ }
+ return cc;
+}
+
+/*
+ * mul20() multiplies two 260-bit integers together. Each word must fit
+ * on 13 bits; source operands use 20 words, destination operand
+ * receives 40 words. All overlaps allowed.
+ *
+ * square20() computes the square of a 260-bit integer. Each word must
+ * fit on 13 bits; source operand uses 20 words, destination operand
+ * receives 40 words. All overlaps allowed.
+ */
+
+#if BR_SLOW_MUL15
+
+static void
+mul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ /*
+ * Two-level Karatsuba: turns a 20x20 multiplication into
+ * nine 5x5 multiplications. We use 13-bit words but do not
+ * propagate carries immediately, so words may expand:
+ *
+ * - First Karatsuba decomposition turns the 20x20 mul on
+ * 13-bit words into three 10x10 muls, two on 13-bit words
+ * and one on 14-bit words.
+ *
+ * - Second Karatsuba decomposition further splits these into:
+ *
+ * * four 5x5 muls on 13-bit words
+ * * four 5x5 muls on 14-bit words
+ * * one 5x5 mul on 15-bit words
+ *
+ * Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit
+ * or 15-bit words, respectively.
+ */
+ uint32_t u[45], v[45], w[90];
+ uint32_t cc;
+ int i;
+
+#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
+ (dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \
+ + (s2w)[5 * (s2_off) + 0]; \
+ (dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \
+ + (s2w)[5 * (s2_off) + 1]; \
+ (dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \
+ + (s2w)[5 * (s2_off) + 2]; \
+ (dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \
+ + (s2w)[5 * (s2_off) + 3]; \
+ (dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \
+ + (s2w)[5 * (s2_off) + 4]; \
+ } while (0)
+
+#define ZADDT(dw, d_off, sw, s_off) do { \
+ (dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \
+ (dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \
+ (dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \
+ (dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \
+ (dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \
+ } while (0)
+
+#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
+ (dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \
+ + (s2w)[5 * (s2_off) + 0]; \
+ (dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \
+ + (s2w)[5 * (s2_off) + 1]; \
+ (dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \
+ + (s2w)[5 * (s2_off) + 2]; \
+ (dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \
+ + (s2w)[5 * (s2_off) + 3]; \
+ (dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \
+ + (s2w)[5 * (s2_off) + 4]; \
+ } while (0)
+
+#define CPR1(w, cprcc) do { \
+ uint32_t cprz = (w) + cprcc; \
+ (w) = cprz & 0x1FFF; \
+ cprcc = cprz >> 13; \
+ } while (0)
+
+#define CPR(dw, d_off) do { \
+ uint32_t cprcc; \
+ cprcc = 0; \
+ CPR1((dw)[(d_off) + 0], cprcc); \
+ CPR1((dw)[(d_off) + 1], cprcc); \
+ CPR1((dw)[(d_off) + 2], cprcc); \
+ CPR1((dw)[(d_off) + 3], cprcc); \
+ CPR1((dw)[(d_off) + 4], cprcc); \
+ CPR1((dw)[(d_off) + 5], cprcc); \
+ CPR1((dw)[(d_off) + 6], cprcc); \
+ CPR1((dw)[(d_off) + 7], cprcc); \
+ CPR1((dw)[(d_off) + 8], cprcc); \
+ (dw)[(d_off) + 9] = cprcc; \
+ } while (0)
+
+ memcpy(u, a, 20 * sizeof *a);
+ ZADD(u, 4, a, 0, a, 1);
+ ZADD(u, 5, a, 2, a, 3);
+ ZADD(u, 6, a, 0, a, 2);
+ ZADD(u, 7, a, 1, a, 3);
+ ZADD(u, 8, u, 6, u, 7);
+
+ memcpy(v, b, 20 * sizeof *b);
+ ZADD(v, 4, b, 0, b, 1);
+ ZADD(v, 5, b, 2, b, 3);
+ ZADD(v, 6, b, 0, b, 2);
+ ZADD(v, 7, b, 1, b, 3);
+ ZADD(v, 8, v, 6, v, 7);
+
+ /*
+ * Do the eight first 8x8 muls. Source words are at most 16382
+ * each, so we can add product results together "as is" in 32-bit
+ * words.
+ */
+ for (i = 0; i < 40; i += 5) {
+ w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]);
+ w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1])
+ + MUL15(u[i + 1], v[i + 0]);
+ w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2])
+ + MUL15(u[i + 1], v[i + 1])
+ + MUL15(u[i + 2], v[i + 0]);
+ w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3])
+ + MUL15(u[i + 1], v[i + 2])
+ + MUL15(u[i + 2], v[i + 1])
+ + MUL15(u[i + 3], v[i + 0]);
+ w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4])
+ + MUL15(u[i + 1], v[i + 3])
+ + MUL15(u[i + 2], v[i + 2])
+ + MUL15(u[i + 3], v[i + 1])
+ + MUL15(u[i + 4], v[i + 0]);
+ w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4])
+ + MUL15(u[i + 2], v[i + 3])
+ + MUL15(u[i + 3], v[i + 2])
+ + MUL15(u[i + 4], v[i + 1]);
+ w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4])
+ + MUL15(u[i + 3], v[i + 3])
+ + MUL15(u[i + 4], v[i + 2]);
+ w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4])
+ + MUL15(u[i + 4], v[i + 3]);
+ w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]);
+ w[(i << 1) + 9] = 0;
+ }
+
+ /*
+ * For the 9th multiplication, source words are up to 32764,
+ * so we must do some carry propagation. If we add up to
+ * 4 products and the carry is no more than 524224, then the
+ * result fits in 32 bits, and the next carry will be no more
+ * than 524224 (because 4*(32764^2)+524224 < 8192*524225).
+ *
+ * We thus just skip one of the products in the middle word,
+ * then do a carry propagation (this reduces words to 13 bits
+ * each, except possibly the last, which may use up to 17 bits
+ * or so), then add the missing product.
+ */
+ w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]);
+ w[80 + 1] = MUL15(u[40 + 0], v[40 + 1])
+ + MUL15(u[40 + 1], v[40 + 0]);
+ w[80 + 2] = MUL15(u[40 + 0], v[40 + 2])
+ + MUL15(u[40 + 1], v[40 + 1])
+ + MUL15(u[40 + 2], v[40 + 0]);
+ w[80 + 3] = MUL15(u[40 + 0], v[40 + 3])
+ + MUL15(u[40 + 1], v[40 + 2])
+ + MUL15(u[40 + 2], v[40 + 1])
+ + MUL15(u[40 + 3], v[40 + 0]);
+ w[80 + 4] = MUL15(u[40 + 0], v[40 + 4])
+ + MUL15(u[40 + 1], v[40 + 3])
+ + MUL15(u[40 + 2], v[40 + 2])
+ + MUL15(u[40 + 3], v[40 + 1]);
+ /* + MUL15(u[40 + 4], v[40 + 0]) */
+ w[80 + 5] = MUL15(u[40 + 1], v[40 + 4])
+ + MUL15(u[40 + 2], v[40 + 3])
+ + MUL15(u[40 + 3], v[40 + 2])
+ + MUL15(u[40 + 4], v[40 + 1]);
+ w[80 + 6] = MUL15(u[40 + 2], v[40 + 4])
+ + MUL15(u[40 + 3], v[40 + 3])
+ + MUL15(u[40 + 4], v[40 + 2]);
+ w[80 + 7] = MUL15(u[40 + 3], v[40 + 4])
+ + MUL15(u[40 + 4], v[40 + 3]);
+ w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]);
+
+ CPR(w, 80);
+
+ w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]);
+
+ /*
+ * The products on 14-bit words in slots 6 and 7 yield values
+ * up to 5*(16382^2) each, and we need to subtract two such
+ * values from the higher word. We need the subtraction to fit
+ * in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit.
+ * However, 10*(16382^2) does not fit. So we must perform a
+ * bit of reduction here.
+ */
+ CPR(w, 60);
+ CPR(w, 70);
+
+ /*
+ * Recompose results.
+ */
+
+ /* 0..1*0..1 into 0..3 */
+ ZSUB2F(w, 8, w, 0, w, 2);
+ ZSUB2F(w, 9, w, 1, w, 3);
+ ZADDT(w, 1, w, 8);
+ ZADDT(w, 2, w, 9);
+
+ /* 2..3*2..3 into 4..7 */
+ ZSUB2F(w, 10, w, 4, w, 6);
+ ZSUB2F(w, 11, w, 5, w, 7);
+ ZADDT(w, 5, w, 10);
+ ZADDT(w, 6, w, 11);
+
+ /* (0..1+2..3)*(0..1+2..3) into 12..15 */
+ ZSUB2F(w, 16, w, 12, w, 14);
+ ZSUB2F(w, 17, w, 13, w, 15);
+ ZADDT(w, 13, w, 16);
+ ZADDT(w, 14, w, 17);
+
+ /* first-level recomposition */
+ ZSUB2F(w, 12, w, 0, w, 4);
+ ZSUB2F(w, 13, w, 1, w, 5);
+ ZSUB2F(w, 14, w, 2, w, 6);
+ ZSUB2F(w, 15, w, 3, w, 7);
+ ZADDT(w, 2, w, 12);
+ ZADDT(w, 3, w, 13);
+ ZADDT(w, 4, w, 14);
+ ZADDT(w, 5, w, 15);
+
+ /*
+ * Perform carry propagation to bring all words down to 13 bits.
+ */
+ cc = norm13(d, w, 40);
+ d[39] += (cc << 13);
+
+#undef ZADD
+#undef ZADDT
+#undef ZSUB2F
+#undef CPR1
+#undef CPR
+}
+
+static inline void
+square20(uint32_t *d, const uint32_t *a)
+{
+ mul20(d, a, a);
+}
+
+#else
+
+static void
+mul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t t[39];
+
+ t[ 0] = MUL15(a[ 0], b[ 0]);
+ t[ 1] = MUL15(a[ 0], b[ 1])
+ + MUL15(a[ 1], b[ 0]);
+ t[ 2] = MUL15(a[ 0], b[ 2])
+ + MUL15(a[ 1], b[ 1])
+ + MUL15(a[ 2], b[ 0]);
+ t[ 3] = MUL15(a[ 0], b[ 3])
+ + MUL15(a[ 1], b[ 2])
+ + MUL15(a[ 2], b[ 1])
+ + MUL15(a[ 3], b[ 0]);
+ t[ 4] = MUL15(a[ 0], b[ 4])
+ + MUL15(a[ 1], b[ 3])
+ + MUL15(a[ 2], b[ 2])
+ + MUL15(a[ 3], b[ 1])
+ + MUL15(a[ 4], b[ 0]);
+ t[ 5] = MUL15(a[ 0], b[ 5])
+ + MUL15(a[ 1], b[ 4])
+ + MUL15(a[ 2], b[ 3])
+ + MUL15(a[ 3], b[ 2])
+ + MUL15(a[ 4], b[ 1])
+ + MUL15(a[ 5], b[ 0]);
+ t[ 6] = MUL15(a[ 0], b[ 6])
+ + MUL15(a[ 1], b[ 5])
+ + MUL15(a[ 2], b[ 4])
+ + MUL15(a[ 3], b[ 3])
+ + MUL15(a[ 4], b[ 2])
+ + MUL15(a[ 5], b[ 1])
+ + MUL15(a[ 6], b[ 0]);
+ t[ 7] = MUL15(a[ 0], b[ 7])
+ + MUL15(a[ 1], b[ 6])
+ + MUL15(a[ 2], b[ 5])
+ + MUL15(a[ 3], b[ 4])
+ + MUL15(a[ 4], b[ 3])
+ + MUL15(a[ 5], b[ 2])
+ + MUL15(a[ 6], b[ 1])
+ + MUL15(a[ 7], b[ 0]);
+ t[ 8] = MUL15(a[ 0], b[ 8])
+ + MUL15(a[ 1], b[ 7])
+ + MUL15(a[ 2], b[ 6])
+ + MUL15(a[ 3], b[ 5])
+ + MUL15(a[ 4], b[ 4])
+ + MUL15(a[ 5], b[ 3])
+ + MUL15(a[ 6], b[ 2])
+ + MUL15(a[ 7], b[ 1])
+ + MUL15(a[ 8], b[ 0]);
+ t[ 9] = MUL15(a[ 0], b[ 9])
+ + MUL15(a[ 1], b[ 8])
+ + MUL15(a[ 2], b[ 7])
+ + MUL15(a[ 3], b[ 6])
+ + MUL15(a[ 4], b[ 5])
+ + MUL15(a[ 5], b[ 4])
+ + MUL15(a[ 6], b[ 3])
+ + MUL15(a[ 7], b[ 2])
+ + MUL15(a[ 8], b[ 1])
+ + MUL15(a[ 9], b[ 0]);
+ t[10] = MUL15(a[ 0], b[10])
+ + MUL15(a[ 1], b[ 9])
+ + MUL15(a[ 2], b[ 8])
+ + MUL15(a[ 3], b[ 7])
+ + MUL15(a[ 4], b[ 6])
+ + MUL15(a[ 5], b[ 5])
+ + MUL15(a[ 6], b[ 4])
+ + MUL15(a[ 7], b[ 3])
+ + MUL15(a[ 8], b[ 2])
+ + MUL15(a[ 9], b[ 1])
+ + MUL15(a[10], b[ 0]);
+ t[11] = MUL15(a[ 0], b[11])
+ + MUL15(a[ 1], b[10])
+ + MUL15(a[ 2], b[ 9])
+ + MUL15(a[ 3], b[ 8])
+ + MUL15(a[ 4], b[ 7])
+ + MUL15(a[ 5], b[ 6])
+ + MUL15(a[ 6], b[ 5])
+ + MUL15(a[ 7], b[ 4])
+ + MUL15(a[ 8], b[ 3])
+ + MUL15(a[ 9], b[ 2])
+ + MUL15(a[10], b[ 1])
+ + MUL15(a[11], b[ 0]);
+ t[12] = MUL15(a[ 0], b[12])
+ + MUL15(a[ 1], b[11])
+ + MUL15(a[ 2], b[10])
+ + MUL15(a[ 3], b[ 9])
+ + MUL15(a[ 4], b[ 8])
+ + MUL15(a[ 5], b[ 7])
+ + MUL15(a[ 6], b[ 6])
+ + MUL15(a[ 7], b[ 5])
+ + MUL15(a[ 8], b[ 4])
+ + MUL15(a[ 9], b[ 3])
+ + MUL15(a[10], b[ 2])
+ + MUL15(a[11], b[ 1])
+ + MUL15(a[12], b[ 0]);
+ t[13] = MUL15(a[ 0], b[13])
+ + MUL15(a[ 1], b[12])
+ + MUL15(a[ 2], b[11])
+ + MUL15(a[ 3], b[10])
+ + MUL15(a[ 4], b[ 9])
+ + MUL15(a[ 5], b[ 8])
+ + MUL15(a[ 6], b[ 7])
+ + MUL15(a[ 7], b[ 6])
+ + MUL15(a[ 8], b[ 5])
+ + MUL15(a[ 9], b[ 4])
+ + MUL15(a[10], b[ 3])
+ + MUL15(a[11], b[ 2])
+ + MUL15(a[12], b[ 1])
+ + MUL15(a[13], b[ 0]);
+ t[14] = MUL15(a[ 0], b[14])
+ + MUL15(a[ 1], b[13])
+ + MUL15(a[ 2], b[12])
+ + MUL15(a[ 3], b[11])
+ + MUL15(a[ 4], b[10])
+ + MUL15(a[ 5], b[ 9])
+ + MUL15(a[ 6], b[ 8])
+ + MUL15(a[ 7], b[ 7])
+ + MUL15(a[ 8], b[ 6])
+ + MUL15(a[ 9], b[ 5])
+ + MUL15(a[10], b[ 4])
+ + MUL15(a[11], b[ 3])
+ + MUL15(a[12], b[ 2])
+ + MUL15(a[13], b[ 1])
+ + MUL15(a[14], b[ 0]);
+ t[15] = MUL15(a[ 0], b[15])
+ + MUL15(a[ 1], b[14])
+ + MUL15(a[ 2], b[13])
+ + MUL15(a[ 3], b[12])
+ + MUL15(a[ 4], b[11])
+ + MUL15(a[ 5], b[10])
+ + MUL15(a[ 6], b[ 9])
+ + MUL15(a[ 7], b[ 8])
+ + MUL15(a[ 8], b[ 7])
+ + MUL15(a[ 9], b[ 6])
+ + MUL15(a[10], b[ 5])
+ + MUL15(a[11], b[ 4])
+ + MUL15(a[12], b[ 3])
+ + MUL15(a[13], b[ 2])
+ + MUL15(a[14], b[ 1])
+ + MUL15(a[15], b[ 0]);
+ t[16] = MUL15(a[ 0], b[16])
+ + MUL15(a[ 1], b[15])
+ + MUL15(a[ 2], b[14])
+ + MUL15(a[ 3], b[13])
+ + MUL15(a[ 4], b[12])
+ + MUL15(a[ 5], b[11])
+ + MUL15(a[ 6], b[10])
+ + MUL15(a[ 7], b[ 9])
+ + MUL15(a[ 8], b[ 8])
+ + MUL15(a[ 9], b[ 7])
+ + MUL15(a[10], b[ 6])
+ + MUL15(a[11], b[ 5])
+ + MUL15(a[12], b[ 4])
+ + MUL15(a[13], b[ 3])
+ + MUL15(a[14], b[ 2])
+ + MUL15(a[15], b[ 1])
+ + MUL15(a[16], b[ 0]);
+ t[17] = MUL15(a[ 0], b[17])
+ + MUL15(a[ 1], b[16])
+ + MUL15(a[ 2], b[15])
+ + MUL15(a[ 3], b[14])
+ + MUL15(a[ 4], b[13])
+ + MUL15(a[ 5], b[12])
+ + MUL15(a[ 6], b[11])
+ + MUL15(a[ 7], b[10])
+ + MUL15(a[ 8], b[ 9])
+ + MUL15(a[ 9], b[ 8])
+ + MUL15(a[10], b[ 7])
+ + MUL15(a[11], b[ 6])
+ + MUL15(a[12], b[ 5])
+ + MUL15(a[13], b[ 4])
+ + MUL15(a[14], b[ 3])
+ + MUL15(a[15], b[ 2])
+ + MUL15(a[16], b[ 1])
+ + MUL15(a[17], b[ 0]);
+ t[18] = MUL15(a[ 0], b[18])
+ + MUL15(a[ 1], b[17])
+ + MUL15(a[ 2], b[16])
+ + MUL15(a[ 3], b[15])
+ + MUL15(a[ 4], b[14])
+ + MUL15(a[ 5], b[13])
+ + MUL15(a[ 6], b[12])
+ + MUL15(a[ 7], b[11])
+ + MUL15(a[ 8], b[10])
+ + MUL15(a[ 9], b[ 9])
+ + MUL15(a[10], b[ 8])
+ + MUL15(a[11], b[ 7])
+ + MUL15(a[12], b[ 6])
+ + MUL15(a[13], b[ 5])
+ + MUL15(a[14], b[ 4])
+ + MUL15(a[15], b[ 3])
+ + MUL15(a[16], b[ 2])
+ + MUL15(a[17], b[ 1])
+ + MUL15(a[18], b[ 0]);
+ t[19] = MUL15(a[ 0], b[19])
+ + MUL15(a[ 1], b[18])
+ + MUL15(a[ 2], b[17])
+ + MUL15(a[ 3], b[16])
+ + MUL15(a[ 4], b[15])
+ + MUL15(a[ 5], b[14])
+ + MUL15(a[ 6], b[13])
+ + MUL15(a[ 7], b[12])
+ + MUL15(a[ 8], b[11])
+ + MUL15(a[ 9], b[10])
+ + MUL15(a[10], b[ 9])
+ + MUL15(a[11], b[ 8])
+ + MUL15(a[12], b[ 7])
+ + MUL15(a[13], b[ 6])
+ + MUL15(a[14], b[ 5])
+ + MUL15(a[15], b[ 4])
+ + MUL15(a[16], b[ 3])
+ + MUL15(a[17], b[ 2])
+ + MUL15(a[18], b[ 1])
+ + MUL15(a[19], b[ 0]);
+ t[20] = MUL15(a[ 1], b[19])
+ + MUL15(a[ 2], b[18])
+ + MUL15(a[ 3], b[17])
+ + MUL15(a[ 4], b[16])
+ + MUL15(a[ 5], b[15])
+ + MUL15(a[ 6], b[14])
+ + MUL15(a[ 7], b[13])
+ + MUL15(a[ 8], b[12])
+ + MUL15(a[ 9], b[11])
+ + MUL15(a[10], b[10])
+ + MUL15(a[11], b[ 9])
+ + MUL15(a[12], b[ 8])
+ + MUL15(a[13], b[ 7])
+ + MUL15(a[14], b[ 6])
+ + MUL15(a[15], b[ 5])
+ + MUL15(a[16], b[ 4])
+ + MUL15(a[17], b[ 3])
+ + MUL15(a[18], b[ 2])
+ + MUL15(a[19], b[ 1]);
+ t[21] = MUL15(a[ 2], b[19])
+ + MUL15(a[ 3], b[18])
+ + MUL15(a[ 4], b[17])
+ + MUL15(a[ 5], b[16])
+ + MUL15(a[ 6], b[15])
+ + MUL15(a[ 7], b[14])
+ + MUL15(a[ 8], b[13])
+ + MUL15(a[ 9], b[12])
+ + MUL15(a[10], b[11])
+ + MUL15(a[11], b[10])
+ + MUL15(a[12], b[ 9])
+ + MUL15(a[13], b[ 8])
+ + MUL15(a[14], b[ 7])
+ + MUL15(a[15], b[ 6])
+ + MUL15(a[16], b[ 5])
+ + MUL15(a[17], b[ 4])
+ + MUL15(a[18], b[ 3])
+ + MUL15(a[19], b[ 2]);
+ t[22] = MUL15(a[ 3], b[19])
+ + MUL15(a[ 4], b[18])
+ + MUL15(a[ 5], b[17])
+ + MUL15(a[ 6], b[16])
+ + MUL15(a[ 7], b[15])
+ + MUL15(a[ 8], b[14])
+ + MUL15(a[ 9], b[13])
+ + MUL15(a[10], b[12])
+ + MUL15(a[11], b[11])
+ + MUL15(a[12], b[10])
+ + MUL15(a[13], b[ 9])
+ + MUL15(a[14], b[ 8])
+ + MUL15(a[15], b[ 7])
+ + MUL15(a[16], b[ 6])
+ + MUL15(a[17], b[ 5])
+ + MUL15(a[18], b[ 4])
+ + MUL15(a[19], b[ 3]);
+ t[23] = MUL15(a[ 4], b[19])
+ + MUL15(a[ 5], b[18])
+ + MUL15(a[ 6], b[17])
+ + MUL15(a[ 7], b[16])
+ + MUL15(a[ 8], b[15])
+ + MUL15(a[ 9], b[14])
+ + MUL15(a[10], b[13])
+ + MUL15(a[11], b[12])
+ + MUL15(a[12], b[11])
+ + MUL15(a[13], b[10])
+ + MUL15(a[14], b[ 9])
+ + MUL15(a[15], b[ 8])
+ + MUL15(a[16], b[ 7])
+ + MUL15(a[17], b[ 6])
+ + MUL15(a[18], b[ 5])
+ + MUL15(a[19], b[ 4]);
+ t[24] = MUL15(a[ 5], b[19])
+ + MUL15(a[ 6], b[18])
+ + MUL15(a[ 7], b[17])
+ + MUL15(a[ 8], b[16])
+ + MUL15(a[ 9], b[15])
+ + MUL15(a[10], b[14])
+ + MUL15(a[11], b[13])
+ + MUL15(a[12], b[12])
+ + MUL15(a[13], b[11])
+ + MUL15(a[14], b[10])
+ + MUL15(a[15], b[ 9])
+ + MUL15(a[16], b[ 8])
+ + MUL15(a[17], b[ 7])
+ + MUL15(a[18], b[ 6])
+ + MUL15(a[19], b[ 5]);
+ t[25] = MUL15(a[ 6], b[19])
+ + MUL15(a[ 7], b[18])
+ + MUL15(a[ 8], b[17])
+ + MUL15(a[ 9], b[16])
+ + MUL15(a[10], b[15])
+ + MUL15(a[11], b[14])
+ + MUL15(a[12], b[13])
+ + MUL15(a[13], b[12])
+ + MUL15(a[14], b[11])
+ + MUL15(a[15], b[10])
+ + MUL15(a[16], b[ 9])
+ + MUL15(a[17], b[ 8])
+ + MUL15(a[18], b[ 7])
+ + MUL15(a[19], b[ 6]);
+ t[26] = MUL15(a[ 7], b[19])
+ + MUL15(a[ 8], b[18])
+ + MUL15(a[ 9], b[17])
+ + MUL15(a[10], b[16])
+ + MUL15(a[11], b[15])
+ + MUL15(a[12], b[14])
+ + MUL15(a[13], b[13])
+ + MUL15(a[14], b[12])
+ + MUL15(a[15], b[11])
+ + MUL15(a[16], b[10])
+ + MUL15(a[17], b[ 9])
+ + MUL15(a[18], b[ 8])
+ + MUL15(a[19], b[ 7]);
+ t[27] = MUL15(a[ 8], b[19])
+ + MUL15(a[ 9], b[18])
+ + MUL15(a[10], b[17])
+ + MUL15(a[11], b[16])
+ + MUL15(a[12], b[15])
+ + MUL15(a[13], b[14])
+ + MUL15(a[14], b[13])
+ + MUL15(a[15], b[12])
+ + MUL15(a[16], b[11])
+ + MUL15(a[17], b[10])
+ + MUL15(a[18], b[ 9])
+ + MUL15(a[19], b[ 8]);
+ t[28] = MUL15(a[ 9], b[19])
+ + MUL15(a[10], b[18])
+ + MUL15(a[11], b[17])
+ + MUL15(a[12], b[16])
+ + MUL15(a[13], b[15])
+ + MUL15(a[14], b[14])
+ + MUL15(a[15], b[13])
+ + MUL15(a[16], b[12])
+ + MUL15(a[17], b[11])
+ + MUL15(a[18], b[10])
+ + MUL15(a[19], b[ 9]);
+ t[29] = MUL15(a[10], b[19])
+ + MUL15(a[11], b[18])
+ + MUL15(a[12], b[17])
+ + MUL15(a[13], b[16])
+ + MUL15(a[14], b[15])
+ + MUL15(a[15], b[14])
+ + MUL15(a[16], b[13])
+ + MUL15(a[17], b[12])
+ + MUL15(a[18], b[11])
+ + MUL15(a[19], b[10]);
+ t[30] = MUL15(a[11], b[19])
+ + MUL15(a[12], b[18])
+ + MUL15(a[13], b[17])
+ + MUL15(a[14], b[16])
+ + MUL15(a[15], b[15])
+ + MUL15(a[16], b[14])
+ + MUL15(a[17], b[13])
+ + MUL15(a[18], b[12])
+ + MUL15(a[19], b[11]);
+ t[31] = MUL15(a[12], b[19])
+ + MUL15(a[13], b[18])
+ + MUL15(a[14], b[17])
+ + MUL15(a[15], b[16])
+ + MUL15(a[16], b[15])
+ + MUL15(a[17], b[14])
+ + MUL15(a[18], b[13])
+ + MUL15(a[19], b[12]);
+ t[32] = MUL15(a[13], b[19])
+ + MUL15(a[14], b[18])
+ + MUL15(a[15], b[17])
+ + MUL15(a[16], b[16])
+ + MUL15(a[17], b[15])
+ + MUL15(a[18], b[14])
+ + MUL15(a[19], b[13]);
+ t[33] = MUL15(a[14], b[19])
+ + MUL15(a[15], b[18])
+ + MUL15(a[16], b[17])
+ + MUL15(a[17], b[16])
+ + MUL15(a[18], b[15])
+ + MUL15(a[19], b[14]);
+ t[34] = MUL15(a[15], b[19])
+ + MUL15(a[16], b[18])
+ + MUL15(a[17], b[17])
+ + MUL15(a[18], b[16])
+ + MUL15(a[19], b[15]);
+ t[35] = MUL15(a[16], b[19])
+ + MUL15(a[17], b[18])
+ + MUL15(a[18], b[17])
+ + MUL15(a[19], b[16]);
+ t[36] = MUL15(a[17], b[19])
+ + MUL15(a[18], b[18])
+ + MUL15(a[19], b[17]);
+ t[37] = MUL15(a[18], b[19])
+ + MUL15(a[19], b[18]);
+ t[38] = MUL15(a[19], b[19]);
+ d[39] = norm13(d, t, 39);
+}
+
+static void
+square20(uint32_t *d, const uint32_t *a)
+{
+ uint32_t t[39];
+
+ t[ 0] = MUL15(a[ 0], a[ 0]);
+ t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1);
+ t[ 2] = MUL15(a[ 1], a[ 1])
+ + ((MUL15(a[ 0], a[ 2])) << 1);
+ t[ 3] = ((MUL15(a[ 0], a[ 3])
+ + MUL15(a[ 1], a[ 2])) << 1);
+ t[ 4] = MUL15(a[ 2], a[ 2])
+ + ((MUL15(a[ 0], a[ 4])
+ + MUL15(a[ 1], a[ 3])) << 1);
+ t[ 5] = ((MUL15(a[ 0], a[ 5])
+ + MUL15(a[ 1], a[ 4])
+ + MUL15(a[ 2], a[ 3])) << 1);
+ t[ 6] = MUL15(a[ 3], a[ 3])
+ + ((MUL15(a[ 0], a[ 6])
+ + MUL15(a[ 1], a[ 5])
+ + MUL15(a[ 2], a[ 4])) << 1);
+ t[ 7] = ((MUL15(a[ 0], a[ 7])
+ + MUL15(a[ 1], a[ 6])
+ + MUL15(a[ 2], a[ 5])
+ + MUL15(a[ 3], a[ 4])) << 1);
+ t[ 8] = MUL15(a[ 4], a[ 4])
+ + ((MUL15(a[ 0], a[ 8])
+ + MUL15(a[ 1], a[ 7])
+ + MUL15(a[ 2], a[ 6])
+ + MUL15(a[ 3], a[ 5])) << 1);
+ t[ 9] = ((MUL15(a[ 0], a[ 9])
+ + MUL15(a[ 1], a[ 8])
+ + MUL15(a[ 2], a[ 7])
+ + MUL15(a[ 3], a[ 6])
+ + MUL15(a[ 4], a[ 5])) << 1);
+ t[10] = MUL15(a[ 5], a[ 5])
+ + ((MUL15(a[ 0], a[10])
+ + MUL15(a[ 1], a[ 9])
+ + MUL15(a[ 2], a[ 8])
+ + MUL15(a[ 3], a[ 7])
+ + MUL15(a[ 4], a[ 6])) << 1);
+ t[11] = ((MUL15(a[ 0], a[11])
+ + MUL15(a[ 1], a[10])
+ + MUL15(a[ 2], a[ 9])
+ + MUL15(a[ 3], a[ 8])
+ + MUL15(a[ 4], a[ 7])
+ + MUL15(a[ 5], a[ 6])) << 1);
+ t[12] = MUL15(a[ 6], a[ 6])
+ + ((MUL15(a[ 0], a[12])
+ + MUL15(a[ 1], a[11])
+ + MUL15(a[ 2], a[10])
+ + MUL15(a[ 3], a[ 9])
+ + MUL15(a[ 4], a[ 8])
+ + MUL15(a[ 5], a[ 7])) << 1);
+ t[13] = ((MUL15(a[ 0], a[13])
+ + MUL15(a[ 1], a[12])
+ + MUL15(a[ 2], a[11])
+ + MUL15(a[ 3], a[10])
+ + MUL15(a[ 4], a[ 9])
+ + MUL15(a[ 5], a[ 8])
+ + MUL15(a[ 6], a[ 7])) << 1);
+ t[14] = MUL15(a[ 7], a[ 7])
+ + ((MUL15(a[ 0], a[14])
+ + MUL15(a[ 1], a[13])
+ + MUL15(a[ 2], a[12])
+ + MUL15(a[ 3], a[11])
+ + MUL15(a[ 4], a[10])
+ + MUL15(a[ 5], a[ 9])
+ + MUL15(a[ 6], a[ 8])) << 1);
+ t[15] = ((MUL15(a[ 0], a[15])
+ + MUL15(a[ 1], a[14])
+ + MUL15(a[ 2], a[13])
+ + MUL15(a[ 3], a[12])
+ + MUL15(a[ 4], a[11])
+ + MUL15(a[ 5], a[10])
+ + MUL15(a[ 6], a[ 9])
+ + MUL15(a[ 7], a[ 8])) << 1);
+ t[16] = MUL15(a[ 8], a[ 8])
+ + ((MUL15(a[ 0], a[16])
+ + MUL15(a[ 1], a[15])
+ + MUL15(a[ 2], a[14])
+ + MUL15(a[ 3], a[13])
+ + MUL15(a[ 4], a[12])
+ + MUL15(a[ 5], a[11])
+ + MUL15(a[ 6], a[10])
+ + MUL15(a[ 7], a[ 9])) << 1);
+ t[17] = ((MUL15(a[ 0], a[17])
+ + MUL15(a[ 1], a[16])
+ + MUL15(a[ 2], a[15])
+ + MUL15(a[ 3], a[14])
+ + MUL15(a[ 4], a[13])
+ + MUL15(a[ 5], a[12])
+ + MUL15(a[ 6], a[11])
+ + MUL15(a[ 7], a[10])
+ + MUL15(a[ 8], a[ 9])) << 1);
+ t[18] = MUL15(a[ 9], a[ 9])
+ + ((MUL15(a[ 0], a[18])
+ + MUL15(a[ 1], a[17])
+ + MUL15(a[ 2], a[16])
+ + MUL15(a[ 3], a[15])
+ + MUL15(a[ 4], a[14])
+ + MUL15(a[ 5], a[13])
+ + MUL15(a[ 6], a[12])
+ + MUL15(a[ 7], a[11])
+ + MUL15(a[ 8], a[10])) << 1);
+ t[19] = ((MUL15(a[ 0], a[19])
+ + MUL15(a[ 1], a[18])
+ + MUL15(a[ 2], a[17])
+ + MUL15(a[ 3], a[16])
+ + MUL15(a[ 4], a[15])
+ + MUL15(a[ 5], a[14])
+ + MUL15(a[ 6], a[13])
+ + MUL15(a[ 7], a[12])
+ + MUL15(a[ 8], a[11])
+ + MUL15(a[ 9], a[10])) << 1);
+ t[20] = MUL15(a[10], a[10])
+ + ((MUL15(a[ 1], a[19])
+ + MUL15(a[ 2], a[18])
+ + MUL15(a[ 3], a[17])
+ + MUL15(a[ 4], a[16])
+ + MUL15(a[ 5], a[15])
+ + MUL15(a[ 6], a[14])
+ + MUL15(a[ 7], a[13])
+ + MUL15(a[ 8], a[12])
+ + MUL15(a[ 9], a[11])) << 1);
+ t[21] = ((MUL15(a[ 2], a[19])
+ + MUL15(a[ 3], a[18])
+ + MUL15(a[ 4], a[17])
+ + MUL15(a[ 5], a[16])
+ + MUL15(a[ 6], a[15])
+ + MUL15(a[ 7], a[14])
+ + MUL15(a[ 8], a[13])
+ + MUL15(a[ 9], a[12])
+ + MUL15(a[10], a[11])) << 1);
+ t[22] = MUL15(a[11], a[11])
+ + ((MUL15(a[ 3], a[19])
+ + MUL15(a[ 4], a[18])
+ + MUL15(a[ 5], a[17])
+ + MUL15(a[ 6], a[16])
+ + MUL15(a[ 7], a[15])
+ + MUL15(a[ 8], a[14])
+ + MUL15(a[ 9], a[13])
+ + MUL15(a[10], a[12])) << 1);
+ t[23] = ((MUL15(a[ 4], a[19])
+ + MUL15(a[ 5], a[18])
+ + MUL15(a[ 6], a[17])
+ + MUL15(a[ 7], a[16])
+ + MUL15(a[ 8], a[15])
+ + MUL15(a[ 9], a[14])
+ + MUL15(a[10], a[13])
+ + MUL15(a[11], a[12])) << 1);
+ t[24] = MUL15(a[12], a[12])
+ + ((MUL15(a[ 5], a[19])
+ + MUL15(a[ 6], a[18])
+ + MUL15(a[ 7], a[17])
+ + MUL15(a[ 8], a[16])
+ + MUL15(a[ 9], a[15])
+ + MUL15(a[10], a[14])
+ + MUL15(a[11], a[13])) << 1);
+ t[25] = ((MUL15(a[ 6], a[19])
+ + MUL15(a[ 7], a[18])
+ + MUL15(a[ 8], a[17])
+ + MUL15(a[ 9], a[16])
+ + MUL15(a[10], a[15])
+ + MUL15(a[11], a[14])
+ + MUL15(a[12], a[13])) << 1);
+ t[26] = MUL15(a[13], a[13])
+ + ((MUL15(a[ 7], a[19])
+ + MUL15(a[ 8], a[18])
+ + MUL15(a[ 9], a[17])
+ + MUL15(a[10], a[16])
+ + MUL15(a[11], a[15])
+ + MUL15(a[12], a[14])) << 1);
+ t[27] = ((MUL15(a[ 8], a[19])
+ + MUL15(a[ 9], a[18])
+ + MUL15(a[10], a[17])
+ + MUL15(a[11], a[16])
+ + MUL15(a[12], a[15])
+ + MUL15(a[13], a[14])) << 1);
+ t[28] = MUL15(a[14], a[14])
+ + ((MUL15(a[ 9], a[19])
+ + MUL15(a[10], a[18])
+ + MUL15(a[11], a[17])
+ + MUL15(a[12], a[16])
+ + MUL15(a[13], a[15])) << 1);
+ t[29] = ((MUL15(a[10], a[19])
+ + MUL15(a[11], a[18])
+ + MUL15(a[12], a[17])
+ + MUL15(a[13], a[16])
+ + MUL15(a[14], a[15])) << 1);
+ t[30] = MUL15(a[15], a[15])
+ + ((MUL15(a[11], a[19])
+ + MUL15(a[12], a[18])
+ + MUL15(a[13], a[17])
+ + MUL15(a[14], a[16])) << 1);
+ t[31] = ((MUL15(a[12], a[19])
+ + MUL15(a[13], a[18])
+ + MUL15(a[14], a[17])
+ + MUL15(a[15], a[16])) << 1);
+ t[32] = MUL15(a[16], a[16])
+ + ((MUL15(a[13], a[19])
+ + MUL15(a[14], a[18])
+ + MUL15(a[15], a[17])) << 1);
+ t[33] = ((MUL15(a[14], a[19])
+ + MUL15(a[15], a[18])
+ + MUL15(a[16], a[17])) << 1);
+ t[34] = MUL15(a[17], a[17])
+ + ((MUL15(a[15], a[19])
+ + MUL15(a[16], a[18])) << 1);
+ t[35] = ((MUL15(a[16], a[19])
+ + MUL15(a[17], a[18])) << 1);
+ t[36] = MUL15(a[18], a[18])
+ + ((MUL15(a[17], a[19])) << 1);
+ t[37] = ((MUL15(a[18], a[19])) << 1);
+ t[38] = MUL15(a[19], a[19]);
+ d[39] = norm13(d, t, 39);
+}
+
+#endif
+
+/*
+ * Modulus for field F256 (field for point coordinates in curve P-256).
+ */
+static const uint32_t F256[] = {
+ 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x001F,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0400, 0x0000,
+ 0x0000, 0x1FF8, 0x1FFF, 0x01FF
+};
+
+/*
+ * The 'b' curve equation coefficient for P-256.
+ */
+static const uint32_t P256_B[] = {
+ 0x004B, 0x1E93, 0x0F89, 0x1C78, 0x03BC, 0x187B, 0x114E, 0x1619,
+ 0x1D06, 0x0328, 0x01AF, 0x0D31, 0x1557, 0x15DE, 0x1ECF, 0x127C,
+ 0x0A3A, 0x0EC5, 0x118D, 0x00B5
+};
+
+/*
+ * Perform a "short reduction" in field F256 (field for curve P-256).
+ * The source value should be less than 262 bits; on output, it will
+ * be at most 257 bits, and less than twice the modulus.
+ */
+static void
+reduce_f256(uint32_t *d)
+{
+ uint32_t x;
+
+ x = d[19] >> 9;
+ d[19] &= 0x01FF;
+ d[17] += x << 3;
+ d[14] -= x << 10;
+ d[7] -= x << 5;
+ d[0] += x;
+ norm13(d, d, 20);
+}
+
+/*
+ * Perform a "final reduction" in field F256 (field for curve P-256).
+ * The source value must be less than twice the modulus. If the value
+ * is not lower than the modulus, then the modulus is subtracted and
+ * this function returns 1; otherwise, it leaves it untouched and it
+ * returns 0.
+ */
+static uint32_t
+reduce_final_f256(uint32_t *d)
+{
+ uint32_t t[20];
+ uint32_t cc;
+ int i;
+
+ memcpy(t, d, sizeof t);
+ cc = 0;
+ for (i = 0; i < 20; i ++) {
+ uint32_t w;
+
+ w = t[i] - F256[i] - cc;
+ cc = w >> 31;
+ t[i] = w & 0x1FFF;
+ }
+ cc ^= 1;
+ CCOPY(cc, d, t, sizeof t);
+ return cc;
+}
+
+/*
+ * Perform a multiplication of two integers modulo
+ * 2^256-2^224+2^192+2^96-1 (for NIST curve P-256). Operands are arrays
+ * of 20 words, each containing 13 bits of data, in little-endian order.
+ * On input, upper word may be up to 13 bits (hence value up to 2^260-1);
+ * on output, value fits on 257 bits and is lower than twice the modulus.
+ */
+static void
+mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t t[40], cc;
+ int i;
+
+ /*
+ * Compute raw multiplication. All result words fit in 13 bits
+ * each.
+ */
+ mul20(t, a, b);
+
+ /*
+ * Modular reduction: each high word in added/subtracted where
+ * necessary.
+ *
+ * The modulus is:
+ * p = 2^256 - 2^224 + 2^192 + 2^96 - 1
+ * Therefore:
+ * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
+ *
+ * For a word x at bit offset n (n >= 256), we have:
+ * x*2^n = x*2^(n-32) - x*2^(n-64)
+ * - x*2^(n - 160) + x*2^(n-256) mod p
+ *
+ * Thus, we can nullify the high word if we reinject it at some
+ * proper emplacements.
+ */
+ for (i = 39; i >= 20; i --) {
+ uint32_t x;
+
+ x = t[i];
+ t[i - 2] += ARSH(x, 6);
+ t[i - 3] += (x << 7) & 0x1FFF;
+ t[i - 4] -= ARSH(x, 12);
+ t[i - 5] -= (x << 1) & 0x1FFF;
+ t[i - 12] -= ARSH(x, 4);
+ t[i - 13] -= (x << 9) & 0x1FFF;
+ t[i - 19] += ARSH(x, 9);
+ t[i - 20] += (x << 4) & 0x1FFF;
+ }
+
+ /*
+ * Propagate carries. This is a signed propagation, and the
+ * result may be negative. The loop above may enlarge values,
+ * but not two much: worst case is the chain involving t[i - 3],
+ * in which a value may be added to itself up to 7 times. Since
+ * starting values are 13-bit each, all words fit on 20 bits
+ * (21 to account for the sign bit).
+ */
+ cc = norm13(t, t, 20);
+
+ /*
+ * Perform modular reduction again for the bits beyond 256 (the carry
+ * and the bits 256..259). Since the largest shift below is by 10
+ * bits, and the values fit on 21 bits, values fit in 32-bit words,
+ * thereby allowing injecting full word values.
+ */
+ cc = (cc << 4) | (t[19] >> 9);
+ t[19] &= 0x01FF;
+ t[17] += cc << 3;
+ t[14] -= cc << 10;
+ t[7] -= cc << 5;
+ t[0] += cc;
+
+ /*
+ * If the carry is negative, then after carry propagation, we may
+ * end up with a value which is negative, and we don't want that.
+ * Thus, in that case, we add the modulus. Note that the subtraction
+ * result, when the carry is negative, is always smaller than the
+ * modulus, so the extra addition will not make the value exceed
+ * twice the modulus.
+ */
+ cc >>= 31;
+ t[0] -= cc;
+ t[7] += cc << 5;
+ t[14] += cc << 10;
+ t[17] -= cc << 3;
+ t[19] += cc << 9;
+
+ norm13(d, t, 20);
+}
+
+/*
+ * Square an integer modulo 2^256-2^224+2^192+2^96-1 (for NIST curve
+ * P-256). Operand is an array of 20 words, each containing 13 bits of
+ * data, in little-endian order. On input, upper word may be up to 13
+ * bits (hence value up to 2^260-1); on output, value fits on 257 bits
+ * and is lower than twice the modulus.
+ */
+static void
+square_f256(uint32_t *d, const uint32_t *a)
+{
+ uint32_t t[40], cc;
+ int i;
+
+ /*
+ * Compute raw square. All result words fit in 13 bits each.
+ */
+ square20(t, a);
+
+ /*
+ * Modular reduction: each high word in added/subtracted where
+ * necessary.
+ *
+ * The modulus is:
+ * p = 2^256 - 2^224 + 2^192 + 2^96 - 1
+ * Therefore:
+ * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
+ *
+ * For a word x at bit offset n (n >= 256), we have:
+ * x*2^n = x*2^(n-32) - x*2^(n-64)
+ * - x*2^(n - 160) + x*2^(n-256) mod p
+ *
+ * Thus, we can nullify the high word if we reinject it at some
+ * proper emplacements.
+ */
+ for (i = 39; i >= 20; i --) {
+ uint32_t x;
+
+ x = t[i];
+ t[i - 2] += ARSH(x, 6);
+ t[i - 3] += (x << 7) & 0x1FFF;
+ t[i - 4] -= ARSH(x, 12);
+ t[i - 5] -= (x << 1) & 0x1FFF;
+ t[i - 12] -= ARSH(x, 4);
+ t[i - 13] -= (x << 9) & 0x1FFF;
+ t[i - 19] += ARSH(x, 9);
+ t[i - 20] += (x << 4) & 0x1FFF;
+ }
+
+ /*
+ * Propagate carries. This is a signed propagation, and the
+ * result may be negative. The loop above may enlarge values,
+ * but not two much: worst case is the chain involving t[i - 3],
+ * in which a value may be added to itself up to 7 times. Since
+ * starting values are 13-bit each, all words fit on 20 bits
+ * (21 to account for the sign bit).
+ */
+ cc = norm13(t, t, 20);
+
+ /*
+ * Perform modular reduction again for the bits beyond 256 (the carry
+ * and the bits 256..259). Since the largest shift below is by 10
+ * bits, and the values fit on 21 bits, values fit in 32-bit words,
+ * thereby allowing injecting full word values.
+ */
+ cc = (cc << 4) | (t[19] >> 9);
+ t[19] &= 0x01FF;
+ t[17] += cc << 3;
+ t[14] -= cc << 10;
+ t[7] -= cc << 5;
+ t[0] += cc;
+
+ /*
+ * If the carry is negative, then after carry propagation, we may
+ * end up with a value which is negative, and we don't want that.
+ * Thus, in that case, we add the modulus. Note that the subtraction
+ * result, when the carry is negative, is always smaller than the
+ * modulus, so the extra addition will not make the value exceed
+ * twice the modulus.
+ */
+ cc >>= 31;
+ t[0] -= cc;
+ t[7] += cc << 5;
+ t[14] += cc << 10;
+ t[17] -= cc << 3;
+ t[19] += cc << 9;
+
+ norm13(d, t, 20);
+}
+
+/*
+ * Jacobian coordinates for a point in P-256: affine coordinates (X,Y)
+ * are such that:
+ * X = x / z^2
+ * Y = y / z^3
+ * For the point at infinity, z = 0.
+ * Each point thus admits many possible representations.
+ *
+ * Coordinates are represented in arrays of 32-bit integers, each holding
+ * 13 bits of data. Values may also be slightly greater than the modulus,
+ * but they will always be lower than twice the modulus.
+ */
+typedef struct {
+ uint32_t x[20];
+ uint32_t y[20];
+ uint32_t z[20];
+} p256_jacobian;
+
+/*
+ * Convert a point to affine coordinates:
+ * - If the point is the point at infinity, then all three coordinates
+ * are set to 0.
+ * - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y'
+ * coordinates are the 'X' and 'Y' affine coordinates.
+ * The coordinates are guaranteed to be lower than the modulus.
+ */
+static void
+p256_to_affine(p256_jacobian *P)
+{
+ uint32_t t1[20], t2[20];
+ int i;
+
+ /*
+ * Invert z with a modular exponentiation: the modulus is
+ * p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is
+ * p-2. Exponent bit pattern (from high to low) is:
+ * - 32 bits of value 1
+ * - 31 bits of value 0
+ * - 1 bit of value 1
+ * - 96 bits of value 0
+ * - 94 bits of value 1
+ * - 1 bit of value 0
+ * - 1 bit of value 1
+ * Thus, we precompute z^(2^31-1) to speed things up.
+ *
+ * If z = 0 (point at infinity) then the modular exponentiation
+ * will yield 0, which leads to the expected result (all three
+ * coordinates set to 0).
+ */
+
+ /*
+ * A simple square-and-multiply for z^(2^31-1). We could save about
+ * two dozen multiplications here with an addition chain, but
+ * this would require a bit more code, and extra stack buffers.
+ */
+ memcpy(t1, P->z, sizeof P->z);
+ for (i = 0; i < 30; i ++) {
+ square_f256(t1, t1);
+ mul_f256(t1, t1, P->z);
+ }
+
+ /*
+ * Square-and-multiply. Apart from the squarings, we have a few
+ * multiplications to set bits to 1; we multiply by the original z
+ * for setting 1 bit, and by t1 for setting 31 bits.
+ */
+ memcpy(t2, P->z, sizeof P->z);
+ for (i = 1; i < 256; i ++) {
+ square_f256(t2, t2);
+ switch (i) {
+ case 31:
+ case 190:
+ case 221:
+ case 252:
+ mul_f256(t2, t2, t1);
+ break;
+ case 63:
+ case 253:
+ case 255:
+ mul_f256(t2, t2, P->z);
+ break;
+ }
+ }
+
+ /*
+ * Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3.
+ */
+ mul_f256(t1, t2, t2);
+ mul_f256(P->x, t1, P->x);
+ mul_f256(t1, t1, t2);
+ mul_f256(P->y, t1, P->y);
+ reduce_final_f256(P->x);
+ reduce_final_f256(P->y);
+
+ /*
+ * Multiply z by 1/z. If z = 0, then this will yield 0, otherwise
+ * this will set z to 1.
+ */
+ mul_f256(P->z, P->z, t2);
+ reduce_final_f256(P->z);
+}
+
+/*
+ * Double a point in P-256. This function works for all valid points,
+ * including the point at infinity.
+ */
+static void
+p256_double(p256_jacobian *Q)
+{
+ /*
+ * Doubling formulas are:
+ *
+ * s = 4*x*y^2
+ * m = 3*(x + z^2)*(x - z^2)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y^4
+ * z' = 2*y*z
+ *
+ * These formulas work for all points, including points of order 2
+ * and points at infinity:
+ * - If y = 0 then z' = 0. But there is no such point in P-256
+ * anyway.
+ * - If z = 0 then z' = 0.
+ */
+ uint32_t t1[20], t2[20], t3[20], t4[20];
+ int i;
+
+ /*
+ * Compute z^2 in t1.
+ */
+ square_f256(t1, Q->z);
+
+ /*
+ * Compute x-z^2 in t2 and x+z^2 in t1.
+ */
+ for (i = 0; i < 20; i ++) {
+ t2[i] = (F256[i] << 1) + Q->x[i] - t1[i];
+ t1[i] += Q->x[i];
+ }
+ norm13(t1, t1, 20);
+ norm13(t2, t2, 20);
+
+ /*
+ * Compute 3*(x+z^2)*(x-z^2) in t1.
+ */
+ mul_f256(t3, t1, t2);
+ for (i = 0; i < 20; i ++) {
+ t1[i] = MUL15(3, t3[i]);
+ }
+ norm13(t1, t1, 20);
+
+ /*
+ * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
+ */
+ square_f256(t3, Q->y);
+ for (i = 0; i < 20; i ++) {
+ t3[i] <<= 1;
+ }
+ norm13(t3, t3, 20);
+ mul_f256(t2, Q->x, t3);
+ for (i = 0; i < 20; i ++) {
+ t2[i] <<= 1;
+ }
+ norm13(t2, t2, 20);
+ reduce_f256(t2);
+
+ /*
+ * Compute x' = m^2 - 2*s.
+ */
+ square_f256(Q->x, t1);
+ for (i = 0; i < 20; i ++) {
+ Q->x[i] += (F256[i] << 2) - (t2[i] << 1);
+ }
+ norm13(Q->x, Q->x, 20);
+ reduce_f256(Q->x);
+
+ /*
+ * Compute z' = 2*y*z.
+ */
+ mul_f256(t4, Q->y, Q->z);
+ for (i = 0; i < 20; i ++) {
+ Q->z[i] = t4[i] << 1;
+ }
+ norm13(Q->z, Q->z, 20);
+ reduce_f256(Q->z);
+
+ /*
+ * Compute y' = m*(s - x') - 8*y^4. Note that we already have
+ * 2*y^2 in t3.
+ */
+ for (i = 0; i < 20; i ++) {
+ t2[i] += (F256[i] << 1) - Q->x[i];
+ }
+ norm13(t2, t2, 20);
+ mul_f256(Q->y, t1, t2);
+ square_f256(t4, t3);
+ for (i = 0; i < 20; i ++) {
+ Q->y[i] += (F256[i] << 2) - (t4[i] << 1);
+ }
+ norm13(Q->y, Q->y, 20);
+ reduce_f256(Q->y);
+}
+
+/*
+ * Add point P2 to point P1.
+ *
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0 but P2 != 0
+ * - If P1 != 0 but P2 == 0
+ * - If P1 == P2
+ *
+ * In all three cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y coordinate
+ * - P1 == 0 and P2 == 0
+ * - The Y coordinate of one of the points is 0 and the other point is
+ * the point at infinity.
+ *
+ * The third case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ */
+static uint32_t
+p256_add(p256_jacobian *P1, const p256_jacobian *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1 * z2^2
+ * u2 = x2 * z1^2
+ * s1 = y1 * z2^3
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1 * z2
+ */
+ uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20];
+ uint32_t ret;
+ int i;
+
+ /*
+ * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
+ */
+ square_f256(t3, P2->z);
+ mul_f256(t1, P1->x, t3);
+ mul_f256(t4, P2->z, t3);
+ mul_f256(t3, P1->y, t4);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ square_f256(t4, P1->z);
+ mul_f256(t2, P2->x, t4);
+ mul_f256(t5, P1->z, t4);
+ mul_f256(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ for (i = 0; i < 20; i ++) {
+ t2[i] += (F256[i] << 1) - t1[i];
+ t4[i] += (F256[i] << 1) - t3[i];
+ }
+ norm13(t2, t2, 20);
+ norm13(t4, t4, 20);
+ reduce_f256(t4);
+ reduce_final_f256(t4);
+ ret = 0;
+ for (i = 0; i < 20; i ++) {
+ ret |= t4[i];
+ }
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ square_f256(t7, t2);
+ mul_f256(t6, t1, t7);
+ mul_f256(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ square_f256(P1->x, t4);
+ for (i = 0; i < 20; i ++) {
+ P1->x[i] += (F256[i] << 3) - t5[i] - (t6[i] << 1);
+ }
+ norm13(P1->x, P1->x, 20);
+ reduce_f256(P1->x);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ for (i = 0; i < 20; i ++) {
+ t6[i] += (F256[i] << 1) - P1->x[i];
+ }
+ norm13(t6, t6, 20);
+ mul_f256(P1->y, t4, t6);
+ mul_f256(t1, t5, t3);
+ for (i = 0; i < 20; i ++) {
+ P1->y[i] += (F256[i] << 1) - t1[i];
+ }
+ norm13(P1->y, P1->y, 20);
+ reduce_f256(P1->y);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ mul_f256(t1, P1->z, P2->z);
+ mul_f256(P1->z, t1, t2);
+
+ return ret;
+}
+
+/*
+ * Add point P2 to point P1. This is a specialised function for the
+ * case when P2 is a non-zero point in affine coordinate.
+ *
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0
+ * - If P1 == P2
+ *
+ * In both cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y coordinate
+ * - The Y coordinate of P2 is 0 and P1 is the point at infinity.
+ *
+ * The second case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ */
+static uint32_t
+p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1
+ * u2 = x2 * z1^2
+ * s1 = y1
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1
+ */
+ uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20];
+ uint32_t ret;
+ int i;
+
+ /*
+ * Compute u1 = x1 (in t1) and s1 = y1 (in t3).
+ */
+ memcpy(t1, P1->x, sizeof t1);
+ memcpy(t3, P1->y, sizeof t3);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ square_f256(t4, P1->z);
+ mul_f256(t2, P2->x, t4);
+ mul_f256(t5, P1->z, t4);
+ mul_f256(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ for (i = 0; i < 20; i ++) {
+ t2[i] += (F256[i] << 1) - t1[i];
+ t4[i] += (F256[i] << 1) - t3[i];
+ }
+ norm13(t2, t2, 20);
+ norm13(t4, t4, 20);
+ reduce_f256(t4);
+ reduce_final_f256(t4);
+ ret = 0;
+ for (i = 0; i < 20; i ++) {
+ ret |= t4[i];
+ }
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ square_f256(t7, t2);
+ mul_f256(t6, t1, t7);
+ mul_f256(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ square_f256(P1->x, t4);
+ for (i = 0; i < 20; i ++) {
+ P1->x[i] += (F256[i] << 3) - t5[i] - (t6[i] << 1);
+ }
+ norm13(P1->x, P1->x, 20);
+ reduce_f256(P1->x);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ for (i = 0; i < 20; i ++) {
+ t6[i] += (F256[i] << 1) - P1->x[i];
+ }
+ norm13(t6, t6, 20);
+ mul_f256(P1->y, t4, t6);
+ mul_f256(t1, t5, t3);
+ for (i = 0; i < 20; i ++) {
+ P1->y[i] += (F256[i] << 1) - t1[i];
+ }
+ norm13(P1->y, P1->y, 20);
+ reduce_f256(P1->y);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ mul_f256(P1->z, P1->z, t2);
+
+ return ret;
+}
+
+/*
+ * Decode a P-256 point. This function does not support the point at
+ * infinity. Returned value is 0 if the point is invalid, 1 otherwise.
+ */
+static uint32_t
+p256_decode(p256_jacobian *P, const void *src, size_t len)
+{
+ const unsigned char *buf;
+ uint32_t tx[20], ty[20], t1[20], t2[20];
+ uint32_t bad;
+ int i;
+
+ if (len != 65) {
+ return 0;
+ }
+ buf = src;
+
+ /*
+ * First byte must be 0x04 (uncompressed format). We could support
+ * "hybrid format" (first byte is 0x06 or 0x07, and encodes the
+ * least significant bit of the Y coordinate), but it is explicitly
+ * forbidden by RFC 5480 (section 2.2).
+ */
+ bad = NEQ(buf[0], 0x04);
+
+ /*
+ * Decode the coordinates, and check that they are both lower
+ * than the modulus.
+ */
+ tx[19] = be8_to_le13(tx, buf + 1, 32);
+ ty[19] = be8_to_le13(ty, buf + 33, 32);
+ bad |= reduce_final_f256(tx);
+ bad |= reduce_final_f256(ty);
+
+ /*
+ * Check curve equation.
+ */
+ square_f256(t1, tx);
+ mul_f256(t1, tx, t1);
+ square_f256(t2, ty);
+ for (i = 0; i < 20; i ++) {
+ t1[i] += (F256[i] << 3) - MUL15(3, tx[i]) + P256_B[i] - t2[i];
+ }
+ norm13(t1, t1, 20);
+ reduce_f256(t1);
+ reduce_final_f256(t1);
+ for (i = 0; i < 20; i ++) {
+ bad |= t1[i];
+ }
+
+ /*
+ * Copy coordinates to the point structure.
+ */
+ memcpy(P->x, tx, sizeof tx);
+ memcpy(P->y, ty, sizeof ty);
+ memset(P->z, 0, sizeof P->z);
+ P->z[0] = 1;
+ return EQ(bad, 0);
+}
+
+/*
+ * Encode a point into a buffer. This function assumes that the point is
+ * valid, in affine coordinates, and not the point at infinity.
+ */
+static void
+p256_encode(void *dst, const p256_jacobian *P)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ buf[0] = 0x04;
+ le13_to_be8(buf + 1, 32, P->x);
+ le13_to_be8(buf + 33, 32, P->y);
+}
+
+/*
+ * Multiply a curve point by an integer. The integer is assumed to be
+ * lower than the curve order, and the base point must not be the point
+ * at infinity.
+ */
+static void
+p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen)
+{
+ /*
+ * qz is a flag that is initially 1, and remains equal to 1
+ * as long as the point is the point at infinity.
+ *
+ * We use a 2-bit window to handle multiplier bits by pairs.
+ * The precomputed window really is the points P2 and P3.
+ */
+ uint32_t qz;
+ p256_jacobian P2, P3, Q, T, U;
+
+ /*
+ * Compute window values.
+ */
+ P2 = *P;
+ p256_double(&P2);
+ P3 = *P;
+ p256_add(&P3, &P2);
+
+ /*
+ * We start with Q = 0. We process multiplier bits 2 by 2.
+ */
+ memset(&Q, 0, sizeof Q);
+ qz = 1;
+ while (xlen -- > 0) {
+ int k;
+
+ for (k = 6; k >= 0; k -= 2) {
+ uint32_t bits;
+ uint32_t bnz;
+
+ p256_double(&Q);
+ p256_double(&Q);
+ T = *P;
+ U = Q;
+ bits = (*x >> k) & (uint32_t)3;
+ bnz = NEQ(bits, 0);
+ CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
+ CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
+ p256_add(&U, &T);
+ CCOPY(bnz & qz, &Q, &T, sizeof Q);
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ }
+ x ++;
+ }
+ *P = Q;
+}
+
+/*
+ * Precomputed window: k*G points, where G is the curve generator, and k
+ * is an integer from 1 to 15 (inclusive). The X and Y coordinates of
+ * the point are encoded as 20 words of 13 bits each (little-endian
+ * order); 13-bit words are then grouped 2-by-2 into 32-bit words
+ * (little-endian order within each word).
+ */
+static const uint32_t Gwin[15][20] = {
+
+ { 0x04C60296, 0x02721176, 0x19D00F4A, 0x102517AC,
+ 0x13B8037D, 0x0748103C, 0x1E730E56, 0x08481FE2,
+ 0x0F97012C, 0x00D605F4, 0x1DFA11F5, 0x0C801A0D,
+ 0x0F670CBB, 0x0AED0CC5, 0x115E0E33, 0x181F0785,
+ 0x13F514A7, 0x0FF30E3B, 0x17171E1A, 0x009F18D0 },
+
+ { 0x1B341978, 0x16911F11, 0x0D9A1A60, 0x1C4E1FC8,
+ 0x1E040969, 0x096A06B0, 0x091C0030, 0x09EF1A29,
+ 0x18C40D03, 0x00F91C9E, 0x13C313D1, 0x096F0748,
+ 0x011419E0, 0x1CC713A6, 0x1DD31DAD, 0x1EE80C36,
+ 0x1ECD0C69, 0x1A0800A4, 0x08861B8E, 0x000E1DD5 },
+
+ { 0x173F1D6C, 0x02CC06F1, 0x14C21FB4, 0x043D1EB6,
+ 0x0F3606B7, 0x1A971C59, 0x1BF71951, 0x01481323,
+ 0x068D0633, 0x00BD12F9, 0x13EA1032, 0x136209E8,
+ 0x1C1E19A7, 0x06C7013E, 0x06C10AB0, 0x14C908BB,
+ 0x05830CE1, 0x1FEF18DD, 0x00620998, 0x010E0D19 },
+
+ { 0x18180852, 0x0604111A, 0x0B771509, 0x1B6F0156,
+ 0x00181FE2, 0x1DCC0AF4, 0x16EF0659, 0x11F70E80,
+ 0x11A912D0, 0x01C414D2, 0x027618C6, 0x05840FC6,
+ 0x100215C4, 0x187E0C3B, 0x12771C96, 0x150C0B5D,
+ 0x0FF705FD, 0x07981C67, 0x1AD20C63, 0x01C11C55 },
+
+ { 0x1E8113ED, 0x0A940370, 0x12920215, 0x1FA31D6F,
+ 0x1F7C0C82, 0x10CD03F7, 0x02640560, 0x081A0B5E,
+ 0x1BD21151, 0x00A21642, 0x0D0B0DA4, 0x0176113F,
+ 0x04440D1D, 0x001A1360, 0x1068012F, 0x1F141E49,
+ 0x10DF136B, 0x0E4F162B, 0x0D44104A, 0x01C1105F },
+
+ { 0x011411A9, 0x01551A4F, 0x0ADA0C6B, 0x01BD0EC8,
+ 0x18120C74, 0x112F1778, 0x099202CB, 0x0C05124B,
+ 0x195316A4, 0x01600685, 0x1E3B1FE2, 0x189014E3,
+ 0x0B5E1FD7, 0x0E0311F8, 0x08E000F7, 0x174E00DE,
+ 0x160702DF, 0x1B5A15BF, 0x03A11237, 0x01D01704 },
+
+ { 0x0C3D12A3, 0x0C501C0C, 0x17AD1300, 0x1715003F,
+ 0x03F719F8, 0x18031ED8, 0x1D980667, 0x0F681896,
+ 0x1B7D00BF, 0x011C14CE, 0x0FA000B4, 0x1C3501B0,
+ 0x0D901C55, 0x06790C10, 0x029E0736, 0x0DEB0400,
+ 0x034F183A, 0x030619B4, 0x0DEF0033, 0x00E71AC7 },
+
+ { 0x1B7D1393, 0x1B3B1076, 0x0BED1B4D, 0x13011F3A,
+ 0x0E0E1238, 0x156A132B, 0x013A02D3, 0x160A0D01,
+ 0x1CED1EE9, 0x00C5165D, 0x184C157E, 0x08141A83,
+ 0x153C0DA5, 0x1ED70F9D, 0x05170D51, 0x02CF13B8,
+ 0x18AE1771, 0x1B04113F, 0x05EC11E9, 0x015A16B3 },
+
+ { 0x04A41EE0, 0x1D1412E4, 0x1C591D79, 0x118511B7,
+ 0x14F00ACB, 0x1AE31E1C, 0x049C0D51, 0x016E061E,
+ 0x1DB71EDF, 0x01D41A35, 0x0E8208FA, 0x14441293,
+ 0x011F1E85, 0x1D54137A, 0x026B114F, 0x151D0832,
+ 0x00A50964, 0x1F9C1E1C, 0x064B12C9, 0x005409D1 },
+
+ { 0x062B123F, 0x0C0D0501, 0x183704C3, 0x08E31120,
+ 0x0A2E0A6C, 0x14440FED, 0x090A0D1E, 0x13271964,
+ 0x0B590A3A, 0x019D1D9B, 0x05780773, 0x09770A91,
+ 0x0F770CA3, 0x053F19D4, 0x02C80DED, 0x1A761304,
+ 0x091E0DD9, 0x15D201B8, 0x151109AA, 0x010F0198 },
+
+ { 0x05E101D1, 0x072314DD, 0x045F1433, 0x1A041541,
+ 0x10B3142E, 0x01840736, 0x1C1B19DB, 0x098B0418,
+ 0x1DBC083B, 0x007D1444, 0x01511740, 0x11DD1F3A,
+ 0x04ED0E2F, 0x1B4B1A62, 0x10480D04, 0x09E911A2,
+ 0x04211AFA, 0x19140893, 0x04D60CC4, 0x01210648 },
+
+ { 0x112703C4, 0x018B1BA1, 0x164C1D50, 0x05160BE0,
+ 0x0BCC1830, 0x01CB1554, 0x13291732, 0x1B2B1918,
+ 0x0DED0817, 0x00E80775, 0x0A2401D3, 0x0BFE08B3,
+ 0x0E531199, 0x058616E9, 0x04770B91, 0x110F0C55,
+ 0x19C11554, 0x0BFB1159, 0x03541C38, 0x000E1C2D },
+
+ { 0x10390C01, 0x02BB0751, 0x0AC5098E, 0x096C17AB,
+ 0x03C90E28, 0x10BD18BF, 0x002E1F2D, 0x092B0986,
+ 0x1BD700AC, 0x002E1F20, 0x1E3D1FD8, 0x077718BB,
+ 0x06F919C4, 0x187407ED, 0x11370E14, 0x081E139C,
+ 0x00481ADB, 0x14AB0289, 0x066A0EBE, 0x00C70ED6 },
+
+ { 0x0694120B, 0x124E1CC9, 0x0E2F0570, 0x17CF081A,
+ 0x078906AC, 0x066D17CF, 0x1B3207F4, 0x0C5705E9,
+ 0x10001C38, 0x00A919DE, 0x06851375, 0x0F900BD8,
+ 0x080401BA, 0x0EEE0D42, 0x1B8B11EA, 0x0B4519F0,
+ 0x090F18C0, 0x062E1508, 0x0DD909F4, 0x01EB067C },
+
+ { 0x0CDC1D5F, 0x0D1818F9, 0x07781636, 0x125B18E8,
+ 0x0D7003AF, 0x13110099, 0x1D9B1899, 0x175C1EB7,
+ 0x0E34171A, 0x01E01153, 0x081A0F36, 0x0B391783,
+ 0x1D1F147E, 0x19CE16D7, 0x11511B21, 0x1F2C10F9,
+ 0x12CA0E51, 0x05A31D39, 0x171A192E, 0x016B0E4F }
+};
+
+/*
+ * Lookup one of the Gwin[] values, by index. This is constant-time.
+ */
+static void
+lookup_Gwin(p256_jacobian *T, uint32_t idx)
+{
+ uint32_t xy[20];
+ uint32_t k;
+ size_t u;
+
+ memset(xy, 0, sizeof xy);
+ for (k = 0; k < 15; k ++) {
+ uint32_t m;
+
+ m = -EQ(idx, k + 1);
+ for (u = 0; u < 20; u ++) {
+ xy[u] |= m & Gwin[k][u];
+ }
+ }
+ for (u = 0; u < 10; u ++) {
+ T->x[(u << 1) + 0] = xy[u] & 0xFFFF;
+ T->x[(u << 1) + 1] = xy[u] >> 16;
+ T->y[(u << 1) + 0] = xy[u + 10] & 0xFFFF;
+ T->y[(u << 1) + 1] = xy[u + 10] >> 16;
+ }
+ memset(T->z, 0, sizeof T->z);
+ T->z[0] = 1;
+}
+
+/*
+ * Multiply the generator by an integer. The integer is assumed non-zero
+ * and lower than the curve order.
+ */
+static void
+p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen)
+{
+ /*
+ * qz is a flag that is initially 1, and remains equal to 1
+ * as long as the point is the point at infinity.
+ *
+ * We use a 4-bit window to handle multiplier bits by groups
+ * of 4. The precomputed window is constant static data, with
+ * points in affine coordinates; we use a constant-time lookup.
+ */
+ p256_jacobian Q;
+ uint32_t qz;
+
+ memset(&Q, 0, sizeof Q);
+ qz = 1;
+ while (xlen -- > 0) {
+ int k;
+ unsigned bx;
+
+ bx = *x ++;
+ for (k = 0; k < 2; k ++) {
+ uint32_t bits;
+ uint32_t bnz;
+ p256_jacobian T, U;
+
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ bits = (bx >> 4) & 0x0F;
+ bnz = NEQ(bits, 0);
+ lookup_Gwin(&T, bits);
+ U = Q;
+ p256_add_mixed(&U, &T);
+ CCOPY(bnz & qz, &Q, &T, sizeof Q);
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ bx <<= 4;
+ }
+ }
+ *P = Q;
+}
+
+static const unsigned char P256_G[] = {
+ 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
+ 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
+ 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
+ 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
+ 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
+ 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
+ 0x68, 0x37, 0xBF, 0x51, 0xF5
+};
+
+static const unsigned char P256_N[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
+ 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
+ 0x25, 0x51
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_G;
+ return P256_G;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_N;
+ return P256_N;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 1;
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ uint32_t r;
+ p256_jacobian P;
+
+ (void)curve;
+ r = p256_decode(&P, G, Glen);
+ p256_mul(&P, x, xlen);
+ if (Glen >= 65) {
+ p256_to_affine(&P);
+ p256_encode(G, &P);
+ }
+ return r;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ p256_jacobian P;
+
+ (void)curve;
+ p256_mulgen(&P, x, xlen);
+ p256_to_affine(&P);
+ p256_encode(R, &P);
+ return 65;
+
+ /*
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+ */
+}
+
+static uint32_t
+api_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)
+{
+ p256_jacobian P, Q;
+ uint32_t r, t, z;
+ int i;
+
+ (void)curve;
+ r = p256_decode(&P, A, len);
+ p256_mul(&P, x, xlen);
+ if (B == NULL) {
+ p256_mulgen(&Q, y, ylen);
+ } else {
+ r &= p256_decode(&Q, B, len);
+ p256_mul(&Q, y, ylen);
+ }
+
+ /*
+ * The final addition may fail in case both points are equal.
+ */
+ t = p256_add(&P, &Q);
+ reduce_final_f256(P.z);
+ z = 0;
+ for (i = 0; i < 20; i ++) {
+ z |= P.z[i];
+ }
+ z = EQ(z, 0);
+ p256_double(&Q);
+
+ /*
+ * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
+ * have the following:
+ *
+ * z = 0, t = 0 return P (normal addition)
+ * z = 0, t = 1 return P (normal addition)
+ * z = 1, t = 0 return Q (a 'double' case)
+ * z = 1, t = 1 report an error (P+Q = 0)
+ */
+ CCOPY(z & ~t, &P, &Q, sizeof Q);
+ p256_to_affine(&P);
+ p256_encode(A, &P);
+ r &= ~(z & t);
+ return r;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_p256_m15 = {
+ (uint32_t)0x00800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_p256_m15.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_p256_m31.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_p256_m31.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_p256_m31.c (revision 346145)
@@ -0,0 +1,1475 @@
+/*
+ * 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"
+
+/*
+ * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
+ * that right-shifting a signed negative integer copies the sign bit
+ * (arithmetic right-shift). This is "implementation-defined behaviour",
+ * i.e. it is not undefined, but it may differ between compilers. Each
+ * compiler is supposed to document its behaviour in that respect. GCC
+ * explicitly defines that an arithmetic right shift is used. We expect
+ * all other compilers to do the same, because underlying CPU offer an
+ * arithmetic right shift opcode that could not be used otherwise.
+ */
+#if BR_NO_ARITH_SHIFT
+#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
+ | ((-((uint32_t)(x) >> 31)) << (32 - (n))))
+#define ARSHW(x, n) (((uint64_t)(x) >> (n)) \
+ | ((-((uint64_t)(x) >> 63)) << (64 - (n))))
+#else
+#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
+#define ARSHW(x, n) ((*(int64_t *)&(x)) >> (n))
+#endif
+
+/*
+ * Convert an integer from unsigned big-endian encoding to a sequence of
+ * 30-bit words in little-endian order. The final "partial" word is
+ * returned.
+ */
+static uint32_t
+be8_to_le30(uint32_t *dst, const unsigned char *src, size_t len)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ uint32_t b;
+
+ b = src[len];
+ if (acc_len < 22) {
+ acc |= b << acc_len;
+ acc_len += 8;
+ } else {
+ *dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF;
+ acc = b >> (30 - acc_len);
+ acc_len -= 22;
+ }
+ }
+ return acc;
+}
+
+/*
+ * Convert an integer (30-bit words, little-endian) to unsigned
+ * big-endian encoding. The total encoding length is provided; all
+ * the destination bytes will be filled.
+ */
+static void
+le30_to_be8(unsigned char *dst, size_t len, const uint32_t *src)
+{
+ uint32_t acc;
+ int acc_len;
+
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ if (acc_len < 8) {
+ uint32_t w;
+
+ w = *src ++;
+ dst[len] = (unsigned char)(acc | (w << acc_len));
+ acc = w >> (8 - acc_len);
+ acc_len += 22;
+ } else {
+ dst[len] = (unsigned char)acc;
+ acc >>= 8;
+ acc_len -= 8;
+ }
+ }
+}
+
+/*
+ * Multiply two integers. Source integers are represented as arrays of
+ * nine 30-bit words, for values up to 2^270-1. Result is encoded over
+ * 18 words of 30 bits each.
+ */
+static void
+mul9(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ /*
+ * Maximum intermediate result is no more than
+ * 10376293531797946367, which fits in 64 bits. Reason:
+ *
+ * 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406
+ * 10376293531797946367 < 9663676407 * 2^30
+ *
+ * Thus, adding together 9 products of 30-bit integers, with
+ * a carry of at most 9663676406, yields an integer that fits
+ * on 64 bits and generates a carry of at most 9663676406.
+ */
+ uint64_t t[17];
+ uint64_t cc;
+ int i;
+
+ t[ 0] = MUL31(a[0], b[0]);
+ t[ 1] = MUL31(a[0], b[1])
+ + MUL31(a[1], b[0]);
+ t[ 2] = MUL31(a[0], b[2])
+ + MUL31(a[1], b[1])
+ + MUL31(a[2], b[0]);
+ t[ 3] = MUL31(a[0], b[3])
+ + MUL31(a[1], b[2])
+ + MUL31(a[2], b[1])
+ + MUL31(a[3], b[0]);
+ t[ 4] = MUL31(a[0], b[4])
+ + MUL31(a[1], b[3])
+ + MUL31(a[2], b[2])
+ + MUL31(a[3], b[1])
+ + MUL31(a[4], b[0]);
+ t[ 5] = MUL31(a[0], b[5])
+ + MUL31(a[1], b[4])
+ + MUL31(a[2], b[3])
+ + MUL31(a[3], b[2])
+ + MUL31(a[4], b[1])
+ + MUL31(a[5], b[0]);
+ t[ 6] = MUL31(a[0], b[6])
+ + MUL31(a[1], b[5])
+ + MUL31(a[2], b[4])
+ + MUL31(a[3], b[3])
+ + MUL31(a[4], b[2])
+ + MUL31(a[5], b[1])
+ + MUL31(a[6], b[0]);
+ t[ 7] = MUL31(a[0], b[7])
+ + MUL31(a[1], b[6])
+ + MUL31(a[2], b[5])
+ + MUL31(a[3], b[4])
+ + MUL31(a[4], b[3])
+ + MUL31(a[5], b[2])
+ + MUL31(a[6], b[1])
+ + MUL31(a[7], b[0]);
+ t[ 8] = MUL31(a[0], b[8])
+ + MUL31(a[1], b[7])
+ + MUL31(a[2], b[6])
+ + MUL31(a[3], b[5])
+ + MUL31(a[4], b[4])
+ + MUL31(a[5], b[3])
+ + MUL31(a[6], b[2])
+ + MUL31(a[7], b[1])
+ + MUL31(a[8], b[0]);
+ t[ 9] = MUL31(a[1], b[8])
+ + MUL31(a[2], b[7])
+ + MUL31(a[3], b[6])
+ + MUL31(a[4], b[5])
+ + MUL31(a[5], b[4])
+ + MUL31(a[6], b[3])
+ + MUL31(a[7], b[2])
+ + MUL31(a[8], b[1]);
+ t[10] = MUL31(a[2], b[8])
+ + MUL31(a[3], b[7])
+ + MUL31(a[4], b[6])
+ + MUL31(a[5], b[5])
+ + MUL31(a[6], b[4])
+ + MUL31(a[7], b[3])
+ + MUL31(a[8], b[2]);
+ t[11] = MUL31(a[3], b[8])
+ + MUL31(a[4], b[7])
+ + MUL31(a[5], b[6])
+ + MUL31(a[6], b[5])
+ + MUL31(a[7], b[4])
+ + MUL31(a[8], b[3]);
+ t[12] = MUL31(a[4], b[8])
+ + MUL31(a[5], b[7])
+ + MUL31(a[6], b[6])
+ + MUL31(a[7], b[5])
+ + MUL31(a[8], b[4]);
+ t[13] = MUL31(a[5], b[8])
+ + MUL31(a[6], b[7])
+ + MUL31(a[7], b[6])
+ + MUL31(a[8], b[5]);
+ t[14] = MUL31(a[6], b[8])
+ + MUL31(a[7], b[7])
+ + MUL31(a[8], b[6]);
+ t[15] = MUL31(a[7], b[8])
+ + MUL31(a[8], b[7]);
+ t[16] = MUL31(a[8], b[8]);
+
+ /*
+ * Propagate carries.
+ */
+ cc = 0;
+ for (i = 0; i < 17; i ++) {
+ uint64_t w;
+
+ w = t[i] + cc;
+ d[i] = (uint32_t)w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+ d[17] = (uint32_t)cc;
+}
+
+/*
+ * Square a 270-bit integer, represented as an array of nine 30-bit words.
+ * Result uses 18 words of 30 bits each.
+ */
+static void
+square9(uint32_t *d, const uint32_t *a)
+{
+ uint64_t t[17];
+ uint64_t cc;
+ int i;
+
+ t[ 0] = MUL31(a[0], a[0]);
+ t[ 1] = ((MUL31(a[0], a[1])) << 1);
+ t[ 2] = MUL31(a[1], a[1])
+ + ((MUL31(a[0], a[2])) << 1);
+ t[ 3] = ((MUL31(a[0], a[3])
+ + MUL31(a[1], a[2])) << 1);
+ t[ 4] = MUL31(a[2], a[2])
+ + ((MUL31(a[0], a[4])
+ + MUL31(a[1], a[3])) << 1);
+ t[ 5] = ((MUL31(a[0], a[5])
+ + MUL31(a[1], a[4])
+ + MUL31(a[2], a[3])) << 1);
+ t[ 6] = MUL31(a[3], a[3])
+ + ((MUL31(a[0], a[6])
+ + MUL31(a[1], a[5])
+ + MUL31(a[2], a[4])) << 1);
+ t[ 7] = ((MUL31(a[0], a[7])
+ + MUL31(a[1], a[6])
+ + MUL31(a[2], a[5])
+ + MUL31(a[3], a[4])) << 1);
+ t[ 8] = MUL31(a[4], a[4])
+ + ((MUL31(a[0], a[8])
+ + MUL31(a[1], a[7])
+ + MUL31(a[2], a[6])
+ + MUL31(a[3], a[5])) << 1);
+ t[ 9] = ((MUL31(a[1], a[8])
+ + MUL31(a[2], a[7])
+ + MUL31(a[3], a[6])
+ + MUL31(a[4], a[5])) << 1);
+ t[10] = MUL31(a[5], a[5])
+ + ((MUL31(a[2], a[8])
+ + MUL31(a[3], a[7])
+ + MUL31(a[4], a[6])) << 1);
+ t[11] = ((MUL31(a[3], a[8])
+ + MUL31(a[4], a[7])
+ + MUL31(a[5], a[6])) << 1);
+ t[12] = MUL31(a[6], a[6])
+ + ((MUL31(a[4], a[8])
+ + MUL31(a[5], a[7])) << 1);
+ t[13] = ((MUL31(a[5], a[8])
+ + MUL31(a[6], a[7])) << 1);
+ t[14] = MUL31(a[7], a[7])
+ + ((MUL31(a[6], a[8])) << 1);
+ t[15] = ((MUL31(a[7], a[8])) << 1);
+ t[16] = MUL31(a[8], a[8]);
+
+ /*
+ * Propagate carries.
+ */
+ cc = 0;
+ for (i = 0; i < 17; i ++) {
+ uint64_t w;
+
+ w = t[i] + cc;
+ d[i] = (uint32_t)w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+ d[17] = (uint32_t)cc;
+}
+
+/*
+ * Base field modulus for P-256.
+ */
+static const uint32_t F256[] = {
+
+ 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x0000003F, 0x00000000,
+ 0x00000000, 0x00001000, 0x3FFFC000, 0x0000FFFF
+};
+
+/*
+ * The 'b' curve equation coefficient for P-256.
+ */
+static const uint32_t P256_B[] = {
+
+ 0x27D2604B, 0x2F38F0F8, 0x053B0F63, 0x0741AC33, 0x1886BC65,
+ 0x2EF555DA, 0x293E7B3E, 0x0D762A8E, 0x00005AC6
+};
+
+/*
+ * Addition in the field. Source operands shall fit on 257 bits; output
+ * will be lower than twice the modulus.
+ */
+static void
+add_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t w, cc;
+ int i;
+
+ cc = 0;
+ for (i = 0; i < 9; i ++) {
+ w = a[i] + b[i] + cc;
+ d[i] = w & 0x3FFFFFFF;
+ cc = w >> 30;
+ }
+ w >>= 16;
+ d[8] &= 0xFFFF;
+ d[3] -= w << 6;
+ d[6] -= w << 12;
+ d[7] += w << 14;
+ cc = w;
+ for (i = 0; i < 9; i ++) {
+ w = d[i] + cc;
+ d[i] = w & 0x3FFFFFFF;
+ cc = ARSH(w, 30);
+ }
+}
+
+/*
+ * Subtraction in the field. Source operands shall be smaller than twice
+ * the modulus; the result will fulfil the same property.
+ */
+static void
+sub_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t w, cc;
+ int i;
+
+ /*
+ * We really compute a - b + 2*p to make sure that the result is
+ * positive.
+ */
+ w = a[0] - b[0] - 0x00002;
+ d[0] = w & 0x3FFFFFFF;
+ w = a[1] - b[1] + ARSH(w, 30);
+ d[1] = w & 0x3FFFFFFF;
+ w = a[2] - b[2] + ARSH(w, 30);
+ d[2] = w & 0x3FFFFFFF;
+ w = a[3] - b[3] + ARSH(w, 30) + 0x00080;
+ d[3] = w & 0x3FFFFFFF;
+ w = a[4] - b[4] + ARSH(w, 30);
+ d[4] = w & 0x3FFFFFFF;
+ w = a[5] - b[5] + ARSH(w, 30);
+ d[5] = w & 0x3FFFFFFF;
+ w = a[6] - b[6] + ARSH(w, 30) + 0x02000;
+ d[6] = w & 0x3FFFFFFF;
+ w = a[7] - b[7] + ARSH(w, 30) - 0x08000;
+ d[7] = w & 0x3FFFFFFF;
+ w = a[8] - b[8] + ARSH(w, 30) + 0x20000;
+ d[8] = w & 0xFFFF;
+ w >>= 16;
+ d[8] &= 0xFFFF;
+ d[3] -= w << 6;
+ d[6] -= w << 12;
+ d[7] += w << 14;
+ cc = w;
+ for (i = 0; i < 9; i ++) {
+ w = d[i] + cc;
+ d[i] = w & 0x3FFFFFFF;
+ cc = ARSH(w, 30);
+ }
+}
+
+/*
+ * Compute a multiplication in F256. Source operands shall be less than
+ * twice the modulus.
+ */
+static void
+mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ uint32_t t[18];
+ uint64_t s[18];
+ uint64_t cc, x;
+ uint32_t z, c;
+ int i;
+
+ mul9(t, a, b);
+
+ /*
+ * Modular reduction: each high word in added/subtracted where
+ * necessary.
+ *
+ * The modulus is:
+ * p = 2^256 - 2^224 + 2^192 + 2^96 - 1
+ * Therefore:
+ * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
+ *
+ * For a word x at bit offset n (n >= 256), we have:
+ * x*2^n = x*2^(n-32) - x*2^(n-64)
+ * - x*2^(n - 160) + x*2^(n-256) mod p
+ *
+ * Thus, we can nullify the high word if we reinject it at some
+ * proper emplacements.
+ *
+ * We use 64-bit intermediate words to allow for carries to
+ * accumulate easily, before performing the final propagation.
+ */
+ for (i = 0; i < 18; i ++) {
+ s[i] = t[i];
+ }
+
+ for (i = 17; i >= 9; i --) {
+ uint64_t y;
+
+ y = s[i];
+ s[i - 1] += ARSHW(y, 2);
+ s[i - 2] += (y << 28) & 0x3FFFFFFF;
+ s[i - 2] -= ARSHW(y, 4);
+ s[i - 3] -= (y << 26) & 0x3FFFFFFF;
+ s[i - 5] -= ARSHW(y, 10);
+ s[i - 6] -= (y << 20) & 0x3FFFFFFF;
+ s[i - 8] += ARSHW(y, 16);
+ s[i - 9] += (y << 14) & 0x3FFFFFFF;
+ }
+
+ /*
+ * Carry propagation must be signed. Moreover, we may have overdone
+ * it a bit, and obtain a negative result.
+ *
+ * The loop above ran 9 times; each time, each word was augmented
+ * by at most one extra word (in absolute value). Thus, the top
+ * word must in fine fit in 39 bits, so the carry below will fit
+ * on 9 bits.
+ */
+ cc = 0;
+ for (i = 0; i < 9; i ++) {
+ x = s[i] + cc;
+ d[i] = (uint32_t)x & 0x3FFFFFFF;
+ cc = ARSHW(x, 30);
+ }
+
+ /*
+ * All nine words fit on 30 bits, but there may be an extra
+ * carry for a few bits (at most 9), and that carry may be
+ * negative. Moreover, we want the result to fit on 257 bits.
+ * The two lines below ensure that the word in d[] has length
+ * 256 bits, and the (signed) carry (beyond 2^256) is in cc. The
+ * significant length of cc is less than 24 bits, so we will be
+ * able to switch to 32-bit operations.
+ */
+ cc = ARSHW(x, 16);
+ d[8] &= 0xFFFF;
+
+ /*
+ * One extra round of reduction, for cc*2^256, which means
+ * adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative)
+ * value. If cc is negative, then it may happen (rarely, but
+ * not neglectibly so) that the result would be negative. In
+ * order to avoid that, if cc is negative, then we add the
+ * modulus once. Note that if cc is negative, then propagating
+ * that carry must yield a value lower than the modulus, so
+ * adding the modulus once will keep the final result under
+ * twice the modulus.
+ */
+ z = (uint32_t)cc;
+ d[3] -= z << 6;
+ d[6] -= (z << 12) & 0x3FFFFFFF;
+ d[7] -= ARSH(z, 18);
+ d[7] += (z << 14) & 0x3FFFFFFF;
+ d[8] += ARSH(z, 16);
+ c = z >> 31;
+ d[0] -= c;
+ d[3] += c << 6;
+ d[6] += c << 12;
+ d[7] -= c << 14;
+ d[8] += c << 16;
+ for (i = 0; i < 9; i ++) {
+ uint32_t w;
+
+ w = d[i] + z;
+ d[i] = w & 0x3FFFFFFF;
+ z = ARSH(w, 30);
+ }
+}
+
+/*
+ * Compute a square in F256. Source operand shall be less than
+ * twice the modulus.
+ */
+static void
+square_f256(uint32_t *d, const uint32_t *a)
+{
+ uint32_t t[18];
+ uint64_t s[18];
+ uint64_t cc, x;
+ uint32_t z, c;
+ int i;
+
+ square9(t, a);
+
+ /*
+ * Modular reduction: each high word in added/subtracted where
+ * necessary.
+ *
+ * The modulus is:
+ * p = 2^256 - 2^224 + 2^192 + 2^96 - 1
+ * Therefore:
+ * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
+ *
+ * For a word x at bit offset n (n >= 256), we have:
+ * x*2^n = x*2^(n-32) - x*2^(n-64)
+ * - x*2^(n - 160) + x*2^(n-256) mod p
+ *
+ * Thus, we can nullify the high word if we reinject it at some
+ * proper emplacements.
+ *
+ * We use 64-bit intermediate words to allow for carries to
+ * accumulate easily, before performing the final propagation.
+ */
+ for (i = 0; i < 18; i ++) {
+ s[i] = t[i];
+ }
+
+ for (i = 17; i >= 9; i --) {
+ uint64_t y;
+
+ y = s[i];
+ s[i - 1] += ARSHW(y, 2);
+ s[i - 2] += (y << 28) & 0x3FFFFFFF;
+ s[i - 2] -= ARSHW(y, 4);
+ s[i - 3] -= (y << 26) & 0x3FFFFFFF;
+ s[i - 5] -= ARSHW(y, 10);
+ s[i - 6] -= (y << 20) & 0x3FFFFFFF;
+ s[i - 8] += ARSHW(y, 16);
+ s[i - 9] += (y << 14) & 0x3FFFFFFF;
+ }
+
+ /*
+ * Carry propagation must be signed. Moreover, we may have overdone
+ * it a bit, and obtain a negative result.
+ *
+ * The loop above ran 9 times; each time, each word was augmented
+ * by at most one extra word (in absolute value). Thus, the top
+ * word must in fine fit in 39 bits, so the carry below will fit
+ * on 9 bits.
+ */
+ cc = 0;
+ for (i = 0; i < 9; i ++) {
+ x = s[i] + cc;
+ d[i] = (uint32_t)x & 0x3FFFFFFF;
+ cc = ARSHW(x, 30);
+ }
+
+ /*
+ * All nine words fit on 30 bits, but there may be an extra
+ * carry for a few bits (at most 9), and that carry may be
+ * negative. Moreover, we want the result to fit on 257 bits.
+ * The two lines below ensure that the word in d[] has length
+ * 256 bits, and the (signed) carry (beyond 2^256) is in cc. The
+ * significant length of cc is less than 24 bits, so we will be
+ * able to switch to 32-bit operations.
+ */
+ cc = ARSHW(x, 16);
+ d[8] &= 0xFFFF;
+
+ /*
+ * One extra round of reduction, for cc*2^256, which means
+ * adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative)
+ * value. If cc is negative, then it may happen (rarely, but
+ * not neglectibly so) that the result would be negative. In
+ * order to avoid that, if cc is negative, then we add the
+ * modulus once. Note that if cc is negative, then propagating
+ * that carry must yield a value lower than the modulus, so
+ * adding the modulus once will keep the final result under
+ * twice the modulus.
+ */
+ z = (uint32_t)cc;
+ d[3] -= z << 6;
+ d[6] -= (z << 12) & 0x3FFFFFFF;
+ d[7] -= ARSH(z, 18);
+ d[7] += (z << 14) & 0x3FFFFFFF;
+ d[8] += ARSH(z, 16);
+ c = z >> 31;
+ d[0] -= c;
+ d[3] += c << 6;
+ d[6] += c << 12;
+ d[7] -= c << 14;
+ d[8] += c << 16;
+ for (i = 0; i < 9; i ++) {
+ uint32_t w;
+
+ w = d[i] + z;
+ d[i] = w & 0x3FFFFFFF;
+ z = ARSH(w, 30);
+ }
+}
+
+/*
+ * Perform a "final reduction" in field F256 (field for curve P-256).
+ * The source value must be less than twice the modulus. If the value
+ * is not lower than the modulus, then the modulus is subtracted and
+ * this function returns 1; otherwise, it leaves it untouched and it
+ * returns 0.
+ */
+static uint32_t
+reduce_final_f256(uint32_t *d)
+{
+ uint32_t t[9];
+ uint32_t cc;
+ int i;
+
+ cc = 0;
+ for (i = 0; i < 9; i ++) {
+ uint32_t w;
+
+ w = d[i] - F256[i] - cc;
+ cc = w >> 31;
+ t[i] = w & 0x3FFFFFFF;
+ }
+ cc ^= 1;
+ CCOPY(cc, d, t, sizeof t);
+ return cc;
+}
+
+/*
+ * Jacobian coordinates for a point in P-256: affine coordinates (X,Y)
+ * are such that:
+ * X = x / z^2
+ * Y = y / z^3
+ * For the point at infinity, z = 0.
+ * Each point thus admits many possible representations.
+ *
+ * Coordinates are represented in arrays of 32-bit integers, each holding
+ * 30 bits of data. Values may also be slightly greater than the modulus,
+ * but they will always be lower than twice the modulus.
+ */
+typedef struct {
+ uint32_t x[9];
+ uint32_t y[9];
+ uint32_t z[9];
+} p256_jacobian;
+
+/*
+ * Convert a point to affine coordinates:
+ * - If the point is the point at infinity, then all three coordinates
+ * are set to 0.
+ * - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y'
+ * coordinates are the 'X' and 'Y' affine coordinates.
+ * The coordinates are guaranteed to be lower than the modulus.
+ */
+static void
+p256_to_affine(p256_jacobian *P)
+{
+ uint32_t t1[9], t2[9];
+ int i;
+
+ /*
+ * Invert z with a modular exponentiation: the modulus is
+ * p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is
+ * p-2. Exponent bit pattern (from high to low) is:
+ * - 32 bits of value 1
+ * - 31 bits of value 0
+ * - 1 bit of value 1
+ * - 96 bits of value 0
+ * - 94 bits of value 1
+ * - 1 bit of value 0
+ * - 1 bit of value 1
+ * Thus, we precompute z^(2^31-1) to speed things up.
+ *
+ * If z = 0 (point at infinity) then the modular exponentiation
+ * will yield 0, which leads to the expected result (all three
+ * coordinates set to 0).
+ */
+
+ /*
+ * A simple square-and-multiply for z^(2^31-1). We could save about
+ * two dozen multiplications here with an addition chain, but
+ * this would require a bit more code, and extra stack buffers.
+ */
+ memcpy(t1, P->z, sizeof P->z);
+ for (i = 0; i < 30; i ++) {
+ square_f256(t1, t1);
+ mul_f256(t1, t1, P->z);
+ }
+
+ /*
+ * Square-and-multiply. Apart from the squarings, we have a few
+ * multiplications to set bits to 1; we multiply by the original z
+ * for setting 1 bit, and by t1 for setting 31 bits.
+ */
+ memcpy(t2, P->z, sizeof P->z);
+ for (i = 1; i < 256; i ++) {
+ square_f256(t2, t2);
+ switch (i) {
+ case 31:
+ case 190:
+ case 221:
+ case 252:
+ mul_f256(t2, t2, t1);
+ break;
+ case 63:
+ case 253:
+ case 255:
+ mul_f256(t2, t2, P->z);
+ break;
+ }
+ }
+
+ /*
+ * Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3.
+ */
+ mul_f256(t1, t2, t2);
+ mul_f256(P->x, t1, P->x);
+ mul_f256(t1, t1, t2);
+ mul_f256(P->y, t1, P->y);
+ reduce_final_f256(P->x);
+ reduce_final_f256(P->y);
+
+ /*
+ * Multiply z by 1/z. If z = 0, then this will yield 0, otherwise
+ * this will set z to 1.
+ */
+ mul_f256(P->z, P->z, t2);
+ reduce_final_f256(P->z);
+}
+
+/*
+ * Double a point in P-256. This function works for all valid points,
+ * including the point at infinity.
+ */
+static void
+p256_double(p256_jacobian *Q)
+{
+ /*
+ * Doubling formulas are:
+ *
+ * s = 4*x*y^2
+ * m = 3*(x + z^2)*(x - z^2)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y^4
+ * z' = 2*y*z
+ *
+ * These formulas work for all points, including points of order 2
+ * and points at infinity:
+ * - If y = 0 then z' = 0. But there is no such point in P-256
+ * anyway.
+ * - If z = 0 then z' = 0.
+ */
+ uint32_t t1[9], t2[9], t3[9], t4[9];
+
+ /*
+ * Compute z^2 in t1.
+ */
+ square_f256(t1, Q->z);
+
+ /*
+ * Compute x-z^2 in t2 and x+z^2 in t1.
+ */
+ add_f256(t2, Q->x, t1);
+ sub_f256(t1, Q->x, t1);
+
+ /*
+ * Compute 3*(x+z^2)*(x-z^2) in t1.
+ */
+ mul_f256(t3, t1, t2);
+ add_f256(t1, t3, t3);
+ add_f256(t1, t3, t1);
+
+ /*
+ * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
+ */
+ square_f256(t3, Q->y);
+ add_f256(t3, t3, t3);
+ mul_f256(t2, Q->x, t3);
+ add_f256(t2, t2, t2);
+
+ /*
+ * Compute x' = m^2 - 2*s.
+ */
+ square_f256(Q->x, t1);
+ sub_f256(Q->x, Q->x, t2);
+ sub_f256(Q->x, Q->x, t2);
+
+ /*
+ * Compute z' = 2*y*z.
+ */
+ mul_f256(t4, Q->y, Q->z);
+ add_f256(Q->z, t4, t4);
+
+ /*
+ * Compute y' = m*(s - x') - 8*y^4. Note that we already have
+ * 2*y^2 in t3.
+ */
+ sub_f256(t2, t2, Q->x);
+ mul_f256(Q->y, t1, t2);
+ square_f256(t4, t3);
+ add_f256(t4, t4, t4);
+ sub_f256(Q->y, Q->y, t4);
+}
+
+/*
+ * Add point P2 to point P1.
+ *
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0 but P2 != 0
+ * - If P1 != 0 but P2 == 0
+ * - If P1 == P2
+ *
+ * In all three cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y coordinate
+ * - P1 == 0 and P2 == 0
+ * - The Y coordinate of one of the points is 0 and the other point is
+ * the point at infinity.
+ *
+ * The third case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ */
+static uint32_t
+p256_add(p256_jacobian *P1, const p256_jacobian *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1 * z2^2
+ * u2 = x2 * z1^2
+ * s1 = y1 * z2^3
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1 * z2
+ */
+ uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9];
+ uint32_t ret;
+ int i;
+
+ /*
+ * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
+ */
+ square_f256(t3, P2->z);
+ mul_f256(t1, P1->x, t3);
+ mul_f256(t4, P2->z, t3);
+ mul_f256(t3, P1->y, t4);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ square_f256(t4, P1->z);
+ mul_f256(t2, P2->x, t4);
+ mul_f256(t5, P1->z, t4);
+ mul_f256(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ sub_f256(t2, t2, t1);
+ sub_f256(t4, t4, t3);
+ reduce_final_f256(t4);
+ ret = 0;
+ for (i = 0; i < 9; i ++) {
+ ret |= t4[i];
+ }
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ square_f256(t7, t2);
+ mul_f256(t6, t1, t7);
+ mul_f256(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ square_f256(P1->x, t4);
+ sub_f256(P1->x, P1->x, t5);
+ sub_f256(P1->x, P1->x, t6);
+ sub_f256(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ sub_f256(t6, t6, P1->x);
+ mul_f256(P1->y, t4, t6);
+ mul_f256(t1, t5, t3);
+ sub_f256(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ mul_f256(t1, P1->z, P2->z);
+ mul_f256(P1->z, t1, t2);
+
+ return ret;
+}
+
+/*
+ * Add point P2 to point P1. This is a specialised function for the
+ * case when P2 is a non-zero point in affine coordinate.
+ *
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0
+ * - If P1 == P2
+ *
+ * In both cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y coordinate
+ * - The Y coordinate of P2 is 0 and P1 is the point at infinity.
+ *
+ * The second case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ */
+static uint32_t
+p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1
+ * u2 = x2 * z1^2
+ * s1 = y1
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1
+ */
+ uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9];
+ uint32_t ret;
+ int i;
+
+ /*
+ * Compute u1 = x1 (in t1) and s1 = y1 (in t3).
+ */
+ memcpy(t1, P1->x, sizeof t1);
+ memcpy(t3, P1->y, sizeof t3);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ square_f256(t4, P1->z);
+ mul_f256(t2, P2->x, t4);
+ mul_f256(t5, P1->z, t4);
+ mul_f256(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ sub_f256(t2, t2, t1);
+ sub_f256(t4, t4, t3);
+ reduce_final_f256(t4);
+ ret = 0;
+ for (i = 0; i < 9; i ++) {
+ ret |= t4[i];
+ }
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ square_f256(t7, t2);
+ mul_f256(t6, t1, t7);
+ mul_f256(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ square_f256(P1->x, t4);
+ sub_f256(P1->x, P1->x, t5);
+ sub_f256(P1->x, P1->x, t6);
+ sub_f256(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ sub_f256(t6, t6, P1->x);
+ mul_f256(P1->y, t4, t6);
+ mul_f256(t1, t5, t3);
+ sub_f256(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ mul_f256(P1->z, P1->z, t2);
+
+ return ret;
+}
+
+/*
+ * Decode a P-256 point. This function does not support the point at
+ * infinity. Returned value is 0 if the point is invalid, 1 otherwise.
+ */
+static uint32_t
+p256_decode(p256_jacobian *P, const void *src, size_t len)
+{
+ const unsigned char *buf;
+ uint32_t tx[9], ty[9], t1[9], t2[9];
+ uint32_t bad;
+ int i;
+
+ if (len != 65) {
+ return 0;
+ }
+ buf = src;
+
+ /*
+ * First byte must be 0x04 (uncompressed format). We could support
+ * "hybrid format" (first byte is 0x06 or 0x07, and encodes the
+ * least significant bit of the Y coordinate), but it is explicitly
+ * forbidden by RFC 5480 (section 2.2).
+ */
+ bad = NEQ(buf[0], 0x04);
+
+ /*
+ * Decode the coordinates, and check that they are both lower
+ * than the modulus.
+ */
+ tx[8] = be8_to_le30(tx, buf + 1, 32);
+ ty[8] = be8_to_le30(ty, buf + 33, 32);
+ bad |= reduce_final_f256(tx);
+ bad |= reduce_final_f256(ty);
+
+ /*
+ * Check curve equation.
+ */
+ square_f256(t1, tx);
+ mul_f256(t1, tx, t1);
+ square_f256(t2, ty);
+ sub_f256(t1, t1, tx);
+ sub_f256(t1, t1, tx);
+ sub_f256(t1, t1, tx);
+ add_f256(t1, t1, P256_B);
+ sub_f256(t1, t1, t2);
+ reduce_final_f256(t1);
+ for (i = 0; i < 9; i ++) {
+ bad |= t1[i];
+ }
+
+ /*
+ * Copy coordinates to the point structure.
+ */
+ memcpy(P->x, tx, sizeof tx);
+ memcpy(P->y, ty, sizeof ty);
+ memset(P->z, 0, sizeof P->z);
+ P->z[0] = 1;
+ return EQ(bad, 0);
+}
+
+/*
+ * Encode a point into a buffer. This function assumes that the point is
+ * valid, in affine coordinates, and not the point at infinity.
+ */
+static void
+p256_encode(void *dst, const p256_jacobian *P)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ buf[0] = 0x04;
+ le30_to_be8(buf + 1, 32, P->x);
+ le30_to_be8(buf + 33, 32, P->y);
+}
+
+/*
+ * Multiply a curve point by an integer. The integer is assumed to be
+ * lower than the curve order, and the base point must not be the point
+ * at infinity.
+ */
+static void
+p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen)
+{
+ /*
+ * qz is a flag that is initially 1, and remains equal to 1
+ * as long as the point is the point at infinity.
+ *
+ * We use a 2-bit window to handle multiplier bits by pairs.
+ * The precomputed window really is the points P2 and P3.
+ */
+ uint32_t qz;
+ p256_jacobian P2, P3, Q, T, U;
+
+ /*
+ * Compute window values.
+ */
+ P2 = *P;
+ p256_double(&P2);
+ P3 = *P;
+ p256_add(&P3, &P2);
+
+ /*
+ * We start with Q = 0. We process multiplier bits 2 by 2.
+ */
+ memset(&Q, 0, sizeof Q);
+ qz = 1;
+ while (xlen -- > 0) {
+ int k;
+
+ for (k = 6; k >= 0; k -= 2) {
+ uint32_t bits;
+ uint32_t bnz;
+
+ p256_double(&Q);
+ p256_double(&Q);
+ T = *P;
+ U = Q;
+ bits = (*x >> k) & (uint32_t)3;
+ bnz = NEQ(bits, 0);
+ CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
+ CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
+ p256_add(&U, &T);
+ CCOPY(bnz & qz, &Q, &T, sizeof Q);
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ }
+ x ++;
+ }
+ *P = Q;
+}
+
+/*
+ * Precomputed window: k*G points, where G is the curve generator, and k
+ * is an integer from 1 to 15 (inclusive). The X and Y coordinates of
+ * the point are encoded as 9 words of 30 bits each (little-endian
+ * order).
+ */
+static const uint32_t Gwin[15][18] = {
+
+ { 0x1898C296, 0x1284E517, 0x1EB33A0F, 0x00DF604B,
+ 0x2440F277, 0x339B958E, 0x04247F8B, 0x347CB84B,
+ 0x00006B17, 0x37BF51F5, 0x2ED901A0, 0x3315ECEC,
+ 0x338CD5DA, 0x0F9E162B, 0x1FAD29F0, 0x27F9B8EE,
+ 0x10B8BF86, 0x00004FE3 },
+
+ { 0x07669978, 0x182D23F1, 0x3F21B35A, 0x225A789D,
+ 0x351AC3C0, 0x08E00C12, 0x34F7E8A5, 0x1EC62340,
+ 0x00007CF2, 0x227873D1, 0x3812DE74, 0x0E982299,
+ 0x1F6B798F, 0x3430DBBA, 0x366B1A7D, 0x2D040293,
+ 0x154436E3, 0x00000777 },
+
+ { 0x06E7FD6C, 0x2D05986F, 0x3ADA985F, 0x31ADC87B,
+ 0x0BF165E6, 0x1FBE5475, 0x30A44C8F, 0x3934698C,
+ 0x00005ECB, 0x227D5032, 0x29E6C49E, 0x04FB83D9,
+ 0x0AAC0D8E, 0x24A2ECD8, 0x2C1B3869, 0x0FF7E374,
+ 0x19031266, 0x00008734 },
+
+ { 0x2B030852, 0x024C0911, 0x05596EF5, 0x07F8B6DE,
+ 0x262BD003, 0x3779967B, 0x08FBBA02, 0x128D4CB4,
+ 0x0000E253, 0x184ED8C6, 0x310B08FC, 0x30EE0055,
+ 0x3F25B0FC, 0x062D764E, 0x3FB97F6A, 0x33CC719D,
+ 0x15D69318, 0x0000E0F1 },
+
+ { 0x03D033ED, 0x05552837, 0x35BE5242, 0x2320BF47,
+ 0x268FDFEF, 0x13215821, 0x140D2D78, 0x02DE9454,
+ 0x00005159, 0x3DA16DA4, 0x0742ED13, 0x0D80888D,
+ 0x004BC035, 0x0A79260D, 0x06FCDAFE, 0x2727D8AE,
+ 0x1F6A2412, 0x0000E0C1 },
+
+ { 0x3C2291A9, 0x1AC2ABA4, 0x3B215B4C, 0x131D037A,
+ 0x17DDE302, 0x0C90B2E2, 0x0602C92D, 0x05CA9DA9,
+ 0x0000B01A, 0x0FC77FE2, 0x35F1214E, 0x07E16BDF,
+ 0x003DDC07, 0x2703791C, 0x3038B7EE, 0x3DAD56FE,
+ 0x041D0C8D, 0x0000E85C },
+
+ { 0x3187B2A3, 0x0018A1C0, 0x00FEF5B3, 0x3E7E2E2A,
+ 0x01FB607E, 0x2CC199F0, 0x37B4625B, 0x0EDBE82F,
+ 0x00008E53, 0x01F400B4, 0x15786A1B, 0x3041B21C,
+ 0x31CD8CF2, 0x35900053, 0x1A7E0E9B, 0x318366D0,
+ 0x076F780C, 0x000073EB },
+
+ { 0x1B6FB393, 0x13767707, 0x3CE97DBB, 0x348E2603,
+ 0x354CADC1, 0x09D0B4EA, 0x1B053404, 0x1DE76FBA,
+ 0x000062D9, 0x0F09957E, 0x295029A8, 0x3E76A78D,
+ 0x3B547DAE, 0x27CEE0A2, 0x0575DC45, 0x1D8244FF,
+ 0x332F647A, 0x0000AD5A },
+
+ { 0x10949EE0, 0x1E7A292E, 0x06DF8B3D, 0x02B2E30B,
+ 0x31F8729E, 0x24E35475, 0x30B71878, 0x35EDBFB7,
+ 0x0000EA68, 0x0DD048FA, 0x21688929, 0x0DE823FE,
+ 0x1C53FAA9, 0x0EA0C84D, 0x052A592A, 0x1FCE7870,
+ 0x11325CB2, 0x00002A27 },
+
+ { 0x04C5723F, 0x30D81A50, 0x048306E4, 0x329B11C7,
+ 0x223FB545, 0x085347A8, 0x2993E591, 0x1B5ACA8E,
+ 0x0000CEF6, 0x04AF0773, 0x28D2EEA9, 0x2751EEEC,
+ 0x037B4A7F, 0x3B4C1059, 0x08F37674, 0x2AE906E1,
+ 0x18A88A6A, 0x00008786 },
+
+ { 0x34BC21D1, 0x0CCE474D, 0x15048BF4, 0x1D0BB409,
+ 0x021CDA16, 0x20DE76C3, 0x34C59063, 0x04EDE20E,
+ 0x00003ED1, 0x282A3740, 0x0BE3BBF3, 0x29889DAE,
+ 0x03413697, 0x34C68A09, 0x210EBE93, 0x0C8A224C,
+ 0x0826B331, 0x00009099 },
+
+ { 0x0624E3C4, 0x140317BA, 0x2F82C99D, 0x260C0A2C,
+ 0x25D55179, 0x194DCC83, 0x3D95E462, 0x356F6A05,
+ 0x0000741D, 0x0D4481D3, 0x2657FC8B, 0x1BA5CA71,
+ 0x3AE44B0D, 0x07B1548E, 0x0E0D5522, 0x05FDC567,
+ 0x2D1AA70E, 0x00000770 },
+
+ { 0x06072C01, 0x23857675, 0x1EAD58A9, 0x0B8A12D9,
+ 0x1EE2FC79, 0x0177CB61, 0x0495A618, 0x20DEB82B,
+ 0x0000177C, 0x2FC7BFD8, 0x310EEF8B, 0x1FB4DF39,
+ 0x3B8530E8, 0x0F4E7226, 0x0246B6D0, 0x2A558A24,
+ 0x163353AF, 0x000063BB },
+
+ { 0x24D2920B, 0x1C249DCC, 0x2069C5E5, 0x09AB2F9E,
+ 0x36DF3CF1, 0x1991FD0C, 0x062B97A7, 0x1E80070E,
+ 0x000054E7, 0x20D0B375, 0x2E9F20BD, 0x35090081,
+ 0x1C7A9DDC, 0x22E7C371, 0x087E3016, 0x03175421,
+ 0x3C6ECA7D, 0x0000F599 },
+
+ { 0x259B9D5F, 0x0D9A318F, 0x23A0EF16, 0x00EBE4B7,
+ 0x088265AE, 0x2CDE2666, 0x2BAE7ADF, 0x1371A5C6,
+ 0x0000F045, 0x0D034F36, 0x1F967378, 0x1B5FA3F4,
+ 0x0EC8739D, 0x1643E62A, 0x1653947E, 0x22D1F4E6,
+ 0x0FB8D64B, 0x0000B5B9 }
+};
+
+/*
+ * Lookup one of the Gwin[] values, by index. This is constant-time.
+ */
+static void
+lookup_Gwin(p256_jacobian *T, uint32_t idx)
+{
+ uint32_t xy[18];
+ uint32_t k;
+ size_t u;
+
+ memset(xy, 0, sizeof xy);
+ for (k = 0; k < 15; k ++) {
+ uint32_t m;
+
+ m = -EQ(idx, k + 1);
+ for (u = 0; u < 18; u ++) {
+ xy[u] |= m & Gwin[k][u];
+ }
+ }
+ memcpy(T->x, &xy[0], sizeof T->x);
+ memcpy(T->y, &xy[9], sizeof T->y);
+ memset(T->z, 0, sizeof T->z);
+ T->z[0] = 1;
+}
+
+/*
+ * Multiply the generator by an integer. The integer is assumed non-zero
+ * and lower than the curve order.
+ */
+static void
+p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen)
+{
+ /*
+ * qz is a flag that is initially 1, and remains equal to 1
+ * as long as the point is the point at infinity.
+ *
+ * We use a 4-bit window to handle multiplier bits by groups
+ * of 4. The precomputed window is constant static data, with
+ * points in affine coordinates; we use a constant-time lookup.
+ */
+ p256_jacobian Q;
+ uint32_t qz;
+
+ memset(&Q, 0, sizeof Q);
+ qz = 1;
+ while (xlen -- > 0) {
+ int k;
+ unsigned bx;
+
+ bx = *x ++;
+ for (k = 0; k < 2; k ++) {
+ uint32_t bits;
+ uint32_t bnz;
+ p256_jacobian T, U;
+
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ bits = (bx >> 4) & 0x0F;
+ bnz = NEQ(bits, 0);
+ lookup_Gwin(&T, bits);
+ U = Q;
+ p256_add_mixed(&U, &T);
+ CCOPY(bnz & qz, &Q, &T, sizeof Q);
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ bx <<= 4;
+ }
+ }
+ *P = Q;
+}
+
+static const unsigned char P256_G[] = {
+ 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
+ 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
+ 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
+ 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
+ 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
+ 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
+ 0x68, 0x37, 0xBF, 0x51, 0xF5
+};
+
+static const unsigned char P256_N[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
+ 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
+ 0x25, 0x51
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_G;
+ return P256_G;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_N;
+ return P256_N;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 1;
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ uint32_t r;
+ p256_jacobian P;
+
+ (void)curve;
+ r = p256_decode(&P, G, Glen);
+ p256_mul(&P, x, xlen);
+ if (Glen >= 65) {
+ p256_to_affine(&P);
+ p256_encode(G, &P);
+ }
+ return r;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ p256_jacobian P;
+
+ (void)curve;
+ p256_mulgen(&P, x, xlen);
+ p256_to_affine(&P);
+ p256_encode(R, &P);
+ return 65;
+
+ /*
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+ */
+}
+
+static uint32_t
+api_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)
+{
+ p256_jacobian P, Q;
+ uint32_t r, t, z;
+ int i;
+
+ (void)curve;
+ r = p256_decode(&P, A, len);
+ p256_mul(&P, x, xlen);
+ if (B == NULL) {
+ p256_mulgen(&Q, y, ylen);
+ } else {
+ r &= p256_decode(&Q, B, len);
+ p256_mul(&Q, y, ylen);
+ }
+
+ /*
+ * The final addition may fail in case both points are equal.
+ */
+ t = p256_add(&P, &Q);
+ reduce_final_f256(P.z);
+ z = 0;
+ for (i = 0; i < 9; i ++) {
+ z |= P.z[i];
+ }
+ z = EQ(z, 0);
+ p256_double(&Q);
+
+ /*
+ * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
+ * have the following:
+ *
+ * z = 0, t = 0 return P (normal addition)
+ * z = 0, t = 1 return P (normal addition)
+ * z = 1, t = 0 return Q (a 'double' case)
+ * z = 1, t = 1 report an error (P+Q = 0)
+ */
+ CCOPY(z & ~t, &P, &Q, sizeof Q);
+ p256_to_affine(&P);
+ p256_encode(A, &P);
+ r &= ~(z & t);
+ return r;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_p256_m31 = {
+ (uint32_t)0x00800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_p256_m31.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_p256_m62.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_p256_m62.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_p256_m62.c (revision 346145)
@@ -0,0 +1,1765 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+#if BR_UMUL128
+#include <intrin.h>
+#endif
+
+static const unsigned char P256_G[] = {
+ 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
+ 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
+ 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
+ 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
+ 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
+ 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
+ 0x68, 0x37, 0xBF, 0x51, 0xF5
+};
+
+static const unsigned char P256_N[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
+ 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
+ 0x25, 0x51
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_G;
+ return P256_G;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_N;
+ return P256_N;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 1;
+}
+
+/*
+ * A field element is encoded as five 64-bit integers, in basis 2^52.
+ * Limbs may occasionally exceed 2^52.
+ *
+ * A _partially reduced_ value is such that the following hold:
+ * - top limb is less than 2^48 + 2^30
+ * - the other limbs fit on 53 bits each
+ * In particular, such a value is less than twice the modulus p.
+ */
+
+#define BIT(n) ((uint64_t)1 << (n))
+#define MASK48 (BIT(48) - BIT(0))
+#define MASK52 (BIT(52) - BIT(0))
+
+/* R = 2^260 mod p */
+static const uint64_t F256_R[] = {
+ 0x0000000000010, 0xF000000000000, 0xFFFFFFFFFFFFF,
+ 0xFFEFFFFFFFFFF, 0x00000000FFFFF
+};
+
+/* Curve equation is y^2 = x^3 - 3*x + B. This constant is B*R mod p
+ (Montgomery representation of B). */
+static const uint64_t P256_B_MONTY[] = {
+ 0xDF6229C4BDDFD, 0xCA8843090D89C, 0x212ED6ACF005C,
+ 0x83415A220ABF7, 0x0C30061DD4874
+};
+
+/*
+ * Addition in the field. Carry propagation is not performed.
+ * On input, limbs may be up to 63 bits each; on output, they will
+ * be up to one bit more than on input.
+ */
+static inline void
+f256_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+ d[0] = a[0] + b[0];
+ d[1] = a[1] + b[1];
+ d[2] = a[2] + b[2];
+ d[3] = a[3] + b[3];
+ d[4] = a[4] + b[4];
+}
+
+/*
+ * Partially reduce the provided value.
+ * Input: limbs can go up to 61 bits each.
+ * Output: partially reduced.
+ */
+static inline void
+f256_partial_reduce(uint64_t *a)
+{
+ uint64_t w, cc, s;
+
+ /*
+ * Propagate carries.
+ */
+ w = a[0];
+ a[0] = w & MASK52;
+ cc = w >> 52;
+ w = a[1] + cc;
+ a[1] = w & MASK52;
+ cc = w >> 52;
+ w = a[2] + cc;
+ a[2] = w & MASK52;
+ cc = w >> 52;
+ w = a[3] + cc;
+ a[3] = w & MASK52;
+ cc = w >> 52;
+ a[4] += cc;
+
+ s = a[4] >> 48; /* s < 2^14 */
+ a[0] += s; /* a[0] < 2^52 + 2^14 */
+ w = a[1] - (s << 44);
+ a[1] = w & MASK52; /* a[1] < 2^52 */
+ cc = -(w >> 52) & 0xFFF; /* cc < 16 */
+ w = a[2] - cc;
+ a[2] = w & MASK52; /* a[2] < 2^52 */
+ cc = w >> 63; /* cc = 0 or 1 */
+ w = a[3] - cc - (s << 36);
+ a[3] = w & MASK52; /* a[3] < 2^52 */
+ cc = w >> 63; /* cc = 0 or 1 */
+ w = a[4] & MASK48;
+ a[4] = w + (s << 16) - cc; /* a[4] < 2^48 + 2^30 */
+}
+
+/*
+ * Subtraction in the field.
+ * Input: limbs must fit on 60 bits each; in particular, the complete
+ * integer will be less than 2^268 + 2^217.
+ * Output: partially reduced.
+ */
+static inline void
+f256_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+ uint64_t t[5], w, s, cc;
+
+ /*
+ * We compute d = 2^13*p + a - b; this ensures a positive
+ * intermediate value.
+ *
+ * Each individual addition/subtraction may yield a positive or
+ * negative result; thus, we need to handle a signed carry, thus
+ * with sign extension. We prefer not to use signed types (int64_t)
+ * because conversion from unsigned to signed is cumbersome (a
+ * direct cast with the top bit set is undefined behavior; instead,
+ * we have to use pointer aliasing, using the guaranteed properties
+ * of exact-width types, but this requires the compiler to optimize
+ * away the writes and reads from RAM), and right-shifting a
+ * signed negative value is implementation-defined. Therefore,
+ * we use a custom sign extension.
+ */
+
+ w = a[0] - b[0] - BIT(13);
+ t[0] = w & MASK52;
+ cc = w >> 52;
+ cc |= -(cc & BIT(11));
+ w = a[1] - b[1] + cc;
+ t[1] = w & MASK52;
+ cc = w >> 52;
+ cc |= -(cc & BIT(11));
+ w = a[2] - b[2] + cc;
+ t[2] = (w & MASK52) + BIT(5);
+ cc = w >> 52;
+ cc |= -(cc & BIT(11));
+ w = a[3] - b[3] + cc;
+ t[3] = (w & MASK52) + BIT(49);
+ cc = w >> 52;
+ cc |= -(cc & BIT(11));
+ t[4] = (BIT(61) - BIT(29)) + a[4] - b[4] + cc;
+
+ /*
+ * Perform partial reduction. Rule is:
+ * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
+ *
+ * At that point:
+ * 0 <= t[0] <= 2^52 - 1
+ * 0 <= t[1] <= 2^52 - 1
+ * 2^5 <= t[2] <= 2^52 + 2^5 - 1
+ * 2^49 <= t[3] <= 2^52 + 2^49 - 1
+ * 2^59 < t[4] <= 2^61 + 2^60 - 2^29
+ *
+ * Thus, the value 's' (t[4] / 2^48) will be necessarily
+ * greater than 2048, and less than 12288.
+ */
+ s = t[4] >> 48;
+
+ d[0] = t[0] + s; /* d[0] <= 2^52 + 12287 */
+ w = t[1] - (s << 44);
+ d[1] = w & MASK52; /* d[1] <= 2^52 - 1 */
+ cc = -(w >> 52) & 0xFFF; /* cc <= 48 */
+ w = t[2] - cc;
+ cc = w >> 63; /* cc = 0 or 1 */
+ d[2] = w + (cc << 52); /* d[2] <= 2^52 + 31 */
+ w = t[3] - cc - (s << 36);
+ cc = w >> 63; /* cc = 0 or 1 */
+ d[3] = w + (cc << 52); /* t[3] <= 2^52 + 2^49 - 1 */
+ d[4] = (t[4] & MASK48) + (s << 16) - cc; /* d[4] < 2^48 + 2^30 */
+
+ /*
+ * If s = 0, then none of the limbs is modified, and there cannot
+ * be an overflow; if s != 0, then (s << 16) > cc, and there is
+ * no overflow either.
+ */
+}
+
+/*
+ * Montgomery multiplication in the field.
+ * Input: limbs must fit on 56 bits each.
+ * Output: partially reduced.
+ */
+static void
+f256_montymul(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+#if BR_INT128
+
+ int i;
+ uint64_t t[5];
+
+ t[0] = 0;
+ t[1] = 0;
+ t[2] = 0;
+ t[3] = 0;
+ t[4] = 0;
+ for (i = 0; i < 5; i ++) {
+ uint64_t x, f, cc, w, s;
+ unsigned __int128 z;
+
+ /*
+ * Since limbs of a[] and b[] fit on 56 bits each,
+ * each individual product fits on 112 bits. Also,
+ * the factor f fits on 52 bits, so f<<48 fits on
+ * 112 bits too. This guarantees that carries (cc)
+ * will fit on 62 bits, thus no overflow.
+ *
+ * The operations below compute:
+ * t <- (t + x*b + f*p) / 2^64
+ */
+ x = a[i];
+ z = (unsigned __int128)b[0] * (unsigned __int128)x
+ + (unsigned __int128)t[0];
+ f = (uint64_t)z & MASK52;
+ cc = (uint64_t)(z >> 52);
+ z = (unsigned __int128)b[1] * (unsigned __int128)x
+ + (unsigned __int128)t[1] + cc
+ + ((unsigned __int128)f << 44);
+ t[0] = (uint64_t)z & MASK52;
+ cc = (uint64_t)(z >> 52);
+ z = (unsigned __int128)b[2] * (unsigned __int128)x
+ + (unsigned __int128)t[2] + cc;
+ t[1] = (uint64_t)z & MASK52;
+ cc = (uint64_t)(z >> 52);
+ z = (unsigned __int128)b[3] * (unsigned __int128)x
+ + (unsigned __int128)t[3] + cc
+ + ((unsigned __int128)f << 36);
+ t[2] = (uint64_t)z & MASK52;
+ cc = (uint64_t)(z >> 52);
+ z = (unsigned __int128)b[4] * (unsigned __int128)x
+ + (unsigned __int128)t[4] + cc
+ + ((unsigned __int128)f << 48)
+ - ((unsigned __int128)f << 16);
+ t[3] = (uint64_t)z & MASK52;
+ t[4] = (uint64_t)(z >> 52);
+
+ /*
+ * t[4] may be up to 62 bits here; we need to do a
+ * partial reduction. Note that limbs t[0] to t[3]
+ * fit on 52 bits each.
+ */
+ s = t[4] >> 48; /* s < 2^14 */
+ t[0] += s; /* t[0] < 2^52 + 2^14 */
+ w = t[1] - (s << 44);
+ t[1] = w & MASK52; /* t[1] < 2^52 */
+ cc = -(w >> 52) & 0xFFF; /* cc < 16 */
+ w = t[2] - cc;
+ t[2] = w & MASK52; /* t[2] < 2^52 */
+ cc = w >> 63; /* cc = 0 or 1 */
+ w = t[3] - cc - (s << 36);
+ t[3] = w & MASK52; /* t[3] < 2^52 */
+ cc = w >> 63; /* cc = 0 or 1 */
+ w = t[4] & MASK48;
+ t[4] = w + (s << 16) - cc; /* t[4] < 2^48 + 2^30 */
+
+ /*
+ * The final t[4] cannot overflow because cc is 0 or 1,
+ * and cc can be 1 only if s != 0.
+ */
+ }
+
+ d[0] = t[0];
+ d[1] = t[1];
+ d[2] = t[2];
+ d[3] = t[3];
+ d[4] = t[4];
+
+#elif BR_UMUL128
+
+ int i;
+ uint64_t t[5];
+
+ t[0] = 0;
+ t[1] = 0;
+ t[2] = 0;
+ t[3] = 0;
+ t[4] = 0;
+ for (i = 0; i < 5; i ++) {
+ uint64_t x, f, cc, w, s, zh, zl;
+ unsigned char k;
+
+ /*
+ * Since limbs of a[] and b[] fit on 56 bits each,
+ * each individual product fits on 112 bits. Also,
+ * the factor f fits on 52 bits, so f<<48 fits on
+ * 112 bits too. This guarantees that carries (cc)
+ * will fit on 62 bits, thus no overflow.
+ *
+ * The operations below compute:
+ * t <- (t + x*b + f*p) / 2^64
+ */
+ x = a[i];
+ zl = _umul128(b[0], x, &zh);
+ k = _addcarry_u64(0, t[0], zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ f = zl & MASK52;
+ cc = (zl >> 52) | (zh << 12);
+
+ zl = _umul128(b[1], x, &zh);
+ k = _addcarry_u64(0, t[1], zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ k = _addcarry_u64(0, cc, zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ k = _addcarry_u64(0, f << 44, zl, &zl);
+ (void)_addcarry_u64(k, f >> 20, zh, &zh);
+ t[0] = zl & MASK52;
+ cc = (zl >> 52) | (zh << 12);
+
+ zl = _umul128(b[2], x, &zh);
+ k = _addcarry_u64(0, t[2], zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ k = _addcarry_u64(0, cc, zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ t[1] = zl & MASK52;
+ cc = (zl >> 52) | (zh << 12);
+
+ zl = _umul128(b[3], x, &zh);
+ k = _addcarry_u64(0, t[3], zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ k = _addcarry_u64(0, cc, zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ k = _addcarry_u64(0, f << 36, zl, &zl);
+ (void)_addcarry_u64(k, f >> 28, zh, &zh);
+ t[2] = zl & MASK52;
+ cc = (zl >> 52) | (zh << 12);
+
+ zl = _umul128(b[4], x, &zh);
+ k = _addcarry_u64(0, t[4], zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ k = _addcarry_u64(0, cc, zl, &zl);
+ (void)_addcarry_u64(k, 0, zh, &zh);
+ k = _addcarry_u64(0, f << 48, zl, &zl);
+ (void)_addcarry_u64(k, f >> 16, zh, &zh);
+ k = _subborrow_u64(0, zl, f << 16, &zl);
+ (void)_subborrow_u64(k, zh, f >> 48, &zh);
+ t[3] = zl & MASK52;
+ t[4] = (zl >> 52) | (zh << 12);
+
+ /*
+ * t[4] may be up to 62 bits here; we need to do a
+ * partial reduction. Note that limbs t[0] to t[3]
+ * fit on 52 bits each.
+ */
+ s = t[4] >> 48; /* s < 2^14 */
+ t[0] += s; /* t[0] < 2^52 + 2^14 */
+ w = t[1] - (s << 44);
+ t[1] = w & MASK52; /* t[1] < 2^52 */
+ cc = -(w >> 52) & 0xFFF; /* cc < 16 */
+ w = t[2] - cc;
+ t[2] = w & MASK52; /* t[2] < 2^52 */
+ cc = w >> 63; /* cc = 0 or 1 */
+ w = t[3] - cc - (s << 36);
+ t[3] = w & MASK52; /* t[3] < 2^52 */
+ cc = w >> 63; /* cc = 0 or 1 */
+ w = t[4] & MASK48;
+ t[4] = w + (s << 16) - cc; /* t[4] < 2^48 + 2^30 */
+
+ /*
+ * The final t[4] cannot overflow because cc is 0 or 1,
+ * and cc can be 1 only if s != 0.
+ */
+ }
+
+ d[0] = t[0];
+ d[1] = t[1];
+ d[2] = t[2];
+ d[3] = t[3];
+ d[4] = t[4];
+
+#endif
+}
+
+/*
+ * Montgomery squaring in the field; currently a basic wrapper around
+ * multiplication (inline, should be optimized away).
+ * TODO: see if some extra speed can be gained here.
+ */
+static inline void
+f256_montysquare(uint64_t *d, const uint64_t *a)
+{
+ f256_montymul(d, a, a);
+}
+
+/*
+ * Convert to Montgomery representation.
+ */
+static void
+f256_tomonty(uint64_t *d, const uint64_t *a)
+{
+ /*
+ * R2 = 2^520 mod p.
+ * If R = 2^260 mod p, then R2 = R^2 mod p; and the Montgomery
+ * multiplication of a by R2 is: a*R2/R = a*R mod p, i.e. the
+ * conversion to Montgomery representation.
+ */
+ static const uint64_t R2[] = {
+ 0x0000000000300, 0xFFFFFFFF00000, 0xFFFFEFFFFFFFB,
+ 0xFDFFFFFFFFFFF, 0x0000004FFFFFF
+ };
+
+ f256_montymul(d, a, R2);
+}
+
+/*
+ * Convert from Montgomery representation.
+ */
+static void
+f256_frommonty(uint64_t *d, const uint64_t *a)
+{
+ /*
+ * Montgomery multiplication by 1 is division by 2^260 modulo p.
+ */
+ static const uint64_t one[] = { 1, 0, 0, 0, 0 };
+
+ f256_montymul(d, a, one);
+}
+
+/*
+ * Inversion in the field. If the source value is 0 modulo p, then this
+ * returns 0 or p. This function uses Montgomery representation.
+ */
+static void
+f256_invert(uint64_t *d, const uint64_t *a)
+{
+ /*
+ * We compute a^(p-2) mod p. The exponent pattern (from high to
+ * low) is:
+ * - 32 bits of value 1
+ * - 31 bits of value 0
+ * - 1 bit of value 1
+ * - 96 bits of value 0
+ * - 94 bits of value 1
+ * - 1 bit of value 0
+ * - 1 bit of value 1
+ * To speed up the square-and-multiply algorithm, we precompute
+ * a^(2^31-1).
+ */
+
+ uint64_t r[5], t[5];
+ int i;
+
+ memcpy(t, a, sizeof t);
+ for (i = 0; i < 30; i ++) {
+ f256_montysquare(t, t);
+ f256_montymul(t, t, a);
+ }
+
+ memcpy(r, t, sizeof t);
+ for (i = 224; i >= 0; i --) {
+ f256_montysquare(r, r);
+ switch (i) {
+ case 0:
+ case 2:
+ case 192:
+ case 224:
+ f256_montymul(r, r, a);
+ break;
+ case 3:
+ case 34:
+ case 65:
+ f256_montymul(r, r, t);
+ break;
+ }
+ }
+ memcpy(d, r, sizeof r);
+}
+
+/*
+ * Finalize reduction.
+ * Input value should be partially reduced.
+ * On output, limbs a[0] to a[3] fit on 52 bits each, limb a[4] fits
+ * on 48 bits, and the integer is less than p.
+ */
+static inline void
+f256_final_reduce(uint64_t *a)
+{
+ uint64_t r[5], t[5], w, cc;
+ int i;
+
+ /*
+ * Propagate carries to ensure that limbs 0 to 3 fit on 52 bits.
+ */
+ cc = 0;
+ for (i = 0; i < 5; i ++) {
+ w = a[i] + cc;
+ r[i] = w & MASK52;
+ cc = w >> 52;
+ }
+
+ /*
+ * We compute t = r + (2^256 - p) = r + 2^224 - 2^192 - 2^96 + 1.
+ * If t < 2^256, then r < p, and we return r. Otherwise, we
+ * want to return r - p = t - 2^256.
+ */
+
+ /*
+ * Add 2^224 + 1, and propagate carries to ensure that limbs
+ * t[0] to t[3] fit in 52 bits each.
+ */
+ w = r[0] + 1;
+ t[0] = w & MASK52;
+ cc = w >> 52;
+ w = r[1] + cc;
+ t[1] = w & MASK52;
+ cc = w >> 52;
+ w = r[2] + cc;
+ t[2] = w & MASK52;
+ cc = w >> 52;
+ w = r[3] + cc;
+ t[3] = w & MASK52;
+ cc = w >> 52;
+ t[4] = r[4] + cc + BIT(16);
+
+ /*
+ * Subtract 2^192 + 2^96. Since we just added 2^224 + 1, the
+ * result cannot be negative.
+ */
+ w = t[1] - BIT(44);
+ t[1] = w & MASK52;
+ cc = w >> 63;
+ w = t[2] - cc;
+ t[2] = w & MASK52;
+ cc = w >> 63;
+ w = t[3] - BIT(36);
+ t[3] = w & MASK52;
+ cc = w >> 63;
+ t[4] -= cc;
+
+ /*
+ * If the top limb t[4] fits on 48 bits, then r[] is already
+ * in the proper range. Otherwise, t[] is the value to return
+ * (truncated to 256 bits).
+ */
+ cc = -(t[4] >> 48);
+ t[4] &= MASK48;
+ for (i = 0; i < 5; i ++) {
+ a[i] = r[i] ^ (cc & (r[i] ^ t[i]));
+ }
+}
+
+/*
+ * Points in affine and Jacobian coordinates.
+ *
+ * - In affine coordinates, the point-at-infinity cannot be encoded.
+ * - Jacobian coordinates (X,Y,Z) correspond to affine (X/Z^2,Y/Z^3);
+ * if Z = 0 then this is the point-at-infinity.
+ */
+typedef struct {
+ uint64_t x[5];
+ uint64_t y[5];
+} p256_affine;
+
+typedef struct {
+ uint64_t x[5];
+ uint64_t y[5];
+ uint64_t z[5];
+} p256_jacobian;
+
+/*
+ * Decode a field element (unsigned big endian notation).
+ */
+static void
+f256_decode(uint64_t *a, const unsigned char *buf)
+{
+ uint64_t w0, w1, w2, w3;
+
+ w3 = br_dec64be(buf + 0);
+ w2 = br_dec64be(buf + 8);
+ w1 = br_dec64be(buf + 16);
+ w0 = br_dec64be(buf + 24);
+ a[0] = w0 & MASK52;
+ a[1] = ((w0 >> 52) | (w1 << 12)) & MASK52;
+ a[2] = ((w1 >> 40) | (w2 << 24)) & MASK52;
+ a[3] = ((w2 >> 28) | (w3 << 36)) & MASK52;
+ a[4] = w3 >> 16;
+}
+
+/*
+ * Encode a field element (unsigned big endian notation). The field
+ * element MUST be fully reduced.
+ */
+static void
+f256_encode(unsigned char *buf, const uint64_t *a)
+{
+ uint64_t w0, w1, w2, w3;
+
+ w0 = a[0] | (a[1] << 52);
+ w1 = (a[1] >> 12) | (a[2] << 40);
+ w2 = (a[2] >> 24) | (a[3] << 28);
+ w3 = (a[3] >> 36) | (a[4] << 16);
+ br_enc64be(buf + 0, w3);
+ br_enc64be(buf + 8, w2);
+ br_enc64be(buf + 16, w1);
+ br_enc64be(buf + 24, w0);
+}
+
+/*
+ * Decode a point. The returned point is in Jacobian coordinates, but
+ * with z = 1. If the encoding is invalid, or encodes a point which is
+ * not on the curve, or encodes the point at infinity, then this function
+ * returns 0. Otherwise, 1 is returned.
+ *
+ * The buffer is assumed to have length exactly 65 bytes.
+ */
+static uint32_t
+point_decode(p256_jacobian *P, const unsigned char *buf)
+{
+ uint64_t x[5], y[5], t[5], x3[5], tt;
+ uint32_t r;
+
+ /*
+ * Header byte shall be 0x04.
+ */
+ r = EQ(buf[0], 0x04);
+
+ /*
+ * Decode X and Y coordinates, and convert them into
+ * Montgomery representation.
+ */
+ f256_decode(x, buf + 1);
+ f256_decode(y, buf + 33);
+ f256_tomonty(x, x);
+ f256_tomonty(y, y);
+
+ /*
+ * Verify y^2 = x^3 + A*x + B. In curve P-256, A = -3.
+ * Note that the Montgomery representation of 0 is 0. We must
+ * take care to apply the final reduction to make sure we have
+ * 0 and not p.
+ */
+ f256_montysquare(t, y);
+ f256_montysquare(x3, x);
+ f256_montymul(x3, x3, x);
+ f256_sub(t, t, x3);
+ f256_add(t, t, x);
+ f256_add(t, t, x);
+ f256_add(t, t, x);
+ f256_sub(t, t, P256_B_MONTY);
+ f256_final_reduce(t);
+ tt = t[0] | t[1] | t[2] | t[3] | t[4];
+ r &= EQ((uint32_t)(tt | (tt >> 32)), 0);
+
+ /*
+ * Return the point in Jacobian coordinates (and Montgomery
+ * representation).
+ */
+ memcpy(P->x, x, sizeof x);
+ memcpy(P->y, y, sizeof y);
+ memcpy(P->z, F256_R, sizeof F256_R);
+ return r;
+}
+
+/*
+ * Final conversion for a point:
+ * - The point is converted back to affine coordinates.
+ * - Final reduction is performed.
+ * - The point is encoded into the provided buffer.
+ *
+ * If the point is the point-at-infinity, all operations are performed,
+ * but the buffer contents are indeterminate, and 0 is returned. Otherwise,
+ * the encoded point is written in the buffer, and 1 is returned.
+ */
+static uint32_t
+point_encode(unsigned char *buf, const p256_jacobian *P)
+{
+ uint64_t t1[5], t2[5], z;
+
+ /* Set t1 = 1/z^2 and t2 = 1/z^3. */
+ f256_invert(t2, P->z);
+ f256_montysquare(t1, t2);
+ f256_montymul(t2, t2, t1);
+
+ /* Compute affine coordinates x (in t1) and y (in t2). */
+ f256_montymul(t1, P->x, t1);
+ f256_montymul(t2, P->y, t2);
+
+ /* Convert back from Montgomery representation, and finalize
+ reductions. */
+ f256_frommonty(t1, t1);
+ f256_frommonty(t2, t2);
+ f256_final_reduce(t1);
+ f256_final_reduce(t2);
+
+ /* Encode. */
+ buf[0] = 0x04;
+ f256_encode(buf + 1, t1);
+ f256_encode(buf + 33, t2);
+
+ /* Return success if and only if P->z != 0. */
+ z = P->z[0] | P->z[1] | P->z[2] | P->z[3] | P->z[4];
+ return NEQ((uint32_t)(z | z >> 32), 0);
+}
+
+/*
+ * Point doubling in Jacobian coordinates: point P is doubled.
+ * Note: if the source point is the point-at-infinity, then the result is
+ * still the point-at-infinity, which is correct. Moreover, if the three
+ * coordinates were zero, then they still are zero in the returned value.
+ */
+static void
+p256_double(p256_jacobian *P)
+{
+ /*
+ * Doubling formulas are:
+ *
+ * s = 4*x*y^2
+ * m = 3*(x + z^2)*(x - z^2)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y^4
+ * z' = 2*y*z
+ *
+ * These formulas work for all points, including points of order 2
+ * and points at infinity:
+ * - If y = 0 then z' = 0. But there is no such point in P-256
+ * anyway.
+ * - If z = 0 then z' = 0.
+ */
+ uint64_t t1[5], t2[5], t3[5], t4[5];
+
+ /*
+ * Compute z^2 in t1.
+ */
+ f256_montysquare(t1, P->z);
+
+ /*
+ * Compute x-z^2 in t2 and x+z^2 in t1.
+ */
+ f256_add(t2, P->x, t1);
+ f256_sub(t1, P->x, t1);
+
+ /*
+ * Compute 3*(x+z^2)*(x-z^2) in t1.
+ */
+ f256_montymul(t3, t1, t2);
+ f256_add(t1, t3, t3);
+ f256_add(t1, t3, t1);
+
+ /*
+ * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
+ */
+ f256_montysquare(t3, P->y);
+ f256_add(t3, t3, t3);
+ f256_montymul(t2, P->x, t3);
+ f256_add(t2, t2, t2);
+
+ /*
+ * Compute x' = m^2 - 2*s.
+ */
+ f256_montysquare(P->x, t1);
+ f256_sub(P->x, P->x, t2);
+ f256_sub(P->x, P->x, t2);
+
+ /*
+ * Compute z' = 2*y*z.
+ */
+ f256_montymul(t4, P->y, P->z);
+ f256_add(P->z, t4, t4);
+ f256_partial_reduce(P->z);
+
+ /*
+ * Compute y' = m*(s - x') - 8*y^4. Note that we already have
+ * 2*y^2 in t3.
+ */
+ f256_sub(t2, t2, P->x);
+ f256_montymul(P->y, t1, t2);
+ f256_montysquare(t4, t3);
+ f256_add(t4, t4, t4);
+ f256_sub(P->y, P->y, t4);
+}
+
+/*
+ * Point addition (Jacobian coordinates): P1 is replaced with P1+P2.
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0 but P2 != 0
+ * - If P1 != 0 but P2 == 0
+ * - If P1 == P2
+ *
+ * In all three cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y coordinate.
+ * - P1 == 0 and P2 == 0.
+ * - The Y coordinate of one of the points is 0 and the other point is
+ * the point at infinity.
+ *
+ * The third case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ *
+ * Note that you can get a returned value of 0 with a correct result,
+ * e.g. if P1 and P2 have the same Y coordinate, but distinct X coordinates.
+ */
+static uint32_t
+p256_add(p256_jacobian *P1, const p256_jacobian *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1 * z2^2
+ * u2 = x2 * z1^2
+ * s1 = y1 * z2^3
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1 * z2
+ */
+ uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt;
+ uint32_t ret;
+
+ /*
+ * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
+ */
+ f256_montysquare(t3, P2->z);
+ f256_montymul(t1, P1->x, t3);
+ f256_montymul(t4, P2->z, t3);
+ f256_montymul(t3, P1->y, t4);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ f256_montysquare(t4, P1->z);
+ f256_montymul(t2, P2->x, t4);
+ f256_montymul(t5, P1->z, t4);
+ f256_montymul(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ f256_sub(t2, t2, t1);
+ f256_sub(t4, t4, t3);
+ f256_final_reduce(t4);
+ tt = t4[0] | t4[1] | t4[2] | t4[3] | t4[4];
+ ret = (uint32_t)(tt | (tt >> 32));
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ f256_montysquare(t7, t2);
+ f256_montymul(t6, t1, t7);
+ f256_montymul(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ f256_montysquare(P1->x, t4);
+ f256_sub(P1->x, P1->x, t5);
+ f256_sub(P1->x, P1->x, t6);
+ f256_sub(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ f256_sub(t6, t6, P1->x);
+ f256_montymul(P1->y, t4, t6);
+ f256_montymul(t1, t5, t3);
+ f256_sub(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ f256_montymul(t1, P1->z, P2->z);
+ f256_montymul(P1->z, t1, t2);
+
+ return ret;
+}
+
+/*
+ * Point addition (mixed coordinates): P1 is replaced with P1+P2.
+ * This is a specialised function for the case when P2 is a non-zero point
+ * in affine coordinates.
+ *
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0
+ * - If P1 == P2
+ *
+ * In both cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y (affine) coordinate.
+ * - The Y coordinate of P2 is 0 and P1 is the point at infinity.
+ *
+ * The second case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ *
+ * Again, a value of 0 may be returned in some cases where the addition
+ * result is correct.
+ */
+static uint32_t
+p256_add_mixed(p256_jacobian *P1, const p256_affine *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1
+ * u2 = x2 * z1^2
+ * s1 = y1
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1
+ */
+ uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt;
+ uint32_t ret;
+
+ /*
+ * Compute u1 = x1 (in t1) and s1 = y1 (in t3).
+ */
+ memcpy(t1, P1->x, sizeof t1);
+ memcpy(t3, P1->y, sizeof t3);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ f256_montysquare(t4, P1->z);
+ f256_montymul(t2, P2->x, t4);
+ f256_montymul(t5, P1->z, t4);
+ f256_montymul(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ f256_sub(t2, t2, t1);
+ f256_sub(t4, t4, t3);
+ f256_final_reduce(t4);
+ tt = t4[0] | t4[1] | t4[2] | t4[3] | t4[4];
+ ret = (uint32_t)(tt | (tt >> 32));
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ f256_montysquare(t7, t2);
+ f256_montymul(t6, t1, t7);
+ f256_montymul(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ f256_montysquare(P1->x, t4);
+ f256_sub(P1->x, P1->x, t5);
+ f256_sub(P1->x, P1->x, t6);
+ f256_sub(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ f256_sub(t6, t6, P1->x);
+ f256_montymul(P1->y, t4, t6);
+ f256_montymul(t1, t5, t3);
+ f256_sub(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ f256_montymul(P1->z, P1->z, t2);
+
+ return ret;
+}
+
+#if 0
+/* unused */
+/*
+ * Point addition (mixed coordinates, complete): P1 is replaced with P1+P2.
+ * This is a specialised function for the case when P2 is a non-zero point
+ * in affine coordinates.
+ *
+ * This function returns the correct result in all cases.
+ */
+static uint32_t
+p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2)
+{
+ /*
+ * Addtions formulas, in the general case, are:
+ *
+ * u1 = x1
+ * u2 = x2 * z1^2
+ * s1 = y1
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1
+ *
+ * These formulas mishandle the two following cases:
+ *
+ * - If P1 is the point-at-infinity (z1 = 0), then z3 is
+ * incorrectly set to 0.
+ *
+ * - If P1 = P2, then u1 = u2 and s1 = s2, and x3, y3 and z3
+ * are all set to 0.
+ *
+ * However, if P1 + P2 = 0, then u1 = u2 but s1 != s2, and then
+ * we correctly get z3 = 0 (the point-at-infinity).
+ *
+ * To fix the case P1 = 0, we perform at the end a copy of P2
+ * over P1, conditional to z1 = 0.
+ *
+ * For P1 = P2: in that case, both h and r are set to 0, and
+ * we get x3, y3 and z3 equal to 0. We can test for that
+ * occurrence to make a mask which will be all-one if P1 = P2,
+ * or all-zero otherwise; then we can compute the double of P2
+ * and add it, combined with the mask, to (x3,y3,z3).
+ *
+ * Using the doubling formulas in p256_double() on (x2,y2),
+ * simplifying since P2 is affine (i.e. z2 = 1, implicitly),
+ * we get:
+ * s = 4*x2*y2^2
+ * m = 3*(x2 + 1)*(x2 - 1)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y2^4
+ * z' = 2*y2
+ * which requires only 6 multiplications. Added to the 11
+ * multiplications of the normal mixed addition in Jacobian
+ * coordinates, we get a cost of 17 multiplications in total.
+ */
+ uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt, zz;
+ int i;
+
+ /*
+ * Set zz to -1 if P1 is the point at infinity, 0 otherwise.
+ */
+ zz = P1->z[0] | P1->z[1] | P1->z[2] | P1->z[3] | P1->z[4];
+ zz = ((zz | -zz) >> 63) - (uint64_t)1;
+
+ /*
+ * Compute u1 = x1 (in t1) and s1 = y1 (in t3).
+ */
+ memcpy(t1, P1->x, sizeof t1);
+ memcpy(t3, P1->y, sizeof t3);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ f256_montysquare(t4, P1->z);
+ f256_montymul(t2, P2->x, t4);
+ f256_montymul(t5, P1->z, t4);
+ f256_montymul(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * reduce.
+ */
+ f256_sub(t2, t2, t1);
+ f256_sub(t4, t4, t3);
+
+ /*
+ * If both h = 0 and r = 0, then P1 = P2, and we want to set
+ * the mask tt to -1; otherwise, the mask will be 0.
+ */
+ f256_final_reduce(t2);
+ f256_final_reduce(t4);
+ tt = t2[0] | t2[1] | t2[2] | t2[3] | t2[4]
+ | t4[0] | t4[1] | t4[2] | t4[3] | t4[4];
+ tt = ((tt | -tt) >> 63) - (uint64_t)1;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ f256_montysquare(t7, t2);
+ f256_montymul(t6, t1, t7);
+ f256_montymul(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ f256_montysquare(P1->x, t4);
+ f256_sub(P1->x, P1->x, t5);
+ f256_sub(P1->x, P1->x, t6);
+ f256_sub(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ f256_sub(t6, t6, P1->x);
+ f256_montymul(P1->y, t4, t6);
+ f256_montymul(t1, t5, t3);
+ f256_sub(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1.
+ */
+ f256_montymul(P1->z, P1->z, t2);
+
+ /*
+ * The "double" result, in case P1 = P2.
+ */
+
+ /*
+ * Compute z' = 2*y2 (in t1).
+ */
+ f256_add(t1, P2->y, P2->y);
+ f256_partial_reduce(t1);
+
+ /*
+ * Compute 2*(y2^2) (in t2) and s = 4*x2*(y2^2) (in t3).
+ */
+ f256_montysquare(t2, P2->y);
+ f256_add(t2, t2, t2);
+ f256_add(t3, t2, t2);
+ f256_montymul(t3, P2->x, t3);
+
+ /*
+ * Compute m = 3*(x2^2 - 1) (in t4).
+ */
+ f256_montysquare(t4, P2->x);
+ f256_sub(t4, t4, F256_R);
+ f256_add(t5, t4, t4);
+ f256_add(t4, t4, t5);
+
+ /*
+ * Compute x' = m^2 - 2*s (in t5).
+ */
+ f256_montysquare(t5, t4);
+ f256_sub(t5, t3);
+ f256_sub(t5, t3);
+
+ /*
+ * Compute y' = m*(s - x') - 8*y2^4 (in t6).
+ */
+ f256_sub(t6, t3, t5);
+ f256_montymul(t6, t6, t4);
+ f256_montysquare(t7, t2);
+ f256_sub(t6, t6, t7);
+ f256_sub(t6, t6, t7);
+
+ /*
+ * We now have the alternate (doubling) coordinates in (t5,t6,t1).
+ * We combine them with (x3,y3,z3).
+ */
+ for (i = 0; i < 5; i ++) {
+ P1->x[i] |= tt & t5[i];
+ P1->y[i] |= tt & t6[i];
+ P1->z[i] |= tt & t1[i];
+ }
+
+ /*
+ * If P1 = 0, then we get z3 = 0 (which is invalid); if z1 is 0,
+ * then we want to replace the result with a copy of P2. The
+ * test on z1 was done at the start, in the zz mask.
+ */
+ for (i = 0; i < 5; i ++) {
+ P1->x[i] ^= zz & (P1->x[i] ^ P2->x[i]);
+ P1->y[i] ^= zz & (P1->y[i] ^ P2->y[i]);
+ P1->z[i] ^= zz & (P1->z[i] ^ F256_R[i]);
+ }
+}
+#endif
+
+/*
+ * Inner function for computing a point multiplication. A window is
+ * provided, with points 1*P to 15*P in affine coordinates.
+ *
+ * Assumptions:
+ * - All provided points are valid points on the curve.
+ * - Multiplier is non-zero, and smaller than the curve order.
+ * - Everything is in Montgomery representation.
+ */
+static void
+point_mul_inner(p256_jacobian *R, const p256_affine *W,
+ const unsigned char *k, size_t klen)
+{
+ p256_jacobian Q;
+ uint32_t qz;
+
+ memset(&Q, 0, sizeof Q);
+ qz = 1;
+ while (klen -- > 0) {
+ int i;
+ unsigned bk;
+
+ bk = *k ++;
+ for (i = 0; i < 2; i ++) {
+ uint32_t bits;
+ uint32_t bnz;
+ p256_affine T;
+ p256_jacobian U;
+ uint32_t n;
+ int j;
+ uint64_t m;
+
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ bits = (bk >> 4) & 0x0F;
+ bnz = NEQ(bits, 0);
+
+ /*
+ * Lookup point in window. If the bits are 0,
+ * we get something invalid, which is not a
+ * problem because we will use it only if the
+ * bits are non-zero.
+ */
+ memset(&T, 0, sizeof T);
+ for (n = 0; n < 15; n ++) {
+ m = -(uint64_t)EQ(bits, n + 1);
+ T.x[0] |= m & W[n].x[0];
+ T.x[1] |= m & W[n].x[1];
+ T.x[2] |= m & W[n].x[2];
+ T.x[3] |= m & W[n].x[3];
+ T.x[4] |= m & W[n].x[4];
+ T.y[0] |= m & W[n].y[0];
+ T.y[1] |= m & W[n].y[1];
+ T.y[2] |= m & W[n].y[2];
+ T.y[3] |= m & W[n].y[3];
+ T.y[4] |= m & W[n].y[4];
+ }
+
+ U = Q;
+ p256_add_mixed(&U, &T);
+
+ /*
+ * If qz is still 1, then Q was all-zeros, and this
+ * is conserved through p256_double().
+ */
+ m = -(uint64_t)(bnz & qz);
+ for (j = 0; j < 5; j ++) {
+ Q.x[j] ^= m & (Q.x[j] ^ T.x[j]);
+ Q.y[j] ^= m & (Q.y[j] ^ T.y[j]);
+ Q.z[j] ^= m & (Q.z[j] ^ F256_R[j]);
+ }
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ bk <<= 4;
+ }
+ }
+ *R = Q;
+}
+
+/*
+ * Convert a window from Jacobian to affine coordinates. A single
+ * field inversion is used. This function works for windows up to
+ * 32 elements.
+ *
+ * The destination array (aff[]) and the source array (jac[]) may
+ * overlap, provided that the start of aff[] is not after the start of
+ * jac[]. Even if the arrays do _not_ overlap, the source array is
+ * modified.
+ */
+static void
+window_to_affine(p256_affine *aff, p256_jacobian *jac, int num)
+{
+ /*
+ * Convert the window points to affine coordinates. We use the
+ * following trick to mutualize the inversion computation: if
+ * we have z1, z2, z3, and z4, and want to invert all of them,
+ * we compute u = 1/(z1*z2*z3*z4), and then we have:
+ * 1/z1 = u*z2*z3*z4
+ * 1/z2 = u*z1*z3*z4
+ * 1/z3 = u*z1*z2*z4
+ * 1/z4 = u*z1*z2*z3
+ *
+ * The partial products are computed recursively:
+ *
+ * - on input (z_1,z_2), return (z_2,z_1) and z_1*z_2
+ * - on input (z_1,z_2,... z_n):
+ * recurse on (z_1,z_2,... z_(n/2)) -> r1 and m1
+ * recurse on (z_(n/2+1),z_(n/2+2)... z_n) -> r2 and m2
+ * multiply elements of r1 by m2 -> s1
+ * multiply elements of r2 by m1 -> s2
+ * return r1||r2 and m1*m2
+ *
+ * In the example below, we suppose that we have 14 elements.
+ * Let z1, z2,... zE be the 14 values to invert (index noted in
+ * hexadecimal, starting at 1).
+ *
+ * - Depth 1:
+ * swap(z1, z2); z12 = z1*z2
+ * swap(z3, z4); z34 = z3*z4
+ * swap(z5, z6); z56 = z5*z6
+ * swap(z7, z8); z78 = z7*z8
+ * swap(z9, zA); z9A = z9*zA
+ * swap(zB, zC); zBC = zB*zC
+ * swap(zD, zE); zDE = zD*zE
+ *
+ * - Depth 2:
+ * z1 <- z1*z34, z2 <- z2*z34, z3 <- z3*z12, z4 <- z4*z12
+ * z1234 = z12*z34
+ * z5 <- z5*z78, z6 <- z6*z78, z7 <- z7*z56, z8 <- z8*z56
+ * z5678 = z56*z78
+ * z9 <- z9*zBC, zA <- zA*zBC, zB <- zB*z9A, zC <- zC*z9A
+ * z9ABC = z9A*zBC
+ *
+ * - Depth 3:
+ * z1 <- z1*z5678, z2 <- z2*z5678, z3 <- z3*z5678, z4 <- z4*z5678
+ * z5 <- z5*z1234, z6 <- z6*z1234, z7 <- z7*z1234, z8 <- z8*z1234
+ * z12345678 = z1234*z5678
+ * z9 <- z9*zDE, zA <- zA*zDE, zB <- zB*zDE, zC <- zC*zDE
+ * zD <- zD*z9ABC, zE*z9ABC
+ * z9ABCDE = z9ABC*zDE
+ *
+ * - Depth 4:
+ * multiply z1..z8 by z9ABCDE
+ * multiply z9..zE by z12345678
+ * final z = z12345678*z9ABCDE
+ */
+
+ uint64_t z[16][5];
+ int i, k, s;
+#define zt (z[15])
+#define zu (z[14])
+#define zv (z[13])
+
+ /*
+ * First recursion step (pairwise swapping and multiplication).
+ * If there is an odd number of elements, then we "invent" an
+ * extra one with coordinate Z = 1 (in Montgomery representation).
+ */
+ for (i = 0; (i + 1) < num; i += 2) {
+ memcpy(zt, jac[i].z, sizeof zt);
+ memcpy(jac[i].z, jac[i + 1].z, sizeof zt);
+ memcpy(jac[i + 1].z, zt, sizeof zt);
+ f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z);
+ }
+ if ((num & 1) != 0) {
+ memcpy(z[num >> 1], jac[num - 1].z, sizeof zt);
+ memcpy(jac[num - 1].z, F256_R, sizeof F256_R);
+ }
+
+ /*
+ * Perform further recursion steps. At the entry of each step,
+ * the process has been done for groups of 's' points. The
+ * integer k is the log2 of s.
+ */
+ for (k = 1, s = 2; s < num; k ++, s <<= 1) {
+ int n;
+
+ for (i = 0; i < num; i ++) {
+ f256_montymul(jac[i].z, jac[i].z, z[(i >> k) ^ 1]);
+ }
+ n = (num + s - 1) >> k;
+ for (i = 0; i < (n >> 1); i ++) {
+ f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]);
+ }
+ if ((n & 1) != 0) {
+ memmove(z[n >> 1], z[n], sizeof zt);
+ }
+ }
+
+ /*
+ * Invert the final result, and convert all points.
+ */
+ f256_invert(zt, z[0]);
+ for (i = 0; i < num; i ++) {
+ f256_montymul(zv, jac[i].z, zt);
+ f256_montysquare(zu, zv);
+ f256_montymul(zv, zv, zu);
+ f256_montymul(aff[i].x, jac[i].x, zu);
+ f256_montymul(aff[i].y, jac[i].y, zv);
+ }
+}
+
+/*
+ * Multiply the provided point by an integer.
+ * Assumptions:
+ * - Source point is a valid curve point.
+ * - Source point is not the point-at-infinity.
+ * - Integer is not 0, and is lower than the curve order.
+ * If these conditions are not met, then the result is indeterminate
+ * (but the process is still constant-time).
+ */
+static void
+p256_mul(p256_jacobian *P, const unsigned char *k, size_t klen)
+{
+ union {
+ p256_affine aff[15];
+ p256_jacobian jac[15];
+ } window;
+ int i;
+
+ /*
+ * Compute window, in Jacobian coordinates.
+ */
+ window.jac[0] = *P;
+ for (i = 2; i < 16; i ++) {
+ window.jac[i - 1] = window.jac[(i >> 1) - 1];
+ if ((i & 1) == 0) {
+ p256_double(&window.jac[i - 1]);
+ } else {
+ p256_add(&window.jac[i - 1], &window.jac[i >> 1]);
+ }
+ }
+
+ /*
+ * Convert the window points to affine coordinates. Point
+ * window[0] is the source point, already in affine coordinates.
+ */
+ window_to_affine(window.aff, window.jac, 15);
+
+ /*
+ * Perform point multiplication.
+ */
+ point_mul_inner(P, window.aff, k, klen);
+}
+
+/*
+ * Precomputed window for the conventional generator: P256_Gwin[n]
+ * contains (n+1)*G (affine coordinates, in Montgomery representation).
+ */
+static const p256_affine P256_Gwin[] = {
+ {
+ { 0x30D418A9143C1, 0xC4FEDB60179E7, 0x62251075BA95F,
+ 0x5C669FB732B77, 0x08905F76B5375 },
+ { 0x5357CE95560A8, 0x43A19E45CDDF2, 0x21F3258B4AB8E,
+ 0xD8552E88688DD, 0x0571FF18A5885 }
+ },
+ {
+ { 0x46D410DDD64DF, 0x0B433827D8500, 0x1490D9AA6AE3C,
+ 0xA3A832205038D, 0x06BB32E52DCF3 },
+ { 0x48D361BEE1A57, 0xB7B236FF82F36, 0x042DBE152CD7C,
+ 0xA3AA9A8FB0E92, 0x08C577517A5B8 }
+ },
+ {
+ { 0x3F904EEBC1272, 0x9E87D81FBFFAC, 0xCBBC98B027F84,
+ 0x47E46AD77DD87, 0x06936A3FD6FF7 },
+ { 0x5C1FC983A7EBD, 0xC3861FE1AB04C, 0x2EE98E583E47A,
+ 0xC06A88208311A, 0x05F06A2AB587C }
+ },
+ {
+ { 0xB50D46918DCC5, 0xD7623C17374B0, 0x100AF24650A6E,
+ 0x76ABCDAACACE8, 0x077362F591B01 },
+ { 0xF24CE4CBABA68, 0x17AD6F4472D96, 0xDDD22E1762847,
+ 0x862EB6C36DEE5, 0x04B14C39CC5AB }
+ },
+ {
+ { 0x8AAEC45C61F5C, 0x9D4B9537DBE1B, 0x76C20C90EC649,
+ 0x3C7D41CB5AAD0, 0x0907960649052 },
+ { 0x9B4AE7BA4F107, 0xF75EB882BEB30, 0x7A1F6873C568E,
+ 0x915C540A9877E, 0x03A076BB9DD1E }
+ },
+ {
+ { 0x47373E77664A1, 0xF246CEE3E4039, 0x17A3AD55AE744,
+ 0x673C50A961A5B, 0x03074B5964213 },
+ { 0x6220D377E44BA, 0x30DFF14B593D3, 0x639F11299C2B5,
+ 0x75F5424D44CEF, 0x04C9916DEA07F }
+ },
+ {
+ { 0x354EA0173B4F1, 0x3C23C00F70746, 0x23BB082BD2021,
+ 0xE03E43EAAB50C, 0x03BA5119D3123 },
+ { 0xD0303F5B9D4DE, 0x17DA67BDD2847, 0xC941956742F2F,
+ 0x8670F933BDC77, 0x0AEDD9164E240 }
+ },
+ {
+ { 0x4CD19499A78FB, 0x4BF9B345527F1, 0x2CFC6B462AB5C,
+ 0x30CDF90F02AF0, 0x0763891F62652 },
+ { 0xA3A9532D49775, 0xD7F9EBA15F59D, 0x60BBF021E3327,
+ 0xF75C23C7B84BE, 0x06EC12F2C706D }
+ },
+ {
+ { 0x6E8F264E20E8E, 0xC79A7A84175C9, 0xC8EB00ABE6BFE,
+ 0x16A4CC09C0444, 0x005B3081D0C4E },
+ { 0x777AA45F33140, 0xDCE5D45E31EB7, 0xB12F1A56AF7BE,
+ 0xF9B2B6E019A88, 0x086659CDFD835 }
+ },
+ {
+ { 0xDBD19DC21EC8C, 0x94FCF81392C18, 0x250B4998F9868,
+ 0x28EB37D2CD648, 0x0C61C947E4B34 },
+ { 0x407880DD9E767, 0x0C83FBE080C2B, 0x9BE5D2C43A899,
+ 0xAB4EF7D2D6577, 0x08719A555B3B4 }
+ },
+ {
+ { 0x260A6245E4043, 0x53E7FDFE0EA7D, 0xAC1AB59DE4079,
+ 0x072EFF3A4158D, 0x0E7090F1949C9 },
+ { 0x85612B944E886, 0xE857F61C81A76, 0xAD643D250F939,
+ 0x88DAC0DAA891E, 0x089300244125B }
+ },
+ {
+ { 0x1AA7D26977684, 0x58A345A3304B7, 0x37385EABDEDEF,
+ 0x155E409D29DEE, 0x0EE1DF780B83E },
+ { 0x12D91CBB5B437, 0x65A8956370CAC, 0xDE6D66170ED2F,
+ 0xAC9B8228CFA8A, 0x0FF57C95C3238 }
+ },
+ {
+ { 0x25634B2ED7097, 0x9156FD30DCCC4, 0x9E98110E35676,
+ 0x7594CBCD43F55, 0x038477ACC395B },
+ { 0x2B90C00EE17FF, 0xF842ED2E33575, 0x1F5BC16874838,
+ 0x7968CD06422BD, 0x0BC0876AB9E7B }
+ },
+ {
+ { 0xA35BB0CF664AF, 0x68F9707E3A242, 0x832660126E48F,
+ 0x72D2717BF54C6, 0x0AAE7333ED12C },
+ { 0x2DB7995D586B1, 0xE732237C227B5, 0x65E7DBBE29569,
+ 0xBBBD8E4193E2A, 0x052706DC3EAA1 }
+ },
+ {
+ { 0xD8B7BC60055BE, 0xD76E27E4B72BC, 0x81937003CC23E,
+ 0xA090E337424E4, 0x02AA0E43EAD3D },
+ { 0x524F6383C45D2, 0x422A41B2540B8, 0x8A4797D766355,
+ 0xDF444EFA6DE77, 0x0042170A9079A }
+ },
+};
+
+/*
+ * Multiply the conventional generator of the curve by the provided
+ * integer. Return is written in *P.
+ *
+ * Assumptions:
+ * - Integer is not 0, and is lower than the curve order.
+ * If this conditions is not met, then the result is indeterminate
+ * (but the process is still constant-time).
+ */
+static void
+p256_mulgen(p256_jacobian *P, const unsigned char *k, size_t klen)
+{
+ point_mul_inner(P, P256_Gwin, k, klen);
+}
+
+/*
+ * Return 1 if all of the following hold:
+ * - klen <= 32
+ * - k != 0
+ * - k is lower than the curve order
+ * Otherwise, return 0.
+ *
+ * Constant-time behaviour: only klen may be observable.
+ */
+static uint32_t
+check_scalar(const unsigned char *k, size_t klen)
+{
+ uint32_t z;
+ int32_t c;
+ size_t u;
+
+ if (klen > 32) {
+ return 0;
+ }
+ z = 0;
+ for (u = 0; u < klen; u ++) {
+ z |= k[u];
+ }
+ if (klen == 32) {
+ c = 0;
+ for (u = 0; u < klen; u ++) {
+ c |= -(int32_t)EQ0(c) & CMP(k[u], P256_N[u]);
+ }
+ } else {
+ c = -1;
+ }
+ return NEQ(z, 0) & LT0(c);
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *k, size_t klen, int curve)
+{
+ uint32_t r;
+ p256_jacobian P;
+
+ (void)curve;
+ if (Glen != 65) {
+ return 0;
+ }
+ r = check_scalar(k, klen);
+ r &= point_decode(&P, G);
+ p256_mul(&P, k, klen);
+ r &= point_encode(G, &P);
+ return r;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *k, size_t klen, int curve)
+{
+ p256_jacobian P;
+
+ (void)curve;
+ p256_mulgen(&P, k, klen);
+ point_encode(R, &P);
+ return 65;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We might want to use Shamir's trick here: make a composite
+ * window of u*P+v*Q points, to merge the two doubling-ladders
+ * into one. This, however, has some complications:
+ *
+ * - During the computation, we may hit the point-at-infinity.
+ * Thus, we would need p256_add_complete_mixed() (complete
+ * formulas for point addition), with a higher cost (17 muls
+ * instead of 11).
+ *
+ * - A 4-bit window would be too large, since it would involve
+ * 16*16-1 = 255 points. For the same window size as in the
+ * p256_mul() case, we would need to reduce the window size
+ * to 2 bits, and thus perform twice as many non-doubling
+ * point additions.
+ *
+ * - The window may itself contain the point-at-infinity, and
+ * thus cannot be in all generality be made of affine points.
+ * Instead, we would need to make it a window of points in
+ * Jacobian coordinates. Even p256_add_complete_mixed() would
+ * be inappropriate.
+ *
+ * For these reasons, the code below performs two separate
+ * point multiplications, then computes the final point addition
+ * (which is both a "normal" addition, and a doubling, to handle
+ * all cases).
+ */
+
+ p256_jacobian P, Q;
+ uint32_t r, t, s;
+ uint64_t z;
+
+ (void)curve;
+ if (len != 65) {
+ return 0;
+ }
+ r = point_decode(&P, A);
+ p256_mul(&P, x, xlen);
+ if (B == NULL) {
+ p256_mulgen(&Q, y, ylen);
+ } else {
+ r &= point_decode(&Q, B);
+ p256_mul(&Q, y, ylen);
+ }
+
+ /*
+ * The final addition may fail in case both points are equal.
+ */
+ t = p256_add(&P, &Q);
+ f256_final_reduce(P.z);
+ z = P.z[0] | P.z[1] | P.z[2] | P.z[3] | P.z[4];
+ s = EQ((uint32_t)(z | (z >> 32)), 0);
+ p256_double(&Q);
+
+ /*
+ * If s is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
+ * have the following:
+ *
+ * s = 0, t = 0 return P (normal addition)
+ * s = 0, t = 1 return P (normal addition)
+ * s = 1, t = 0 return Q (a 'double' case)
+ * s = 1, t = 1 report an error (P+Q = 0)
+ */
+ CCOPY(s & ~t, &P, &Q, sizeof Q);
+ point_encode(A, &P);
+ r &= ~(s & t);
+ return r;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_p256_m62 = {
+ (uint32_t)0x00800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_p256_m62_get(void)
+{
+ return &br_ec_p256_m62;
+}
+
+#else
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_p256_m62_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/ec/ec_p256_m62.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_p256_m64.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_p256_m64.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_p256_m64.c (revision 346145)
@@ -0,0 +1,1730 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+#if BR_UMUL128
+#include <intrin.h>
+#endif
+
+static const unsigned char P256_G[] = {
+ 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
+ 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
+ 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
+ 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
+ 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
+ 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
+ 0x68, 0x37, 0xBF, 0x51, 0xF5
+};
+
+static const unsigned char P256_N[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
+ 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
+ 0x25, 0x51
+};
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_G;
+ return P256_G;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ (void)curve;
+ *len = sizeof P256_N;
+ return P256_N;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ (void)curve;
+ *len = 32;
+ return 1;
+}
+
+/*
+ * A field element is encoded as four 64-bit integers, in basis 2^64.
+ * Values may reach up to 2^256-1. Montgomery multiplication is used.
+ */
+
+/* R = 2^256 mod p */
+static const uint64_t F256_R[] = {
+ 0x0000000000000001, 0xFFFFFFFF00000000,
+ 0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFE
+};
+
+/* Curve equation is y^2 = x^3 - 3*x + B. This constant is B*R mod p
+ (Montgomery representation of B). */
+static const uint64_t P256_B_MONTY[] = {
+ 0xD89CDF6229C4BDDF, 0xACF005CD78843090,
+ 0xE5A220ABF7212ED6, 0xDC30061D04874834
+};
+
+/*
+ * Addition in the field.
+ */
+static inline void
+f256_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+#if BR_INT128
+ unsigned __int128 w;
+ uint64_t t;
+
+ w = (unsigned __int128)a[0] + b[0];
+ d[0] = (uint64_t)w;
+ w = (unsigned __int128)a[1] + b[1] + (w >> 64);
+ d[1] = (uint64_t)w;
+ w = (unsigned __int128)a[2] + b[2] + (w >> 64);
+ d[2] = (uint64_t)w;
+ w = (unsigned __int128)a[3] + b[3] + (w >> 64);
+ d[3] = (uint64_t)w;
+ t = (uint64_t)(w >> 64);
+
+ /*
+ * 2^256 = 2^224 - 2^192 - 2^96 + 1 in the field.
+ */
+ w = (unsigned __int128)d[0] + t;
+ d[0] = (uint64_t)w;
+ w = (unsigned __int128)d[1] + (w >> 64) - (t << 32);
+ d[1] = (uint64_t)w;
+ /* Here, carry "w >> 64" can only be 0 or -1 */
+ w = (unsigned __int128)d[2] - ((w >> 64) & 1);
+ d[2] = (uint64_t)w;
+ /* Again, carry is 0 or -1 */
+ d[3] += (uint64_t)(w >> 64) + (t << 32) - t;
+
+#elif BR_UMUL128
+
+ unsigned char cc;
+ uint64_t t;
+
+ cc = _addcarry_u64(0, a[0], b[0], &d[0]);
+ cc = _addcarry_u64(cc, a[1], b[1], &d[1]);
+ cc = _addcarry_u64(cc, a[2], b[2], &d[2]);
+ cc = _addcarry_u64(cc, a[3], b[3], &d[3]);
+
+ /*
+ * If there is a carry, then we want to subtract p, which we
+ * do by adding 2^256 - p.
+ */
+ t = cc;
+ cc = _addcarry_u64(cc, d[0], 0, &d[0]);
+ cc = _addcarry_u64(cc, d[1], -(t << 32), &d[1]);
+ cc = _addcarry_u64(cc, d[2], -t, &d[2]);
+ (void)_addcarry_u64(cc, d[3], (t << 32) - (t << 1), &d[3]);
+
+#endif
+}
+
+/*
+ * Subtraction in the field.
+ */
+static inline void
+f256_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+#if BR_INT128
+
+ unsigned __int128 w;
+ uint64_t t;
+
+ w = (unsigned __int128)a[0] - b[0];
+ d[0] = (uint64_t)w;
+ w = (unsigned __int128)a[1] - b[1] - ((w >> 64) & 1);
+ d[1] = (uint64_t)w;
+ w = (unsigned __int128)a[2] - b[2] - ((w >> 64) & 1);
+ d[2] = (uint64_t)w;
+ w = (unsigned __int128)a[3] - b[3] - ((w >> 64) & 1);
+ d[3] = (uint64_t)w;
+ t = (uint64_t)(w >> 64) & 1;
+
+ /*
+ * p = 2^256 - 2^224 + 2^192 + 2^96 - 1.
+ */
+ w = (unsigned __int128)d[0] - t;
+ d[0] = (uint64_t)w;
+ w = (unsigned __int128)d[1] + (t << 32) - ((w >> 64) & 1);
+ d[1] = (uint64_t)w;
+ /* Here, carry "w >> 64" can only be 0 or +1 */
+ w = (unsigned __int128)d[2] + (w >> 64);
+ d[2] = (uint64_t)w;
+ /* Again, carry is 0 or +1 */
+ d[3] += (uint64_t)(w >> 64) - (t << 32) + t;
+
+#elif BR_UMUL128
+
+ unsigned char cc;
+ uint64_t t;
+
+ cc = _subborrow_u64(0, a[0], b[0], &d[0]);
+ cc = _subborrow_u64(cc, a[1], b[1], &d[1]);
+ cc = _subborrow_u64(cc, a[2], b[2], &d[2]);
+ cc = _subborrow_u64(cc, a[3], b[3], &d[3]);
+
+ /*
+ * If there is a carry, then we need to add p.
+ */
+ t = cc;
+ cc = _addcarry_u64(0, d[0], -t, &d[0]);
+ cc = _addcarry_u64(cc, d[1], (-t) >> 32, &d[1]);
+ cc = _addcarry_u64(cc, d[2], 0, &d[2]);
+ (void)_addcarry_u64(cc, d[3], t - (t << 32), &d[3]);
+
+#endif
+}
+
+/*
+ * Montgomery multiplication in the field.
+ */
+static void
+f256_montymul(uint64_t *d, const uint64_t *a, const uint64_t *b)
+{
+#if BR_INT128
+
+ uint64_t x, f, t0, t1, t2, t3, t4;
+ unsigned __int128 z, ff;
+ int i;
+
+ /*
+ * When computing d <- d + a[u]*b, we also add f*p such
+ * that d + a[u]*b + f*p is a multiple of 2^64. Since
+ * p = -1 mod 2^64, we can compute f = d[0] + a[u]*b[0] mod 2^64.
+ */
+
+ /*
+ * Step 1: t <- (a[0]*b + f*p) / 2^64
+ * We have f = a[0]*b[0] mod 2^64. Since p = -1 mod 2^64, this
+ * ensures that (a[0]*b + f*p) is a multiple of 2^64.
+ *
+ * We also have: f*p = f*2^256 - f*2^224 + f*2^192 + f*2^96 - f.
+ */
+ x = a[0];
+ z = (unsigned __int128)b[0] * x;
+ f = (uint64_t)z;
+ z = (unsigned __int128)b[1] * x + (z >> 64) + (uint64_t)(f << 32);
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)b[2] * x + (z >> 64) + (uint64_t)(f >> 32);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)b[3] * x + (z >> 64) + f;
+ t2 = (uint64_t)z;
+ t3 = (uint64_t)(z >> 64);
+ ff = ((unsigned __int128)f << 64) - ((unsigned __int128)f << 32);
+ z = (unsigned __int128)t2 + (uint64_t)ff;
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)t3 + (z >> 64) + (ff >> 64);
+ t3 = (uint64_t)z;
+ t4 = (uint64_t)(z >> 64);
+
+ /*
+ * Steps 2 to 4: t <- (t + a[i]*b + f*p) / 2^64
+ */
+ for (i = 1; i < 4; i ++) {
+ x = a[i];
+
+ /* t <- (t + x*b - f) / 2^64 */
+ z = (unsigned __int128)b[0] * x + t0;
+ f = (uint64_t)z;
+ z = (unsigned __int128)b[1] * x + t1 + (z >> 64);
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)b[2] * x + t2 + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)b[3] * x + t3 + (z >> 64);
+ t2 = (uint64_t)z;
+ z = t4 + (z >> 64);
+ t3 = (uint64_t)z;
+ t4 = (uint64_t)(z >> 64);
+
+ /* t <- t + f*2^32, carry in the upper half of z */
+ z = (unsigned __int128)t0 + (uint64_t)(f << 32);
+ t0 = (uint64_t)z;
+ z = (z >> 64) + (unsigned __int128)t1 + (uint64_t)(f >> 32);
+ t1 = (uint64_t)z;
+
+ /* t <- t + f*2^192 - f*2^160 + f*2^128 */
+ ff = ((unsigned __int128)f << 64)
+ - ((unsigned __int128)f << 32) + f;
+ z = (z >> 64) + (unsigned __int128)t2 + (uint64_t)ff;
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)t3 + (z >> 64) + (ff >> 64);
+ t3 = (uint64_t)z;
+ t4 += (uint64_t)(z >> 64);
+ }
+
+ /*
+ * At that point, we have computed t = (a*b + F*p) / 2^256, where
+ * F is a 256-bit integer whose limbs are the "f" coefficients
+ * in the steps above. We have:
+ * a <= 2^256-1
+ * b <= 2^256-1
+ * F <= 2^256-1
+ * Hence:
+ * a*b + F*p <= (2^256-1)*(2^256-1) + p*(2^256-1)
+ * a*b + F*p <= 2^256*(2^256 - 2 + p) + 1 - p
+ * Therefore:
+ * t < 2^256 + p - 2
+ * Since p < 2^256, it follows that:
+ * t4 can be only 0 or 1
+ * t - p < 2^256
+ * We can therefore subtract p from t, conditionally on t4, to
+ * get a nonnegative result that fits on 256 bits.
+ */
+ z = (unsigned __int128)t0 + t4;
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)t1 - (t4 << 32) + (z >> 64);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)t2 - (z >> 127);
+ t2 = (uint64_t)z;
+ t3 = t3 - (uint64_t)(z >> 127) - t4 + (t4 << 32);
+
+ d[0] = t0;
+ d[1] = t1;
+ d[2] = t2;
+ d[3] = t3;
+
+#elif BR_UMUL128
+
+ uint64_t x, f, t0, t1, t2, t3, t4;
+ uint64_t zl, zh, ffl, ffh;
+ unsigned char k, m;
+ int i;
+
+ /*
+ * When computing d <- d + a[u]*b, we also add f*p such
+ * that d + a[u]*b + f*p is a multiple of 2^64. Since
+ * p = -1 mod 2^64, we can compute f = d[0] + a[u]*b[0] mod 2^64.
+ */
+
+ /*
+ * Step 1: t <- (a[0]*b + f*p) / 2^64
+ * We have f = a[0]*b[0] mod 2^64. Since p = -1 mod 2^64, this
+ * ensures that (a[0]*b + f*p) is a multiple of 2^64.
+ *
+ * We also have: f*p = f*2^256 - f*2^224 + f*2^192 + f*2^96 - f.
+ */
+ x = a[0];
+
+ zl = _umul128(b[0], x, &zh);
+ f = zl;
+ t0 = zh;
+
+ zl = _umul128(b[1], x, &zh);
+ k = _addcarry_u64(0, zl, t0, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ k = _addcarry_u64(0, zl, f << 32, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ t0 = zl;
+ t1 = zh;
+
+ zl = _umul128(b[2], x, &zh);
+ k = _addcarry_u64(0, zl, t1, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ k = _addcarry_u64(0, zl, f >> 32, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ t1 = zl;
+ t2 = zh;
+
+ zl = _umul128(b[3], x, &zh);
+ k = _addcarry_u64(0, zl, t2, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ k = _addcarry_u64(0, zl, f, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ t2 = zl;
+ t3 = zh;
+
+ t4 = _addcarry_u64(0, t3, f, &t3);
+ k = _subborrow_u64(0, t2, f << 32, &t2);
+ k = _subborrow_u64(k, t3, f >> 32, &t3);
+ (void)_subborrow_u64(k, t4, 0, &t4);
+
+ /*
+ * Steps 2 to 4: t <- (t + a[i]*b + f*p) / 2^64
+ */
+ for (i = 1; i < 4; i ++) {
+ x = a[i];
+ /* f = t0 + x * b[0]; -- computed below */
+
+ /* t <- (t + x*b - f) / 2^64 */
+ zl = _umul128(b[0], x, &zh);
+ k = _addcarry_u64(0, zl, t0, &f);
+ (void)_addcarry_u64(k, zh, 0, &t0);
+
+ zl = _umul128(b[1], x, &zh);
+ k = _addcarry_u64(0, zl, t0, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ k = _addcarry_u64(0, zl, t1, &t0);
+ (void)_addcarry_u64(k, zh, 0, &t1);
+
+ zl = _umul128(b[2], x, &zh);
+ k = _addcarry_u64(0, zl, t1, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ k = _addcarry_u64(0, zl, t2, &t1);
+ (void)_addcarry_u64(k, zh, 0, &t2);
+
+ zl = _umul128(b[3], x, &zh);
+ k = _addcarry_u64(0, zl, t2, &zl);
+ (void)_addcarry_u64(k, zh, 0, &zh);
+ k = _addcarry_u64(0, zl, t3, &t2);
+ (void)_addcarry_u64(k, zh, 0, &t3);
+
+ t4 = _addcarry_u64(0, t3, t4, &t3);
+
+ /* t <- t + f*2^32, carry in k */
+ k = _addcarry_u64(0, t0, f << 32, &t0);
+ k = _addcarry_u64(k, t1, f >> 32, &t1);
+
+ /* t <- t + f*2^192 - f*2^160 + f*2^128 */
+ m = _subborrow_u64(0, f, f << 32, &ffl);
+ (void)_subborrow_u64(m, f, f >> 32, &ffh);
+ k = _addcarry_u64(k, t2, ffl, &t2);
+ k = _addcarry_u64(k, t3, ffh, &t3);
+ (void)_addcarry_u64(k, t4, 0, &t4);
+ }
+
+ /*
+ * At that point, we have computed t = (a*b + F*p) / 2^256, where
+ * F is a 256-bit integer whose limbs are the "f" coefficients
+ * in the steps above. We have:
+ * a <= 2^256-1
+ * b <= 2^256-1
+ * F <= 2^256-1
+ * Hence:
+ * a*b + F*p <= (2^256-1)*(2^256-1) + p*(2^256-1)
+ * a*b + F*p <= 2^256*(2^256 - 2 + p) + 1 - p
+ * Therefore:
+ * t < 2^256 + p - 2
+ * Since p < 2^256, it follows that:
+ * t4 can be only 0 or 1
+ * t - p < 2^256
+ * We can therefore subtract p from t, conditionally on t4, to
+ * get a nonnegative result that fits on 256 bits.
+ */
+ k = _addcarry_u64(0, t0, t4, &t0);
+ k = _addcarry_u64(k, t1, -(t4 << 32), &t1);
+ k = _addcarry_u64(k, t2, -t4, &t2);
+ (void)_addcarry_u64(k, t3, (t4 << 32) - (t4 << 1), &t3);
+
+ d[0] = t0;
+ d[1] = t1;
+ d[2] = t2;
+ d[3] = t3;
+
+#endif
+}
+
+/*
+ * Montgomery squaring in the field; currently a basic wrapper around
+ * multiplication (inline, should be optimized away).
+ * TODO: see if some extra speed can be gained here.
+ */
+static inline void
+f256_montysquare(uint64_t *d, const uint64_t *a)
+{
+ f256_montymul(d, a, a);
+}
+
+/*
+ * Convert to Montgomery representation.
+ */
+static void
+f256_tomonty(uint64_t *d, const uint64_t *a)
+{
+ /*
+ * R2 = 2^512 mod p.
+ * If R = 2^256 mod p, then R2 = R^2 mod p; and the Montgomery
+ * multiplication of a by R2 is: a*R2/R = a*R mod p, i.e. the
+ * conversion to Montgomery representation.
+ */
+ static const uint64_t R2[] = {
+ 0x0000000000000003,
+ 0xFFFFFFFBFFFFFFFF,
+ 0xFFFFFFFFFFFFFFFE,
+ 0x00000004FFFFFFFD
+ };
+
+ f256_montymul(d, a, R2);
+}
+
+/*
+ * Convert from Montgomery representation.
+ */
+static void
+f256_frommonty(uint64_t *d, const uint64_t *a)
+{
+ /*
+ * Montgomery multiplication by 1 is division by 2^256 modulo p.
+ */
+ static const uint64_t one[] = { 1, 0, 0, 0 };
+
+ f256_montymul(d, a, one);
+}
+
+/*
+ * Inversion in the field. If the source value is 0 modulo p, then this
+ * returns 0 or p. This function uses Montgomery representation.
+ */
+static void
+f256_invert(uint64_t *d, const uint64_t *a)
+{
+ /*
+ * We compute a^(p-2) mod p. The exponent pattern (from high to
+ * low) is:
+ * - 32 bits of value 1
+ * - 31 bits of value 0
+ * - 1 bit of value 1
+ * - 96 bits of value 0
+ * - 94 bits of value 1
+ * - 1 bit of value 0
+ * - 1 bit of value 1
+ * To speed up the square-and-multiply algorithm, we precompute
+ * a^(2^31-1).
+ */
+
+ uint64_t r[4], t[4];
+ int i;
+
+ memcpy(t, a, sizeof t);
+ for (i = 0; i < 30; i ++) {
+ f256_montysquare(t, t);
+ f256_montymul(t, t, a);
+ }
+
+ memcpy(r, t, sizeof t);
+ for (i = 224; i >= 0; i --) {
+ f256_montysquare(r, r);
+ switch (i) {
+ case 0:
+ case 2:
+ case 192:
+ case 224:
+ f256_montymul(r, r, a);
+ break;
+ case 3:
+ case 34:
+ case 65:
+ f256_montymul(r, r, t);
+ break;
+ }
+ }
+ memcpy(d, r, sizeof r);
+}
+
+/*
+ * Finalize reduction.
+ * Input value fits on 256 bits. This function subtracts p if and only
+ * if the input is greater than or equal to p.
+ */
+static inline void
+f256_final_reduce(uint64_t *a)
+{
+#if BR_INT128
+
+ uint64_t t0, t1, t2, t3, cc;
+ unsigned __int128 z;
+
+ /*
+ * We add 2^224 - 2^192 - 2^96 + 1 to a. If there is no carry,
+ * then a < p; otherwise, the addition result we computed is
+ * the value we must return.
+ */
+ z = (unsigned __int128)a[0] + 1;
+ t0 = (uint64_t)z;
+ z = (unsigned __int128)a[1] + (z >> 64) - ((uint64_t)1 << 32);
+ t1 = (uint64_t)z;
+ z = (unsigned __int128)a[2] - (z >> 127);
+ t2 = (uint64_t)z;
+ z = (unsigned __int128)a[3] - (z >> 127) + 0xFFFFFFFF;
+ t3 = (uint64_t)z;
+ cc = -(uint64_t)(z >> 64);
+
+ a[0] ^= cc & (a[0] ^ t0);
+ a[1] ^= cc & (a[1] ^ t1);
+ a[2] ^= cc & (a[2] ^ t2);
+ a[3] ^= cc & (a[3] ^ t3);
+
+#elif BR_UMUL128
+
+ uint64_t t0, t1, t2, t3, m;
+ unsigned char k;
+
+ k = _addcarry_u64(0, a[0], (uint64_t)1, &t0);
+ k = _addcarry_u64(k, a[1], -((uint64_t)1 << 32), &t1);
+ k = _addcarry_u64(k, a[2], -(uint64_t)1, &t2);
+ k = _addcarry_u64(k, a[3], ((uint64_t)1 << 32) - 2, &t3);
+ m = -(uint64_t)k;
+
+ a[0] ^= m & (a[0] ^ t0);
+ a[1] ^= m & (a[1] ^ t1);
+ a[2] ^= m & (a[2] ^ t2);
+ a[3] ^= m & (a[3] ^ t3);
+
+#endif
+}
+
+/*
+ * Points in affine and Jacobian coordinates.
+ *
+ * - In affine coordinates, the point-at-infinity cannot be encoded.
+ * - Jacobian coordinates (X,Y,Z) correspond to affine (X/Z^2,Y/Z^3);
+ * if Z = 0 then this is the point-at-infinity.
+ */
+typedef struct {
+ uint64_t x[4];
+ uint64_t y[4];
+} p256_affine;
+
+typedef struct {
+ uint64_t x[4];
+ uint64_t y[4];
+ uint64_t z[4];
+} p256_jacobian;
+
+/*
+ * Decode a point. The returned point is in Jacobian coordinates, but
+ * with z = 1. If the encoding is invalid, or encodes a point which is
+ * not on the curve, or encodes the point at infinity, then this function
+ * returns 0. Otherwise, 1 is returned.
+ *
+ * The buffer is assumed to have length exactly 65 bytes.
+ */
+static uint32_t
+point_decode(p256_jacobian *P, const unsigned char *buf)
+{
+ uint64_t x[4], y[4], t[4], x3[4], tt;
+ uint32_t r;
+
+ /*
+ * Header byte shall be 0x04.
+ */
+ r = EQ(buf[0], 0x04);
+
+ /*
+ * Decode X and Y coordinates, and convert them into
+ * Montgomery representation.
+ */
+ x[3] = br_dec64be(buf + 1);
+ x[2] = br_dec64be(buf + 9);
+ x[1] = br_dec64be(buf + 17);
+ x[0] = br_dec64be(buf + 25);
+ y[3] = br_dec64be(buf + 33);
+ y[2] = br_dec64be(buf + 41);
+ y[1] = br_dec64be(buf + 49);
+ y[0] = br_dec64be(buf + 57);
+ f256_tomonty(x, x);
+ f256_tomonty(y, y);
+
+ /*
+ * Verify y^2 = x^3 + A*x + B. In curve P-256, A = -3.
+ * Note that the Montgomery representation of 0 is 0. We must
+ * take care to apply the final reduction to make sure we have
+ * 0 and not p.
+ */
+ f256_montysquare(t, y);
+ f256_montysquare(x3, x);
+ f256_montymul(x3, x3, x);
+ f256_sub(t, t, x3);
+ f256_add(t, t, x);
+ f256_add(t, t, x);
+ f256_add(t, t, x);
+ f256_sub(t, t, P256_B_MONTY);
+ f256_final_reduce(t);
+ tt = t[0] | t[1] | t[2] | t[3];
+ r &= EQ((uint32_t)(tt | (tt >> 32)), 0);
+
+ /*
+ * Return the point in Jacobian coordinates (and Montgomery
+ * representation).
+ */
+ memcpy(P->x, x, sizeof x);
+ memcpy(P->y, y, sizeof y);
+ memcpy(P->z, F256_R, sizeof F256_R);
+ return r;
+}
+
+/*
+ * Final conversion for a point:
+ * - The point is converted back to affine coordinates.
+ * - Final reduction is performed.
+ * - The point is encoded into the provided buffer.
+ *
+ * If the point is the point-at-infinity, all operations are performed,
+ * but the buffer contents are indeterminate, and 0 is returned. Otherwise,
+ * the encoded point is written in the buffer, and 1 is returned.
+ */
+static uint32_t
+point_encode(unsigned char *buf, const p256_jacobian *P)
+{
+ uint64_t t1[4], t2[4], z;
+
+ /* Set t1 = 1/z^2 and t2 = 1/z^3. */
+ f256_invert(t2, P->z);
+ f256_montysquare(t1, t2);
+ f256_montymul(t2, t2, t1);
+
+ /* Compute affine coordinates x (in t1) and y (in t2). */
+ f256_montymul(t1, P->x, t1);
+ f256_montymul(t2, P->y, t2);
+
+ /* Convert back from Montgomery representation, and finalize
+ reductions. */
+ f256_frommonty(t1, t1);
+ f256_frommonty(t2, t2);
+ f256_final_reduce(t1);
+ f256_final_reduce(t2);
+
+ /* Encode. */
+ buf[0] = 0x04;
+ br_enc64be(buf + 1, t1[3]);
+ br_enc64be(buf + 9, t1[2]);
+ br_enc64be(buf + 17, t1[1]);
+ br_enc64be(buf + 25, t1[0]);
+ br_enc64be(buf + 33, t2[3]);
+ br_enc64be(buf + 41, t2[2]);
+ br_enc64be(buf + 49, t2[1]);
+ br_enc64be(buf + 57, t2[0]);
+
+ /* Return success if and only if P->z != 0. */
+ z = P->z[0] | P->z[1] | P->z[2] | P->z[3];
+ return NEQ((uint32_t)(z | z >> 32), 0);
+}
+
+/*
+ * Point doubling in Jacobian coordinates: point P is doubled.
+ * Note: if the source point is the point-at-infinity, then the result is
+ * still the point-at-infinity, which is correct. Moreover, if the three
+ * coordinates were zero, then they still are zero in the returned value.
+ *
+ * (Note: this is true even without the final reduction: if the three
+ * coordinates are encoded as four words of value zero each, then the
+ * result will also have all-zero coordinate encodings, not the alternate
+ * encoding as the integer p.)
+ */
+static void
+p256_double(p256_jacobian *P)
+{
+ /*
+ * Doubling formulas are:
+ *
+ * s = 4*x*y^2
+ * m = 3*(x + z^2)*(x - z^2)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y^4
+ * z' = 2*y*z
+ *
+ * These formulas work for all points, including points of order 2
+ * and points at infinity:
+ * - If y = 0 then z' = 0. But there is no such point in P-256
+ * anyway.
+ * - If z = 0 then z' = 0.
+ */
+ uint64_t t1[4], t2[4], t3[4], t4[4];
+
+ /*
+ * Compute z^2 in t1.
+ */
+ f256_montysquare(t1, P->z);
+
+ /*
+ * Compute x-z^2 in t2 and x+z^2 in t1.
+ */
+ f256_add(t2, P->x, t1);
+ f256_sub(t1, P->x, t1);
+
+ /*
+ * Compute 3*(x+z^2)*(x-z^2) in t1.
+ */
+ f256_montymul(t3, t1, t2);
+ f256_add(t1, t3, t3);
+ f256_add(t1, t3, t1);
+
+ /*
+ * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
+ */
+ f256_montysquare(t3, P->y);
+ f256_add(t3, t3, t3);
+ f256_montymul(t2, P->x, t3);
+ f256_add(t2, t2, t2);
+
+ /*
+ * Compute x' = m^2 - 2*s.
+ */
+ f256_montysquare(P->x, t1);
+ f256_sub(P->x, P->x, t2);
+ f256_sub(P->x, P->x, t2);
+
+ /*
+ * Compute z' = 2*y*z.
+ */
+ f256_montymul(t4, P->y, P->z);
+ f256_add(P->z, t4, t4);
+
+ /*
+ * Compute y' = m*(s - x') - 8*y^4. Note that we already have
+ * 2*y^2 in t3.
+ */
+ f256_sub(t2, t2, P->x);
+ f256_montymul(P->y, t1, t2);
+ f256_montysquare(t4, t3);
+ f256_add(t4, t4, t4);
+ f256_sub(P->y, P->y, t4);
+}
+
+/*
+ * Point addition (Jacobian coordinates): P1 is replaced with P1+P2.
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0 but P2 != 0
+ * - If P1 != 0 but P2 == 0
+ * - If P1 == P2
+ *
+ * In all three cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y coordinate.
+ * - P1 == 0 and P2 == 0.
+ * - The Y coordinate of one of the points is 0 and the other point is
+ * the point at infinity.
+ *
+ * The third case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ *
+ * Note that you can get a returned value of 0 with a correct result,
+ * e.g. if P1 and P2 have the same Y coordinate, but distinct X coordinates.
+ */
+static uint32_t
+p256_add(p256_jacobian *P1, const p256_jacobian *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1 * z2^2
+ * u2 = x2 * z1^2
+ * s1 = y1 * z2^3
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1 * z2
+ */
+ uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt;
+ uint32_t ret;
+
+ /*
+ * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
+ */
+ f256_montysquare(t3, P2->z);
+ f256_montymul(t1, P1->x, t3);
+ f256_montymul(t4, P2->z, t3);
+ f256_montymul(t3, P1->y, t4);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ f256_montysquare(t4, P1->z);
+ f256_montymul(t2, P2->x, t4);
+ f256_montymul(t5, P1->z, t4);
+ f256_montymul(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ f256_sub(t2, t2, t1);
+ f256_sub(t4, t4, t3);
+ f256_final_reduce(t4);
+ tt = t4[0] | t4[1] | t4[2] | t4[3];
+ ret = (uint32_t)(tt | (tt >> 32));
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ f256_montysquare(t7, t2);
+ f256_montymul(t6, t1, t7);
+ f256_montymul(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ f256_montysquare(P1->x, t4);
+ f256_sub(P1->x, P1->x, t5);
+ f256_sub(P1->x, P1->x, t6);
+ f256_sub(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ f256_sub(t6, t6, P1->x);
+ f256_montymul(P1->y, t4, t6);
+ f256_montymul(t1, t5, t3);
+ f256_sub(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ f256_montymul(t1, P1->z, P2->z);
+ f256_montymul(P1->z, t1, t2);
+
+ return ret;
+}
+
+/*
+ * Point addition (mixed coordinates): P1 is replaced with P1+P2.
+ * This is a specialised function for the case when P2 is a non-zero point
+ * in affine coordinates.
+ *
+ * This function computes the wrong result in the following cases:
+ *
+ * - If P1 == 0
+ * - If P1 == P2
+ *
+ * In both cases, P1 is set to the point at infinity.
+ *
+ * Returned value is 0 if one of the following occurs:
+ *
+ * - P1 and P2 have the same Y (affine) coordinate.
+ * - The Y coordinate of P2 is 0 and P1 is the point at infinity.
+ *
+ * The second case cannot actually happen with valid points, since a point
+ * with Y == 0 is a point of order 2, and there is no point of order 2 on
+ * curve P-256.
+ *
+ * Therefore, assuming that P1 != 0 on input, then the caller
+ * can apply the following:
+ *
+ * - If the result is not the point at infinity, then it is correct.
+ * - Otherwise, if the returned value is 1, then this is a case of
+ * P1+P2 == 0, so the result is indeed the point at infinity.
+ * - Otherwise, P1 == P2, so a "double" operation should have been
+ * performed.
+ *
+ * Again, a value of 0 may be returned in some cases where the addition
+ * result is correct.
+ */
+static uint32_t
+p256_add_mixed(p256_jacobian *P1, const p256_affine *P2)
+{
+ /*
+ * Addtions formulas are:
+ *
+ * u1 = x1
+ * u2 = x2 * z1^2
+ * s1 = y1
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1
+ */
+ uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt;
+ uint32_t ret;
+
+ /*
+ * Compute u1 = x1 (in t1) and s1 = y1 (in t3).
+ */
+ memcpy(t1, P1->x, sizeof t1);
+ memcpy(t3, P1->y, sizeof t3);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ f256_montysquare(t4, P1->z);
+ f256_montymul(t2, P2->x, t4);
+ f256_montymul(t5, P1->z, t4);
+ f256_montymul(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * We need to test whether r is zero, so we will do some extra
+ * reduce.
+ */
+ f256_sub(t2, t2, t1);
+ f256_sub(t4, t4, t3);
+ f256_final_reduce(t4);
+ tt = t4[0] | t4[1] | t4[2] | t4[3];
+ ret = (uint32_t)(tt | (tt >> 32));
+ ret = (ret | -ret) >> 31;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ f256_montysquare(t7, t2);
+ f256_montymul(t6, t1, t7);
+ f256_montymul(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ f256_montysquare(P1->x, t4);
+ f256_sub(P1->x, P1->x, t5);
+ f256_sub(P1->x, P1->x, t6);
+ f256_sub(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ f256_sub(t6, t6, P1->x);
+ f256_montymul(P1->y, t4, t6);
+ f256_montymul(t1, t5, t3);
+ f256_sub(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ f256_montymul(P1->z, P1->z, t2);
+
+ return ret;
+}
+
+#if 0
+/* unused */
+/*
+ * Point addition (mixed coordinates, complete): P1 is replaced with P1+P2.
+ * This is a specialised function for the case when P2 is a non-zero point
+ * in affine coordinates.
+ *
+ * This function returns the correct result in all cases.
+ */
+static uint32_t
+p256_add_complete_mixed(p256_jacobian *P1, const p256_affine *P2)
+{
+ /*
+ * Addtions formulas, in the general case, are:
+ *
+ * u1 = x1
+ * u2 = x2 * z1^2
+ * s1 = y1
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1
+ *
+ * These formulas mishandle the two following cases:
+ *
+ * - If P1 is the point-at-infinity (z1 = 0), then z3 is
+ * incorrectly set to 0.
+ *
+ * - If P1 = P2, then u1 = u2 and s1 = s2, and x3, y3 and z3
+ * are all set to 0.
+ *
+ * However, if P1 + P2 = 0, then u1 = u2 but s1 != s2, and then
+ * we correctly get z3 = 0 (the point-at-infinity).
+ *
+ * To fix the case P1 = 0, we perform at the end a copy of P2
+ * over P1, conditional to z1 = 0.
+ *
+ * For P1 = P2: in that case, both h and r are set to 0, and
+ * we get x3, y3 and z3 equal to 0. We can test for that
+ * occurrence to make a mask which will be all-one if P1 = P2,
+ * or all-zero otherwise; then we can compute the double of P2
+ * and add it, combined with the mask, to (x3,y3,z3).
+ *
+ * Using the doubling formulas in p256_double() on (x2,y2),
+ * simplifying since P2 is affine (i.e. z2 = 1, implicitly),
+ * we get:
+ * s = 4*x2*y2^2
+ * m = 3*(x2 + 1)*(x2 - 1)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y2^4
+ * z' = 2*y2
+ * which requires only 6 multiplications. Added to the 11
+ * multiplications of the normal mixed addition in Jacobian
+ * coordinates, we get a cost of 17 multiplications in total.
+ */
+ uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt, zz;
+ int i;
+
+ /*
+ * Set zz to -1 if P1 is the point at infinity, 0 otherwise.
+ */
+ zz = P1->z[0] | P1->z[1] | P1->z[2] | P1->z[3];
+ zz = ((zz | -zz) >> 63) - (uint64_t)1;
+
+ /*
+ * Compute u1 = x1 (in t1) and s1 = y1 (in t3).
+ */
+ memcpy(t1, P1->x, sizeof t1);
+ memcpy(t3, P1->y, sizeof t3);
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ f256_montysquare(t4, P1->z);
+ f256_montymul(t2, P2->x, t4);
+ f256_montymul(t5, P1->z, t4);
+ f256_montymul(t4, P2->y, t5);
+
+ /*
+ * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
+ * reduce.
+ */
+ f256_sub(t2, t2, t1);
+ f256_sub(t4, t4, t3);
+
+ /*
+ * If both h = 0 and r = 0, then P1 = P2, and we want to set
+ * the mask tt to -1; otherwise, the mask will be 0.
+ */
+ f256_final_reduce(t2);
+ f256_final_reduce(t4);
+ tt = t2[0] | t2[1] | t2[2] | t2[3] | t4[0] | t4[1] | t4[2] | t4[3];
+ tt = ((tt | -tt) >> 63) - (uint64_t)1;
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5);
+ */
+ f256_montysquare(t7, t2);
+ f256_montymul(t6, t1, t7);
+ f256_montymul(t5, t7, t2);
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ */
+ f256_montysquare(P1->x, t4);
+ f256_sub(P1->x, P1->x, t5);
+ f256_sub(P1->x, P1->x, t6);
+ f256_sub(P1->x, P1->x, t6);
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ f256_sub(t6, t6, P1->x);
+ f256_montymul(P1->y, t4, t6);
+ f256_montymul(t1, t5, t3);
+ f256_sub(P1->y, P1->y, t1);
+
+ /*
+ * Compute z3 = h*z1.
+ */
+ f256_montymul(P1->z, P1->z, t2);
+
+ /*
+ * The "double" result, in case P1 = P2.
+ */
+
+ /*
+ * Compute z' = 2*y2 (in t1).
+ */
+ f256_add(t1, P2->y, P2->y);
+
+ /*
+ * Compute 2*(y2^2) (in t2) and s = 4*x2*(y2^2) (in t3).
+ */
+ f256_montysquare(t2, P2->y);
+ f256_add(t2, t2, t2);
+ f256_add(t3, t2, t2);
+ f256_montymul(t3, P2->x, t3);
+
+ /*
+ * Compute m = 3*(x2^2 - 1) (in t4).
+ */
+ f256_montysquare(t4, P2->x);
+ f256_sub(t4, t4, F256_R);
+ f256_add(t5, t4, t4);
+ f256_add(t4, t4, t5);
+
+ /*
+ * Compute x' = m^2 - 2*s (in t5).
+ */
+ f256_montysquare(t5, t4);
+ f256_sub(t5, t3);
+ f256_sub(t5, t3);
+
+ /*
+ * Compute y' = m*(s - x') - 8*y2^4 (in t6).
+ */
+ f256_sub(t6, t3, t5);
+ f256_montymul(t6, t6, t4);
+ f256_montysquare(t7, t2);
+ f256_sub(t6, t6, t7);
+ f256_sub(t6, t6, t7);
+
+ /*
+ * We now have the alternate (doubling) coordinates in (t5,t6,t1).
+ * We combine them with (x3,y3,z3).
+ */
+ for (i = 0; i < 4; i ++) {
+ P1->x[i] |= tt & t5[i];
+ P1->y[i] |= tt & t6[i];
+ P1->z[i] |= tt & t1[i];
+ }
+
+ /*
+ * If P1 = 0, then we get z3 = 0 (which is invalid); if z1 is 0,
+ * then we want to replace the result with a copy of P2. The
+ * test on z1 was done at the start, in the zz mask.
+ */
+ for (i = 0; i < 4; i ++) {
+ P1->x[i] ^= zz & (P1->x[i] ^ P2->x[i]);
+ P1->y[i] ^= zz & (P1->y[i] ^ P2->y[i]);
+ P1->z[i] ^= zz & (P1->z[i] ^ F256_R[i]);
+ }
+}
+#endif
+
+/*
+ * Inner function for computing a point multiplication. A window is
+ * provided, with points 1*P to 15*P in affine coordinates.
+ *
+ * Assumptions:
+ * - All provided points are valid points on the curve.
+ * - Multiplier is non-zero, and smaller than the curve order.
+ * - Everything is in Montgomery representation.
+ */
+static void
+point_mul_inner(p256_jacobian *R, const p256_affine *W,
+ const unsigned char *k, size_t klen)
+{
+ p256_jacobian Q;
+ uint32_t qz;
+
+ memset(&Q, 0, sizeof Q);
+ qz = 1;
+ while (klen -- > 0) {
+ int i;
+ unsigned bk;
+
+ bk = *k ++;
+ for (i = 0; i < 2; i ++) {
+ uint32_t bits;
+ uint32_t bnz;
+ p256_affine T;
+ p256_jacobian U;
+ uint32_t n;
+ int j;
+ uint64_t m;
+
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ p256_double(&Q);
+ bits = (bk >> 4) & 0x0F;
+ bnz = NEQ(bits, 0);
+
+ /*
+ * Lookup point in window. If the bits are 0,
+ * we get something invalid, which is not a
+ * problem because we will use it only if the
+ * bits are non-zero.
+ */
+ memset(&T, 0, sizeof T);
+ for (n = 0; n < 15; n ++) {
+ m = -(uint64_t)EQ(bits, n + 1);
+ T.x[0] |= m & W[n].x[0];
+ T.x[1] |= m & W[n].x[1];
+ T.x[2] |= m & W[n].x[2];
+ T.x[3] |= m & W[n].x[3];
+ T.y[0] |= m & W[n].y[0];
+ T.y[1] |= m & W[n].y[1];
+ T.y[2] |= m & W[n].y[2];
+ T.y[3] |= m & W[n].y[3];
+ }
+
+ U = Q;
+ p256_add_mixed(&U, &T);
+
+ /*
+ * If qz is still 1, then Q was all-zeros, and this
+ * is conserved through p256_double().
+ */
+ m = -(uint64_t)(bnz & qz);
+ for (j = 0; j < 4; j ++) {
+ Q.x[j] |= m & T.x[j];
+ Q.y[j] |= m & T.y[j];
+ Q.z[j] |= m & F256_R[j];
+ }
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ bk <<= 4;
+ }
+ }
+ *R = Q;
+}
+
+/*
+ * Convert a window from Jacobian to affine coordinates. A single
+ * field inversion is used. This function works for windows up to
+ * 32 elements.
+ *
+ * The destination array (aff[]) and the source array (jac[]) may
+ * overlap, provided that the start of aff[] is not after the start of
+ * jac[]. Even if the arrays do _not_ overlap, the source array is
+ * modified.
+ */
+static void
+window_to_affine(p256_affine *aff, p256_jacobian *jac, int num)
+{
+ /*
+ * Convert the window points to affine coordinates. We use the
+ * following trick to mutualize the inversion computation: if
+ * we have z1, z2, z3, and z4, and want to inverse all of them,
+ * we compute u = 1/(z1*z2*z3*z4), and then we have:
+ * 1/z1 = u*z2*z3*z4
+ * 1/z2 = u*z1*z3*z4
+ * 1/z3 = u*z1*z2*z4
+ * 1/z4 = u*z1*z2*z3
+ *
+ * The partial products are computed recursively:
+ *
+ * - on input (z_1,z_2), return (z_2,z_1) and z_1*z_2
+ * - on input (z_1,z_2,... z_n):
+ * recurse on (z_1,z_2,... z_(n/2)) -> r1 and m1
+ * recurse on (z_(n/2+1),z_(n/2+2)... z_n) -> r2 and m2
+ * multiply elements of r1 by m2 -> s1
+ * multiply elements of r2 by m1 -> s2
+ * return r1||r2 and m1*m2
+ *
+ * In the example below, we suppose that we have 14 elements.
+ * Let z1, z2,... zE be the 14 values to invert (index noted in
+ * hexadecimal, starting at 1).
+ *
+ * - Depth 1:
+ * swap(z1, z2); z12 = z1*z2
+ * swap(z3, z4); z34 = z3*z4
+ * swap(z5, z6); z56 = z5*z6
+ * swap(z7, z8); z78 = z7*z8
+ * swap(z9, zA); z9A = z9*zA
+ * swap(zB, zC); zBC = zB*zC
+ * swap(zD, zE); zDE = zD*zE
+ *
+ * - Depth 2:
+ * z1 <- z1*z34, z2 <- z2*z34, z3 <- z3*z12, z4 <- z4*z12
+ * z1234 = z12*z34
+ * z5 <- z5*z78, z6 <- z6*z78, z7 <- z7*z56, z8 <- z8*z56
+ * z5678 = z56*z78
+ * z9 <- z9*zBC, zA <- zA*zBC, zB <- zB*z9A, zC <- zC*z9A
+ * z9ABC = z9A*zBC
+ *
+ * - Depth 3:
+ * z1 <- z1*z5678, z2 <- z2*z5678, z3 <- z3*z5678, z4 <- z4*z5678
+ * z5 <- z5*z1234, z6 <- z6*z1234, z7 <- z7*z1234, z8 <- z8*z1234
+ * z12345678 = z1234*z5678
+ * z9 <- z9*zDE, zA <- zA*zDE, zB <- zB*zDE, zC <- zC*zDE
+ * zD <- zD*z9ABC, zE*z9ABC
+ * z9ABCDE = z9ABC*zDE
+ *
+ * - Depth 4:
+ * multiply z1..z8 by z9ABCDE
+ * multiply z9..zE by z12345678
+ * final z = z12345678*z9ABCDE
+ */
+
+ uint64_t z[16][4];
+ int i, k, s;
+#define zt (z[15])
+#define zu (z[14])
+#define zv (z[13])
+
+ /*
+ * First recursion step (pairwise swapping and multiplication).
+ * If there is an odd number of elements, then we "invent" an
+ * extra one with coordinate Z = 1 (in Montgomery representation).
+ */
+ for (i = 0; (i + 1) < num; i += 2) {
+ memcpy(zt, jac[i].z, sizeof zt);
+ memcpy(jac[i].z, jac[i + 1].z, sizeof zt);
+ memcpy(jac[i + 1].z, zt, sizeof zt);
+ f256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z);
+ }
+ if ((num & 1) != 0) {
+ memcpy(z[num >> 1], jac[num - 1].z, sizeof zt);
+ memcpy(jac[num - 1].z, F256_R, sizeof F256_R);
+ }
+
+ /*
+ * Perform further recursion steps. At the entry of each step,
+ * the process has been done for groups of 's' points. The
+ * integer k is the log2 of s.
+ */
+ for (k = 1, s = 2; s < num; k ++, s <<= 1) {
+ int n;
+
+ for (i = 0; i < num; i ++) {
+ f256_montymul(jac[i].z, jac[i].z, z[(i >> k) ^ 1]);
+ }
+ n = (num + s - 1) >> k;
+ for (i = 0; i < (n >> 1); i ++) {
+ f256_montymul(z[i], z[i << 1], z[(i << 1) + 1]);
+ }
+ if ((n & 1) != 0) {
+ memmove(z[n >> 1], z[n], sizeof zt);
+ }
+ }
+
+ /*
+ * Invert the final result, and convert all points.
+ */
+ f256_invert(zt, z[0]);
+ for (i = 0; i < num; i ++) {
+ f256_montymul(zv, jac[i].z, zt);
+ f256_montysquare(zu, zv);
+ f256_montymul(zv, zv, zu);
+ f256_montymul(aff[i].x, jac[i].x, zu);
+ f256_montymul(aff[i].y, jac[i].y, zv);
+ }
+}
+
+/*
+ * Multiply the provided point by an integer.
+ * Assumptions:
+ * - Source point is a valid curve point.
+ * - Source point is not the point-at-infinity.
+ * - Integer is not 0, and is lower than the curve order.
+ * If these conditions are not met, then the result is indeterminate
+ * (but the process is still constant-time).
+ */
+static void
+p256_mul(p256_jacobian *P, const unsigned char *k, size_t klen)
+{
+ union {
+ p256_affine aff[15];
+ p256_jacobian jac[15];
+ } window;
+ int i;
+
+ /*
+ * Compute window, in Jacobian coordinates.
+ */
+ window.jac[0] = *P;
+ for (i = 2; i < 16; i ++) {
+ window.jac[i - 1] = window.jac[(i >> 1) - 1];
+ if ((i & 1) == 0) {
+ p256_double(&window.jac[i - 1]);
+ } else {
+ p256_add(&window.jac[i - 1], &window.jac[i >> 1]);
+ }
+ }
+
+ /*
+ * Convert the window points to affine coordinates. Point
+ * window[0] is the source point, already in affine coordinates.
+ */
+ window_to_affine(window.aff, window.jac, 15);
+
+ /*
+ * Perform point multiplication.
+ */
+ point_mul_inner(P, window.aff, k, klen);
+}
+
+/*
+ * Precomputed window for the conventional generator: P256_Gwin[n]
+ * contains (n+1)*G (affine coordinates, in Montgomery representation).
+ */
+static const p256_affine P256_Gwin[] = {
+ {
+ { 0x79E730D418A9143C, 0x75BA95FC5FEDB601,
+ 0x79FB732B77622510, 0x18905F76A53755C6 },
+ { 0xDDF25357CE95560A, 0x8B4AB8E4BA19E45C,
+ 0xD2E88688DD21F325, 0x8571FF1825885D85 }
+ },
+ {
+ { 0x850046D410DDD64D, 0xAA6AE3C1A433827D,
+ 0x732205038D1490D9, 0xF6BB32E43DCF3A3B },
+ { 0x2F3648D361BEE1A5, 0x152CD7CBEB236FF8,
+ 0x19A8FB0E92042DBE, 0x78C577510A5B8A3B }
+ },
+ {
+ { 0xFFAC3F904EEBC127, 0xB027F84A087D81FB,
+ 0x66AD77DD87CBBC98, 0x26936A3FB6FF747E },
+ { 0xB04C5C1FC983A7EB, 0x583E47AD0861FE1A,
+ 0x788208311A2EE98E, 0xD5F06A29E587CC07 }
+ },
+ {
+ { 0x74B0B50D46918DCC, 0x4650A6EDC623C173,
+ 0x0CDAACACE8100AF2, 0x577362F541B0176B },
+ { 0x2D96F24CE4CBABA6, 0x17628471FAD6F447,
+ 0x6B6C36DEE5DDD22E, 0x84B14C394C5AB863 }
+ },
+ {
+ { 0xBE1B8AAEC45C61F5, 0x90EC649A94B9537D,
+ 0x941CB5AAD076C20C, 0xC9079605890523C8 },
+ { 0xEB309B4AE7BA4F10, 0x73C568EFE5EB882B,
+ 0x3540A9877E7A1F68, 0x73A076BB2DD1E916 }
+ },
+ {
+ { 0x403947373E77664A, 0x55AE744F346CEE3E,
+ 0xD50A961A5B17A3AD, 0x13074B5954213673 },
+ { 0x93D36220D377E44B, 0x299C2B53ADFF14B5,
+ 0xF424D44CEF639F11, 0xA4C9916D4A07F75F }
+ },
+ {
+ { 0x0746354EA0173B4F, 0x2BD20213D23C00F7,
+ 0xF43EAAB50C23BB08, 0x13BA5119C3123E03 },
+ { 0x2847D0303F5B9D4D, 0x6742F2F25DA67BDD,
+ 0xEF933BDC77C94195, 0xEAEDD9156E240867 }
+ },
+ {
+ { 0x27F14CD19499A78F, 0x462AB5C56F9B3455,
+ 0x8F90F02AF02CFC6B, 0xB763891EB265230D },
+ { 0xF59DA3A9532D4977, 0x21E3327DCF9EBA15,
+ 0x123C7B84BE60BBF0, 0x56EC12F27706DF76 }
+ },
+ {
+ { 0x75C96E8F264E20E8, 0xABE6BFED59A7A841,
+ 0x2CC09C0444C8EB00, 0xE05B3080F0C4E16B },
+ { 0x1EB7777AA45F3314, 0x56AF7BEDCE5D45E3,
+ 0x2B6E019A88B12F1A, 0x086659CDFD835F9B }
+ },
+ {
+ { 0x2C18DBD19DC21EC8, 0x98F9868A0FCF8139,
+ 0x737D2CD648250B49, 0xCC61C94724B3428F },
+ { 0x0C2B407880DD9E76, 0xC43A8991383FBE08,
+ 0x5F7D2D65779BE5D2, 0x78719A54EB3B4AB5 }
+ },
+ {
+ { 0xEA7D260A6245E404, 0x9DE407956E7FDFE0,
+ 0x1FF3A4158DAC1AB5, 0x3E7090F1649C9073 },
+ { 0x1A7685612B944E88, 0x250F939EE57F61C8,
+ 0x0C0DAA891EAD643D, 0x68930023E125B88E }
+ },
+ {
+ { 0x04B71AA7D2697768, 0xABDEDEF5CA345A33,
+ 0x2409D29DEE37385E, 0x4EE1DF77CB83E156 },
+ { 0x0CAC12D91CBB5B43, 0x170ED2F6CA895637,
+ 0x28228CFA8ADE6D66, 0x7FF57C9553238ACA }
+ },
+ {
+ { 0xCCC425634B2ED709, 0x0E356769856FD30D,
+ 0xBCBCD43F559E9811, 0x738477AC5395B759 },
+ { 0x35752B90C00EE17F, 0x68748390742ED2E3,
+ 0x7CD06422BD1F5BC1, 0xFBC08769C9E7B797 }
+ },
+ {
+ { 0xA242A35BB0CF664A, 0x126E48F77F9707E3,
+ 0x1717BF54C6832660, 0xFAAE7332FD12C72E },
+ { 0x27B52DB7995D586B, 0xBE29569E832237C2,
+ 0xE8E4193E2A65E7DB, 0x152706DC2EAA1BBB }
+ },
+ {
+ { 0x72BCD8B7BC60055B, 0x03CC23EE56E27E4B,
+ 0xEE337424E4819370, 0xE2AA0E430AD3DA09 },
+ { 0x40B8524F6383C45D, 0xD766355442A41B25,
+ 0x64EFA6DE778A4797, 0x2042170A7079ADF4 }
+ }
+};
+
+/*
+ * Multiply the conventional generator of the curve by the provided
+ * integer. Return is written in *P.
+ *
+ * Assumptions:
+ * - Integer is not 0, and is lower than the curve order.
+ * If this conditions is not met, then the result is indeterminate
+ * (but the process is still constant-time).
+ */
+static void
+p256_mulgen(p256_jacobian *P, const unsigned char *k, size_t klen)
+{
+ point_mul_inner(P, P256_Gwin, k, klen);
+}
+
+/*
+ * Return 1 if all of the following hold:
+ * - klen <= 32
+ * - k != 0
+ * - k is lower than the curve order
+ * Otherwise, return 0.
+ *
+ * Constant-time behaviour: only klen may be observable.
+ */
+static uint32_t
+check_scalar(const unsigned char *k, size_t klen)
+{
+ uint32_t z;
+ int32_t c;
+ size_t u;
+
+ if (klen > 32) {
+ return 0;
+ }
+ z = 0;
+ for (u = 0; u < klen; u ++) {
+ z |= k[u];
+ }
+ if (klen == 32) {
+ c = 0;
+ for (u = 0; u < klen; u ++) {
+ c |= -(int32_t)EQ0(c) & CMP(k[u], P256_N[u]);
+ }
+ } else {
+ c = -1;
+ }
+ return NEQ(z, 0) & LT0(c);
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *k, size_t klen, int curve)
+{
+ uint32_t r;
+ p256_jacobian P;
+
+ (void)curve;
+ if (Glen != 65) {
+ return 0;
+ }
+ r = check_scalar(k, klen);
+ r &= point_decode(&P, G);
+ p256_mul(&P, k, klen);
+ r &= point_encode(G, &P);
+ return r;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *k, size_t klen, int curve)
+{
+ p256_jacobian P;
+
+ (void)curve;
+ p256_mulgen(&P, k, klen);
+ point_encode(R, &P);
+ return 65;
+}
+
+static uint32_t
+api_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)
+{
+ /*
+ * We might want to use Shamir's trick here: make a composite
+ * window of u*P+v*Q points, to merge the two doubling-ladders
+ * into one. This, however, has some complications:
+ *
+ * - During the computation, we may hit the point-at-infinity.
+ * Thus, we would need p256_add_complete_mixed() (complete
+ * formulas for point addition), with a higher cost (17 muls
+ * instead of 11).
+ *
+ * - A 4-bit window would be too large, since it would involve
+ * 16*16-1 = 255 points. For the same window size as in the
+ * p256_mul() case, we would need to reduce the window size
+ * to 2 bits, and thus perform twice as many non-doubling
+ * point additions.
+ *
+ * - The window may itself contain the point-at-infinity, and
+ * thus cannot be in all generality be made of affine points.
+ * Instead, we would need to make it a window of points in
+ * Jacobian coordinates. Even p256_add_complete_mixed() would
+ * be inappropriate.
+ *
+ * For these reasons, the code below performs two separate
+ * point multiplications, then computes the final point addition
+ * (which is both a "normal" addition, and a doubling, to handle
+ * all cases).
+ */
+
+ p256_jacobian P, Q;
+ uint32_t r, t, s;
+ uint64_t z;
+
+ (void)curve;
+ if (len != 65) {
+ return 0;
+ }
+ r = point_decode(&P, A);
+ p256_mul(&P, x, xlen);
+ if (B == NULL) {
+ p256_mulgen(&Q, y, ylen);
+ } else {
+ r &= point_decode(&Q, B);
+ p256_mul(&Q, y, ylen);
+ }
+
+ /*
+ * The final addition may fail in case both points are equal.
+ */
+ t = p256_add(&P, &Q);
+ f256_final_reduce(P.z);
+ z = P.z[0] | P.z[1] | P.z[2] | P.z[3];
+ s = EQ((uint32_t)(z | (z >> 32)), 0);
+ p256_double(&Q);
+
+ /*
+ * If s is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
+ * have the following:
+ *
+ * s = 0, t = 0 return P (normal addition)
+ * s = 0, t = 1 return P (normal addition)
+ * s = 1, t = 0 return Q (a 'double' case)
+ * s = 1, t = 1 report an error (P+Q = 0)
+ */
+ CCOPY(s & ~t, &P, &Q, sizeof Q);
+ point_encode(A, &P);
+ r &= ~(s & t);
+ return r;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_p256_m64 = {
+ (uint32_t)0x00800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_p256_m64_get(void)
+{
+ return &br_ec_p256_m64;
+}
+
+#else
+
+/* see bearssl_ec.h */
+const br_ec_impl *
+br_ec_p256_m64_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/ec/ec_p256_m64.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_prime_i15.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_prime_i15.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_prime_i15.c (revision 346145)
@@ -0,0 +1,820 @@
+/*
+ * 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"
+
+/*
+ * Parameters for supported curves:
+ * - field modulus p
+ * - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
+ * - b*R mod p (b is the second curve equation parameter)
+ */
+
+static const uint16_t P256_P[] = {
+ 0x0111,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x003F, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x4000, 0x7FFF,
+ 0x7FFF, 0x0001
+};
+
+static const uint16_t P256_R2[] = {
+ 0x0111,
+ 0x0000, 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFC, 0x7FFF,
+ 0x7FBF, 0x7FFF, 0x7FBF, 0x7FFF, 0x7FFF, 0x7FFF, 0x77FF, 0x7FFF,
+ 0x4FFF, 0x0000
+};
+
+static const uint16_t P256_B[] = {
+ 0x0111,
+ 0x770C, 0x5EEF, 0x29C4, 0x3EC4, 0x6273, 0x0486, 0x4543, 0x3993,
+ 0x3C01, 0x6B56, 0x212E, 0x57EE, 0x4882, 0x204B, 0x7483, 0x3C16,
+ 0x0187, 0x0000
+};
+
+static const uint16_t P384_P[] = {
+ 0x0199,
+ 0x7FFF, 0x7FFF, 0x0003, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FFF,
+ 0x7EFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x01FF
+};
+
+static const uint16_t P384_R2[] = {
+ 0x0199,
+ 0x1000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x0001, 0x0000, 0x0010,
+ 0x0000, 0x0000, 0x0000, 0x7F00, 0x7FFF, 0x01FF, 0x0000, 0x1000,
+ 0x0000, 0x2000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000
+};
+
+static const uint16_t P384_B[] = {
+ 0x0199,
+ 0x7333, 0x2096, 0x70D1, 0x2310, 0x3020, 0x6197, 0x1464, 0x35BB,
+ 0x70CA, 0x0117, 0x1920, 0x4136, 0x5FC8, 0x5713, 0x4938, 0x7DD2,
+ 0x4DD2, 0x4A71, 0x0220, 0x683E, 0x2C87, 0x4DB1, 0x7BFF, 0x6C09,
+ 0x0452, 0x0084
+};
+
+static const uint16_t P521_P[] = {
+ 0x022B,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x07FF
+};
+
+static const uint16_t P521_R2[] = {
+ 0x022B,
+ 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000
+};
+
+static const uint16_t P521_B[] = {
+ 0x022B,
+ 0x7002, 0x6A07, 0x751A, 0x228F, 0x71EF, 0x5869, 0x20F4, 0x1EFC,
+ 0x7357, 0x37E0, 0x4EEC, 0x605E, 0x1652, 0x26F6, 0x31FA, 0x4A8F,
+ 0x6193, 0x3C2A, 0x3C42, 0x48C7, 0x3489, 0x6771, 0x4C57, 0x5CCD,
+ 0x2725, 0x545B, 0x503B, 0x5B42, 0x21A0, 0x2534, 0x687E, 0x70E4,
+ 0x1618, 0x27D7, 0x0465
+};
+
+typedef struct {
+ const uint16_t *p;
+ const uint16_t *b;
+ const uint16_t *R2;
+ uint16_t p0i;
+ size_t point_len;
+} curve_params;
+
+static inline const curve_params *
+id_to_curve(int curve)
+{
+ static const curve_params pp[] = {
+ { P256_P, P256_B, P256_R2, 0x0001, 65 },
+ { P384_P, P384_B, P384_R2, 0x0001, 97 },
+ { P521_P, P521_B, P521_R2, 0x0001, 133 }
+ };
+
+ return &pp[curve - BR_EC_secp256r1];
+}
+
+#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
+
+/*
+ * Type for a point in Jacobian coordinates:
+ * -- three values, x, y and z, in Montgomery representation
+ * -- affine coordinates are X = x / z^2 and Y = y / z^3
+ * -- for the point at infinity, z = 0
+ */
+typedef struct {
+ uint16_t c[3][I15_LEN];
+} jacobian;
+
+/*
+ * We use a custom interpreter that uses a dozen registers, and
+ * only six operations:
+ * MSET(d, a) copy a into d
+ * MADD(d, a) d = d+a (modular)
+ * MSUB(d, a) d = d-a (modular)
+ * MMUL(d, a, b) d = a*b (Montgomery multiplication)
+ * MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
+ * MTZ(d) clear return value if d = 0
+ * Destination of MMUL (d) must be distinct from operands (a and b).
+ * There is no such constraint for MSUB and MADD.
+ *
+ * Registers include the operand coordinates, and temporaries.
+ */
+#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
+#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
+#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
+#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
+#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
+#define MTZ(d) (0x5000 + ((d) << 8))
+#define ENDCODE 0
+
+/*
+ * Registers for the input operands.
+ */
+#define P1x 0
+#define P1y 1
+#define P1z 2
+#define P2x 3
+#define P2y 4
+#define P2z 5
+
+/*
+ * Alternate names for the first input operand.
+ */
+#define Px 0
+#define Py 1
+#define Pz 2
+
+/*
+ * Temporaries.
+ */
+#define t1 6
+#define t2 7
+#define t3 8
+#define t4 9
+#define t5 10
+#define t6 11
+#define t7 12
+
+/*
+ * Extra scratch registers available when there is no second operand (e.g.
+ * for "double" and "affine").
+ */
+#define t8 3
+#define t9 4
+#define t10 5
+
+/*
+ * Doubling formulas are:
+ *
+ * s = 4*x*y^2
+ * m = 3*(x + z^2)*(x - z^2)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y^4
+ * z' = 2*y*z
+ *
+ * If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
+ * should. This case should not happen anyway, because our curves have
+ * prime order, and thus do not contain any point of order 2.
+ *
+ * If P is infinity (z = 0), then again the formulas yield infinity,
+ * which is correct. Thus, this code works for all points.
+ *
+ * Cost: 8 multiplications
+ */
+static const uint16_t code_double[] = {
+ /*
+ * Compute z^2 (in t1).
+ */
+ MMUL(t1, Pz, Pz),
+
+ /*
+ * Compute x-z^2 (in t2) and then x+z^2 (in t1).
+ */
+ MSET(t2, Px),
+ MSUB(t2, t1),
+ MADD(t1, Px),
+
+ /*
+ * Compute m = 3*(x+z^2)*(x-z^2) (in t1).
+ */
+ MMUL(t3, t1, t2),
+ MSET(t1, t3),
+ MADD(t1, t3),
+ MADD(t1, t3),
+
+ /*
+ * Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
+ */
+ MMUL(t3, Py, Py),
+ MADD(t3, t3),
+ MMUL(t2, Px, t3),
+ MADD(t2, t2),
+
+ /*
+ * Compute x' = m^2 - 2*s.
+ */
+ MMUL(Px, t1, t1),
+ MSUB(Px, t2),
+ MSUB(Px, t2),
+
+ /*
+ * Compute z' = 2*y*z.
+ */
+ MMUL(t4, Py, Pz),
+ MSET(Pz, t4),
+ MADD(Pz, t4),
+
+ /*
+ * Compute y' = m*(s - x') - 8*y^4. Note that we already have
+ * 2*y^2 in t3.
+ */
+ MSUB(t2, Px),
+ MMUL(Py, t1, t2),
+ MMUL(t4, t3, t3),
+ MSUB(Py, t4),
+ MSUB(Py, t4),
+
+ ENDCODE
+};
+
+/*
+ * Addtions formulas are:
+ *
+ * u1 = x1 * z2^2
+ * u2 = x2 * z1^2
+ * s1 = y1 * z2^3
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1 * z2
+ *
+ * If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
+ * z3 == 0, so the result is correct.
+ * If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
+ * not correct.
+ * h == 0 only if u1 == u2; this happens in two cases:
+ * -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
+ * -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
+ *
+ * Thus, the following situations are not handled correctly:
+ * -- P1 = 0 and P2 != 0
+ * -- P1 != 0 and P2 = 0
+ * -- P1 = P2
+ * All other cases are properly computed. However, even in "incorrect"
+ * situations, the three coordinates still are properly formed field
+ * elements.
+ *
+ * The returned flag is cleared if r == 0. This happens in the following
+ * cases:
+ * -- Both points are on the same horizontal line (same Y coordinate).
+ * -- Both points are infinity.
+ * -- One point is infinity and the other is on line Y = 0.
+ * The third case cannot happen with our curves (there is no valid point
+ * on line Y = 0 since that would be a point of order 2). If the two
+ * source points are non-infinity, then remains only the case where the
+ * two points are on the same horizontal line.
+ *
+ * This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
+ * P2 != 0:
+ * -- If the returned value is not the point at infinity, then it was properly
+ * computed.
+ * -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
+ * is indeed the point at infinity.
+ * -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
+ * use the 'double' code.
+ *
+ * Cost: 16 multiplications
+ */
+static const uint16_t code_add[] = {
+ /*
+ * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
+ */
+ MMUL(t3, P2z, P2z),
+ MMUL(t1, P1x, t3),
+ MMUL(t4, P2z, t3),
+ MMUL(t3, P1y, t4),
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ MMUL(t4, P1z, P1z),
+ MMUL(t2, P2x, t4),
+ MMUL(t5, P1z, t4),
+ MMUL(t4, P2y, t5),
+
+ /*
+ * Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
+ */
+ MSUB(t2, t1),
+ MSUB(t4, t3),
+
+ /*
+ * Report cases where r = 0 through the returned flag.
+ */
+ MTZ(t4),
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5).
+ */
+ MMUL(t7, t2, t2),
+ MMUL(t6, t1, t7),
+ MMUL(t5, t7, t2),
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ * t1 and t7 can be used as scratch registers.
+ */
+ MMUL(P1x, t4, t4),
+ MSUB(P1x, t5),
+ MSUB(P1x, t6),
+ MSUB(P1x, t6),
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ MSUB(t6, P1x),
+ MMUL(P1y, t4, t6),
+ MMUL(t1, t5, t3),
+ MSUB(P1y, t1),
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ MMUL(t1, P1z, P2z),
+ MMUL(P1z, t1, t2),
+
+ ENDCODE
+};
+
+/*
+ * Check that the point is on the curve. This code snippet assumes the
+ * following conventions:
+ * -- Coordinates x and y have been freshly decoded in P1 (but not
+ * converted to Montgomery coordinates yet).
+ * -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
+ */
+static const uint16_t code_check[] = {
+
+ /* Convert x and y to Montgomery representation. */
+ MMUL(t1, P1x, P2x),
+ MMUL(t2, P1y, P2x),
+ MSET(P1x, t1),
+ MSET(P1y, t2),
+
+ /* Compute x^3 in t1. */
+ MMUL(t2, P1x, P1x),
+ MMUL(t1, P1x, t2),
+
+ /* Subtract 3*x from t1. */
+ MSUB(t1, P1x),
+ MSUB(t1, P1x),
+ MSUB(t1, P1x),
+
+ /* Add b. */
+ MADD(t1, P2y),
+
+ /* Compute y^2 in t2. */
+ MMUL(t2, P1y, P1y),
+
+ /* Compare y^2 with x^3 - 3*x + b; they must match. */
+ MSUB(t1, t2),
+ MTZ(t1),
+
+ /* Set z to 1 (in Montgomery representation). */
+ MMUL(P1z, P2x, P2z),
+
+ ENDCODE
+};
+
+/*
+ * Conversion back to affine coordinates. This code snippet assumes that
+ * the z coordinate of P2 is set to 1 (not in Montgomery representation).
+ */
+static const uint16_t code_affine[] = {
+
+ /* Save z*R in t1. */
+ MSET(t1, P1z),
+
+ /* Compute z^3 in t2. */
+ MMUL(t2, P1z, P1z),
+ MMUL(t3, P1z, t2),
+ MMUL(t2, t3, P2z),
+
+ /* Invert to (1/z^3) in t2. */
+ MINV(t2, t3, t4),
+
+ /* Compute y. */
+ MSET(t3, P1y),
+ MMUL(P1y, t2, t3),
+
+ /* Compute (1/z^2) in t3. */
+ MMUL(t3, t2, t1),
+
+ /* Compute x. */
+ MSET(t2, P1x),
+ MMUL(P1x, t2, t3),
+
+ ENDCODE
+};
+
+static uint32_t
+run_code(jacobian *P1, const jacobian *P2,
+ const curve_params *cc, const uint16_t *code)
+{
+ uint32_t r;
+ uint16_t t[13][I15_LEN];
+ size_t u;
+
+ r = 1;
+
+ /*
+ * Copy the two operands in the dedicated registers.
+ */
+ memcpy(t[P1x], P1->c, 3 * I15_LEN * sizeof(uint16_t));
+ memcpy(t[P2x], P2->c, 3 * I15_LEN * sizeof(uint16_t));
+
+ /*
+ * Run formulas.
+ */
+ for (u = 0;; u ++) {
+ unsigned op, d, a, b;
+
+ op = code[u];
+ if (op == 0) {
+ break;
+ }
+ d = (op >> 8) & 0x0F;
+ a = (op >> 4) & 0x0F;
+ b = op & 0x0F;
+ op >>= 12;
+ switch (op) {
+ uint32_t ctl;
+ size_t plen;
+ unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
+
+ case 0:
+ memcpy(t[d], t[a], I15_LEN * sizeof(uint16_t));
+ break;
+ case 1:
+ ctl = br_i15_add(t[d], t[a], 1);
+ ctl |= NOT(br_i15_sub(t[d], cc->p, 0));
+ br_i15_sub(t[d], cc->p, ctl);
+ break;
+ case 2:
+ br_i15_add(t[d], cc->p, br_i15_sub(t[d], t[a], 1));
+ break;
+ case 3:
+ br_i15_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
+ break;
+ case 4:
+ plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
+ br_i15_encode(tp, plen, cc->p);
+ tp[plen - 1] -= 2;
+ br_i15_modpow(t[d], tp, plen,
+ cc->p, cc->p0i, t[a], t[b]);
+ break;
+ default:
+ r &= ~br_i15_iszero(t[d]);
+ break;
+ }
+ }
+
+ /*
+ * Copy back result.
+ */
+ memcpy(P1->c, t[P1x], 3 * I15_LEN * sizeof(uint16_t));
+ return r;
+}
+
+static void
+set_one(uint16_t *x, const uint16_t *p)
+{
+ size_t plen;
+
+ plen = (p[0] + 31) >> 4;
+ memset(x, 0, plen * sizeof *x);
+ x[0] = p[0];
+ x[1] = 0x0001;
+}
+
+static void
+point_zero(jacobian *P, const curve_params *cc)
+{
+ memset(P, 0, sizeof *P);
+ P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
+}
+
+static inline void
+point_double(jacobian *P, const curve_params *cc)
+{
+ run_code(P, P, cc, code_double);
+}
+
+static inline uint32_t
+point_add(jacobian *P1, const jacobian *P2, const curve_params *cc)
+{
+ return run_code(P1, P2, cc, code_add);
+}
+
+static void
+point_mul(jacobian *P, const unsigned char *x, size_t xlen,
+ const curve_params *cc)
+{
+ /*
+ * We do a simple double-and-add ladder with a 2-bit window
+ * to make only one add every two doublings. We thus first
+ * precompute 2P and 3P in some local buffers.
+ *
+ * We always perform two doublings and one addition; the
+ * addition is with P, 2P and 3P and is done in a temporary
+ * array.
+ *
+ * The addition code cannot handle cases where one of the
+ * operands is infinity, which is the case at the start of the
+ * ladder. We therefore need to maintain a flag that controls
+ * this situation.
+ */
+ uint32_t qz;
+ jacobian P2, P3, Q, T, U;
+
+ memcpy(&P2, P, sizeof P2);
+ point_double(&P2, cc);
+ memcpy(&P3, P, sizeof P3);
+ point_add(&P3, &P2, cc);
+
+ point_zero(&Q, cc);
+ qz = 1;
+ while (xlen -- > 0) {
+ int k;
+
+ for (k = 6; k >= 0; k -= 2) {
+ uint32_t bits;
+ uint32_t bnz;
+
+ point_double(&Q, cc);
+ point_double(&Q, cc);
+ memcpy(&T, P, sizeof T);
+ memcpy(&U, &Q, sizeof U);
+ bits = (*x >> k) & (uint32_t)3;
+ bnz = NEQ(bits, 0);
+ CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
+ CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
+ point_add(&U, &T, cc);
+ CCOPY(bnz & qz, &Q, &T, sizeof Q);
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ }
+ x ++;
+ }
+ memcpy(P, &Q, sizeof Q);
+}
+
+/*
+ * Decode point into Jacobian coordinates. This function does not support
+ * the point at infinity. If the point is invalid then this returns 0, but
+ * the coordinates are still set to properly formed field elements.
+ */
+static uint32_t
+point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc)
+{
+ /*
+ * Points must use uncompressed format:
+ * -- first byte is 0x04;
+ * -- coordinates X and Y use unsigned big-endian, with the same
+ * length as the field modulus.
+ *
+ * We don't support hybrid format (uncompressed, but first byte
+ * has value 0x06 or 0x07, depending on the least significant bit
+ * of Y) because it is rather useless, and explicitly forbidden
+ * by PKIX (RFC 5480, section 2.2).
+ *
+ * We don't support compressed format either, because it is not
+ * much used in practice (there are or were patent-related
+ * concerns about point compression, which explains the lack of
+ * generalised support). Also, point compression support would
+ * need a bit more code.
+ */
+ const unsigned char *buf;
+ size_t plen, zlen;
+ uint32_t r;
+ jacobian Q;
+
+ buf = src;
+ point_zero(P, cc);
+ plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
+ if (len != 1 + (plen << 1)) {
+ return 0;
+ }
+ r = br_i15_decode_mod(P->c[0], buf + 1, plen, cc->p);
+ r &= br_i15_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
+
+ /*
+ * Check first byte.
+ */
+ r &= EQ(buf[0], 0x04);
+ /* obsolete
+ r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
+ & ~(uint32_t)(buf[0] ^ buf[plen << 1]));
+ */
+
+ /*
+ * Convert coordinates and check that the point is valid.
+ */
+ zlen = ((cc->p[0] + 31) >> 4) * sizeof(uint16_t);
+ memcpy(Q.c[0], cc->R2, zlen);
+ memcpy(Q.c[1], cc->b, zlen);
+ set_one(Q.c[2], cc->p);
+ r &= ~run_code(P, &Q, cc, code_check);
+ return r;
+}
+
+/*
+ * Encode a point. This method assumes that the point is correct and is
+ * not the point at infinity. Encoded size is always 1+2*plen, where
+ * plen is the field modulus length, in bytes.
+ */
+static void
+point_encode(void *dst, const jacobian *P, const curve_params *cc)
+{
+ unsigned char *buf;
+ size_t plen;
+ jacobian Q, T;
+
+ buf = dst;
+ plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
+ buf[0] = 0x04;
+ memcpy(&Q, P, sizeof *P);
+ set_one(T.c[2], cc->p);
+ run_code(&Q, &T, cc, code_affine);
+ br_i15_encode(buf + 1, plen, Q.c[0]);
+ br_i15_encode(buf + 1 + plen, plen, Q.c[1]);
+}
+
+static const br_ec_curve_def *
+id_to_curve_def(int curve)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return &br_secp256r1;
+ case BR_EC_secp384r1:
+ return &br_secp384r1;
+ case BR_EC_secp521r1:
+ return &br_secp521r1;
+ }
+ return NULL;
+}
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ const br_ec_curve_def *cd;
+
+ cd = id_to_curve_def(curve);
+ *len = cd->generator_len;
+ return cd->generator;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ const br_ec_curve_def *cd;
+
+ cd = id_to_curve_def(curve);
+ *len = cd->order_len;
+ return cd->order;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ api_generator(curve, len);
+ *len >>= 1;
+ return 1;
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ uint32_t r;
+ const curve_params *cc;
+ jacobian P;
+
+ cc = id_to_curve(curve);
+ r = point_decode(&P, G, Glen, cc);
+ point_mul(&P, x, xlen, cc);
+ if (Glen == cc->point_len) {
+ point_encode(G, &P, cc);
+ }
+ return r;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ uint32_t r, t, z;
+ const curve_params *cc;
+ jacobian P, Q;
+
+ /*
+ * TODO: see about merging the two ladders. Right now, we do
+ * two independent point multiplications, which is a bit
+ * wasteful of CPU resources (but yields short code).
+ */
+
+ cc = id_to_curve(curve);
+ r = point_decode(&P, A, len, cc);
+ if (B == NULL) {
+ size_t Glen;
+
+ B = api_generator(curve, &Glen);
+ }
+ r &= point_decode(&Q, B, len, cc);
+ point_mul(&P, x, xlen, cc);
+ point_mul(&Q, y, ylen, cc);
+
+ /*
+ * We want to compute P+Q. Since the base points A and B are distinct
+ * from infinity, and the multipliers are non-zero and lower than the
+ * curve order, then we know that P and Q are non-infinity. This
+ * leaves two special situations to test for:
+ * -- If P = Q then we must use point_double().
+ * -- If P+Q = 0 then we must report an error.
+ */
+ t = point_add(&P, &Q, cc);
+ point_double(&Q, cc);
+ z = br_i15_iszero(P.c[2]);
+
+ /*
+ * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
+ * have the following:
+ *
+ * z = 0, t = 0 return P (normal addition)
+ * z = 0, t = 1 return P (normal addition)
+ * z = 1, t = 0 return Q (a 'double' case)
+ * z = 1, t = 1 report an error (P+Q = 0)
+ */
+ CCOPY(z & ~t, &P, &Q, sizeof Q);
+ point_encode(A, &P, cc);
+ r &= ~(z & t);
+
+ return r;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_prime_i15 = {
+ (uint32_t)0x03800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_prime_i15.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_prime_i31.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_prime_i31.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_prime_i31.c (revision 346145)
@@ -0,0 +1,819 @@
+/*
+ * 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"
+
+/*
+ * Parameters for supported curves (field modulus, and 'b' equation
+ * parameter; both values use the 'i31' format, and 'b' is in Montgomery
+ * representation).
+ */
+
+static const uint32_t P256_P[] = {
+ 0x00000108,
+ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
+ 0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
+ 0x000000FF
+};
+
+static const uint32_t P256_R2[] = {
+ 0x00000108,
+ 0x00014000, 0x00018000, 0x00000000, 0x7FF40000,
+ 0x7FEFFFFF, 0x7FF7FFFF, 0x7FAFFFFF, 0x005FFFFF,
+ 0x00000000
+};
+
+static const uint32_t P256_B[] = {
+ 0x00000108,
+ 0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
+ 0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
+ 0x0000000E
+};
+
+static const uint32_t P384_P[] = {
+ 0x0000018C,
+ 0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8,
+ 0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
+ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
+ 0x00000FFF
+};
+
+static const uint32_t P384_R2[] = {
+ 0x0000018C,
+ 0x00000000, 0x00000080, 0x7FFFFE00, 0x000001FF,
+ 0x00000800, 0x00000000, 0x7FFFE000, 0x00001FFF,
+ 0x00008000, 0x00008000, 0x00000000, 0x00000000,
+ 0x00000000
+};
+
+static const uint32_t P384_B[] = {
+ 0x0000018C,
+ 0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
+ 0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
+ 0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
+ 0x000008A5
+};
+
+static const uint32_t P521_P[] = {
+ 0x00000219,
+ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
+ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
+ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
+ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
+ 0x01FFFFFF
+};
+
+static const uint32_t P521_R2[] = {
+ 0x00000219,
+ 0x00001000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000
+};
+
+static const uint32_t P521_B[] = {
+ 0x00000219,
+ 0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
+ 0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
+ 0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
+ 0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
+ 0x00654FAE
+};
+
+typedef struct {
+ const uint32_t *p;
+ const uint32_t *b;
+ const uint32_t *R2;
+ uint32_t p0i;
+} curve_params;
+
+static inline const curve_params *
+id_to_curve(int curve)
+{
+ static const curve_params pp[] = {
+ { P256_P, P256_B, P256_R2, 0x00000001 },
+ { P384_P, P384_B, P384_R2, 0x00000001 },
+ { P521_P, P521_B, P521_R2, 0x00000001 }
+ };
+
+ return &pp[curve - BR_EC_secp256r1];
+}
+
+#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
+
+/*
+ * Type for a point in Jacobian coordinates:
+ * -- three values, x, y and z, in Montgomery representation
+ * -- affine coordinates are X = x / z^2 and Y = y / z^3
+ * -- for the point at infinity, z = 0
+ */
+typedef struct {
+ uint32_t c[3][I31_LEN];
+} jacobian;
+
+/*
+ * We use a custom interpreter that uses a dozen registers, and
+ * only six operations:
+ * MSET(d, a) copy a into d
+ * MADD(d, a) d = d+a (modular)
+ * MSUB(d, a) d = d-a (modular)
+ * MMUL(d, a, b) d = a*b (Montgomery multiplication)
+ * MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
+ * MTZ(d) clear return value if d = 0
+ * Destination of MMUL (d) must be distinct from operands (a and b).
+ * There is no such constraint for MSUB and MADD.
+ *
+ * Registers include the operand coordinates, and temporaries.
+ */
+#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
+#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
+#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
+#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
+#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
+#define MTZ(d) (0x5000 + ((d) << 8))
+#define ENDCODE 0
+
+/*
+ * Registers for the input operands.
+ */
+#define P1x 0
+#define P1y 1
+#define P1z 2
+#define P2x 3
+#define P2y 4
+#define P2z 5
+
+/*
+ * Alternate names for the first input operand.
+ */
+#define Px 0
+#define Py 1
+#define Pz 2
+
+/*
+ * Temporaries.
+ */
+#define t1 6
+#define t2 7
+#define t3 8
+#define t4 9
+#define t5 10
+#define t6 11
+#define t7 12
+
+/*
+ * Extra scratch registers available when there is no second operand (e.g.
+ * for "double" and "affine").
+ */
+#define t8 3
+#define t9 4
+#define t10 5
+
+/*
+ * Doubling formulas are:
+ *
+ * s = 4*x*y^2
+ * m = 3*(x + z^2)*(x - z^2)
+ * x' = m^2 - 2*s
+ * y' = m*(s - x') - 8*y^4
+ * z' = 2*y*z
+ *
+ * If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
+ * should. This case should not happen anyway, because our curves have
+ * prime order, and thus do not contain any point of order 2.
+ *
+ * If P is infinity (z = 0), then again the formulas yield infinity,
+ * which is correct. Thus, this code works for all points.
+ *
+ * Cost: 8 multiplications
+ */
+static const uint16_t code_double[] = {
+ /*
+ * Compute z^2 (in t1).
+ */
+ MMUL(t1, Pz, Pz),
+
+ /*
+ * Compute x-z^2 (in t2) and then x+z^2 (in t1).
+ */
+ MSET(t2, Px),
+ MSUB(t2, t1),
+ MADD(t1, Px),
+
+ /*
+ * Compute m = 3*(x+z^2)*(x-z^2) (in t1).
+ */
+ MMUL(t3, t1, t2),
+ MSET(t1, t3),
+ MADD(t1, t3),
+ MADD(t1, t3),
+
+ /*
+ * Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
+ */
+ MMUL(t3, Py, Py),
+ MADD(t3, t3),
+ MMUL(t2, Px, t3),
+ MADD(t2, t2),
+
+ /*
+ * Compute x' = m^2 - 2*s.
+ */
+ MMUL(Px, t1, t1),
+ MSUB(Px, t2),
+ MSUB(Px, t2),
+
+ /*
+ * Compute z' = 2*y*z.
+ */
+ MMUL(t4, Py, Pz),
+ MSET(Pz, t4),
+ MADD(Pz, t4),
+
+ /*
+ * Compute y' = m*(s - x') - 8*y^4. Note that we already have
+ * 2*y^2 in t3.
+ */
+ MSUB(t2, Px),
+ MMUL(Py, t1, t2),
+ MMUL(t4, t3, t3),
+ MSUB(Py, t4),
+ MSUB(Py, t4),
+
+ ENDCODE
+};
+
+/*
+ * Addtions formulas are:
+ *
+ * u1 = x1 * z2^2
+ * u2 = x2 * z1^2
+ * s1 = y1 * z2^3
+ * s2 = y2 * z1^3
+ * h = u2 - u1
+ * r = s2 - s1
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
+ * z3 = h * z1 * z2
+ *
+ * If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
+ * z3 == 0, so the result is correct.
+ * If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
+ * not correct.
+ * h == 0 only if u1 == u2; this happens in two cases:
+ * -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
+ * -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
+ *
+ * Thus, the following situations are not handled correctly:
+ * -- P1 = 0 and P2 != 0
+ * -- P1 != 0 and P2 = 0
+ * -- P1 = P2
+ * All other cases are properly computed. However, even in "incorrect"
+ * situations, the three coordinates still are properly formed field
+ * elements.
+ *
+ * The returned flag is cleared if r == 0. This happens in the following
+ * cases:
+ * -- Both points are on the same horizontal line (same Y coordinate).
+ * -- Both points are infinity.
+ * -- One point is infinity and the other is on line Y = 0.
+ * The third case cannot happen with our curves (there is no valid point
+ * on line Y = 0 since that would be a point of order 2). If the two
+ * source points are non-infinity, then remains only the case where the
+ * two points are on the same horizontal line.
+ *
+ * This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
+ * P2 != 0:
+ * -- If the returned value is not the point at infinity, then it was properly
+ * computed.
+ * -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
+ * is indeed the point at infinity.
+ * -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
+ * use the 'double' code.
+ *
+ * Cost: 16 multiplications
+ */
+static const uint16_t code_add[] = {
+ /*
+ * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
+ */
+ MMUL(t3, P2z, P2z),
+ MMUL(t1, P1x, t3),
+ MMUL(t4, P2z, t3),
+ MMUL(t3, P1y, t4),
+
+ /*
+ * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
+ */
+ MMUL(t4, P1z, P1z),
+ MMUL(t2, P2x, t4),
+ MMUL(t5, P1z, t4),
+ MMUL(t4, P2y, t5),
+
+ /*
+ * Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
+ */
+ MSUB(t2, t1),
+ MSUB(t4, t3),
+
+ /*
+ * Report cases where r = 0 through the returned flag.
+ */
+ MTZ(t4),
+
+ /*
+ * Compute u1*h^2 (in t6) and h^3 (in t5).
+ */
+ MMUL(t7, t2, t2),
+ MMUL(t6, t1, t7),
+ MMUL(t5, t7, t2),
+
+ /*
+ * Compute x3 = r^2 - h^3 - 2*u1*h^2.
+ * t1 and t7 can be used as scratch registers.
+ */
+ MMUL(P1x, t4, t4),
+ MSUB(P1x, t5),
+ MSUB(P1x, t6),
+ MSUB(P1x, t6),
+
+ /*
+ * Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
+ */
+ MSUB(t6, P1x),
+ MMUL(P1y, t4, t6),
+ MMUL(t1, t5, t3),
+ MSUB(P1y, t1),
+
+ /*
+ * Compute z3 = h*z1*z2.
+ */
+ MMUL(t1, P1z, P2z),
+ MMUL(P1z, t1, t2),
+
+ ENDCODE
+};
+
+/*
+ * Check that the point is on the curve. This code snippet assumes the
+ * following conventions:
+ * -- Coordinates x and y have been freshly decoded in P1 (but not
+ * converted to Montgomery coordinates yet).
+ * -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
+ */
+static const uint16_t code_check[] = {
+
+ /* Convert x and y to Montgomery representation. */
+ MMUL(t1, P1x, P2x),
+ MMUL(t2, P1y, P2x),
+ MSET(P1x, t1),
+ MSET(P1y, t2),
+
+ /* Compute x^3 in t1. */
+ MMUL(t2, P1x, P1x),
+ MMUL(t1, P1x, t2),
+
+ /* Subtract 3*x from t1. */
+ MSUB(t1, P1x),
+ MSUB(t1, P1x),
+ MSUB(t1, P1x),
+
+ /* Add b. */
+ MADD(t1, P2y),
+
+ /* Compute y^2 in t2. */
+ MMUL(t2, P1y, P1y),
+
+ /* Compare y^2 with x^3 - 3*x + b; they must match. */
+ MSUB(t1, t2),
+ MTZ(t1),
+
+ /* Set z to 1 (in Montgomery representation). */
+ MMUL(P1z, P2x, P2z),
+
+ ENDCODE
+};
+
+/*
+ * Conversion back to affine coordinates. This code snippet assumes that
+ * the z coordinate of P2 is set to 1 (not in Montgomery representation).
+ */
+static const uint16_t code_affine[] = {
+
+ /* Save z*R in t1. */
+ MSET(t1, P1z),
+
+ /* Compute z^3 in t2. */
+ MMUL(t2, P1z, P1z),
+ MMUL(t3, P1z, t2),
+ MMUL(t2, t3, P2z),
+
+ /* Invert to (1/z^3) in t2. */
+ MINV(t2, t3, t4),
+
+ /* Compute y. */
+ MSET(t3, P1y),
+ MMUL(P1y, t2, t3),
+
+ /* Compute (1/z^2) in t3. */
+ MMUL(t3, t2, t1),
+
+ /* Compute x. */
+ MSET(t2, P1x),
+ MMUL(P1x, t2, t3),
+
+ ENDCODE
+};
+
+static uint32_t
+run_code(jacobian *P1, const jacobian *P2,
+ const curve_params *cc, const uint16_t *code)
+{
+ uint32_t r;
+ uint32_t t[13][I31_LEN];
+ size_t u;
+
+ r = 1;
+
+ /*
+ * Copy the two operands in the dedicated registers.
+ */
+ memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t));
+ memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t));
+
+ /*
+ * Run formulas.
+ */
+ for (u = 0;; u ++) {
+ unsigned op, d, a, b;
+
+ op = code[u];
+ if (op == 0) {
+ break;
+ }
+ d = (op >> 8) & 0x0F;
+ a = (op >> 4) & 0x0F;
+ b = op & 0x0F;
+ op >>= 12;
+ switch (op) {
+ uint32_t ctl;
+ size_t plen;
+ unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
+
+ case 0:
+ memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t));
+ break;
+ case 1:
+ ctl = br_i31_add(t[d], t[a], 1);
+ ctl |= NOT(br_i31_sub(t[d], cc->p, 0));
+ br_i31_sub(t[d], cc->p, ctl);
+ break;
+ case 2:
+ br_i31_add(t[d], cc->p, br_i31_sub(t[d], t[a], 1));
+ break;
+ case 3:
+ br_i31_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
+ break;
+ case 4:
+ plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
+ br_i31_encode(tp, plen, cc->p);
+ tp[plen - 1] -= 2;
+ br_i31_modpow(t[d], tp, plen,
+ cc->p, cc->p0i, t[a], t[b]);
+ break;
+ default:
+ r &= ~br_i31_iszero(t[d]);
+ break;
+ }
+ }
+
+ /*
+ * Copy back result.
+ */
+ memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t));
+ return r;
+}
+
+static void
+set_one(uint32_t *x, const uint32_t *p)
+{
+ size_t plen;
+
+ plen = (p[0] + 63) >> 5;
+ memset(x, 0, plen * sizeof *x);
+ x[0] = p[0];
+ x[1] = 0x00000001;
+}
+
+static void
+point_zero(jacobian *P, const curve_params *cc)
+{
+ memset(P, 0, sizeof *P);
+ P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
+}
+
+static inline void
+point_double(jacobian *P, const curve_params *cc)
+{
+ run_code(P, P, cc, code_double);
+}
+
+static inline uint32_t
+point_add(jacobian *P1, const jacobian *P2, const curve_params *cc)
+{
+ return run_code(P1, P2, cc, code_add);
+}
+
+static void
+point_mul(jacobian *P, const unsigned char *x, size_t xlen,
+ const curve_params *cc)
+{
+ /*
+ * We do a simple double-and-add ladder with a 2-bit window
+ * to make only one add every two doublings. We thus first
+ * precompute 2P and 3P in some local buffers.
+ *
+ * We always perform two doublings and one addition; the
+ * addition is with P, 2P and 3P and is done in a temporary
+ * array.
+ *
+ * The addition code cannot handle cases where one of the
+ * operands is infinity, which is the case at the start of the
+ * ladder. We therefore need to maintain a flag that controls
+ * this situation.
+ */
+ uint32_t qz;
+ jacobian P2, P3, Q, T, U;
+
+ memcpy(&P2, P, sizeof P2);
+ point_double(&P2, cc);
+ memcpy(&P3, P, sizeof P3);
+ point_add(&P3, &P2, cc);
+
+ point_zero(&Q, cc);
+ qz = 1;
+ while (xlen -- > 0) {
+ int k;
+
+ for (k = 6; k >= 0; k -= 2) {
+ uint32_t bits;
+ uint32_t bnz;
+
+ point_double(&Q, cc);
+ point_double(&Q, cc);
+ memcpy(&T, P, sizeof T);
+ memcpy(&U, &Q, sizeof U);
+ bits = (*x >> k) & (uint32_t)3;
+ bnz = NEQ(bits, 0);
+ CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
+ CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
+ point_add(&U, &T, cc);
+ CCOPY(bnz & qz, &Q, &T, sizeof Q);
+ CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
+ qz &= ~bnz;
+ }
+ x ++;
+ }
+ memcpy(P, &Q, sizeof Q);
+}
+
+/*
+ * Decode point into Jacobian coordinates. This function does not support
+ * the point at infinity. If the point is invalid then this returns 0, but
+ * the coordinates are still set to properly formed field elements.
+ */
+static uint32_t
+point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc)
+{
+ /*
+ * Points must use uncompressed format:
+ * -- first byte is 0x04;
+ * -- coordinates X and Y use unsigned big-endian, with the same
+ * length as the field modulus.
+ *
+ * We don't support hybrid format (uncompressed, but first byte
+ * has value 0x06 or 0x07, depending on the least significant bit
+ * of Y) because it is rather useless, and explicitly forbidden
+ * by PKIX (RFC 5480, section 2.2).
+ *
+ * We don't support compressed format either, because it is not
+ * much used in practice (there are or were patent-related
+ * concerns about point compression, which explains the lack of
+ * generalised support). Also, point compression support would
+ * need a bit more code.
+ */
+ const unsigned char *buf;
+ size_t plen, zlen;
+ uint32_t r;
+ jacobian Q;
+
+ buf = src;
+ point_zero(P, cc);
+ plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
+ if (len != 1 + (plen << 1)) {
+ return 0;
+ }
+ r = br_i31_decode_mod(P->c[0], buf + 1, plen, cc->p);
+ r &= br_i31_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
+
+ /*
+ * Check first byte.
+ */
+ r &= EQ(buf[0], 0x04);
+ /* obsolete
+ r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
+ & ~(uint32_t)(buf[0] ^ buf[plen << 1]));
+ */
+
+ /*
+ * Convert coordinates and check that the point is valid.
+ */
+ zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t);
+ memcpy(Q.c[0], cc->R2, zlen);
+ memcpy(Q.c[1], cc->b, zlen);
+ set_one(Q.c[2], cc->p);
+ r &= ~run_code(P, &Q, cc, code_check);
+ return r;
+}
+
+/*
+ * Encode a point. This method assumes that the point is correct and is
+ * not the point at infinity. Encoded size is always 1+2*plen, where
+ * plen is the field modulus length, in bytes.
+ */
+static void
+point_encode(void *dst, const jacobian *P, const curve_params *cc)
+{
+ unsigned char *buf;
+ uint32_t xbl;
+ size_t plen;
+ jacobian Q, T;
+
+ buf = dst;
+ xbl = cc->p[0];
+ xbl -= (xbl >> 5);
+ plen = (xbl + 7) >> 3;
+ buf[0] = 0x04;
+ memcpy(&Q, P, sizeof *P);
+ set_one(T.c[2], cc->p);
+ run_code(&Q, &T, cc, code_affine);
+ br_i31_encode(buf + 1, plen, Q.c[0]);
+ br_i31_encode(buf + 1 + plen, plen, Q.c[1]);
+}
+
+static const br_ec_curve_def *
+id_to_curve_def(int curve)
+{
+ switch (curve) {
+ case BR_EC_secp256r1:
+ return &br_secp256r1;
+ case BR_EC_secp384r1:
+ return &br_secp384r1;
+ case BR_EC_secp521r1:
+ return &br_secp521r1;
+ }
+ return NULL;
+}
+
+static const unsigned char *
+api_generator(int curve, size_t *len)
+{
+ const br_ec_curve_def *cd;
+
+ cd = id_to_curve_def(curve);
+ *len = cd->generator_len;
+ return cd->generator;
+}
+
+static const unsigned char *
+api_order(int curve, size_t *len)
+{
+ const br_ec_curve_def *cd;
+
+ cd = id_to_curve_def(curve);
+ *len = cd->order_len;
+ return cd->order;
+}
+
+static size_t
+api_xoff(int curve, size_t *len)
+{
+ api_generator(curve, len);
+ *len >>= 1;
+ return 1;
+}
+
+static uint32_t
+api_mul(unsigned char *G, size_t Glen,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ uint32_t r;
+ const curve_params *cc;
+ jacobian P;
+
+ cc = id_to_curve(curve);
+ r = point_decode(&P, G, Glen, cc);
+ point_mul(&P, x, xlen, cc);
+ point_encode(G, &P, cc);
+ return r;
+}
+
+static size_t
+api_mulgen(unsigned char *R,
+ const unsigned char *x, size_t xlen, int curve)
+{
+ const unsigned char *G;
+ size_t Glen;
+
+ G = api_generator(curve, &Glen);
+ memcpy(R, G, Glen);
+ api_mul(R, Glen, x, xlen, curve);
+ return Glen;
+}
+
+static uint32_t
+api_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)
+{
+ uint32_t r, t, z;
+ const curve_params *cc;
+ jacobian P, Q;
+
+ /*
+ * TODO: see about merging the two ladders. Right now, we do
+ * two independent point multiplications, which is a bit
+ * wasteful of CPU resources (but yields short code).
+ */
+
+ cc = id_to_curve(curve);
+ r = point_decode(&P, A, len, cc);
+ if (B == NULL) {
+ size_t Glen;
+
+ B = api_generator(curve, &Glen);
+ }
+ r &= point_decode(&Q, B, len, cc);
+ point_mul(&P, x, xlen, cc);
+ point_mul(&Q, y, ylen, cc);
+
+ /*
+ * We want to compute P+Q. Since the base points A and B are distinct
+ * from infinity, and the multipliers are non-zero and lower than the
+ * curve order, then we know that P and Q are non-infinity. This
+ * leaves two special situations to test for:
+ * -- If P = Q then we must use point_double().
+ * -- If P+Q = 0 then we must report an error.
+ */
+ t = point_add(&P, &Q, cc);
+ point_double(&Q, cc);
+ z = br_i31_iszero(P.c[2]);
+
+ /*
+ * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
+ * have the following:
+ *
+ * z = 0, t = 0 return P (normal addition)
+ * z = 0, t = 1 return P (normal addition)
+ * z = 1, t = 0 return Q (a 'double' case)
+ * z = 1, t = 1 report an error (P+Q = 0)
+ */
+ CCOPY(z & ~t, &P, &Q, sizeof Q);
+ point_encode(A, &P, cc);
+ r &= ~(z & t);
+
+ return r;
+}
+
+/* see bearssl_ec.h */
+const br_ec_impl br_ec_prime_i31 = {
+ (uint32_t)0x03800000,
+ &api_generator,
+ &api_order,
+ &api_xoff,
+ &api_mul,
+ &api_mulgen,
+ &api_muladd
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_prime_i31.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_pubkey.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_pubkey.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_pubkey.c (revision 346145)
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+static const unsigned char POINT_LEN[] = {
+ 0, /* 0: not a valid curve ID */
+ 43, /* sect163k1 */
+ 43, /* sect163r1 */
+ 43, /* sect163r2 */
+ 51, /* sect193r1 */
+ 51, /* sect193r2 */
+ 61, /* sect233k1 */
+ 61, /* sect233r1 */
+ 61, /* sect239k1 */
+ 73, /* sect283k1 */
+ 73, /* sect283r1 */
+ 105, /* sect409k1 */
+ 105, /* sect409r1 */
+ 145, /* sect571k1 */
+ 145, /* sect571r1 */
+ 41, /* secp160k1 */
+ 41, /* secp160r1 */
+ 41, /* secp160r2 */
+ 49, /* secp192k1 */
+ 49, /* secp192r1 */
+ 57, /* secp224k1 */
+ 57, /* secp224r1 */
+ 65, /* secp256k1 */
+ 65, /* secp256r1 */
+ 97, /* secp384r1 */
+ 133, /* secp521r1 */
+ 65, /* brainpoolP256r1 */
+ 97, /* brainpoolP384r1 */
+ 129, /* brainpoolP512r1 */
+ 32, /* curve25519 */
+ 56, /* curve448 */
+};
+
+/* see bearssl_ec.h */
+size_t
+br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
+ void *kbuf, const br_ec_private_key *sk)
+{
+ int curve;
+ size_t len;
+
+ curve = sk->curve;
+ if (curve < 0 || curve >= 32 || curve >= (int)(sizeof POINT_LEN)
+ || ((impl->supported_curves >> curve) & 1) == 0)
+ {
+ return 0;
+ }
+ if (kbuf == NULL) {
+ return POINT_LEN[curve];
+ }
+ len = impl->mulgen(kbuf, sk->x, sk->xlen, curve);
+ if (pk != NULL) {
+ pk->curve = curve;
+ pk->q = kbuf;
+ pk->qlen = len;
+ }
+ return len;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ec_pubkey.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_secp256r1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_secp256r1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_secp256r1.c (revision 346145)
@@ -0,0 +1,51 @@
+/*
+ * 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"
+
+static const unsigned char P256_N[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
+};
+
+static const unsigned char P256_G[] = {
+ 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42,
+ 0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40,
+ 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33,
+ 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
+ 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
+ 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E,
+ 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E,
+ 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51,
+ 0xF5
+};
+
+/* see inner.h */
+const br_ec_curve_def br_secp256r1 = {
+ BR_EC_secp256r1,
+ P256_N, sizeof P256_N,
+ P256_G, sizeof P256_G
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_secp256r1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_secp384r1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_secp384r1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_secp384r1.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+static const unsigned char P384_N[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF,
+ 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A,
+ 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
+};
+
+static const unsigned char P384_G[] = {
+ 0x04, 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05,
+ 0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD,
+ 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B,
+ 0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A,
+ 0x38, 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29,
+ 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A,
+ 0xB7, 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C,
+ 0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC,
+ 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14,
+ 0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8,
+ 0xC0, 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81,
+ 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E,
+ 0x5F
+};
+
+/* see inner.h */
+const br_ec_curve_def br_secp384r1 = {
+ BR_EC_secp384r1,
+ P384_N, sizeof P384_N,
+ P384_G, sizeof P384_G
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_secp384r1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ec_secp521r1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ec_secp521r1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ec_secp521r1.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+static const unsigned char P521_N[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
+ 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
+ 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
+ 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
+ 0x64, 0x09
+};
+
+static const unsigned char P521_G[] = {
+ 0x04, 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04,
+ 0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23,
+ 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05,
+ 0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B,
+ 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF,
+ 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2,
+ 0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85,
+ 0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2,
+ 0xE5, 0xBD, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6A,
+ 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F,
+ 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44,
+ 0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD,
+ 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE, 0x72,
+ 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9,
+ 0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35, 0x3C, 0x70,
+ 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94,
+ 0x76, 0x9F, 0xD1, 0x66, 0x50
+};
+
+/* see inner.h */
+const br_ec_curve_def br_secp521r1 = {
+ BR_EC_secp521r1,
+ P521_N, sizeof P521_N,
+ P521_G, sizeof P521_G
+};
Property changes on: stable/12/contrib/bearssl/src/ec/ec_secp521r1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_atr.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_atr.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_atr.c (revision 346145)
@@ -0,0 +1,134 @@
+/*
+ * 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 bearssl_ec.h */
+size_t
+br_ecdsa_asn1_to_raw(void *sig, size_t sig_len)
+{
+ /*
+ * Note: this code is a bit lenient in that it accepts a few
+ * deviations to DER with regards to minimality of encoding of
+ * lengths and integer values. These deviations are still
+ * unambiguous.
+ *
+ * Signature format is a SEQUENCE of two INTEGER values. We
+ * support only integers of less than 127 bytes each (signed
+ * encoding) so the resulting raw signature will have length
+ * at most 254 bytes.
+ */
+
+ unsigned char *buf, *r, *s;
+ size_t zlen, rlen, slen, off;
+ unsigned char tmp[254];
+
+ buf = sig;
+ if (sig_len < 8) {
+ return 0;
+ }
+
+ /*
+ * First byte is SEQUENCE tag.
+ */
+ if (buf[0] != 0x30) {
+ return 0;
+ }
+
+ /*
+ * The SEQUENCE length will be encoded over one or two bytes. We
+ * limit the total SEQUENCE contents to 255 bytes, because it
+ * makes things simpler; this is enough for subgroup orders up
+ * to 999 bits.
+ */
+ zlen = buf[1];
+ if (zlen > 0x80) {
+ if (zlen != 0x81) {
+ return 0;
+ }
+ zlen = buf[2];
+ if (zlen != sig_len - 3) {
+ return 0;
+ }
+ off = 3;
+ } else {
+ if (zlen != sig_len - 2) {
+ return 0;
+ }
+ off = 2;
+ }
+
+ /*
+ * First INTEGER (r).
+ */
+ if (buf[off ++] != 0x02) {
+ return 0;
+ }
+ rlen = buf[off ++];
+ if (rlen >= 0x80) {
+ return 0;
+ }
+ r = buf + off;
+ off += rlen;
+
+ /*
+ * Second INTEGER (s).
+ */
+ if (off + 2 > sig_len) {
+ return 0;
+ }
+ if (buf[off ++] != 0x02) {
+ return 0;
+ }
+ slen = buf[off ++];
+ if (slen >= 0x80 || slen != sig_len - off) {
+ return 0;
+ }
+ s = buf + off;
+
+ /*
+ * Removing leading zeros from r and s.
+ */
+ while (rlen > 0 && *r == 0) {
+ rlen --;
+ r ++;
+ }
+ while (slen > 0 && *s == 0) {
+ slen --;
+ s ++;
+ }
+
+ /*
+ * Compute common length for the two integers, then copy integers
+ * into the temporary buffer, and finally copy it back over the
+ * signature buffer.
+ */
+ zlen = rlen > slen ? rlen : slen;
+ sig_len = zlen << 1;
+ memset(tmp, 0, sig_len);
+ memcpy(tmp + zlen - rlen, r, rlen);
+ memcpy(tmp + sig_len - slen, s, slen);
+ memcpy(sig, tmp, sig_len);
+ return sig_len;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_atr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_asn1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_asn1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_asn1.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+/* see bearssl_ec.h */
+br_ecdsa_sign
+br_ecdsa_sign_asn1_get_default(void)
+{
+#if BR_LOMUL
+ return &br_ecdsa_i15_sign_asn1;
+#else
+ return &br_ecdsa_i31_sign_asn1;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_asn1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_raw.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_raw.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_raw.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+/* see bearssl_ec.h */
+br_ecdsa_sign
+br_ecdsa_sign_raw_get_default(void)
+{
+#if BR_LOMUL
+ return &br_ecdsa_i15_sign_raw;
+#else
+ return &br_ecdsa_i31_sign_raw;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_default_sign_raw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_asn1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_asn1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_asn1.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+/* see bearssl_ec.h */
+br_ecdsa_vrfy
+br_ecdsa_vrfy_asn1_get_default(void)
+{
+#if BR_LOMUL
+ return &br_ecdsa_i15_vrfy_asn1;
+#else
+ return &br_ecdsa_i31_vrfy_asn1;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_asn1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_raw.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_raw.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_raw.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+/* see bearssl_ec.h */
+br_ecdsa_vrfy
+br_ecdsa_vrfy_raw_get_default(void)
+{
+#if BR_LOMUL
+ return &br_ecdsa_i15_vrfy_raw;
+#else
+ return &br_ecdsa_i31_vrfy_raw;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_default_vrfy_raw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i15_bits.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i15_bits.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i15_bits.c (revision 346145)
@@ -0,0 +1,47 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_ecdsa_i15_bits2int(uint16_t *x,
+ const void *src, size_t len, uint32_t ebitlen)
+{
+ uint32_t bitlen, hbitlen;
+ int sc;
+
+ bitlen = ebitlen - (ebitlen >> 4);
+ hbitlen = (uint32_t)len << 3;
+ if (hbitlen > bitlen) {
+ len = (bitlen + 7) >> 3;
+ sc = (int)((hbitlen - bitlen) & 7);
+ } else {
+ sc = 0;
+ }
+ br_i15_zero(x, ebitlen);
+ br_i15_decode(x, src, len);
+ br_i15_rshift(x, sc);
+ x[0] = ebitlen;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i15_bits.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_asn1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_asn1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_asn1.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
+
+/* see bearssl_ec.h */
+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)
+{
+ unsigned char rsig[(ORDER_LEN << 1) + 12];
+ size_t sig_len;
+
+ sig_len = br_ecdsa_i15_sign_raw(impl, hf, hash_value, sk, rsig);
+ if (sig_len == 0) {
+ return 0;
+ }
+ sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
+ memcpy(sig, rsig, sig_len);
+ return sig_len;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_asn1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_raw.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_raw.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_raw.c (revision 346145)
@@ -0,0 +1,174 @@
+/*
+ * 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"
+
+#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
+#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
+#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
+
+/* see bearssl_ec.h */
+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)
+{
+ /*
+ * IMPORTANT: this code is fit only for curves with a prime
+ * order. This is needed so that modular reduction of the X
+ * coordinate of a point can be done with a simple subtraction.
+ * We also rely on the last byte of the curve order to be distinct
+ * from 0 and 1.
+ */
+ const br_ec_curve_def *cd;
+ uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], x[I15_LEN];
+ uint16_t m[I15_LEN], k[I15_LEN], t1[I15_LEN], t2[I15_LEN];
+ unsigned char tt[ORDER_LEN << 1];
+ unsigned char eU[POINT_LEN];
+ size_t hash_len, nlen, ulen;
+ uint16_t n0i;
+ uint32_t ctl;
+ br_hmac_drbg_context drbg;
+
+ /*
+ * If the curve is not supported, then exit with an error.
+ */
+ if (((impl->supported_curves >> sk->curve) & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Get the curve parameters (generator and order).
+ */
+ switch (sk->curve) {
+ case BR_EC_secp256r1:
+ cd = &br_secp256r1;
+ break;
+ case BR_EC_secp384r1:
+ cd = &br_secp384r1;
+ break;
+ case BR_EC_secp521r1:
+ cd = &br_secp521r1;
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * Get modulus.
+ */
+ nlen = cd->order_len;
+ br_i15_decode(n, cd->order, nlen);
+ n0i = br_i15_ninv15(n[1]);
+
+ /*
+ * Get private key as an i15 integer. This also checks that the
+ * private key is well-defined (not zero, and less than the
+ * curve order).
+ */
+ if (!br_i15_decode_mod(x, sk->x, sk->xlen, n)) {
+ return 0;
+ }
+ if (br_i15_iszero(x)) {
+ return 0;
+ }
+
+ /*
+ * Get hash length.
+ */
+ hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+
+ /*
+ * Truncate and reduce the hash value modulo the curve order.
+ */
+ br_ecdsa_i15_bits2int(m, hash_value, hash_len, n[0]);
+ br_i15_sub(m, n, br_i15_sub(m, n, 0) ^ 1);
+
+ /*
+ * RFC 6979 generation of the "k" value.
+ *
+ * The process uses HMAC_DRBG (with the hash function used to
+ * process the message that is to be signed). The seed is the
+ * concatenation of the encodings of the private key and
+ * the hash value (after truncation and modular reduction).
+ */
+ br_i15_encode(tt, nlen, x);
+ br_i15_encode(tt + nlen, nlen, m);
+ br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
+ for (;;) {
+ br_hmac_drbg_generate(&drbg, tt, nlen);
+ br_ecdsa_i15_bits2int(k, tt, nlen, n[0]);
+ if (br_i15_iszero(k)) {
+ continue;
+ }
+ if (br_i15_sub(k, n, 0)) {
+ break;
+ }
+ }
+
+ /*
+ * Compute k*G and extract the X coordinate, then reduce it
+ * modulo the curve order. Since we support only curves with
+ * prime order, that reduction is only a matter of computing
+ * a subtraction.
+ */
+ br_i15_encode(tt, nlen, k);
+ ulen = impl->mulgen(eU, tt, nlen, sk->curve);
+ br_i15_zero(r, n[0]);
+ br_i15_decode(r, &eU[1], ulen >> 1);
+ r[0] = n[0];
+ br_i15_sub(r, n, br_i15_sub(r, n, 0) ^ 1);
+
+ /*
+ * Compute 1/k in double-Montgomery representation. We do so by
+ * first converting _from_ Montgomery representation (twice),
+ * then using a modular exponentiation.
+ */
+ br_i15_from_monty(k, n, n0i);
+ br_i15_from_monty(k, n, n0i);
+ memcpy(tt, cd->order, nlen);
+ tt[nlen - 1] -= 2;
+ br_i15_modpow(k, tt, nlen, n, n0i, t1, t2);
+
+ /*
+ * Compute s = (m+xr)/k (mod n).
+ * The k[] array contains R^2/k (double-Montgomery representation);
+ * we thus can use direct Montgomery multiplications and conversions
+ * from Montgomery, avoiding any call to br_i15_to_monty() (which
+ * is slower).
+ */
+ br_i15_from_monty(m, n, n0i);
+ br_i15_montymul(t1, x, r, n, n0i);
+ ctl = br_i15_add(t1, m, 1);
+ ctl |= br_i15_sub(t1, n, 0) ^ 1;
+ br_i15_sub(t1, n, ctl);
+ br_i15_montymul(s, t1, k, n, n0i);
+
+ /*
+ * Encode r and s in the signature.
+ */
+ br_i15_encode(sig, nlen, r);
+ br_i15_encode((unsigned char *)sig + nlen, nlen, s);
+ return nlen << 1;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i15_sign_raw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_asn1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_asn1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_asn1.c (revision 346145)
@@ -0,0 +1,48 @@
+/*
+ * 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"
+
+#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
+
+/* see bearssl_ec.h */
+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)
+{
+ /*
+ * We use a double-sized buffer because a malformed ASN.1 signature
+ * may trigger a size expansion when converting to "raw" format.
+ */
+ unsigned char rsig[(FIELD_LEN << 2) + 24];
+
+ if (sig_len > ((sizeof rsig) >> 1)) {
+ return 0;
+ }
+ memcpy(rsig, sig, sig_len);
+ sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
+ return br_ecdsa_i15_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_asn1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_raw.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_raw.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_raw.c (revision 346145)
@@ -0,0 +1,166 @@
+/*
+ * 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"
+
+#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
+#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
+
+/* see bearssl_ec.h */
+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)
+{
+ /*
+ * IMPORTANT: this code is fit only for curves with a prime
+ * order. This is needed so that modular reduction of the X
+ * coordinate of a point can be done with a simple subtraction.
+ */
+ const br_ec_curve_def *cd;
+ uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], t1[I15_LEN], t2[I15_LEN];
+ unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
+ unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
+ unsigned char eU[POINT_LEN];
+ size_t nlen, rlen, ulen;
+ uint16_t n0i;
+ uint32_t res;
+
+ /*
+ * If the curve is not supported, then report an error.
+ */
+ if (((impl->supported_curves >> pk->curve) & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Get the curve parameters (generator and order).
+ */
+ switch (pk->curve) {
+ case BR_EC_secp256r1:
+ cd = &br_secp256r1;
+ break;
+ case BR_EC_secp384r1:
+ cd = &br_secp384r1;
+ break;
+ case BR_EC_secp521r1:
+ cd = &br_secp521r1;
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * Signature length must be even.
+ */
+ if (sig_len & 1) {
+ return 0;
+ }
+ rlen = sig_len >> 1;
+
+ /*
+ * Public key point must have the proper size for this curve.
+ */
+ if (pk->qlen != cd->generator_len) {
+ return 0;
+ }
+
+ /*
+ * Get modulus; then decode the r and s values. They must be
+ * lower than the modulus, and s must not be null.
+ */
+ nlen = cd->order_len;
+ br_i15_decode(n, cd->order, nlen);
+ n0i = br_i15_ninv15(n[1]);
+ if (!br_i15_decode_mod(r, sig, rlen, n)) {
+ return 0;
+ }
+ if (!br_i15_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
+ return 0;
+ }
+ if (br_i15_iszero(s)) {
+ return 0;
+ }
+
+ /*
+ * Invert s. We do that with a modular exponentiation; we use
+ * the fact that for all the curves we support, the least
+ * significant byte is not 0 or 1, so we can subtract 2 without
+ * any carry to process.
+ * We also want 1/s in Montgomery representation, which can be
+ * done by converting _from_ Montgomery representation before
+ * the inversion (because (1/s)*R = 1/(s/R)).
+ */
+ br_i15_from_monty(s, n, n0i);
+ memcpy(tx, cd->order, nlen);
+ tx[nlen - 1] -= 2;
+ br_i15_modpow(s, tx, nlen, n, n0i, t1, t2);
+
+ /*
+ * Truncate the hash to the modulus length (in bits) and reduce
+ * it modulo the curve order. The modular reduction can be done
+ * with a subtraction since the truncation already reduced the
+ * value to the modulus bit length.
+ */
+ br_ecdsa_i15_bits2int(t1, hash, hash_len, n[0]);
+ br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
+
+ /*
+ * Multiply the (truncated, reduced) hash value with 1/s, result in
+ * t2, encoded in ty.
+ */
+ br_i15_montymul(t2, t1, s, n, n0i);
+ br_i15_encode(ty, nlen, t2);
+
+ /*
+ * Multiply r with 1/s, result in t1, encoded in tx.
+ */
+ br_i15_montymul(t1, r, s, n, n0i);
+ br_i15_encode(tx, nlen, t1);
+
+ /*
+ * Compute the point x*Q + y*G.
+ */
+ ulen = cd->generator_len;
+ memcpy(eU, pk->q, ulen);
+ res = impl->muladd(eU, NULL, ulen,
+ tx, nlen, ty, nlen, cd->curve);
+
+ /*
+ * Get the X coordinate, reduce modulo the curve order, and
+ * compare with the 'r' value.
+ *
+ * The modular reduction can be done with subtractions because
+ * we work with curves of prime order, so the curve order is
+ * close to the field order (Hasse's theorem).
+ */
+ br_i15_zero(t1, n[0]);
+ br_i15_decode(t1, &eU[1], ulen >> 1);
+ t1[0] = n[0];
+ br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
+ res &= ~br_i15_sub(t1, r, 1);
+ res &= br_i15_iszero(t1);
+ return res;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i15_vrfy_raw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i31_bits.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i31_bits.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i31_bits.c (revision 346145)
@@ -0,0 +1,47 @@
+/*
+ * 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_ecdsa_i31_bits2int(uint32_t *x,
+ const void *src, size_t len, uint32_t ebitlen)
+{
+ uint32_t bitlen, hbitlen;
+ int sc;
+
+ bitlen = ebitlen - (ebitlen >> 5);
+ hbitlen = (uint32_t)len << 3;
+ if (hbitlen > bitlen) {
+ len = (bitlen + 7) >> 3;
+ sc = (int)((hbitlen - bitlen) & 7);
+ } else {
+ sc = 0;
+ }
+ br_i31_zero(x, ebitlen);
+ br_i31_decode(x, src, len);
+ br_i31_rshift(x, sc);
+ x[0] = ebitlen;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i31_bits.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_asn1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_asn1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_asn1.c (revision 346145)
@@ -0,0 +1,45 @@
+/*
+ * 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"
+
+#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
+
+/* see bearssl_ec.h */
+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)
+{
+ unsigned char rsig[(ORDER_LEN << 1) + 12];
+ size_t sig_len;
+
+ sig_len = br_ecdsa_i31_sign_raw(impl, hf, hash_value, sk, rsig);
+ if (sig_len == 0) {
+ return 0;
+ }
+ sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
+ memcpy(sig, rsig, sig_len);
+ return sig_len;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_asn1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_raw.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_raw.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_raw.c (revision 346145)
@@ -0,0 +1,173 @@
+/*
+ * 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"
+
+#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
+#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
+#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
+
+/* see bearssl_ec.h */
+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)
+{
+ /*
+ * IMPORTANT: this code is fit only for curves with a prime
+ * order. This is needed so that modular reduction of the X
+ * coordinate of a point can be done with a simple subtraction.
+ * We also rely on the last byte of the curve order to be distinct
+ * from 0 and 1.
+ */
+ const br_ec_curve_def *cd;
+ uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], x[I31_LEN];
+ uint32_t m[I31_LEN], k[I31_LEN], t1[I31_LEN], t2[I31_LEN];
+ unsigned char tt[ORDER_LEN << 1];
+ unsigned char eU[POINT_LEN];
+ size_t hash_len, nlen, ulen;
+ uint32_t n0i, ctl;
+ br_hmac_drbg_context drbg;
+
+ /*
+ * If the curve is not supported, then exit with an error.
+ */
+ if (((impl->supported_curves >> sk->curve) & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Get the curve parameters (generator and order).
+ */
+ switch (sk->curve) {
+ case BR_EC_secp256r1:
+ cd = &br_secp256r1;
+ break;
+ case BR_EC_secp384r1:
+ cd = &br_secp384r1;
+ break;
+ case BR_EC_secp521r1:
+ cd = &br_secp521r1;
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * Get modulus.
+ */
+ nlen = cd->order_len;
+ br_i31_decode(n, cd->order, nlen);
+ n0i = br_i31_ninv31(n[1]);
+
+ /*
+ * Get private key as an i31 integer. This also checks that the
+ * private key is well-defined (not zero, and less than the
+ * curve order).
+ */
+ if (!br_i31_decode_mod(x, sk->x, sk->xlen, n)) {
+ return 0;
+ }
+ if (br_i31_iszero(x)) {
+ return 0;
+ }
+
+ /*
+ * Get hash length.
+ */
+ hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+
+ /*
+ * Truncate and reduce the hash value modulo the curve order.
+ */
+ br_ecdsa_i31_bits2int(m, hash_value, hash_len, n[0]);
+ br_i31_sub(m, n, br_i31_sub(m, n, 0) ^ 1);
+
+ /*
+ * RFC 6979 generation of the "k" value.
+ *
+ * The process uses HMAC_DRBG (with the hash function used to
+ * process the message that is to be signed). The seed is the
+ * concatenation of the encodings of the private key and
+ * the hash value (after truncation and modular reduction).
+ */
+ br_i31_encode(tt, nlen, x);
+ br_i31_encode(tt + nlen, nlen, m);
+ br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
+ for (;;) {
+ br_hmac_drbg_generate(&drbg, tt, nlen);
+ br_ecdsa_i31_bits2int(k, tt, nlen, n[0]);
+ if (br_i31_iszero(k)) {
+ continue;
+ }
+ if (br_i31_sub(k, n, 0)) {
+ break;
+ }
+ }
+
+ /*
+ * Compute k*G and extract the X coordinate, then reduce it
+ * modulo the curve order. Since we support only curves with
+ * prime order, that reduction is only a matter of computing
+ * a subtraction.
+ */
+ br_i31_encode(tt, nlen, k);
+ ulen = impl->mulgen(eU, tt, nlen, sk->curve);
+ br_i31_zero(r, n[0]);
+ br_i31_decode(r, &eU[1], ulen >> 1);
+ r[0] = n[0];
+ br_i31_sub(r, n, br_i31_sub(r, n, 0) ^ 1);
+
+ /*
+ * Compute 1/k in double-Montgomery representation. We do so by
+ * first converting _from_ Montgomery representation (twice),
+ * then using a modular exponentiation.
+ */
+ br_i31_from_monty(k, n, n0i);
+ br_i31_from_monty(k, n, n0i);
+ memcpy(tt, cd->order, nlen);
+ tt[nlen - 1] -= 2;
+ br_i31_modpow(k, tt, nlen, n, n0i, t1, t2);
+
+ /*
+ * Compute s = (m+xr)/k (mod n).
+ * The k[] array contains R^2/k (double-Montgomery representation);
+ * we thus can use direct Montgomery multiplications and conversions
+ * from Montgomery, avoiding any call to br_i31_to_monty() (which
+ * is slower).
+ */
+ br_i31_from_monty(m, n, n0i);
+ br_i31_montymul(t1, x, r, n, n0i);
+ ctl = br_i31_add(t1, m, 1);
+ ctl |= br_i31_sub(t1, n, 0) ^ 1;
+ br_i31_sub(t1, n, ctl);
+ br_i31_montymul(s, t1, k, n, n0i);
+
+ /*
+ * Encode r and s in the signature.
+ */
+ br_i31_encode(sig, nlen, r);
+ br_i31_encode((unsigned char *)sig + nlen, nlen, s);
+ return nlen << 1;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i31_sign_raw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_asn1.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_asn1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_asn1.c (revision 346145)
@@ -0,0 +1,48 @@
+/*
+ * 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"
+
+#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
+
+/* see bearssl_ec.h */
+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)
+{
+ /*
+ * We use a double-sized buffer because a malformed ASN.1 signature
+ * may trigger a size expansion when converting to "raw" format.
+ */
+ unsigned char rsig[(FIELD_LEN << 2) + 24];
+
+ if (sig_len > ((sizeof rsig) >> 1)) {
+ return 0;
+ }
+ memcpy(rsig, sig, sig_len);
+ sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
+ return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_asn1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_raw.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_raw.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_raw.c (revision 346145)
@@ -0,0 +1,165 @@
+/*
+ * 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"
+
+#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
+#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
+
+/* see bearssl_ec.h */
+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)
+{
+ /*
+ * IMPORTANT: this code is fit only for curves with a prime
+ * order. This is needed so that modular reduction of the X
+ * coordinate of a point can be done with a simple subtraction.
+ */
+ const br_ec_curve_def *cd;
+ uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN];
+ unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
+ unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
+ unsigned char eU[POINT_LEN];
+ size_t nlen, rlen, ulen;
+ uint32_t n0i, res;
+
+ /*
+ * If the curve is not supported, then report an error.
+ */
+ if (((impl->supported_curves >> pk->curve) & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Get the curve parameters (generator and order).
+ */
+ switch (pk->curve) {
+ case BR_EC_secp256r1:
+ cd = &br_secp256r1;
+ break;
+ case BR_EC_secp384r1:
+ cd = &br_secp384r1;
+ break;
+ case BR_EC_secp521r1:
+ cd = &br_secp521r1;
+ break;
+ default:
+ return 0;
+ }
+
+ /*
+ * Signature length must be even.
+ */
+ if (sig_len & 1) {
+ return 0;
+ }
+ rlen = sig_len >> 1;
+
+ /*
+ * Public key point must have the proper size for this curve.
+ */
+ if (pk->qlen != cd->generator_len) {
+ return 0;
+ }
+
+ /*
+ * Get modulus; then decode the r and s values. They must be
+ * lower than the modulus, and s must not be null.
+ */
+ nlen = cd->order_len;
+ br_i31_decode(n, cd->order, nlen);
+ n0i = br_i31_ninv31(n[1]);
+ if (!br_i31_decode_mod(r, sig, rlen, n)) {
+ return 0;
+ }
+ if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
+ return 0;
+ }
+ if (br_i31_iszero(s)) {
+ return 0;
+ }
+
+ /*
+ * Invert s. We do that with a modular exponentiation; we use
+ * the fact that for all the curves we support, the least
+ * significant byte is not 0 or 1, so we can subtract 2 without
+ * any carry to process.
+ * We also want 1/s in Montgomery representation, which can be
+ * done by converting _from_ Montgomery representation before
+ * the inversion (because (1/s)*R = 1/(s/R)).
+ */
+ br_i31_from_monty(s, n, n0i);
+ memcpy(tx, cd->order, nlen);
+ tx[nlen - 1] -= 2;
+ br_i31_modpow(s, tx, nlen, n, n0i, t1, t2);
+
+ /*
+ * Truncate the hash to the modulus length (in bits) and reduce
+ * it modulo the curve order. The modular reduction can be done
+ * with a subtraction since the truncation already reduced the
+ * value to the modulus bit length.
+ */
+ br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]);
+ br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
+
+ /*
+ * Multiply the (truncated, reduced) hash value with 1/s, result in
+ * t2, encoded in ty.
+ */
+ br_i31_montymul(t2, t1, s, n, n0i);
+ br_i31_encode(ty, nlen, t2);
+
+ /*
+ * Multiply r with 1/s, result in t1, encoded in tx.
+ */
+ br_i31_montymul(t1, r, s, n, n0i);
+ br_i31_encode(tx, nlen, t1);
+
+ /*
+ * Compute the point x*Q + y*G.
+ */
+ ulen = cd->generator_len;
+ memcpy(eU, pk->q, ulen);
+ res = impl->muladd(eU, NULL, ulen,
+ tx, nlen, ty, nlen, cd->curve);
+
+ /*
+ * Get the X coordinate, reduce modulo the curve order, and
+ * compare with the 'r' value.
+ *
+ * The modular reduction can be done with subtractions because
+ * we work with curves of prime order, so the curve order is
+ * close to the field order (Hasse's theorem).
+ */
+ br_i31_zero(t1, n[0]);
+ br_i31_decode(t1, &eU[1], ulen >> 1);
+ t1[0] = n[0];
+ br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
+ res &= ~br_i31_sub(t1, r, 1);
+ res &= br_i31_iszero(t1);
+ return res;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_i31_vrfy_raw.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ec/ecdsa_rta.c
===================================================================
--- stable/12/contrib/bearssl/src/ec/ecdsa_rta.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ec/ecdsa_rta.c (revision 346145)
@@ -0,0 +1,121 @@
+/*
+ * 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"
+
+/*
+ * Compute ASN.1 encoded length for the provided integer. The ASN.1
+ * encoding is signed, so its leading bit must have value 0; it must
+ * also be of minimal length (so leading bytes of value 0 must be
+ * removed, except if that would contradict the rule about the sign
+ * bit).
+ */
+static size_t
+asn1_int_length(const unsigned char *x, size_t xlen)
+{
+ while (xlen > 0 && *x == 0) {
+ x ++;
+ xlen --;
+ }
+ if (xlen == 0 || *x >= 0x80) {
+ xlen ++;
+ }
+ return xlen;
+}
+
+/* see bearssl_ec.h */
+size_t
+br_ecdsa_raw_to_asn1(void *sig, size_t sig_len)
+{
+ /*
+ * Internal buffer is large enough to accommodate a signature
+ * such that r and s fit on 125 bytes each (signed encoding),
+ * meaning a curve order of up to 999 bits. This is the limit
+ * that ensures "simple" length encodings.
+ */
+ unsigned char *buf;
+ size_t hlen, rlen, slen, zlen, off;
+ unsigned char tmp[257];
+
+ buf = sig;
+ if ((sig_len & 1) != 0) {
+ return 0;
+ }
+
+ /*
+ * Compute lengths for the two integers.
+ */
+ hlen = sig_len >> 1;
+ rlen = asn1_int_length(buf, hlen);
+ slen = asn1_int_length(buf + hlen, hlen);
+ if (rlen > 125 || slen > 125) {
+ return 0;
+ }
+
+ /*
+ * SEQUENCE header.
+ */
+ tmp[0] = 0x30;
+ zlen = rlen + slen + 4;
+ if (zlen >= 0x80) {
+ tmp[1] = 0x81;
+ tmp[2] = zlen;
+ off = 3;
+ } else {
+ tmp[1] = zlen;
+ off = 2;
+ }
+
+ /*
+ * First INTEGER (r).
+ */
+ tmp[off ++] = 0x02;
+ tmp[off ++] = rlen;
+ if (rlen > hlen) {
+ tmp[off] = 0x00;
+ memcpy(tmp + off + 1, buf, hlen);
+ } else {
+ memcpy(tmp + off, buf + hlen - rlen, rlen);
+ }
+ off += rlen;
+
+ /*
+ * Second INTEGER (s).
+ */
+ tmp[off ++] = 0x02;
+ tmp[off ++] = slen;
+ if (slen > hlen) {
+ tmp[off] = 0x00;
+ memcpy(tmp + off + 1, buf + hlen, hlen);
+ } else {
+ memcpy(tmp + off, buf + sig_len - slen, slen);
+ }
+ off += slen;
+
+ /*
+ * Return ASN.1 signature.
+ */
+ memcpy(sig, tmp, off);
+ return off;
+}
Property changes on: stable/12/contrib/bearssl/src/ec/ecdsa_rta.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/dig_oid.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/dig_oid.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/dig_oid.c (revision 346145)
@@ -0,0 +1,84 @@
+/*
+ * 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"
+
+/*
+ * This file contains the encoded OID for the standard hash functions.
+ * Such OID appear in, for instance, the PKCS#1 v1.5 padding for RSA
+ * signatures.
+ */
+
+static const unsigned char md5_OID[] = {
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05
+};
+
+static const unsigned char sha1_OID[] = {
+ 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char sha224_OID[] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char sha256_OID[] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char sha384_OID[] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char sha512_OID[] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+/* see inner.h */
+const unsigned char *
+br_digest_OID(int digest_id, size_t *len)
+{
+ switch (digest_id) {
+ case br_md5_ID:
+ *len = sizeof md5_OID;
+ return md5_OID;
+ case br_sha1_ID:
+ *len = sizeof sha1_OID;
+ return sha1_OID;
+ case br_sha224_ID:
+ *len = sizeof sha224_OID;
+ return sha224_OID;
+ case br_sha256_ID:
+ *len = sizeof sha256_OID;
+ return sha256_OID;
+ case br_sha384_ID:
+ *len = sizeof sha384_OID;
+ return sha384_OID;
+ case br_sha512_ID:
+ *len = sizeof sha512_OID;
+ return sha512_OID;
+ default:
+ *len = 0;
+ return NULL;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/hash/dig_oid.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/dig_size.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/dig_size.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/dig_size.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+size_t
+br_digest_size_by_ID(int digest_id)
+{
+ switch (digest_id) {
+ case br_md5sha1_ID:
+ return br_md5_SIZE + br_sha1_SIZE;
+ case br_md5_ID:
+ return br_md5_SIZE;
+ case br_sha1_ID:
+ return br_sha1_SIZE;
+ case br_sha224_ID:
+ return br_sha224_SIZE;
+ case br_sha256_ID:
+ return br_sha256_SIZE;
+ case br_sha384_ID:
+ return br_sha384_SIZE;
+ case br_sha512_ID:
+ return br_sha512_SIZE;
+ default:
+ /* abort(); */
+ return 0;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/hash/dig_size.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/ghash_ctmul.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/ghash_ctmul.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/ghash_ctmul.c (revision 346145)
@@ -0,0 +1,345 @@
+/*
+ * 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"
+
+/*
+ * We compute "carryless multiplications" through normal integer
+ * multiplications, masking out enough bits to create "holes" in which
+ * carries may expand without altering our bits; we really use 8 data
+ * bits per 32-bit word, spaced every fourth bit. Accumulated carries
+ * may not exceed 8 in total, which fits in 4 bits.
+ *
+ * It would be possible to use a 3-bit spacing, allowing two operands,
+ * one with 7 non-zero data bits, the other one with 10 or 11 non-zero
+ * data bits; this asymmetric splitting makes the overall code more
+ * complex with thresholds and exceptions, and does not appear to be
+ * worth the effort.
+ */
+
+/*
+ * We cannot really autodetect whether multiplications are "slow" or
+ * not. A typical example is the ARM Cortex M0+, which exists in two
+ * versions: one with a 1-cycle multiplication opcode, the other with
+ * a 32-cycle multiplication opcode. They both use exactly the same
+ * architecture and ABI, and cannot be distinguished from each other
+ * at compile-time.
+ *
+ * Since most modern CPU (even embedded CPU) still have fast
+ * multiplications, we use the "fast mul" code by default.
+ */
+
+#if BR_SLOW_MUL
+
+/*
+ * This implementation uses Karatsuba-like reduction to make fewer
+ * integer multiplications (9 instead of 16), at the expense of extra
+ * logical operations (XOR, shifts...). On modern x86 CPU that offer
+ * fast, pipelined multiplications, this code is about twice slower than
+ * the simpler code with 16 multiplications. This tendency may be
+ * reversed on low-end platforms with expensive multiplications.
+ */
+
+#define MUL32(h, l, x, y) do { \
+ uint64_t mul32tmp = MUL(x, y); \
+ (h) = (uint32_t)(mul32tmp >> 32); \
+ (l) = (uint32_t)mul32tmp; \
+ } while (0)
+
+static inline void
+bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
+{
+ uint32_t x0, x1, x2, x3;
+ uint32_t y0, y1, y2, y3;
+ uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8;
+ uint32_t b0, b1, b2, b3, b4, b5, b6, b7, b8;
+
+ x0 = x & (uint32_t)0x11111111;
+ x1 = x & (uint32_t)0x22222222;
+ x2 = x & (uint32_t)0x44444444;
+ x3 = x & (uint32_t)0x88888888;
+ y0 = y & (uint32_t)0x11111111;
+ y1 = y & (uint32_t)0x22222222;
+ y2 = y & (uint32_t)0x44444444;
+ y3 = y & (uint32_t)0x88888888;
+
+ /*
+ * (x0+W*x1)*(y0+W*y1) -> a0:b0
+ * (x2+W*x3)*(y2+W*y3) -> a3:b3
+ * ((x0+x2)+W*(x1+x3))*((y0+y2)+W*(y1+y3)) -> a6:b6
+ */
+ a0 = x0;
+ b0 = y0;
+ a1 = x1 >> 1;
+ b1 = y1 >> 1;
+ a2 = a0 ^ a1;
+ b2 = b0 ^ b1;
+ a3 = x2 >> 2;
+ b3 = y2 >> 2;
+ a4 = x3 >> 3;
+ b4 = y3 >> 3;
+ a5 = a3 ^ a4;
+ b5 = b3 ^ b4;
+ a6 = a0 ^ a3;
+ b6 = b0 ^ b3;
+ a7 = a1 ^ a4;
+ b7 = b1 ^ b4;
+ a8 = a6 ^ a7;
+ b8 = b6 ^ b7;
+
+ MUL32(b0, a0, b0, a0);
+ MUL32(b1, a1, b1, a1);
+ MUL32(b2, a2, b2, a2);
+ MUL32(b3, a3, b3, a3);
+ MUL32(b4, a4, b4, a4);
+ MUL32(b5, a5, b5, a5);
+ MUL32(b6, a6, b6, a6);
+ MUL32(b7, a7, b7, a7);
+ MUL32(b8, a8, b8, a8);
+
+ a0 &= (uint32_t)0x11111111;
+ a1 &= (uint32_t)0x11111111;
+ a2 &= (uint32_t)0x11111111;
+ a3 &= (uint32_t)0x11111111;
+ a4 &= (uint32_t)0x11111111;
+ a5 &= (uint32_t)0x11111111;
+ a6 &= (uint32_t)0x11111111;
+ a7 &= (uint32_t)0x11111111;
+ a8 &= (uint32_t)0x11111111;
+ b0 &= (uint32_t)0x11111111;
+ b1 &= (uint32_t)0x11111111;
+ b2 &= (uint32_t)0x11111111;
+ b3 &= (uint32_t)0x11111111;
+ b4 &= (uint32_t)0x11111111;
+ b5 &= (uint32_t)0x11111111;
+ b6 &= (uint32_t)0x11111111;
+ b7 &= (uint32_t)0x11111111;
+ b8 &= (uint32_t)0x11111111;
+
+ a2 ^= a0 ^ a1;
+ b2 ^= b0 ^ b1;
+ a0 ^= (a2 << 1) ^ (a1 << 2);
+ b0 ^= (b2 << 1) ^ (b1 << 2);
+ a5 ^= a3 ^ a4;
+ b5 ^= b3 ^ b4;
+ a3 ^= (a5 << 1) ^ (a4 << 2);
+ b3 ^= (b5 << 1) ^ (b4 << 2);
+ a8 ^= a6 ^ a7;
+ b8 ^= b6 ^ b7;
+ a6 ^= (a8 << 1) ^ (a7 << 2);
+ b6 ^= (b8 << 1) ^ (b7 << 2);
+ a6 ^= a0 ^ a3;
+ b6 ^= b0 ^ b3;
+ *lo = a0 ^ (a6 << 2) ^ (a3 << 4);
+ *hi = b0 ^ (b6 << 2) ^ (b3 << 4) ^ (a6 >> 30) ^ (a3 >> 28);
+}
+
+#else
+
+/*
+ * Simple multiplication in GF(2)[X], using 16 integer multiplications.
+ */
+
+static inline void
+bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
+{
+ uint32_t x0, x1, x2, x3;
+ uint32_t y0, y1, y2, y3;
+ uint64_t z0, z1, z2, z3;
+ uint64_t z;
+
+ x0 = x & (uint32_t)0x11111111;
+ x1 = x & (uint32_t)0x22222222;
+ x2 = x & (uint32_t)0x44444444;
+ x3 = x & (uint32_t)0x88888888;
+ y0 = y & (uint32_t)0x11111111;
+ y1 = y & (uint32_t)0x22222222;
+ y2 = y & (uint32_t)0x44444444;
+ y3 = y & (uint32_t)0x88888888;
+ z0 = MUL(x0, y0) ^ MUL(x1, y3) ^ MUL(x2, y2) ^ MUL(x3, y1);
+ z1 = MUL(x0, y1) ^ MUL(x1, y0) ^ MUL(x2, y3) ^ MUL(x3, y2);
+ z2 = MUL(x0, y2) ^ MUL(x1, y1) ^ MUL(x2, y0) ^ MUL(x3, y3);
+ z3 = MUL(x0, y3) ^ MUL(x1, y2) ^ MUL(x2, y1) ^ MUL(x3, y0);
+ z0 &= (uint64_t)0x1111111111111111;
+ z1 &= (uint64_t)0x2222222222222222;
+ z2 &= (uint64_t)0x4444444444444444;
+ z3 &= (uint64_t)0x8888888888888888;
+ z = z0 | z1 | z2 | z3;
+ *lo = (uint32_t)z;
+ *hi = (uint32_t)(z >> 32);
+}
+
+#endif
+
+/* see bearssl_hash.h */
+void
+br_ghash_ctmul(void *y, const void *h, const void *data, size_t len)
+{
+ const unsigned char *buf, *hb;
+ unsigned char *yb;
+ uint32_t yw[4];
+ uint32_t hw[4];
+
+ /*
+ * Throughout the loop we handle the y and h values as arrays
+ * of 32-bit words.
+ */
+ buf = data;
+ yb = y;
+ hb = h;
+ yw[3] = br_dec32be(yb);
+ yw[2] = br_dec32be(yb + 4);
+ yw[1] = br_dec32be(yb + 8);
+ yw[0] = br_dec32be(yb + 12);
+ hw[3] = br_dec32be(hb);
+ hw[2] = br_dec32be(hb + 4);
+ hw[1] = br_dec32be(hb + 8);
+ hw[0] = br_dec32be(hb + 12);
+ while (len > 0) {
+ const unsigned char *src;
+ unsigned char tmp[16];
+ int i;
+ uint32_t a[9], b[9], zw[8];
+ uint32_t c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3;
+
+ /*
+ * Get the next 16-byte block (using zero-padding if
+ * necessary).
+ */
+ if (len >= 16) {
+ src = buf;
+ buf += 16;
+ len -= 16;
+ } else {
+ memcpy(tmp, buf, len);
+ memset(tmp + len, 0, (sizeof tmp) - len);
+ src = tmp;
+ len = 0;
+ }
+
+ /*
+ * Decode the block. The GHASH standard mandates
+ * big-endian encoding.
+ */
+ yw[3] ^= br_dec32be(src);
+ yw[2] ^= br_dec32be(src + 4);
+ yw[1] ^= br_dec32be(src + 8);
+ yw[0] ^= br_dec32be(src + 12);
+
+ /*
+ * We multiply two 128-bit field elements. We use
+ * Karatsuba to turn that into three 64-bit
+ * multiplications, which are themselves done with a
+ * total of nine 32-bit multiplications.
+ */
+
+ /*
+ * y[0,1]*h[0,1] -> 0..2
+ * y[2,3]*h[2,3] -> 3..5
+ * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6..8
+ */
+ a[0] = yw[0];
+ b[0] = hw[0];
+ a[1] = yw[1];
+ b[1] = hw[1];
+ a[2] = a[0] ^ a[1];
+ b[2] = b[0] ^ b[1];
+
+ a[3] = yw[2];
+ b[3] = hw[2];
+ a[4] = yw[3];
+ b[4] = hw[3];
+ a[5] = a[3] ^ a[4];
+ b[5] = b[3] ^ b[4];
+
+ a[6] = a[0] ^ a[3];
+ b[6] = b[0] ^ b[3];
+ a[7] = a[1] ^ a[4];
+ b[7] = b[1] ^ b[4];
+ a[8] = a[6] ^ a[7];
+ b[8] = b[6] ^ b[7];
+
+ for (i = 0; i < 9; i ++) {
+ bmul(&b[i], &a[i], b[i], a[i]);
+ }
+
+ c0 = a[0];
+ c1 = b[0] ^ a[2] ^ a[0] ^ a[1];
+ c2 = a[1] ^ b[2] ^ b[0] ^ b[1];
+ c3 = b[1];
+ d0 = a[3];
+ d1 = b[3] ^ a[5] ^ a[3] ^ a[4];
+ d2 = a[4] ^ b[5] ^ b[3] ^ b[4];
+ d3 = b[4];
+ e0 = a[6];
+ e1 = b[6] ^ a[8] ^ a[6] ^ a[7];
+ e2 = a[7] ^ b[8] ^ b[6] ^ b[7];
+ e3 = b[7];
+
+ e0 ^= c0 ^ d0;
+ e1 ^= c1 ^ d1;
+ e2 ^= c2 ^ d2;
+ e3 ^= c3 ^ d3;
+ c2 ^= e0;
+ c3 ^= e1;
+ d0 ^= e2;
+ d1 ^= e3;
+
+ /*
+ * GHASH specification has the bits "reversed" (most
+ * significant is in fact least significant), which does
+ * not matter for a carryless multiplication, except that
+ * the 255-bit result must be shifted by 1 bit.
+ */
+ zw[0] = c0 << 1;
+ zw[1] = (c1 << 1) | (c0 >> 31);
+ zw[2] = (c2 << 1) | (c1 >> 31);
+ zw[3] = (c3 << 1) | (c2 >> 31);
+ zw[4] = (d0 << 1) | (c3 >> 31);
+ zw[5] = (d1 << 1) | (d0 >> 31);
+ zw[6] = (d2 << 1) | (d1 >> 31);
+ zw[7] = (d3 << 1) | (d2 >> 31);
+
+ /*
+ * We now do the reduction modulo the field polynomial
+ * to get back to 128 bits.
+ */
+ for (i = 0; i < 4; i ++) {
+ uint32_t lw;
+
+ lw = zw[i];
+ zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
+ zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
+ }
+ memcpy(yw, zw + 4, sizeof yw);
+ }
+
+ /*
+ * Encode back the result.
+ */
+ br_enc32be(yb, yw[3]);
+ br_enc32be(yb + 4, yw[2]);
+ br_enc32be(yb + 8, yw[1]);
+ br_enc32be(yb + 12, yw[0]);
+}
Property changes on: stable/12/contrib/bearssl/src/hash/ghash_ctmul.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/ghash_ctmul32.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/ghash_ctmul32.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/ghash_ctmul32.c (revision 346145)
@@ -0,0 +1,251 @@
+/*
+ * 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"
+
+/*
+ * This implementation uses 32-bit multiplications, and only the low
+ * 32 bits for each multiplication result. This is meant primarily for
+ * the ARM Cortex M0 and M0+, whose multiplication opcode does not yield
+ * the upper 32 bits; but it might also be useful on architectures where
+ * access to the upper 32 bits requires use of specific registers that
+ * create contention (e.g. on i386, "mul" necessarily outputs the result
+ * in edx:eax, while "imul" can use any registers but is limited to the
+ * low 32 bits).
+ *
+ * The implementation trick that is used here is bit-reversing (bit 0
+ * is swapped with bit 31, bit 1 with bit 30, and so on). In GF(2)[X],
+ * for all values x and y, we have:
+ * rev32(x) * rev32(y) = rev64(x * y)
+ * In other words, if we bit-reverse (over 32 bits) the operands, then we
+ * bit-reverse (over 64 bits) the result.
+ */
+
+/*
+ * Multiplication in GF(2)[X], truncated to its low 32 bits.
+ */
+static inline uint32_t
+bmul32(uint32_t x, uint32_t y)
+{
+ uint32_t x0, x1, x2, x3;
+ uint32_t y0, y1, y2, y3;
+ uint32_t z0, z1, z2, z3;
+
+ x0 = x & (uint32_t)0x11111111;
+ x1 = x & (uint32_t)0x22222222;
+ x2 = x & (uint32_t)0x44444444;
+ x3 = x & (uint32_t)0x88888888;
+ y0 = y & (uint32_t)0x11111111;
+ y1 = y & (uint32_t)0x22222222;
+ y2 = y & (uint32_t)0x44444444;
+ y3 = y & (uint32_t)0x88888888;
+ z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
+ z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
+ z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
+ z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
+ z0 &= (uint32_t)0x11111111;
+ z1 &= (uint32_t)0x22222222;
+ z2 &= (uint32_t)0x44444444;
+ z3 &= (uint32_t)0x88888888;
+ return z0 | z1 | z2 | z3;
+}
+
+/*
+ * Bit-reverse a 32-bit word.
+ */
+static uint32_t
+rev32(uint32_t x)
+{
+#define RMS(m, s) do { \
+ x = ((x & (uint32_t)(m)) << (s)) \
+ | ((x >> (s)) & (uint32_t)(m)); \
+ } while (0)
+
+ RMS(0x55555555, 1);
+ RMS(0x33333333, 2);
+ RMS(0x0F0F0F0F, 4);
+ RMS(0x00FF00FF, 8);
+ return (x << 16) | (x >> 16);
+
+#undef RMS
+}
+
+/* see bearssl_hash.h */
+void
+br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len)
+{
+ /*
+ * This implementation is similar to br_ghash_ctmul() except
+ * that we have to do the multiplication twice, with the
+ * "normal" and "bit reversed" operands. Hence we end up with
+ * eighteen 32-bit multiplications instead of nine.
+ */
+
+ const unsigned char *buf, *hb;
+ unsigned char *yb;
+ uint32_t yw[4];
+ uint32_t hw[4], hwr[4];
+
+ buf = data;
+ yb = y;
+ hb = h;
+ yw[3] = br_dec32be(yb);
+ yw[2] = br_dec32be(yb + 4);
+ yw[1] = br_dec32be(yb + 8);
+ yw[0] = br_dec32be(yb + 12);
+ hw[3] = br_dec32be(hb);
+ hw[2] = br_dec32be(hb + 4);
+ hw[1] = br_dec32be(hb + 8);
+ hw[0] = br_dec32be(hb + 12);
+ hwr[3] = rev32(hw[3]);
+ hwr[2] = rev32(hw[2]);
+ hwr[1] = rev32(hw[1]);
+ hwr[0] = rev32(hw[0]);
+ while (len > 0) {
+ const unsigned char *src;
+ unsigned char tmp[16];
+ int i;
+ uint32_t a[18], b[18], c[18];
+ uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
+ uint32_t zw[8];
+
+ if (len >= 16) {
+ src = buf;
+ buf += 16;
+ len -= 16;
+ } else {
+ memcpy(tmp, buf, len);
+ memset(tmp + len, 0, (sizeof tmp) - len);
+ src = tmp;
+ len = 0;
+ }
+ yw[3] ^= br_dec32be(src);
+ yw[2] ^= br_dec32be(src + 4);
+ yw[1] ^= br_dec32be(src + 8);
+ yw[0] ^= br_dec32be(src + 12);
+
+ /*
+ * We are using Karatsuba: the 128x128 multiplication is
+ * reduced to three 64x64 multiplications, hence nine
+ * 32x32 multiplications. With the bit-reversal trick,
+ * we have to perform 18 32x32 multiplications.
+ */
+
+ /*
+ * y[0,1]*h[0,1] -> 0,1,4
+ * y[2,3]*h[2,3] -> 2,3,5
+ * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,7,8
+ */
+
+ a[0] = yw[0];
+ a[1] = yw[1];
+ a[2] = yw[2];
+ a[3] = yw[3];
+ a[4] = a[0] ^ a[1];
+ a[5] = a[2] ^ a[3];
+ a[6] = a[0] ^ a[2];
+ a[7] = a[1] ^ a[3];
+ a[8] = a[6] ^ a[7];
+
+ a[ 9] = rev32(yw[0]);
+ a[10] = rev32(yw[1]);
+ a[11] = rev32(yw[2]);
+ a[12] = rev32(yw[3]);
+ a[13] = a[ 9] ^ a[10];
+ a[14] = a[11] ^ a[12];
+ a[15] = a[ 9] ^ a[11];
+ a[16] = a[10] ^ a[12];
+ a[17] = a[15] ^ a[16];
+
+ b[0] = hw[0];
+ b[1] = hw[1];
+ b[2] = hw[2];
+ b[3] = hw[3];
+ b[4] = b[0] ^ b[1];
+ b[5] = b[2] ^ b[3];
+ b[6] = b[0] ^ b[2];
+ b[7] = b[1] ^ b[3];
+ b[8] = b[6] ^ b[7];
+
+ b[ 9] = hwr[0];
+ b[10] = hwr[1];
+ b[11] = hwr[2];
+ b[12] = hwr[3];
+ b[13] = b[ 9] ^ b[10];
+ b[14] = b[11] ^ b[12];
+ b[15] = b[ 9] ^ b[11];
+ b[16] = b[10] ^ b[12];
+ b[17] = b[15] ^ b[16];
+
+ for (i = 0; i < 18; i ++) {
+ c[i] = bmul32(a[i], b[i]);
+ }
+
+ c[4] ^= c[0] ^ c[1];
+ c[5] ^= c[2] ^ c[3];
+ c[8] ^= c[6] ^ c[7];
+
+ c[13] ^= c[ 9] ^ c[10];
+ c[14] ^= c[11] ^ c[12];
+ c[17] ^= c[15] ^ c[16];
+
+ /*
+ * y[0,1]*h[0,1] -> 0,9^4,1^13,10
+ * y[2,3]*h[2,3] -> 2,11^5,3^14,12
+ * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,15^8,7^17,16
+ */
+ d0 = c[0];
+ d1 = c[4] ^ (rev32(c[9]) >> 1);
+ d2 = c[1] ^ c[0] ^ c[2] ^ c[6] ^ (rev32(c[13]) >> 1);
+ d3 = c[4] ^ c[5] ^ c[8]
+ ^ (rev32(c[10] ^ c[9] ^ c[11] ^ c[15]) >> 1);
+ d4 = c[2] ^ c[1] ^ c[3] ^ c[7]
+ ^ (rev32(c[13] ^ c[14] ^ c[17]) >> 1);
+ d5 = c[5] ^ (rev32(c[11] ^ c[10] ^ c[12] ^ c[16]) >> 1);
+ d6 = c[3] ^ (rev32(c[14]) >> 1);
+ d7 = rev32(c[12]) >> 1;
+
+ zw[0] = d0 << 1;
+ zw[1] = (d1 << 1) | (d0 >> 31);
+ zw[2] = (d2 << 1) | (d1 >> 31);
+ zw[3] = (d3 << 1) | (d2 >> 31);
+ zw[4] = (d4 << 1) | (d3 >> 31);
+ zw[5] = (d5 << 1) | (d4 >> 31);
+ zw[6] = (d6 << 1) | (d5 >> 31);
+ zw[7] = (d7 << 1) | (d6 >> 31);
+
+ for (i = 0; i < 4; i ++) {
+ uint32_t lw;
+
+ lw = zw[i];
+ zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
+ zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
+ }
+ memcpy(yw, zw + 4, sizeof yw);
+ }
+ br_enc32be(yb, yw[3]);
+ br_enc32be(yb + 4, yw[2]);
+ br_enc32be(yb + 8, yw[1]);
+ br_enc32be(yb + 12, yw[0]);
+}
Property changes on: stable/12/contrib/bearssl/src/hash/ghash_ctmul32.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/ghash_ctmul64.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/ghash_ctmul64.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/ghash_ctmul64.c (revision 346145)
@@ -0,0 +1,154 @@
+/*
+ * 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"
+
+/*
+ * This is the 64-bit variant of br_ghash_ctmul32(), with 64-bit operands
+ * and bit reversal of 64-bit words.
+ */
+
+static inline uint64_t
+bmul64(uint64_t x, uint64_t y)
+{
+ uint64_t x0, x1, x2, x3;
+ uint64_t y0, y1, y2, y3;
+ uint64_t z0, z1, z2, z3;
+
+ x0 = x & (uint64_t)0x1111111111111111;
+ x1 = x & (uint64_t)0x2222222222222222;
+ x2 = x & (uint64_t)0x4444444444444444;
+ x3 = x & (uint64_t)0x8888888888888888;
+ y0 = y & (uint64_t)0x1111111111111111;
+ y1 = y & (uint64_t)0x2222222222222222;
+ y2 = y & (uint64_t)0x4444444444444444;
+ y3 = y & (uint64_t)0x8888888888888888;
+ z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
+ z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
+ z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
+ z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
+ z0 &= (uint64_t)0x1111111111111111;
+ z1 &= (uint64_t)0x2222222222222222;
+ z2 &= (uint64_t)0x4444444444444444;
+ z3 &= (uint64_t)0x8888888888888888;
+ return z0 | z1 | z2 | z3;
+}
+
+static uint64_t
+rev64(uint64_t x)
+{
+#define RMS(m, s) do { \
+ x = ((x & (uint64_t)(m)) << (s)) \
+ | ((x >> (s)) & (uint64_t)(m)); \
+ } while (0)
+
+ RMS(0x5555555555555555, 1);
+ RMS(0x3333333333333333, 2);
+ RMS(0x0F0F0F0F0F0F0F0F, 4);
+ RMS(0x00FF00FF00FF00FF, 8);
+ RMS(0x0000FFFF0000FFFF, 16);
+ return (x << 32) | (x >> 32);
+
+#undef RMS
+}
+
+/* see bearssl_ghash.h */
+void
+br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len)
+{
+ const unsigned char *buf, *hb;
+ unsigned char *yb;
+ uint64_t y0, y1;
+ uint64_t h0, h1, h2, h0r, h1r, h2r;
+
+ buf = data;
+ yb = y;
+ hb = h;
+ y1 = br_dec64be(yb);
+ y0 = br_dec64be(yb + 8);
+ h1 = br_dec64be(hb);
+ h0 = br_dec64be(hb + 8);
+ h0r = rev64(h0);
+ h1r = rev64(h1);
+ h2 = h0 ^ h1;
+ h2r = h0r ^ h1r;
+ while (len > 0) {
+ const unsigned char *src;
+ unsigned char tmp[16];
+ uint64_t y0r, y1r, y2, y2r;
+ uint64_t z0, z1, z2, z0h, z1h, z2h;
+ uint64_t v0, v1, v2, v3;
+
+ if (len >= 16) {
+ src = buf;
+ buf += 16;
+ len -= 16;
+ } else {
+ memcpy(tmp, buf, len);
+ memset(tmp + len, 0, (sizeof tmp) - len);
+ src = tmp;
+ len = 0;
+ }
+ y1 ^= br_dec64be(src);
+ y0 ^= br_dec64be(src + 8);
+
+ y0r = rev64(y0);
+ y1r = rev64(y1);
+ y2 = y0 ^ y1;
+ y2r = y0r ^ y1r;
+
+ z0 = bmul64(y0, h0);
+ z1 = bmul64(y1, h1);
+ z2 = bmul64(y2, h2);
+ z0h = bmul64(y0r, h0r);
+ z1h = bmul64(y1r, h1r);
+ z2h = bmul64(y2r, h2r);
+ z2 ^= z0 ^ z1;
+ z2h ^= z0h ^ z1h;
+ z0h = rev64(z0h) >> 1;
+ z1h = rev64(z1h) >> 1;
+ z2h = rev64(z2h) >> 1;
+
+ v0 = z0;
+ v1 = z0h ^ z2;
+ v2 = z1 ^ z2h;
+ v3 = z1h;
+
+ v3 = (v3 << 1) | (v2 >> 63);
+ v2 = (v2 << 1) | (v1 >> 63);
+ v1 = (v1 << 1) | (v0 >> 63);
+ v0 = (v0 << 1);
+
+ v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
+ v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
+ v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
+ v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
+
+ y0 = v2;
+ y1 = v3;
+ }
+
+ br_enc64be(yb, y1);
+ br_enc64be(yb + 8, y0);
+}
Property changes on: stable/12/contrib/bearssl/src/hash/ghash_ctmul64.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/ghash_pclmul.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/ghash_pclmul.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/ghash_pclmul.c (revision 346145)
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+/*
+ * This is the GHASH implementation that leverages the pclmulqdq opcode
+ * (from the AES-NI instructions).
+ */
+
+#if BR_AES_X86NI
+
+/*
+ * Test CPU support for PCLMULQDQ.
+ */
+static inline int
+pclmul_supported(void)
+{
+ /*
+ * Bit mask for features in ECX:
+ * 1 PCLMULQDQ support
+ */
+ return br_cpuid(0, 0, 0x00000002, 0);
+}
+
+/* see bearssl_hash.h */
+br_ghash
+br_ghash_pclmul_get(void)
+{
+ return pclmul_supported() ? &br_ghash_pclmul : 0;
+}
+
+BR_TARGETS_X86_UP
+
+/*
+ * GHASH is defined over elements of GF(2^128) with "full little-endian"
+ * representation: leftmost byte is least significant, and, within each
+ * byte, leftmost _bit_ is least significant. The natural ordering in
+ * x86 is "mixed little-endian": bytes are ordered from least to most
+ * significant, but bits within a byte are in most-to-least significant
+ * order. Going to full little-endian representation would require
+ * reversing bits within each byte, which is doable but expensive.
+ *
+ * Instead, we go to full big-endian representation, by swapping bytes
+ * around, which is done with a single _mm_shuffle_epi8() opcode (it
+ * comes with SSSE3; all CPU that offer pclmulqdq also have SSSE3). We
+ * can use a full big-endian representation because in a carryless
+ * multiplication, we have a nice bit reversal property:
+ *
+ * rev_128(x) * rev_128(y) = rev_255(x * y)
+ *
+ * So by using full big-endian, we still get the right result, except
+ * that it is right-shifted by 1 bit. The left-shift is relatively
+ * inexpensive, and it can be mutualised.
+ *
+ *
+ * Since SSE2 opcodes do not have facilities for shitfting full 128-bit
+ * values with bit precision, we have to break down values into 64-bit
+ * chunks. We number chunks from 0 to 3 in left to right order.
+ */
+
+/*
+ * Byte-swap a complete 128-bit value. This normally uses
+ * _mm_shuffle_epi8(), which gets translated to pshufb (an SSSE3 opcode).
+ * However, this crashes old Clang versions, so, for Clang before 3.8,
+ * we use an alternate (and less efficient) version.
+ */
+#if BR_CLANG && !BR_CLANG_3_8
+#define BYTESWAP_DECL
+#define BYTESWAP_PREP (void)0
+#define BYTESWAP(x) do { \
+ __m128i byteswap1, byteswap2; \
+ byteswap1 = (x); \
+ byteswap2 = _mm_srli_epi16(byteswap1, 8); \
+ byteswap1 = _mm_slli_epi16(byteswap1, 8); \
+ byteswap1 = _mm_or_si128(byteswap1, byteswap2); \
+ byteswap1 = _mm_shufflelo_epi16(byteswap1, 0x1B); \
+ byteswap1 = _mm_shufflehi_epi16(byteswap1, 0x1B); \
+ (x) = _mm_shuffle_epi32(byteswap1, 0x4E); \
+ } while (0)
+#else
+#define BYTESWAP_DECL __m128i byteswap_index;
+#define BYTESWAP_PREP do { \
+ byteswap_index = _mm_set_epi8( \
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \
+ } while (0)
+#define BYTESWAP(x) do { \
+ (x) = _mm_shuffle_epi8((x), byteswap_index); \
+ } while (0)
+#endif
+
+/*
+ * Call pclmulqdq. Clang appears to have trouble with the intrinsic, so,
+ * for that compiler, we use inline assembly. Inline assembly is
+ * potentially a bit slower because the compiler does not understand
+ * what the opcode does, and thus cannot optimize instruction
+ * scheduling.
+ *
+ * We use a target of "sse2" only, so that Clang may still handle the
+ * '__m128i' type and allocate SSE2 registers.
+ */
+#if BR_CLANG
+BR_TARGET("sse2")
+static inline __m128i
+pclmulqdq00(__m128i x, __m128i y)
+{
+ __asm__ ("pclmulqdq $0x00, %1, %0" : "+x" (x) : "x" (y));
+ return x;
+}
+BR_TARGET("sse2")
+static inline __m128i
+pclmulqdq11(__m128i x, __m128i y)
+{
+ __asm__ ("pclmulqdq $0x11, %1, %0" : "+x" (x) : "x" (y));
+ return x;
+}
+#else
+#define pclmulqdq00(x, y) _mm_clmulepi64_si128(x, y, 0x00)
+#define pclmulqdq11(x, y) _mm_clmulepi64_si128(x, y, 0x11)
+#endif
+
+/*
+ * From a 128-bit value kw, compute kx as the XOR of the two 64-bit
+ * halves of kw (into the right half of kx; left half is unspecified).
+ */
+#define BK(kw, kx) do { \
+ kx = _mm_xor_si128(kw, _mm_shuffle_epi32(kw, 0x0E)); \
+ } while (0)
+
+/*
+ * Combine two 64-bit values (k0:k1) into a 128-bit (kw) value and
+ * the XOR of the two values (kx).
+ */
+#define PBK(k0, k1, kw, kx) do { \
+ kw = _mm_unpacklo_epi64(k1, k0); \
+ kx = _mm_xor_si128(k0, k1); \
+ } while (0)
+
+/*
+ * Left-shift by 1 bit a 256-bit value (in four 64-bit words).
+ */
+#define SL_256(x0, x1, x2, x3) do { \
+ x0 = _mm_or_si128( \
+ _mm_slli_epi64(x0, 1), \
+ _mm_srli_epi64(x1, 63)); \
+ x1 = _mm_or_si128( \
+ _mm_slli_epi64(x1, 1), \
+ _mm_srli_epi64(x2, 63)); \
+ x2 = _mm_or_si128( \
+ _mm_slli_epi64(x2, 1), \
+ _mm_srli_epi64(x3, 63)); \
+ x3 = _mm_slli_epi64(x3, 1); \
+ } while (0)
+
+/*
+ * Perform reduction in GF(2^128). The 256-bit value is in x0..x3;
+ * result is written in x0..x1.
+ */
+#define REDUCE_F128(x0, x1, x2, x3) do { \
+ x1 = _mm_xor_si128( \
+ x1, \
+ _mm_xor_si128( \
+ _mm_xor_si128( \
+ x3, \
+ _mm_srli_epi64(x3, 1)), \
+ _mm_xor_si128( \
+ _mm_srli_epi64(x3, 2), \
+ _mm_srli_epi64(x3, 7)))); \
+ x2 = _mm_xor_si128( \
+ _mm_xor_si128( \
+ x2, \
+ _mm_slli_epi64(x3, 63)), \
+ _mm_xor_si128( \
+ _mm_slli_epi64(x3, 62), \
+ _mm_slli_epi64(x3, 57))); \
+ x0 = _mm_xor_si128( \
+ x0, \
+ _mm_xor_si128( \
+ _mm_xor_si128( \
+ x2, \
+ _mm_srli_epi64(x2, 1)), \
+ _mm_xor_si128( \
+ _mm_srli_epi64(x2, 2), \
+ _mm_srli_epi64(x2, 7)))); \
+ x1 = _mm_xor_si128( \
+ _mm_xor_si128( \
+ x1, \
+ _mm_slli_epi64(x2, 63)), \
+ _mm_xor_si128( \
+ _mm_slli_epi64(x2, 62), \
+ _mm_slli_epi64(x2, 57))); \
+ } while (0)
+
+/*
+ * Square value kw into (dw,dx).
+ */
+#define SQUARE_F128(kw, dw, dx) do { \
+ __m128i z0, z1, z2, z3; \
+ z1 = pclmulqdq11(kw, kw); \
+ z3 = pclmulqdq00(kw, kw); \
+ z0 = _mm_shuffle_epi32(z1, 0x0E); \
+ z2 = _mm_shuffle_epi32(z3, 0x0E); \
+ SL_256(z0, z1, z2, z3); \
+ REDUCE_F128(z0, z1, z2, z3); \
+ PBK(z0, z1, dw, dx); \
+ } while (0)
+
+/* see bearssl_hash.h */
+BR_TARGET("ssse3,pclmul")
+void
+br_ghash_pclmul(void *y, const void *h, const void *data, size_t len)
+{
+ const unsigned char *buf1, *buf2;
+ unsigned char tmp[64];
+ size_t num4, num1;
+ __m128i yw, h1w, h1x;
+ BYTESWAP_DECL
+
+ /*
+ * We split data into two chunks. First chunk starts at buf1
+ * and contains num4 blocks of 64-byte values. Second chunk
+ * starts at buf2 and contains num1 blocks of 16-byte values.
+ * We want the first chunk to be as large as possible.
+ */
+ buf1 = data;
+ num4 = len >> 6;
+ len &= 63;
+ buf2 = buf1 + (num4 << 6);
+ num1 = (len + 15) >> 4;
+ if ((len & 15) != 0) {
+ memcpy(tmp, buf2, len);
+ memset(tmp + len, 0, (num1 << 4) - len);
+ buf2 = tmp;
+ }
+
+ /*
+ * Preparatory step for endian conversions.
+ */
+ BYTESWAP_PREP;
+
+ /*
+ * Load y and h.
+ */
+ yw = _mm_loadu_si128(y);
+ h1w = _mm_loadu_si128(h);
+ BYTESWAP(yw);
+ BYTESWAP(h1w);
+ BK(h1w, h1x);
+
+ if (num4 > 0) {
+ __m128i h2w, h2x, h3w, h3x, h4w, h4x;
+ __m128i t0, t1, t2, t3;
+
+ /*
+ * Compute h2 = h^2.
+ */
+ SQUARE_F128(h1w, h2w, h2x);
+
+ /*
+ * Compute h3 = h^3 = h*(h^2).
+ */
+ t1 = pclmulqdq11(h1w, h2w);
+ t3 = pclmulqdq00(h1w, h2w);
+ t2 = _mm_xor_si128(pclmulqdq00(h1x, h2x),
+ _mm_xor_si128(t1, t3));
+ t0 = _mm_shuffle_epi32(t1, 0x0E);
+ t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
+ t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
+ SL_256(t0, t1, t2, t3);
+ REDUCE_F128(t0, t1, t2, t3);
+ PBK(t0, t1, h3w, h3x);
+
+ /*
+ * Compute h4 = h^4 = (h^2)^2.
+ */
+ SQUARE_F128(h2w, h4w, h4x);
+
+ while (num4 -- > 0) {
+ __m128i aw0, aw1, aw2, aw3;
+ __m128i ax0, ax1, ax2, ax3;
+
+ aw0 = _mm_loadu_si128((void *)(buf1 + 0));
+ aw1 = _mm_loadu_si128((void *)(buf1 + 16));
+ aw2 = _mm_loadu_si128((void *)(buf1 + 32));
+ aw3 = _mm_loadu_si128((void *)(buf1 + 48));
+ BYTESWAP(aw0);
+ BYTESWAP(aw1);
+ BYTESWAP(aw2);
+ BYTESWAP(aw3);
+ buf1 += 64;
+
+ aw0 = _mm_xor_si128(aw0, yw);
+ BK(aw1, ax1);
+ BK(aw2, ax2);
+ BK(aw3, ax3);
+ BK(aw0, ax0);
+
+ t1 = _mm_xor_si128(
+ _mm_xor_si128(
+ pclmulqdq11(aw0, h4w),
+ pclmulqdq11(aw1, h3w)),
+ _mm_xor_si128(
+ pclmulqdq11(aw2, h2w),
+ pclmulqdq11(aw3, h1w)));
+ t3 = _mm_xor_si128(
+ _mm_xor_si128(
+ pclmulqdq00(aw0, h4w),
+ pclmulqdq00(aw1, h3w)),
+ _mm_xor_si128(
+ pclmulqdq00(aw2, h2w),
+ pclmulqdq00(aw3, h1w)));
+ t2 = _mm_xor_si128(
+ _mm_xor_si128(
+ pclmulqdq00(ax0, h4x),
+ pclmulqdq00(ax1, h3x)),
+ _mm_xor_si128(
+ pclmulqdq00(ax2, h2x),
+ pclmulqdq00(ax3, h1x)));
+ t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3));
+ t0 = _mm_shuffle_epi32(t1, 0x0E);
+ t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
+ t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
+ SL_256(t0, t1, t2, t3);
+ REDUCE_F128(t0, t1, t2, t3);
+ yw = _mm_unpacklo_epi64(t1, t0);
+ }
+ }
+
+ while (num1 -- > 0) {
+ __m128i aw, ax;
+ __m128i t0, t1, t2, t3;
+
+ aw = _mm_loadu_si128((void *)buf2);
+ BYTESWAP(aw);
+ buf2 += 16;
+
+ aw = _mm_xor_si128(aw, yw);
+ BK(aw, ax);
+
+ t1 = pclmulqdq11(aw, h1w);
+ t3 = pclmulqdq00(aw, h1w);
+ t2 = pclmulqdq00(ax, h1x);
+ t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3));
+ t0 = _mm_shuffle_epi32(t1, 0x0E);
+ t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
+ t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
+ SL_256(t0, t1, t2, t3);
+ REDUCE_F128(t0, t1, t2, t3);
+ yw = _mm_unpacklo_epi64(t1, t0);
+ }
+
+ BYTESWAP(yw);
+ _mm_storeu_si128(y, yw);
+}
+
+BR_TARGETS_X86_DOWN
+
+#else
+
+/* see bearssl_hash.h */
+br_ghash
+br_ghash_pclmul_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/hash/ghash_pclmul.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/ghash_pwr8.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/ghash_pwr8.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/ghash_pwr8.c (revision 346145)
@@ -0,0 +1,411 @@
+/*
+ * 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.
+ */
+
+#define BR_POWER_ASM_MACROS 1
+#include "inner.h"
+
+/*
+ * This is the GHASH implementation that leverages the POWER8 opcodes.
+ */
+
+#if BR_POWER8
+
+/*
+ * Some symbolic names for registers.
+ * HB0 = 16 bytes of value 0
+ * HB1 = 16 bytes of value 1
+ * HB2 = 16 bytes of value 2
+ * HB6 = 16 bytes of value 6
+ * HB7 = 16 bytes of value 7
+ * TT0, TT1 and TT2 are temporaries
+ *
+ * BSW holds the pattern for byteswapping 32-bit words; this is set only
+ * on little-endian systems. XBSW is the same register with the +32 offset
+ * for access with the VSX opcodes.
+ */
+#define HB0 0
+#define HB1 1
+#define HB2 2
+#define HB6 3
+#define HB7 4
+#define TT0 5
+#define TT1 6
+#define TT2 7
+
+#define BSW 8
+#define XBSW 40
+
+/*
+ * Macro to initialise the constants.
+ */
+#define INIT \
+ vxor(HB0, HB0, HB0) \
+ vspltisb(HB1, 1) \
+ vspltisb(HB2, 2) \
+ vspltisb(HB6, 6) \
+ vspltisb(HB7, 7) \
+ INIT_BSW
+
+/*
+ * Fix endianness of a value after reading it or before writing it, if
+ * necessary.
+ */
+#if BR_POWER8_LE
+#define INIT_BSW lxvw4x(XBSW, 0, %[idx2be])
+#define FIX_ENDIAN(xx) vperm(xx, xx, xx, BSW)
+#else
+#define INIT_BSW
+#define FIX_ENDIAN(xx)
+#endif
+
+/*
+ * Left-shift x0:x1 by one bit to the left. This is a corrective action
+ * needed because GHASH is defined in full little-endian specification,
+ * while the opcodes use full big-endian convention, so the 255-bit product
+ * ends up one bit to the right.
+ */
+#define SL_256(x0, x1) \
+ vsldoi(TT0, HB0, x1, 1) \
+ vsl(x0, x0, HB1) \
+ vsr(TT0, TT0, HB7) \
+ vsl(x1, x1, HB1) \
+ vxor(x0, x0, TT0)
+
+/*
+ * Reduce x0:x1 in GF(2^128), result in xd (register xd may be the same as
+ * x0 or x1, or a different register). x0 and x1 are modified.
+ */
+#define REDUCE_F128(xd, x0, x1) \
+ vxor(x0, x0, x1) \
+ vsr(TT0, x1, HB1) \
+ vsr(TT1, x1, HB2) \
+ vsr(TT2, x1, HB7) \
+ vxor(x0, x0, TT0) \
+ vxor(TT1, TT1, TT2) \
+ vxor(x0, x0, TT1) \
+ vsldoi(x1, x1, HB0, 15) \
+ vsl(TT1, x1, HB6) \
+ vsl(TT2, x1, HB1) \
+ vxor(x1, TT1, TT2) \
+ vsr(TT0, x1, HB1) \
+ vsr(TT1, x1, HB2) \
+ vsr(TT2, x1, HB7) \
+ vxor(x0, x0, x1) \
+ vxor(x0, x0, TT0) \
+ vxor(TT1, TT1, TT2) \
+ vxor(xd, x0, TT1)
+
+/* see bearssl_hash.h */
+void
+br_ghash_pwr8(void *y, const void *h, const void *data, size_t len)
+{
+ const unsigned char *buf1, *buf2;
+ size_t num4, num1;
+ unsigned char tmp[64];
+ long cc0, cc1, cc2, cc3;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ buf1 = data;
+
+ /*
+ * Assembly code requires data into two chunks; first chunk
+ * must contain a number of blocks which is a multiple of 4.
+ * Since the processing for the first chunk is faster, we want
+ * to make it as big as possible.
+ *
+ * For the remainder, there are two possibilities:
+ * -- if the remainder size is a multiple of 16, then use it
+ * in place;
+ * -- otherwise, copy it to the tmp[] array and pad it with
+ * zeros.
+ */
+ num4 = len >> 6;
+ buf2 = buf1 + (num4 << 6);
+ len &= 63;
+ num1 = (len + 15) >> 4;
+ if ((len & 15) != 0) {
+ memcpy(tmp, buf2, len);
+ memset(tmp + len, 0, (num1 << 4) - len);
+ buf2 = tmp;
+ }
+
+ cc0 = 0;
+ cc1 = 16;
+ cc2 = 32;
+ cc3 = 48;
+ asm volatile (
+ INIT
+
+ /*
+ * Load current h (denoted hereafter h1) in v9.
+ */
+ lxvw4x(41, 0, %[h])
+ FIX_ENDIAN(9)
+
+ /*
+ * Load current y into v28.
+ */
+ lxvw4x(60, 0, %[y])
+ FIX_ENDIAN(28)
+
+ /*
+ * Split h1 into three registers:
+ * v17 = h1_1:h1_0
+ * v18 = 0:h1_0
+ * v19 = h1_1:0
+ */
+ xxpermdi(49, 41, 41, 2)
+ vsldoi(18, HB0, 9, 8)
+ vsldoi(19, 9, HB0, 8)
+
+ /*
+ * If num4 is 0, skip directly to the second chunk.
+ */
+ cmpldi(%[num4], 0)
+ beq(chunk1)
+
+ /*
+ * Compute h2 = h*h in v10.
+ */
+ vpmsumd(10, 18, 18)
+ vpmsumd(11, 19, 19)
+ SL_256(10, 11)
+ REDUCE_F128(10, 10, 11)
+
+ /*
+ * Compute h3 = h*h*h in v11.
+ * We first split h2 into:
+ * v10 = h2_0:h2_1
+ * v11 = 0:h2_0
+ * v12 = h2_1:0
+ * Then we do the product with h1, and reduce into v11.
+ */
+ vsldoi(11, HB0, 10, 8)
+ vsldoi(12, 10, HB0, 8)
+ vpmsumd(13, 10, 17)
+ vpmsumd(11, 11, 18)
+ vpmsumd(12, 12, 19)
+ vsldoi(14, HB0, 13, 8)
+ vsldoi(15, 13, HB0, 8)
+ vxor(11, 11, 14)
+ vxor(12, 12, 15)
+ SL_256(11, 12)
+ REDUCE_F128(11, 11, 12)
+
+ /*
+ * Compute h4 = h*h*h*h in v12. This is done by squaring h2.
+ */
+ vsldoi(12, HB0, 10, 8)
+ vsldoi(13, 10, HB0, 8)
+ vpmsumd(12, 12, 12)
+ vpmsumd(13, 13, 13)
+ SL_256(12, 13)
+ REDUCE_F128(12, 12, 13)
+
+ /*
+ * Repack h1, h2, h3 and h4:
+ * v13 = h4_0:h3_0
+ * v14 = h4_1:h3_1
+ * v15 = h2_0:h1_0
+ * v16 = h2_1:h1_1
+ */
+ xxpermdi(45, 44, 43, 0)
+ xxpermdi(46, 44, 43, 3)
+ xxpermdi(47, 42, 41, 0)
+ xxpermdi(48, 42, 41, 3)
+
+ /*
+ * Loop for each group of four blocks.
+ */
+ mtctr(%[num4])
+ label(loop4)
+ /*
+ * Read the four next blocks.
+ * v20 = y + a0 = b0
+ * v21 = a1 = b1
+ * v22 = a2 = b2
+ * v23 = a3 = b3
+ */
+ lxvw4x(52, %[cc0], %[buf1])
+ lxvw4x(53, %[cc1], %[buf1])
+ lxvw4x(54, %[cc2], %[buf1])
+ lxvw4x(55, %[cc3], %[buf1])
+ FIX_ENDIAN(20)
+ FIX_ENDIAN(21)
+ FIX_ENDIAN(22)
+ FIX_ENDIAN(23)
+ addi(%[buf1], %[buf1], 64)
+ vxor(20, 20, 28)
+
+ /*
+ * Repack the blocks into v9, v10, v11 and v12.
+ * v9 = b0_0:b1_0
+ * v10 = b0_1:b1_1
+ * v11 = b2_0:b3_0
+ * v12 = b2_1:b3_1
+ */
+ xxpermdi(41, 52, 53, 0)
+ xxpermdi(42, 52, 53, 3)
+ xxpermdi(43, 54, 55, 0)
+ xxpermdi(44, 54, 55, 3)
+
+ /*
+ * Compute the products.
+ * v20 = b0_0*h4_0 + b1_0*h3_0
+ * v21 = b0_1*h4_0 + b1_1*h3_0
+ * v22 = b0_0*h4_1 + b1_0*h3_1
+ * v23 = b0_1*h4_1 + b1_1*h3_1
+ * v24 = b2_0*h2_0 + b3_0*h1_0
+ * v25 = b2_1*h2_0 + b3_1*h1_0
+ * v26 = b2_0*h2_1 + b3_0*h1_1
+ * v27 = b2_1*h2_1 + b3_1*h1_1
+ */
+ vpmsumd(20, 13, 9)
+ vpmsumd(21, 13, 10)
+ vpmsumd(22, 14, 9)
+ vpmsumd(23, 14, 10)
+ vpmsumd(24, 15, 11)
+ vpmsumd(25, 15, 12)
+ vpmsumd(26, 16, 11)
+ vpmsumd(27, 16, 12)
+
+ /*
+ * Sum products into a single 256-bit result in v11:v12.
+ */
+ vxor(11, 20, 24)
+ vxor(12, 23, 27)
+ vxor( 9, 21, 22)
+ vxor(10, 25, 26)
+ vxor(20, 9, 10)
+ vsldoi( 9, HB0, 20, 8)
+ vsldoi(10, 20, HB0, 8)
+ vxor(11, 11, 9)
+ vxor(12, 12, 10)
+
+ /*
+ * Fix and reduce in GF(2^128); this is the new y (in v28).
+ */
+ SL_256(11, 12)
+ REDUCE_F128(28, 11, 12)
+
+ /*
+ * Loop for next group of four blocks.
+ */
+ bdnz(loop4)
+
+ /*
+ * Process second chunk, one block at a time.
+ */
+ label(chunk1)
+ cmpldi(%[num1], 0)
+ beq(done)
+
+ mtctr(%[num1])
+ label(loop1)
+ /*
+ * Load next data block and XOR it into y.
+ */
+ lxvw4x(41, 0, %[buf2])
+#if BR_POWER8_LE
+ FIX_ENDIAN(9)
+#endif
+ addi(%[buf2], %[buf2], 16)
+ vxor(9, 28, 9)
+
+ /*
+ * Split y into doublewords:
+ * v9 = y_0:y_1
+ * v10 = 0:y_0
+ * v11 = y_1:0
+ */
+ vsldoi(10, HB0, 9, 8)
+ vsldoi(11, 9, HB0, 8)
+
+ /*
+ * Compute products with h:
+ * v12 = y_0 * h_0
+ * v13 = y_1 * h_1
+ * v14 = y_1 * h_0 + y_0 * h_1
+ */
+ vpmsumd(14, 9, 17)
+ vpmsumd(12, 10, 18)
+ vpmsumd(13, 11, 19)
+
+ /*
+ * Propagate v14 into v12:v13 to finalise product.
+ */
+ vsldoi(10, HB0, 14, 8)
+ vsldoi(11, 14, HB0, 8)
+ vxor(12, 12, 10)
+ vxor(13, 13, 11)
+
+ /*
+ * Fix result and reduce into v28 (next value for y).
+ */
+ SL_256(12, 13)
+ REDUCE_F128(28, 12, 13)
+ bdnz(loop1)
+
+ label(done)
+ /*
+ * Write back the new y.
+ */
+ FIX_ENDIAN(28)
+ stxvw4x(60, 0, %[y])
+
+: [buf1] "+b" (buf1), [buf2] "+b" (buf2)
+: [y] "b" (y), [h] "b" (h), [num4] "b" (num4), [num1] "b" (num1),
+ [cc0] "b" (cc0), [cc1] "b" (cc1), [cc2] "b" (cc2), [cc3] "b" (cc3)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+ "ctr", "memory"
+ );
+}
+
+/* see bearssl_hash.h */
+br_ghash
+br_ghash_pwr8_get(void)
+{
+ return &br_ghash_pwr8;
+}
+
+#else
+
+/* see bearssl_hash.h */
+br_ghash
+br_ghash_pwr8_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/hash/ghash_pwr8.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/md5.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/md5.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/md5.c (revision 346145)
@@ -0,0 +1,208 @@
+/*
+ * 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"
+
+#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D))
+#define G(B, C, D) ((((C) ^ (B)) & (D)) ^ (C))
+#define H(B, C, D) ((B) ^ (C) ^ (D))
+#define I(B, C, D) ((C) ^ ((B) | ~(D)))
+
+#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+/* see inner.h */
+const uint32_t br_md5_IV[4] = {
+ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476
+};
+
+static const uint32_t K[64] = {
+ 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
+ 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
+ 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
+ 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
+
+ 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
+ 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
+ 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
+ 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
+
+ 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
+ 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
+ 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
+ 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
+
+ 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
+ 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
+ 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
+ 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
+};
+
+static const unsigned char MP[48] = {
+ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
+ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
+ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
+};
+
+/* see inner.h */
+void
+br_md5_round(const unsigned char *buf, uint32_t *val)
+{
+ uint32_t m[16];
+ uint32_t a, b, c, d;
+ int i;
+
+ a = val[0];
+ b = val[1];
+ c = val[2];
+ d = val[3];
+ /* obsolete
+ for (i = 0; i < 16; i ++) {
+ m[i] = br_dec32le(buf + (i << 2));
+ }
+ */
+ br_range_dec32le(m, 16, buf);
+
+ for (i = 0; i < 16; i += 4) {
+ a = b + ROTL(a + F(b, c, d) + m[i + 0] + K[i + 0], 7);
+ d = a + ROTL(d + F(a, b, c) + m[i + 1] + K[i + 1], 12);
+ c = d + ROTL(c + F(d, a, b) + m[i + 2] + K[i + 2], 17);
+ b = c + ROTL(b + F(c, d, a) + m[i + 3] + K[i + 3], 22);
+ }
+ for (i = 16; i < 32; i += 4) {
+ a = b + ROTL(a + G(b, c, d) + m[MP[i - 16]] + K[i + 0], 5);
+ d = a + ROTL(d + G(a, b, c) + m[MP[i - 15]] + K[i + 1], 9);
+ c = d + ROTL(c + G(d, a, b) + m[MP[i - 14]] + K[i + 2], 14);
+ b = c + ROTL(b + G(c, d, a) + m[MP[i - 13]] + K[i + 3], 20);
+ }
+ for (i = 32; i < 48; i += 4) {
+ a = b + ROTL(a + H(b, c, d) + m[MP[i - 16]] + K[i + 0], 4);
+ d = a + ROTL(d + H(a, b, c) + m[MP[i - 15]] + K[i + 1], 11);
+ c = d + ROTL(c + H(d, a, b) + m[MP[i - 14]] + K[i + 2], 16);
+ b = c + ROTL(b + H(c, d, a) + m[MP[i - 13]] + K[i + 3], 23);
+ }
+ for (i = 48; i < 64; i += 4) {
+ a = b + ROTL(a + I(b, c, d) + m[MP[i - 16]] + K[i + 0], 6);
+ d = a + ROTL(d + I(a, b, c) + m[MP[i - 15]] + K[i + 1], 10);
+ c = d + ROTL(c + I(d, a, b) + m[MP[i - 14]] + K[i + 2], 15);
+ b = c + ROTL(b + I(c, d, a) + m[MP[i - 13]] + K[i + 3], 21);
+ }
+
+ val[0] += a;
+ val[1] += b;
+ val[2] += c;
+ val[3] += d;
+}
+
+/* see bearssl.h */
+void
+br_md5_init(br_md5_context *cc)
+{
+ cc->vtable = &br_md5_vtable;
+ memcpy(cc->val, br_md5_IV, sizeof cc->val);
+ cc->count = 0;
+}
+
+/* see bearssl.h */
+void
+br_md5_update(br_md5_context *cc, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t ptr;
+
+ buf = data;
+ ptr = (size_t)cc->count & 63;
+ while (len > 0) {
+ size_t clen;
+
+ clen = 64 - ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(cc->buf + ptr, buf, clen);
+ ptr += clen;
+ buf += clen;
+ len -= clen;
+ cc->count += (uint64_t)clen;
+ if (ptr == 64) {
+ br_md5_round(cc->buf, cc->val);
+ ptr = 0;
+ }
+ }
+}
+
+/* see bearssl.h */
+void
+br_md5_out(const br_md5_context *cc, void *dst)
+{
+ unsigned char buf[64];
+ uint32_t val[4];
+ size_t ptr;
+
+ ptr = (size_t)cc->count & 63;
+ memcpy(buf, cc->buf, ptr);
+ memcpy(val, cc->val, sizeof val);
+ buf[ptr ++] = 0x80;
+ if (ptr > 56) {
+ memset(buf + ptr, 0, 64 - ptr);
+ br_md5_round(buf, val);
+ memset(buf, 0, 56);
+ } else {
+ memset(buf + ptr, 0, 56 - ptr);
+ }
+ br_enc64le(buf + 56, cc->count << 3);
+ br_md5_round(buf, val);
+ br_range_enc32le(dst, val, 4);
+}
+
+/* see bearssl.h */
+uint64_t
+br_md5_state(const br_md5_context *cc, void *dst)
+{
+ br_range_enc32le(dst, cc->val, 4);
+ return cc->count;
+}
+
+/* see bearssl.h */
+void
+br_md5_set_state(br_md5_context *cc, const void *stb, uint64_t count)
+{
+ br_range_dec32le(cc->val, 4, stb);
+ cc->count = count;
+}
+
+/* see bearssl.h */
+const br_hash_class br_md5_vtable = {
+ sizeof(br_md5_context),
+ BR_HASHDESC_ID(br_md5_ID)
+ | BR_HASHDESC_OUT(16)
+ | BR_HASHDESC_STATE(16)
+ | BR_HASHDESC_LBLEN(6)
+ | BR_HASHDESC_MD_PADDING,
+ (void (*)(const br_hash_class **))&br_md5_init,
+ (void (*)(const br_hash_class **, const void *, size_t))&br_md5_update,
+ (void (*)(const br_hash_class *const *, void *))&br_md5_out,
+ (uint64_t (*)(const br_hash_class *const *, void *))&br_md5_state,
+ (void (*)(const br_hash_class **, const void *, uint64_t))
+ &br_md5_set_state
+};
Property changes on: stable/12/contrib/bearssl/src/hash/md5.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/md5sha1.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/md5sha1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/md5sha1.c (revision 346145)
@@ -0,0 +1,141 @@
+/*
+ * 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 bearssl.h */
+void
+br_md5sha1_init(br_md5sha1_context *cc)
+{
+ cc->vtable = &br_md5sha1_vtable;
+ memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5);
+ memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1);
+ cc->count = 0;
+}
+
+/* see bearssl.h */
+void
+br_md5sha1_update(br_md5sha1_context *cc, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t ptr;
+
+ buf = data;
+ ptr = (size_t)cc->count & 63;
+ while (len > 0) {
+ size_t clen;
+
+ clen = 64 - ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(cc->buf + ptr, buf, clen);
+ ptr += clen;
+ buf += clen;
+ len -= clen;
+ cc->count += (uint64_t)clen;
+ if (ptr == 64) {
+ br_md5_round(cc->buf, cc->val_md5);
+ br_sha1_round(cc->buf, cc->val_sha1);
+ ptr = 0;
+ }
+ }
+}
+
+/* see bearssl.h */
+void
+br_md5sha1_out(const br_md5sha1_context *cc, void *dst)
+{
+ unsigned char buf[64];
+ uint32_t val_md5[4];
+ uint32_t val_sha1[5];
+ size_t ptr;
+ unsigned char *out;
+ uint64_t count;
+
+ count = cc->count;
+ ptr = (size_t)count & 63;
+ memcpy(buf, cc->buf, ptr);
+ memcpy(val_md5, cc->val_md5, sizeof val_md5);
+ memcpy(val_sha1, cc->val_sha1, sizeof val_sha1);
+ buf[ptr ++] = 0x80;
+ if (ptr > 56) {
+ memset(buf + ptr, 0, 64 - ptr);
+ br_md5_round(buf, val_md5);
+ br_sha1_round(buf, val_sha1);
+ memset(buf, 0, 56);
+ } else {
+ memset(buf + ptr, 0, 56 - ptr);
+ }
+ count <<= 3;
+ br_enc64le(buf + 56, count);
+ br_md5_round(buf, val_md5);
+ br_enc64be(buf + 56, count);
+ br_sha1_round(buf, val_sha1);
+ out = dst;
+ br_range_enc32le(out, val_md5, 4);
+ br_range_enc32be(out + 16, val_sha1, 5);
+}
+
+/* see bearssl.h */
+uint64_t
+br_md5sha1_state(const br_md5sha1_context *cc, void *dst)
+{
+ unsigned char *out;
+
+ out = dst;
+ br_range_enc32le(out, cc->val_md5, 4);
+ br_range_enc32be(out + 16, cc->val_sha1, 5);
+ return cc->count;
+}
+
+/* see bearssl.h */
+void
+br_md5sha1_set_state(br_md5sha1_context *cc, const void *stb, uint64_t count)
+{
+ const unsigned char *buf;
+
+ buf = stb;
+ br_range_dec32le(cc->val_md5, 4, buf);
+ br_range_dec32be(cc->val_sha1, 5, buf + 16);
+ cc->count = count;
+}
+
+/* see bearssl.h */
+const br_hash_class br_md5sha1_vtable = {
+ sizeof(br_md5sha1_context),
+ BR_HASHDESC_ID(br_md5sha1_ID)
+ | BR_HASHDESC_OUT(36)
+ | BR_HASHDESC_STATE(36)
+ | BR_HASHDESC_LBLEN(6),
+ (void (*)(const br_hash_class **))&br_md5sha1_init,
+ (void (*)(const br_hash_class **, const void *, size_t))
+ &br_md5sha1_update,
+ (void (*)(const br_hash_class *const *, void *))
+ &br_md5sha1_out,
+ (uint64_t (*)(const br_hash_class *const *, void *))
+ &br_md5sha1_state,
+ (void (*)(const br_hash_class **, const void *, uint64_t))
+ &br_md5sha1_set_state
+};
Property changes on: stable/12/contrib/bearssl/src/hash/md5sha1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/mgf1.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/mgf1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/mgf1.c (revision 346145)
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_mgf1_xor(void *data, size_t len,
+ const br_hash_class *dig, const void *seed, size_t seed_len)
+{
+ unsigned char *buf;
+ size_t u, hlen;
+ uint32_t c;
+
+ buf = data;
+ hlen = br_digest_size(dig);
+ for (u = 0, c = 0; u < len; u += hlen, c ++) {
+ br_hash_compat_context hc;
+ unsigned char tmp[64];
+ size_t v;
+
+ hc.vtable = dig;
+ dig->init(&hc.vtable);
+ dig->update(&hc.vtable, seed, seed_len);
+ br_enc32be(tmp, c);
+ dig->update(&hc.vtable, tmp, 4);
+ dig->out(&hc.vtable, tmp);
+ for (v = 0; v < hlen; v ++) {
+ if ((u + v) >= len) {
+ break;
+ }
+ buf[u + v] ^= tmp[v];
+ }
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/hash/mgf1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/multihash.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/multihash.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/multihash.c (revision 346145)
@@ -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 "inner.h"
+
+/*
+ * An aggregate context that is large enough for all supported hash
+ * functions.
+ */
+typedef union {
+ const br_hash_class *vtable;
+ br_md5_context md5;
+ br_sha1_context sha1;
+ br_sha224_context sha224;
+ br_sha256_context sha256;
+ br_sha384_context sha384;
+ br_sha512_context sha512;
+} gen_hash_context;
+
+/*
+ * Get the offset to the state for a specific hash function within the
+ * context structure. This shall be called only for the supported hash
+ * functions,
+ */
+static size_t
+get_state_offset(int id)
+{
+ if (id >= 5) {
+ /*
+ * SHA-384 has id 5, and SHA-512 has id 6. Both use
+ * eight 64-bit words for their state.
+ */
+ return offsetof(br_multihash_context, val_64)
+ + ((size_t)(id - 5) * (8 * sizeof(uint64_t)));
+ } else {
+ /*
+ * MD5 has id 1, SHA-1 has id 2, SHA-224 has id 3 and
+ * SHA-256 has id 4. They use 32-bit words for their
+ * states (4 words for MD5, 5 for SHA-1, 8 for SHA-224
+ * and 8 for SHA-256).
+ */
+ unsigned x;
+
+ x = id - 1;
+ x = ((x + (x & (x >> 1))) << 2) + (x >> 1);
+ return offsetof(br_multihash_context, val_32)
+ + x * sizeof(uint32_t);
+ }
+}
+
+/* see bearssl_hash.h */
+void
+br_multihash_zero(br_multihash_context *ctx)
+{
+ /*
+ * This is not standard, but yields very short and efficient code,
+ * and it works "everywhere".
+ */
+ memset(ctx, 0, sizeof *ctx);
+}
+
+/* see bearssl_hash.h */
+void
+br_multihash_init(br_multihash_context *ctx)
+{
+ int i;
+
+ ctx->count = 0;
+ for (i = 1; i <= 6; i ++) {
+ const br_hash_class *hc;
+
+ hc = ctx->impl[i - 1];
+ if (hc != NULL) {
+ gen_hash_context g;
+
+ hc->init(&g.vtable);
+ hc->state(&g.vtable,
+ (unsigned char *)ctx + get_state_offset(i));
+ }
+ }
+}
+
+/* see bearssl_hash.h */
+void
+br_multihash_update(br_multihash_context *ctx, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t ptr;
+
+ buf = data;
+ ptr = (size_t)ctx->count & 127;
+ while (len > 0) {
+ size_t clen;
+
+ clen = 128 - ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(ctx->buf + ptr, buf, clen);
+ ptr += clen;
+ buf += clen;
+ len -= clen;
+ ctx->count += (uint64_t)clen;
+ if (ptr == 128) {
+ int i;
+
+ for (i = 1; i <= 6; i ++) {
+ const br_hash_class *hc;
+
+ hc = ctx->impl[i - 1];
+ if (hc != NULL) {
+ gen_hash_context g;
+ unsigned char *state;
+
+ state = (unsigned char *)ctx
+ + get_state_offset(i);
+ hc->set_state(&g.vtable,
+ state, ctx->count - 128);
+ hc->update(&g.vtable, ctx->buf, 128);
+ hc->state(&g.vtable, state);
+ }
+ }
+ ptr = 0;
+ }
+ }
+}
+
+/* see bearssl_hash.h */
+size_t
+br_multihash_out(const br_multihash_context *ctx, int id, void *dst)
+{
+ const br_hash_class *hc;
+ gen_hash_context g;
+ const unsigned char *state;
+
+ hc = ctx->impl[id - 1];
+ if (hc == NULL) {
+ return 0;
+ }
+ state = (const unsigned char *)ctx + get_state_offset(id);
+ hc->set_state(&g.vtable, state, ctx->count & ~(uint64_t)127);
+ hc->update(&g.vtable, ctx->buf, ctx->count & (uint64_t)127);
+ hc->out(&g.vtable, dst);
+ return (hc->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+}
Property changes on: stable/12/contrib/bearssl/src/hash/multihash.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/sha1.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/sha1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/sha1.c (revision 346145)
@@ -0,0 +1,191 @@
+/*
+ * 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"
+
+#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D))
+#define G(B, C, D) ((B) ^ (C) ^ (D))
+#define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B)))
+#define I(B, C, D) G(B, C, D)
+
+#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+#define K1 ((uint32_t)0x5A827999)
+#define K2 ((uint32_t)0x6ED9EBA1)
+#define K3 ((uint32_t)0x8F1BBCDC)
+#define K4 ((uint32_t)0xCA62C1D6)
+
+/* see inner.h */
+const uint32_t br_sha1_IV[5] = {
+ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
+};
+
+/* see inner.h */
+void
+br_sha1_round(const unsigned char *buf, uint32_t *val)
+{
+ uint32_t m[80];
+ uint32_t a, b, c, d, e;
+ int i;
+
+ a = val[0];
+ b = val[1];
+ c = val[2];
+ d = val[3];
+ e = val[4];
+ br_range_dec32be(m, 16, buf);
+ for (i = 16; i < 80; i ++) {
+ uint32_t x = m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16];
+ m[i] = ROTL(x, 1);
+ }
+
+ for (i = 0; i < 20; i += 5) {
+ e += ROTL(a, 5) + F(b, c, d) + K1 + m[i + 0]; b = ROTL(b, 30);
+ d += ROTL(e, 5) + F(a, b, c) + K1 + m[i + 1]; a = ROTL(a, 30);
+ c += ROTL(d, 5) + F(e, a, b) + K1 + m[i + 2]; e = ROTL(e, 30);
+ b += ROTL(c, 5) + F(d, e, a) + K1 + m[i + 3]; d = ROTL(d, 30);
+ a += ROTL(b, 5) + F(c, d, e) + K1 + m[i + 4]; c = ROTL(c, 30);
+ }
+ for (i = 20; i < 40; i += 5) {
+ e += ROTL(a, 5) + G(b, c, d) + K2 + m[i + 0]; b = ROTL(b, 30);
+ d += ROTL(e, 5) + G(a, b, c) + K2 + m[i + 1]; a = ROTL(a, 30);
+ c += ROTL(d, 5) + G(e, a, b) + K2 + m[i + 2]; e = ROTL(e, 30);
+ b += ROTL(c, 5) + G(d, e, a) + K2 + m[i + 3]; d = ROTL(d, 30);
+ a += ROTL(b, 5) + G(c, d, e) + K2 + m[i + 4]; c = ROTL(c, 30);
+ }
+ for (i = 40; i < 60; i += 5) {
+ e += ROTL(a, 5) + H(b, c, d) + K3 + m[i + 0]; b = ROTL(b, 30);
+ d += ROTL(e, 5) + H(a, b, c) + K3 + m[i + 1]; a = ROTL(a, 30);
+ c += ROTL(d, 5) + H(e, a, b) + K3 + m[i + 2]; e = ROTL(e, 30);
+ b += ROTL(c, 5) + H(d, e, a) + K3 + m[i + 3]; d = ROTL(d, 30);
+ a += ROTL(b, 5) + H(c, d, e) + K3 + m[i + 4]; c = ROTL(c, 30);
+ }
+ for (i = 60; i < 80; i += 5) {
+ e += ROTL(a, 5) + I(b, c, d) + K4 + m[i + 0]; b = ROTL(b, 30);
+ d += ROTL(e, 5) + I(a, b, c) + K4 + m[i + 1]; a = ROTL(a, 30);
+ c += ROTL(d, 5) + I(e, a, b) + K4 + m[i + 2]; e = ROTL(e, 30);
+ b += ROTL(c, 5) + I(d, e, a) + K4 + m[i + 3]; d = ROTL(d, 30);
+ a += ROTL(b, 5) + I(c, d, e) + K4 + m[i + 4]; c = ROTL(c, 30);
+ }
+
+ val[0] += a;
+ val[1] += b;
+ val[2] += c;
+ val[3] += d;
+ val[4] += e;
+}
+
+/* see bearssl.h */
+void
+br_sha1_init(br_sha1_context *cc)
+{
+ cc->vtable = &br_sha1_vtable;
+ memcpy(cc->val, br_sha1_IV, sizeof cc->val);
+ cc->count = 0;
+}
+
+/* see bearssl.h */
+void
+br_sha1_update(br_sha1_context *cc, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t ptr;
+
+ buf = data;
+ ptr = (size_t)cc->count & 63;
+ while (len > 0) {
+ size_t clen;
+
+ clen = 64 - ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(cc->buf + ptr, buf, clen);
+ ptr += clen;
+ buf += clen;
+ len -= clen;
+ cc->count += (uint64_t)clen;
+ if (ptr == 64) {
+ br_sha1_round(cc->buf, cc->val);
+ ptr = 0;
+ }
+ }
+}
+
+/* see bearssl.h */
+void
+br_sha1_out(const br_sha1_context *cc, void *dst)
+{
+ unsigned char buf[64];
+ uint32_t val[5];
+ size_t ptr;
+
+ ptr = (size_t)cc->count & 63;
+ memcpy(buf, cc->buf, ptr);
+ memcpy(val, cc->val, sizeof val);
+ buf[ptr ++] = 0x80;
+ if (ptr > 56) {
+ memset(buf + ptr, 0, 64 - ptr);
+ br_sha1_round(buf, val);
+ memset(buf, 0, 56);
+ } else {
+ memset(buf + ptr, 0, 56 - ptr);
+ }
+ br_enc64be(buf + 56, cc->count << 3);
+ br_sha1_round(buf, val);
+ br_range_enc32be(dst, val, 5);
+}
+
+/* see bearssl.h */
+uint64_t
+br_sha1_state(const br_sha1_context *cc, void *dst)
+{
+ br_range_enc32be(dst, cc->val, 5);
+ return cc->count;
+}
+
+/* see bearssl.h */
+void
+br_sha1_set_state(br_sha1_context *cc, const void *stb, uint64_t count)
+{
+ br_range_dec32be(cc->val, 5, stb);
+ cc->count = count;
+}
+
+/* see bearssl.h */
+const br_hash_class br_sha1_vtable = {
+ sizeof(br_sha1_context),
+ BR_HASHDESC_ID(br_sha1_ID)
+ | BR_HASHDESC_OUT(20)
+ | BR_HASHDESC_STATE(20)
+ | BR_HASHDESC_LBLEN(6)
+ | BR_HASHDESC_MD_PADDING
+ | BR_HASHDESC_MD_PADDING_BE,
+ (void (*)(const br_hash_class **))&br_sha1_init,
+ (void (*)(const br_hash_class **, const void *, size_t))&br_sha1_update,
+ (void (*)(const br_hash_class *const *, void *))&br_sha1_out,
+ (uint64_t (*)(const br_hash_class *const *, void *))&br_sha1_state,
+ (void (*)(const br_hash_class **, const void *, uint64_t))
+ &br_sha1_set_state
+};
Property changes on: stable/12/contrib/bearssl/src/hash/sha1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/sha2big.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/sha2big.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/sha2big.c (revision 346145)
@@ -0,0 +1,285 @@
+/*
+ * 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"
+
+#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
+#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X)))
+
+#define ROTR(x, n) (((uint64_t)(x) << (64 - (n))) | ((uint64_t)(x) >> (n)))
+
+#define BSG5_0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define BSG5_1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SSG5_0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ (uint64_t)((x) >> 7))
+#define SSG5_1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ (uint64_t)((x) >> 6))
+
+static const uint64_t IV384[8] = {
+ 0xCBBB9D5DC1059ED8, 0x629A292A367CD507,
+ 0x9159015A3070DD17, 0x152FECD8F70E5939,
+ 0x67332667FFC00B31, 0x8EB44A8768581511,
+ 0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4
+};
+
+static const uint64_t IV512[8] = {
+ 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
+ 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
+ 0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
+ 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
+};
+
+static const uint64_t K[80] = {
+ 0x428A2F98D728AE22, 0x7137449123EF65CD,
+ 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
+ 0x3956C25BF348B538, 0x59F111F1B605D019,
+ 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
+ 0xD807AA98A3030242, 0x12835B0145706FBE,
+ 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
+ 0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1,
+ 0x9BDC06A725C71235, 0xC19BF174CF692694,
+ 0xE49B69C19EF14AD2, 0xEFBE4786384F25E3,
+ 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
+ 0x2DE92C6F592B0275, 0x4A7484AA6EA6E483,
+ 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
+ 0x983E5152EE66DFAB, 0xA831C66D2DB43210,
+ 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
+ 0xC6E00BF33DA88FC2, 0xD5A79147930AA725,
+ 0x06CA6351E003826F, 0x142929670A0E6E70,
+ 0x27B70A8546D22FFC, 0x2E1B21385C26C926,
+ 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
+ 0x650A73548BAF63DE, 0x766A0ABB3C77B2A8,
+ 0x81C2C92E47EDAEE6, 0x92722C851482353B,
+ 0xA2BFE8A14CF10364, 0xA81A664BBC423001,
+ 0xC24B8B70D0F89791, 0xC76C51A30654BE30,
+ 0xD192E819D6EF5218, 0xD69906245565A910,
+ 0xF40E35855771202A, 0x106AA07032BBD1B8,
+ 0x19A4C116B8D2D0C8, 0x1E376C085141AB53,
+ 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
+ 0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB,
+ 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
+ 0x748F82EE5DEFB2FC, 0x78A5636F43172F60,
+ 0x84C87814A1F0AB72, 0x8CC702081A6439EC,
+ 0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9,
+ 0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
+ 0xCA273ECEEA26619C, 0xD186B8C721C0C207,
+ 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
+ 0x06F067AA72176FBA, 0x0A637DC5A2C898A6,
+ 0x113F9804BEF90DAE, 0x1B710B35131C471B,
+ 0x28DB77F523047D84, 0x32CAAB7B40C72493,
+ 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
+ 0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A,
+ 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817
+};
+
+static void
+sha2big_round(const unsigned char *buf, uint64_t *val)
+{
+
+#define SHA2BIG_STEP(A, B, C, D, E, F, G, H, j) do { \
+ uint64_t T1, T2; \
+ T1 = H + BSG5_1(E) + CH(E, F, G) + K[j] + w[j]; \
+ T2 = BSG5_0(A) + MAJ(A, B, C); \
+ D += T1; \
+ H = T1 + T2; \
+ } while (0)
+
+ int i;
+ uint64_t a, b, c, d, e, f, g, h;
+ uint64_t w[80];
+
+ br_range_dec64be(w, 16, buf);
+ for (i = 16; i < 80; i ++) {
+ w[i] = SSG5_1(w[i - 2]) + w[i - 7]
+ + SSG5_0(w[i - 15]) + w[i - 16];
+ }
+ a = val[0];
+ b = val[1];
+ c = val[2];
+ d = val[3];
+ e = val[4];
+ f = val[5];
+ g = val[6];
+ h = val[7];
+ for (i = 0; i < 80; i += 8) {
+ SHA2BIG_STEP(a, b, c, d, e, f, g, h, i + 0);
+ SHA2BIG_STEP(h, a, b, c, d, e, f, g, i + 1);
+ SHA2BIG_STEP(g, h, a, b, c, d, e, f, i + 2);
+ SHA2BIG_STEP(f, g, h, a, b, c, d, e, i + 3);
+ SHA2BIG_STEP(e, f, g, h, a, b, c, d, i + 4);
+ SHA2BIG_STEP(d, e, f, g, h, a, b, c, i + 5);
+ SHA2BIG_STEP(c, d, e, f, g, h, a, b, i + 6);
+ SHA2BIG_STEP(b, c, d, e, f, g, h, a, i + 7);
+ }
+ val[0] += a;
+ val[1] += b;
+ val[2] += c;
+ val[3] += d;
+ val[4] += e;
+ val[5] += f;
+ val[6] += g;
+ val[7] += h;
+}
+
+static void
+sha2big_update(br_sha384_context *cc, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t ptr;
+
+ buf = data;
+ ptr = (size_t)cc->count & 127;
+ cc->count += (uint64_t)len;
+ while (len > 0) {
+ size_t clen;
+
+ clen = 128 - ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(cc->buf + ptr, buf, clen);
+ ptr += clen;
+ buf += clen;
+ len -= clen;
+ if (ptr == 128) {
+ sha2big_round(cc->buf, cc->val);
+ ptr = 0;
+ }
+ }
+}
+
+static void
+sha2big_out(const br_sha384_context *cc, void *dst, int num)
+{
+ unsigned char buf[128];
+ uint64_t val[8];
+ size_t ptr;
+
+ ptr = (size_t)cc->count & 127;
+ memcpy(buf, cc->buf, ptr);
+ memcpy(val, cc->val, sizeof val);
+ buf[ptr ++] = 0x80;
+ if (ptr > 112) {
+ memset(buf + ptr, 0, 128 - ptr);
+ sha2big_round(buf, val);
+ memset(buf, 0, 112);
+ } else {
+ memset(buf + ptr, 0, 112 - ptr);
+ }
+ br_enc64be(buf + 112, cc->count >> 61);
+ br_enc64be(buf + 120, cc->count << 3);
+ sha2big_round(buf, val);
+ br_range_enc64be(dst, val, num);
+}
+
+/* see bearssl.h */
+void
+br_sha384_init(br_sha384_context *cc)
+{
+ cc->vtable = &br_sha384_vtable;
+ memcpy(cc->val, IV384, sizeof IV384);
+ cc->count = 0;
+}
+
+/* see bearssl.h */
+void
+br_sha384_update(br_sha384_context *cc, const void *data, size_t len)
+{
+ sha2big_update(cc, data, len);
+}
+
+/* see bearssl.h */
+void
+br_sha384_out(const br_sha384_context *cc, void *dst)
+{
+ sha2big_out(cc, dst, 6);
+}
+
+/* see bearssl.h */
+uint64_t
+br_sha384_state(const br_sha384_context *cc, void *dst)
+{
+ br_range_enc64be(dst, cc->val, 8);
+ return cc->count;
+}
+
+/* see bearssl.h */
+void
+br_sha384_set_state(br_sha384_context *cc, const void *stb, uint64_t count)
+{
+ br_range_dec64be(cc->val, 8, stb);
+ cc->count = count;
+}
+
+/* see bearssl.h */
+void
+br_sha512_init(br_sha512_context *cc)
+{
+ cc->vtable = &br_sha512_vtable;
+ memcpy(cc->val, IV512, sizeof IV512);
+ cc->count = 0;
+}
+
+/* see bearssl.h */
+void
+br_sha512_out(const br_sha512_context *cc, void *dst)
+{
+ sha2big_out(cc, dst, 8);
+}
+
+/* see bearssl.h */
+const br_hash_class br_sha384_vtable = {
+ sizeof(br_sha384_context),
+ BR_HASHDESC_ID(br_sha384_ID)
+ | BR_HASHDESC_OUT(48)
+ | BR_HASHDESC_STATE(64)
+ | BR_HASHDESC_LBLEN(7)
+ | BR_HASHDESC_MD_PADDING
+ | BR_HASHDESC_MD_PADDING_BE
+ | BR_HASHDESC_MD_PADDING_128,
+ (void (*)(const br_hash_class **))&br_sha384_init,
+ (void (*)(const br_hash_class **, const void *, size_t))
+ &br_sha384_update,
+ (void (*)(const br_hash_class *const *, void *))&br_sha384_out,
+ (uint64_t (*)(const br_hash_class *const *, void *))&br_sha384_state,
+ (void (*)(const br_hash_class **, const void *, uint64_t))
+ &br_sha384_set_state
+};
+
+/* see bearssl.h */
+const br_hash_class br_sha512_vtable = {
+ sizeof(br_sha512_context),
+ BR_HASHDESC_ID(br_sha512_ID)
+ | BR_HASHDESC_OUT(64)
+ | BR_HASHDESC_STATE(64)
+ | BR_HASHDESC_LBLEN(7)
+ | BR_HASHDESC_MD_PADDING
+ | BR_HASHDESC_MD_PADDING_BE
+ | BR_HASHDESC_MD_PADDING_128,
+ (void (*)(const br_hash_class **))&br_sha512_init,
+ (void (*)(const br_hash_class **, const void *, size_t))
+ &br_sha512_update,
+ (void (*)(const br_hash_class *const *, void *))&br_sha512_out,
+ (uint64_t (*)(const br_hash_class *const *, void *))&br_sha512_state,
+ (void (*)(const br_hash_class **, const void *, uint64_t))
+ &br_sha512_set_state
+};
Property changes on: stable/12/contrib/bearssl/src/hash/sha2big.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/hash/sha2small.c
===================================================================
--- stable/12/contrib/bearssl/src/hash/sha2small.c (nonexistent)
+++ stable/12/contrib/bearssl/src/hash/sha2small.c (revision 346145)
@@ -0,0 +1,341 @@
+/*
+ * 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"
+
+#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
+#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X)))
+
+#define ROTR(x, n) (((uint32_t)(x) << (32 - (n))) | ((uint32_t)(x) >> (n)))
+
+#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ (uint32_t)((x) >> 3))
+#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ (uint32_t)((x) >> 10))
+
+/* see inner.h */
+const uint32_t br_sha224_IV[8] = {
+ 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
+ 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
+};
+
+/* see inner.h */
+const uint32_t br_sha256_IV[8] = {
+ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+ 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+};
+
+static const uint32_t K[64] = {
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
+};
+
+/* see inner.h */
+void
+br_sha2small_round(const unsigned char *buf, uint32_t *val)
+{
+
+#define SHA2_STEP(A, B, C, D, E, F, G, H, j) do { \
+ uint32_t T1, T2; \
+ T1 = H + BSG2_1(E) + CH(E, F, G) + K[j] + w[j]; \
+ T2 = BSG2_0(A) + MAJ(A, B, C); \
+ D += T1; \
+ H = T1 + T2; \
+ } while (0)
+
+ int i;
+ uint32_t a, b, c, d, e, f, g, h;
+ uint32_t w[64];
+
+ br_range_dec32be(w, 16, buf);
+ for (i = 16; i < 64; i ++) {
+ w[i] = SSG2_1(w[i - 2]) + w[i - 7]
+ + SSG2_0(w[i - 15]) + w[i - 16];
+ }
+ a = val[0];
+ b = val[1];
+ c = val[2];
+ d = val[3];
+ e = val[4];
+ f = val[5];
+ g = val[6];
+ h = val[7];
+ for (i = 0; i < 64; i += 8) {
+ SHA2_STEP(a, b, c, d, e, f, g, h, i + 0);
+ SHA2_STEP(h, a, b, c, d, e, f, g, i + 1);
+ SHA2_STEP(g, h, a, b, c, d, e, f, i + 2);
+ SHA2_STEP(f, g, h, a, b, c, d, e, i + 3);
+ SHA2_STEP(e, f, g, h, a, b, c, d, i + 4);
+ SHA2_STEP(d, e, f, g, h, a, b, c, i + 5);
+ SHA2_STEP(c, d, e, f, g, h, a, b, i + 6);
+ SHA2_STEP(b, c, d, e, f, g, h, a, i + 7);
+ }
+ val[0] += a;
+ val[1] += b;
+ val[2] += c;
+ val[3] += d;
+ val[4] += e;
+ val[5] += f;
+ val[6] += g;
+ val[7] += h;
+
+#if 0
+/* obsolete */
+#define SHA2_MEXP1(pc) do { \
+ W[pc] = br_dec32be(buf + ((pc) << 2)); \
+ } while (0)
+
+#define SHA2_MEXP2(pc) do { \
+ W[(pc) & 0x0F] = SSG2_1(W[((pc) - 2) & 0x0F]) \
+ + W[((pc) - 7) & 0x0F] \
+ + SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]; \
+ } while (0)
+
+#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, pc) do { \
+ uint32_t t1, t2; \
+ SHA2_MEXP ## n(pc); \
+ t1 = h + BSG2_1(e) + CH(e, f, g) \
+ + K[pcount + (pc)] + W[(pc) & 0x0F]; \
+ t2 = BSG2_0(a) + MAJ(a, b, c); \
+ d += t1; \
+ h = t1 + t2; \
+ } while (0)
+
+#define SHA2_STEP1(a, b, c, d, e, f, g, h, pc) \
+ SHA2_STEPn(1, a, b, c, d, e, f, g, h, pc)
+#define SHA2_STEP2(a, b, c, d, e, f, g, h, pc) \
+ SHA2_STEPn(2, a, b, c, d, e, f, g, h, pc)
+
+ uint32_t A, B, C, D, E, F, G, H;
+ uint32_t W[16];
+ unsigned pcount;
+
+ A = val[0];
+ B = val[1];
+ C = val[2];
+ D = val[3];
+ E = val[4];
+ F = val[5];
+ G = val[6];
+ H = val[7];
+ pcount = 0;
+ SHA2_STEP1(A, B, C, D, E, F, G, H, 0);
+ SHA2_STEP1(H, A, B, C, D, E, F, G, 1);
+ SHA2_STEP1(G, H, A, B, C, D, E, F, 2);
+ SHA2_STEP1(F, G, H, A, B, C, D, E, 3);
+ SHA2_STEP1(E, F, G, H, A, B, C, D, 4);
+ SHA2_STEP1(D, E, F, G, H, A, B, C, 5);
+ SHA2_STEP1(C, D, E, F, G, H, A, B, 6);
+ SHA2_STEP1(B, C, D, E, F, G, H, A, 7);
+ SHA2_STEP1(A, B, C, D, E, F, G, H, 8);
+ SHA2_STEP1(H, A, B, C, D, E, F, G, 9);
+ SHA2_STEP1(G, H, A, B, C, D, E, F, 10);
+ SHA2_STEP1(F, G, H, A, B, C, D, E, 11);
+ SHA2_STEP1(E, F, G, H, A, B, C, D, 12);
+ SHA2_STEP1(D, E, F, G, H, A, B, C, 13);
+ SHA2_STEP1(C, D, E, F, G, H, A, B, 14);
+ SHA2_STEP1(B, C, D, E, F, G, H, A, 15);
+ for (pcount = 16; pcount < 64; pcount += 16) {
+ SHA2_STEP2(A, B, C, D, E, F, G, H, 0);
+ SHA2_STEP2(H, A, B, C, D, E, F, G, 1);
+ SHA2_STEP2(G, H, A, B, C, D, E, F, 2);
+ SHA2_STEP2(F, G, H, A, B, C, D, E, 3);
+ SHA2_STEP2(E, F, G, H, A, B, C, D, 4);
+ SHA2_STEP2(D, E, F, G, H, A, B, C, 5);
+ SHA2_STEP2(C, D, E, F, G, H, A, B, 6);
+ SHA2_STEP2(B, C, D, E, F, G, H, A, 7);
+ SHA2_STEP2(A, B, C, D, E, F, G, H, 8);
+ SHA2_STEP2(H, A, B, C, D, E, F, G, 9);
+ SHA2_STEP2(G, H, A, B, C, D, E, F, 10);
+ SHA2_STEP2(F, G, H, A, B, C, D, E, 11);
+ SHA2_STEP2(E, F, G, H, A, B, C, D, 12);
+ SHA2_STEP2(D, E, F, G, H, A, B, C, 13);
+ SHA2_STEP2(C, D, E, F, G, H, A, B, 14);
+ SHA2_STEP2(B, C, D, E, F, G, H, A, 15);
+ }
+ val[0] += A;
+ val[1] += B;
+ val[2] += C;
+ val[3] += D;
+ val[4] += E;
+ val[5] += F;
+ val[6] += G;
+ val[7] += H;
+#endif
+}
+
+static void
+sha2small_update(br_sha224_context *cc, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t ptr;
+
+ buf = data;
+ ptr = (size_t)cc->count & 63;
+ cc->count += (uint64_t)len;
+ while (len > 0) {
+ size_t clen;
+
+ clen = 64 - ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(cc->buf + ptr, buf, clen);
+ ptr += clen;
+ buf += clen;
+ len -= clen;
+ if (ptr == 64) {
+ br_sha2small_round(cc->buf, cc->val);
+ ptr = 0;
+ }
+ }
+}
+
+static void
+sha2small_out(const br_sha224_context *cc, void *dst, int num)
+{
+ unsigned char buf[64];
+ uint32_t val[8];
+ size_t ptr;
+
+ ptr = (size_t)cc->count & 63;
+ memcpy(buf, cc->buf, ptr);
+ memcpy(val, cc->val, sizeof val);
+ buf[ptr ++] = 0x80;
+ if (ptr > 56) {
+ memset(buf + ptr, 0, 64 - ptr);
+ br_sha2small_round(buf, val);
+ memset(buf, 0, 56);
+ } else {
+ memset(buf + ptr, 0, 56 - ptr);
+ }
+ br_enc64be(buf + 56, cc->count << 3);
+ br_sha2small_round(buf, val);
+ br_range_enc32be(dst, val, num);
+}
+
+/* see bearssl.h */
+void
+br_sha224_init(br_sha224_context *cc)
+{
+ cc->vtable = &br_sha224_vtable;
+ memcpy(cc->val, br_sha224_IV, sizeof cc->val);
+ cc->count = 0;
+}
+
+/* see bearssl.h */
+void
+br_sha224_update(br_sha224_context *cc, const void *data, size_t len)
+{
+ sha2small_update(cc, data, len);
+}
+
+/* see bearssl.h */
+void
+br_sha224_out(const br_sha224_context *cc, void *dst)
+{
+ sha2small_out(cc, dst, 7);
+}
+
+/* see bearssl.h */
+uint64_t
+br_sha224_state(const br_sha224_context *cc, void *dst)
+{
+ br_range_enc32be(dst, cc->val, 8);
+ return cc->count;
+}
+
+/* see bearssl.h */
+void
+br_sha224_set_state(br_sha224_context *cc, const void *stb, uint64_t count)
+{
+ br_range_dec32be(cc->val, 8, stb);
+ cc->count = count;
+}
+
+/* see bearssl.h */
+void
+br_sha256_init(br_sha256_context *cc)
+{
+ cc->vtable = &br_sha256_vtable;
+ memcpy(cc->val, br_sha256_IV, sizeof cc->val);
+ cc->count = 0;
+}
+
+/* see bearssl.h */
+void
+br_sha256_out(const br_sha256_context *cc, void *dst)
+{
+ sha2small_out(cc, dst, 8);
+}
+
+/* see bearssl.h */
+const br_hash_class br_sha224_vtable = {
+ sizeof(br_sha224_context),
+ BR_HASHDESC_ID(br_sha224_ID)
+ | BR_HASHDESC_OUT(28)
+ | BR_HASHDESC_STATE(32)
+ | BR_HASHDESC_LBLEN(6)
+ | BR_HASHDESC_MD_PADDING
+ | BR_HASHDESC_MD_PADDING_BE,
+ (void (*)(const br_hash_class **))&br_sha224_init,
+ (void (*)(const br_hash_class **,
+ const void *, size_t))&br_sha224_update,
+ (void (*)(const br_hash_class *const *, void *))&br_sha224_out,
+ (uint64_t (*)(const br_hash_class *const *, void *))&br_sha224_state,
+ (void (*)(const br_hash_class **, const void *, uint64_t))
+ &br_sha224_set_state
+};
+
+/* see bearssl.h */
+const br_hash_class br_sha256_vtable = {
+ sizeof(br_sha256_context),
+ BR_HASHDESC_ID(br_sha256_ID)
+ | BR_HASHDESC_OUT(32)
+ | BR_HASHDESC_STATE(32)
+ | BR_HASHDESC_LBLEN(6)
+ | BR_HASHDESC_MD_PADDING
+ | BR_HASHDESC_MD_PADDING_BE,
+ (void (*)(const br_hash_class **))&br_sha256_init,
+ (void (*)(const br_hash_class **,
+ const void *, size_t))&br_sha256_update,
+ (void (*)(const br_hash_class *const *, void *))&br_sha256_out,
+ (uint64_t (*)(const br_hash_class *const *, void *))&br_sha256_state,
+ (void (*)(const br_hash_class **, const void *, uint64_t))
+ &br_sha256_set_state
+};
Property changes on: stable/12/contrib/bearssl/src/hash/sha2small.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/inner.h
===================================================================
--- stable/12/contrib/bearssl/src/inner.h (nonexistent)
+++ stable/12/contrib/bearssl/src/inner.h (revision 346145)
@@ -0,0 +1,2557 @@
+/*
+ * 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 INNER_H__
+#define INNER_H__
+
+#include <string.h>
+#include <limits.h>
+
+#include "config.h"
+#include "bearssl.h"
+
+/*
+ * On MSVC, disable the warning about applying unary minus on an
+ * unsigned type: it is standard, we do it all the time, and for
+ * good reasons.
+ */
+#if _MSC_VER
+#pragma warning( disable : 4146 )
+#endif
+
+/*
+ * Maximum size for a RSA modulus (in bits). Allocated stack buffers
+ * depend on that size, so this value should be kept small. Currently,
+ * 2048-bit RSA keys offer adequate security, and should still do so for
+ * the next few decades; however, a number of widespread PKI have
+ * already set their root keys to RSA-4096, so we should be able to
+ * process such keys.
+ *
+ * This value MUST be a multiple of 64. This value MUST NOT exceed 47666
+ * (some computations in RSA key generation rely on the factor size being
+ * no more than 23833 bits). RSA key sizes beyond 3072 bits don't make a
+ * lot of sense anyway.
+ */
+#define BR_MAX_RSA_SIZE 4096
+
+/*
+ * Minimum size for a RSA modulus (in bits); this value is used only to
+ * filter out invalid parameters for key pair generation. Normally,
+ * applications should not use RSA keys smaller than 2048 bits; but some
+ * specific cases might need shorter keys, for legacy or research
+ * purposes.
+ */
+#define BR_MIN_RSA_SIZE 512
+
+/*
+ * Maximum size for a RSA factor (in bits). This is for RSA private-key
+ * operations. Default is to support factors up to a bit more than half
+ * the maximum modulus size.
+ *
+ * This value MUST be a multiple of 32.
+ */
+#define BR_MAX_RSA_FACTOR ((BR_MAX_RSA_SIZE + 64) >> 1)
+
+/*
+ * Maximum size for an EC curve (modulus or order), in bits. Size of
+ * stack buffers depends on that parameter. This size MUST be a multiple
+ * of 8 (so that decoding an integer with that many bytes does not
+ * overflow).
+ */
+#define BR_MAX_EC_SIZE 528
+
+/*
+ * Some macros to recognize the current architecture. Right now, we are
+ * interested into automatically recognizing architecture with efficient
+ * 64-bit types so that we may automatically use implementations that
+ * use 64-bit registers in that case. Future versions may detect, e.g.,
+ * availability of SSE2 intrinsics.
+ *
+ * If 'unsigned long' is a 64-bit type, then we assume that 64-bit types
+ * are efficient. Otherwise, we rely on macros that depend on compiler,
+ * OS and architecture. In any case, failure to detect the architecture
+ * as 64-bit means that the 32-bit code will be used, and that code
+ * works also on 64-bit architectures (the 64-bit code may simply be
+ * more efficient).
+ *
+ * The test on 'unsigned long' should already catch most cases, the one
+ * notable exception being Windows code where 'unsigned long' is kept to
+ * 32-bit for compatibility with all the legacy code that liberally uses
+ * the 'DWORD' type for 32-bit values.
+ *
+ * Macro names are taken from: http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
+ */
+#ifndef BR_64
+#if ((ULONG_MAX >> 31) >> 31) == 3
+#define BR_64 1
+#elif defined(__ia64) || defined(__itanium__) || defined(_M_IA64)
+#define BR_64 1
+#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) \
+ || defined(__64BIT__) || defined(_LP64) || defined(__LP64__)
+#define BR_64 1
+#elif defined(__sparc64__)
+#define BR_64 1
+#elif defined(__x86_64__) || defined(_M_X64)
+#define BR_64 1
+#elif defined(__aarch64__) || defined(_M_ARM64)
+#define BR_64 1
+#elif defined(__mips64)
+#define BR_64 1
+#endif
+#endif
+
+/*
+ * Set BR_LOMUL on platforms where it makes sense.
+ */
+#ifndef BR_LOMUL
+#if BR_ARMEL_CORTEXM_GCC
+#define BR_LOMUL 1
+#endif
+#endif
+
+/*
+ * Architecture detection.
+ */
+#ifndef BR_i386
+#if __i386__ || _M_IX86
+#define BR_i386 1
+#endif
+#endif
+
+#ifndef BR_amd64
+#if __x86_64__ || _M_X64
+#define BR_amd64 1
+#endif
+#endif
+
+/*
+ * Compiler brand and version.
+ *
+ * Implementations that use intrinsics need to detect the compiler type
+ * and version because some specific actions may be needed to activate
+ * the corresponding opcodes, both for header inclusion, and when using
+ * them in a function.
+ *
+ * BR_GCC, BR_CLANG and BR_MSC will be set to 1 for, respectively, GCC,
+ * Clang and MS Visual C. For each of them, sub-macros will be defined
+ * for versions; each sub-macro is set whenever the compiler version is
+ * at least as recent as the one corresponding to the macro.
+ */
+
+/*
+ * GCC thresholds are on versions 4.4 to 4.9 and 5.0.
+ */
+#ifndef BR_GCC
+#if __GNUC__ && !__clang__
+#define BR_GCC 1
+
+#if __GNUC__ > 4
+#define BR_GCC_5_0 1
+#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9
+#define BR_GCC_4_9 1
+#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8
+#define BR_GCC_4_8 1
+#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7
+#define BR_GCC_4_7 1
+#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6
+#define BR_GCC_4_6 1
+#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 5
+#define BR_GCC_4_5 1
+#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 4
+#define BR_GCC_4_4 1
+#endif
+
+#if BR_GCC_5_0
+#define BR_GCC_4_9 1
+#endif
+#if BR_GCC_4_9
+#define BR_GCC_4_8 1
+#endif
+#if BR_GCC_4_8
+#define BR_GCC_4_7 1
+#endif
+#if BR_GCC_4_7
+#define BR_GCC_4_6 1
+#endif
+#if BR_GCC_4_6
+#define BR_GCC_4_5 1
+#endif
+#if BR_GCC_4_5
+#define BR_GCC_4_4 1
+#endif
+
+#endif
+#endif
+
+/*
+ * Clang thresholds are on versions 3.7.0 and 3.8.0.
+ */
+#ifndef BR_CLANG
+#if __clang__
+#define BR_CLANG 1
+
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8)
+#define BR_CLANG_3_8 1
+#elif __clang_major__ == 3 && __clang_minor__ >= 7
+#define BR_CLANG_3_7 1
+#endif
+
+#if BR_CLANG_3_8
+#define BR_CLANG_3_7 1
+#endif
+
+#endif
+#endif
+
+/*
+ * MS Visual C thresholds are on Visual Studio 2005 to 2015.
+ */
+#ifndef BR_MSC
+#if _MSC_VER
+#define BR_MSC 1
+
+#if _MSC_VER >= 1900
+#define BR_MSC_2015 1
+#elif _MSC_VER >= 1800
+#define BR_MSC_2013 1
+#elif _MSC_VER >= 1700
+#define BR_MSC_2012 1
+#elif _MSC_VER >= 1600
+#define BR_MSC_2010 1
+#elif _MSC_VER >= 1500
+#define BR_MSC_2008 1
+#elif _MSC_VER >= 1400
+#define BR_MSC_2005 1
+#endif
+
+#if BR_MSC_2015
+#define BR_MSC_2013 1
+#endif
+#if BR_MSC_2013
+#define BR_MSC_2012 1
+#endif
+#if BR_MSC_2012
+#define BR_MSC_2010 1
+#endif
+#if BR_MSC_2010
+#define BR_MSC_2008 1
+#endif
+#if BR_MSC_2008
+#define BR_MSC_2005 1
+#endif
+
+#endif
+#endif
+
+/*
+ * GCC 4.4+ and Clang 3.7+ allow tagging specific functions with a
+ * 'target' attribute that activates support for specific opcodes.
+ */
+#if BR_GCC_4_4 || BR_CLANG_3_7
+#define BR_TARGET(x) __attribute__((target(x)))
+#else
+#define BR_TARGET(x)
+#endif
+
+/*
+ * AES-NI intrinsics are available on x86 (32-bit and 64-bit) with
+ * GCC 4.8+, Clang 3.7+ and MSC 2012+.
+ */
+#ifndef BR_AES_X86NI
+#if (BR_i386 || BR_amd64) && (BR_GCC_4_8 || BR_CLANG_3_7 || BR_MSC_2012)
+#define BR_AES_X86NI 1
+#endif
+#endif
+
+/*
+ * SSE2 intrinsics are available on x86 (32-bit and 64-bit) with
+ * GCC 4.4+, Clang 3.7+ and MSC 2005+.
+ */
+#ifndef BR_SSE2
+#if (BR_i386 || BR_amd64) && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005)
+#define BR_SSE2 1
+#endif
+#endif
+
+/*
+ * RDRAND intrinsics are available on x86 (32-bit and 64-bit) with
+ * GCC 4.6+, Clang 3.7+ and MSC 2012+.
+ */
+#ifndef BR_RDRAND
+#if (BR_i386 || BR_amd64) && (BR_GCC_4_6 || BR_CLANG_3_7 || BR_MSC_2012)
+#define BR_RDRAND 1
+#endif
+#endif
+
+/*
+ * Determine type of OS for random number generation. Macro names and
+ * values are documented on:
+ * https://sourceforge.net/p/predef/wiki/OperatingSystems/
+ *
+ * TODO: enrich the list of detected system. Also add detection for
+ * alternate system calls like getentropy(), which are usually
+ * preferable when available.
+ */
+
+#ifndef BR_USE_URANDOM
+#if defined _AIX \
+ || defined __ANDROID__ \
+ || defined __FreeBSD__ \
+ || defined __NetBSD__ \
+ || defined __OpenBSD__ \
+ || defined __DragonFly__ \
+ || defined __linux__ \
+ || (defined __sun && (defined __SVR4 || defined __svr4__)) \
+ || (defined __APPLE__ && defined __MACH__)
+#define BR_USE_URANDOM 1
+#endif
+#endif
+
+#ifndef BR_USE_WIN32_RAND
+#if defined _WIN32 || defined _WIN64
+#define BR_USE_WIN32_RAND 1
+#endif
+#endif
+
+/*
+ * POWER8 crypto support. We rely on compiler macros for the
+ * architecture, since we do not have a reliable, simple way to detect
+ * the required support at runtime (we could try running an opcode, and
+ * trapping the exception or signal on illegal instruction, but this
+ * induces some non-trivial OS dependencies that we would prefer to
+ * avoid if possible).
+ */
+#ifndef BR_POWER8
+#if __GNUC__ && ((_ARCH_PWR8 || _ARCH_PPC) && __CRYPTO__)
+#define BR_POWER8 1
+#endif
+#endif
+
+/*
+ * Detect endinanness on POWER8.
+ */
+#if BR_POWER8
+#if defined BR_POWER8_LE
+#undef BR_POWER8_BE
+#if BR_POWER8_LE
+#define BR_POWER8_BE 0
+#else
+#define BR_POWER8_BE 1
+#endif
+#elif defined BR_POWER8_BE
+#undef BR_POWER8_LE
+#if BR_POWER8_BE
+#define BR_POWER8_LE 0
+#else
+#define BR_POWER8_LE 1
+#endif
+#else
+#if __LITTLE_ENDIAN__
+#define BR_POWER8_LE 1
+#define BR_POWER8_BE 0
+#else
+#define BR_POWER8_LE 0
+#define BR_POWER8_BE 1
+#endif
+#endif
+#endif
+
+/*
+ * Detect support for 128-bit integers.
+ */
+#if !defined BR_INT128 && !defined BR_UMUL128
+#ifdef __SIZEOF_INT128__
+#define BR_INT128 1
+#elif _M_X64
+#define BR_UMUL128 1
+#endif
+#endif
+
+/*
+ * Detect support for unaligned accesses with known endianness.
+ *
+ * x86 (both 32-bit and 64-bit) is little-endian and allows unaligned
+ * accesses.
+ *
+ * POWER/PowerPC allows unaligned accesses when big-endian. POWER8 and
+ * later also allow unaligned accesses when little-endian.
+ */
+#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED
+
+#if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64
+#define BR_LE_UNALIGNED 1
+#elif BR_POWER8_BE
+#define BR_BE_UNALIGNED 1
+#elif BR_POWER8_LE
+#define BR_LE_UNALIGNED 1
+#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \
+ && __BIG_ENDIAN__
+#define BR_BE_UNALIGNED 1
+#endif
+
+#endif
+
+/*
+ * Detect support for an OS-provided time source.
+ */
+
+#ifndef BR_USE_UNIX_TIME
+#if defined __unix__ || defined __linux__ \
+ || defined _POSIX_SOURCE || defined _POSIX_C_SOURCE \
+ || (defined __APPLE__ && defined __MACH__)
+#define BR_USE_UNIX_TIME 1
+#endif
+#endif
+
+#ifndef BR_USE_WIN32_TIME
+#if defined _WIN32 || defined _WIN64
+#define BR_USE_WIN32_TIME 1
+#endif
+#endif
+
+/* ==================================================================== */
+/*
+ * Encoding/decoding functions.
+ *
+ * 32-bit and 64-bit decoding, both little-endian and big-endian, is
+ * implemented with the inline functions below.
+ *
+ * When allowed by some compile-time options (autodetected or provided),
+ * optimised code is used, to perform direct memory access when the
+ * underlying architecture supports it, both for endianness and
+ * alignment. This, however, may trigger strict aliasing issues; the
+ * code below uses unions to perform (supposedly) safe type punning.
+ * Since the C aliasing rules are relatively complex and were amended,
+ * or at least re-explained with different phrasing, in all successive
+ * versions of the C standard, it is always a bit risky to bet that any
+ * specific version of a C compiler got it right, for some notion of
+ * "right".
+ */
+
+typedef union {
+ uint16_t u;
+ unsigned char b[sizeof(uint16_t)];
+} br_union_u16;
+
+typedef union {
+ uint32_t u;
+ unsigned char b[sizeof(uint32_t)];
+} br_union_u32;
+
+typedef union {
+ uint64_t u;
+ unsigned char b[sizeof(uint64_t)];
+} br_union_u64;
+
+static inline void
+br_enc16le(void *dst, unsigned x)
+{
+#if BR_LE_UNALIGNED
+ ((br_union_u16 *)dst)->u = x;
+#else
+ unsigned char *buf;
+
+ buf = dst;
+ buf[0] = (unsigned char)x;
+ buf[1] = (unsigned char)(x >> 8);
+#endif
+}
+
+static inline void
+br_enc16be(void *dst, unsigned x)
+{
+#if BR_BE_UNALIGNED
+ ((br_union_u16 *)dst)->u = x;
+#else
+ unsigned char *buf;
+
+ buf = dst;
+ buf[0] = (unsigned char)(x >> 8);
+ buf[1] = (unsigned char)x;
+#endif
+}
+
+static inline unsigned
+br_dec16le(const void *src)
+{
+#if BR_LE_UNALIGNED
+ return ((const br_union_u16 *)src)->u;
+#else
+ const unsigned char *buf;
+
+ buf = src;
+ return (unsigned)buf[0] | ((unsigned)buf[1] << 8);
+#endif
+}
+
+static inline unsigned
+br_dec16be(const void *src)
+{
+#if BR_BE_UNALIGNED
+ return ((const br_union_u16 *)src)->u;
+#else
+ const unsigned char *buf;
+
+ buf = src;
+ return ((unsigned)buf[0] << 8) | (unsigned)buf[1];
+#endif
+}
+
+static inline void
+br_enc32le(void *dst, uint32_t x)
+{
+#if BR_LE_UNALIGNED
+ ((br_union_u32 *)dst)->u = x;
+#else
+ unsigned char *buf;
+
+ buf = dst;
+ buf[0] = (unsigned char)x;
+ buf[1] = (unsigned char)(x >> 8);
+ buf[2] = (unsigned char)(x >> 16);
+ buf[3] = (unsigned char)(x >> 24);
+#endif
+}
+
+static inline void
+br_enc32be(void *dst, uint32_t x)
+{
+#if BR_BE_UNALIGNED
+ ((br_union_u32 *)dst)->u = x;
+#else
+ unsigned char *buf;
+
+ buf = dst;
+ buf[0] = (unsigned char)(x >> 24);
+ buf[1] = (unsigned char)(x >> 16);
+ buf[2] = (unsigned char)(x >> 8);
+ buf[3] = (unsigned char)x;
+#endif
+}
+
+static inline uint32_t
+br_dec32le(const void *src)
+{
+#if BR_LE_UNALIGNED
+ return ((const br_union_u32 *)src)->u;
+#else
+ const unsigned char *buf;
+
+ buf = src;
+ return (uint32_t)buf[0]
+ | ((uint32_t)buf[1] << 8)
+ | ((uint32_t)buf[2] << 16)
+ | ((uint32_t)buf[3] << 24);
+#endif
+}
+
+static inline uint32_t
+br_dec32be(const void *src)
+{
+#if BR_BE_UNALIGNED
+ return ((const br_union_u32 *)src)->u;
+#else
+ const unsigned char *buf;
+
+ buf = src;
+ return ((uint32_t)buf[0] << 24)
+ | ((uint32_t)buf[1] << 16)
+ | ((uint32_t)buf[2] << 8)
+ | (uint32_t)buf[3];
+#endif
+}
+
+static inline void
+br_enc64le(void *dst, uint64_t x)
+{
+#if BR_LE_UNALIGNED
+ ((br_union_u64 *)dst)->u = x;
+#else
+ unsigned char *buf;
+
+ buf = dst;
+ br_enc32le(buf, (uint32_t)x);
+ br_enc32le(buf + 4, (uint32_t)(x >> 32));
+#endif
+}
+
+static inline void
+br_enc64be(void *dst, uint64_t x)
+{
+#if BR_BE_UNALIGNED
+ ((br_union_u64 *)dst)->u = x;
+#else
+ unsigned char *buf;
+
+ buf = dst;
+ br_enc32be(buf, (uint32_t)(x >> 32));
+ br_enc32be(buf + 4, (uint32_t)x);
+#endif
+}
+
+static inline uint64_t
+br_dec64le(const void *src)
+{
+#if BR_LE_UNALIGNED
+ return ((const br_union_u64 *)src)->u;
+#else
+ const unsigned char *buf;
+
+ buf = src;
+ return (uint64_t)br_dec32le(buf)
+ | ((uint64_t)br_dec32le(buf + 4) << 32);
+#endif
+}
+
+static inline uint64_t
+br_dec64be(const void *src)
+{
+#if BR_BE_UNALIGNED
+ return ((const br_union_u64 *)src)->u;
+#else
+ const unsigned char *buf;
+
+ buf = src;
+ return ((uint64_t)br_dec32be(buf) << 32)
+ | (uint64_t)br_dec32be(buf + 4);
+#endif
+}
+
+/*
+ * Range decoding and encoding (for several successive values).
+ */
+void br_range_dec16le(uint16_t *v, size_t num, const void *src);
+void br_range_dec16be(uint16_t *v, size_t num, const void *src);
+void br_range_enc16le(void *dst, const uint16_t *v, size_t num);
+void br_range_enc16be(void *dst, const uint16_t *v, size_t num);
+
+void br_range_dec32le(uint32_t *v, size_t num, const void *src);
+void br_range_dec32be(uint32_t *v, size_t num, const void *src);
+void br_range_enc32le(void *dst, const uint32_t *v, size_t num);
+void br_range_enc32be(void *dst, const uint32_t *v, size_t num);
+
+void br_range_dec64le(uint64_t *v, size_t num, const void *src);
+void br_range_dec64be(uint64_t *v, size_t num, const void *src);
+void br_range_enc64le(void *dst, const uint64_t *v, size_t num);
+void br_range_enc64be(void *dst, const uint64_t *v, size_t num);
+
+/*
+ * Byte-swap a 32-bit integer.
+ */
+static inline uint32_t
+br_swap32(uint32_t x)
+{
+ x = ((x & (uint32_t)0x00FF00FF) << 8)
+ | ((x >> 8) & (uint32_t)0x00FF00FF);
+ return (x << 16) | (x >> 16);
+}
+
+/* ==================================================================== */
+/*
+ * Support code for hash functions.
+ */
+
+/*
+ * IV for MD5, SHA-1, SHA-224 and SHA-256.
+ */
+extern const uint32_t br_md5_IV[];
+extern const uint32_t br_sha1_IV[];
+extern const uint32_t br_sha224_IV[];
+extern const uint32_t br_sha256_IV[];
+
+/*
+ * Round functions for MD5, SHA-1, SHA-224 and SHA-256 (SHA-224 and
+ * SHA-256 use the same round function).
+ */
+void br_md5_round(const unsigned char *buf, uint32_t *val);
+void br_sha1_round(const unsigned char *buf, uint32_t *val);
+void br_sha2small_round(const unsigned char *buf, uint32_t *val);
+
+/*
+ * The core function for the TLS PRF. It computes
+ * P_hash(secret, label + seed), and XORs the result into the dst buffer.
+ */
+void br_tls_phash(void *dst, size_t len,
+ const br_hash_class *dig,
+ const void *secret, size_t secret_len, const char *label,
+ size_t seed_num, const br_tls_prf_seed_chunk *seed);
+
+/*
+ * Copy all configured hash implementations from a multihash context
+ * to another.
+ */
+static inline void
+br_multihash_copyimpl(br_multihash_context *dst,
+ const br_multihash_context *src)
+{
+ memcpy((void *)dst->impl, src->impl, sizeof src->impl);
+}
+
+/* ==================================================================== */
+/*
+ * Constant-time primitives. These functions manipulate 32-bit values in
+ * order to provide constant-time comparisons and multiplexers.
+ *
+ * Boolean values (the "ctl" bits) MUST have value 0 or 1.
+ *
+ * Implementation notes:
+ * =====================
+ *
+ * The uintN_t types are unsigned and with width exactly N bits; the C
+ * standard guarantees that computations are performed modulo 2^N, and
+ * there can be no overflow. Negation (unary '-') works on unsigned types
+ * as well.
+ *
+ * The intN_t types are guaranteed to have width exactly N bits, with no
+ * padding bit, and using two's complement representation. Casting
+ * intN_t to uintN_t really is conversion modulo 2^N. Beware that intN_t
+ * types, being signed, trigger implementation-defined behaviour on
+ * overflow (including raising some signal): with GCC, while modular
+ * arithmetics are usually applied, the optimizer may assume that
+ * overflows don't occur (unless the -fwrapv command-line option is
+ * added); Clang has the additional -ftrapv option to explicitly trap on
+ * integer overflow or underflow.
+ */
+
+/*
+ * Negate a boolean.
+ */
+static inline uint32_t
+NOT(uint32_t ctl)
+{
+ return ctl ^ 1;
+}
+
+/*
+ * Multiplexer: returns x if ctl == 1, y if ctl == 0.
+ */
+static inline uint32_t
+MUX(uint32_t ctl, uint32_t x, uint32_t y)
+{
+ return y ^ (-ctl & (x ^ y));
+}
+
+/*
+ * Equality check: returns 1 if x == y, 0 otherwise.
+ */
+static inline uint32_t
+EQ(uint32_t x, uint32_t y)
+{
+ uint32_t q;
+
+ q = x ^ y;
+ return NOT((q | -q) >> 31);
+}
+
+/*
+ * Inequality check: returns 1 if x != y, 0 otherwise.
+ */
+static inline uint32_t
+NEQ(uint32_t x, uint32_t y)
+{
+ uint32_t q;
+
+ q = x ^ y;
+ return (q | -q) >> 31;
+}
+
+/*
+ * Comparison: returns 1 if x > y, 0 otherwise.
+ */
+static inline uint32_t
+GT(uint32_t x, uint32_t y)
+{
+ /*
+ * If both x < 2^31 and x < 2^31, then y-x will have its high
+ * bit set if x > y, cleared otherwise.
+ *
+ * If either x >= 2^31 or y >= 2^31 (but not both), then the
+ * result is the high bit of x.
+ *
+ * If both x >= 2^31 and y >= 2^31, then we can virtually
+ * subtract 2^31 from both, and we are back to the first case.
+ * Since (y-2^31)-(x-2^31) = y-x, the subtraction is already
+ * fine.
+ */
+ uint32_t z;
+
+ z = y - x;
+ return (z ^ ((x ^ y) & (x ^ z))) >> 31;
+}
+
+/*
+ * Other comparisons (greater-or-equal, lower-than, lower-or-equal).
+ */
+#define GE(x, y) NOT(GT(y, x))
+#define LT(x, y) GT(y, x)
+#define LE(x, y) NOT(GT(x, y))
+
+/*
+ * General comparison: returned value is -1, 0 or 1, depending on
+ * whether x is lower than, equal to, or greater than y.
+ */
+static inline int32_t
+CMP(uint32_t x, uint32_t y)
+{
+ return (int32_t)GT(x, y) | -(int32_t)GT(y, x);
+}
+
+/*
+ * Returns 1 if x == 0, 0 otherwise. Take care that the operand is signed.
+ */
+static inline uint32_t
+EQ0(int32_t x)
+{
+ uint32_t q;
+
+ q = (uint32_t)x;
+ return ~(q | -q) >> 31;
+}
+
+/*
+ * Returns 1 if x > 0, 0 otherwise. Take care that the operand is signed.
+ */
+static inline uint32_t
+GT0(int32_t x)
+{
+ /*
+ * High bit of -x is 0 if x == 0, but 1 if x > 0.
+ */
+ uint32_t q;
+
+ q = (uint32_t)x;
+ return (~q & -q) >> 31;
+}
+
+/*
+ * Returns 1 if x >= 0, 0 otherwise. Take care that the operand is signed.
+ */
+static inline uint32_t
+GE0(int32_t x)
+{
+ return ~(uint32_t)x >> 31;
+}
+
+/*
+ * Returns 1 if x < 0, 0 otherwise. Take care that the operand is signed.
+ */
+static inline uint32_t
+LT0(int32_t x)
+{
+ return (uint32_t)x >> 31;
+}
+
+/*
+ * Returns 1 if x <= 0, 0 otherwise. Take care that the operand is signed.
+ */
+static inline uint32_t
+LE0(int32_t x)
+{
+ uint32_t q;
+
+ /*
+ * ~-x has its high bit set if and only if -x is nonnegative (as
+ * a signed int), i.e. x is in the -(2^31-1) to 0 range. We must
+ * do an OR with x itself to account for x = -2^31.
+ */
+ q = (uint32_t)x;
+ return (q | ~-q) >> 31;
+}
+
+/*
+ * Conditional copy: src[] is copied into dst[] if and only if ctl is 1.
+ * dst[] and src[] may overlap completely (but not partially).
+ */
+void br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len);
+
+#define CCOPY br_ccopy
+
+/*
+ * Compute the bit length of a 32-bit integer. Returned value is between 0
+ * and 32 (inclusive).
+ */
+static inline uint32_t
+BIT_LENGTH(uint32_t x)
+{
+ uint32_t k, c;
+
+ k = NEQ(x, 0);
+ c = GT(x, 0xFFFF); x = MUX(c, x >> 16, x); k += c << 4;
+ c = GT(x, 0x00FF); x = MUX(c, x >> 8, x); k += c << 3;
+ c = GT(x, 0x000F); x = MUX(c, x >> 4, x); k += c << 2;
+ c = GT(x, 0x0003); x = MUX(c, x >> 2, x); k += c << 1;
+ k += GT(x, 0x0001);
+ return k;
+}
+
+/*
+ * Compute the minimum of x and y.
+ */
+static inline uint32_t
+MIN(uint32_t x, uint32_t y)
+{
+ return MUX(GT(x, y), y, x);
+}
+
+/*
+ * Compute the maximum of x and y.
+ */
+static inline uint32_t
+MAX(uint32_t x, uint32_t y)
+{
+ return MUX(GT(x, y), x, y);
+}
+
+/*
+ * Multiply two 32-bit integers, with a 64-bit result. This default
+ * implementation assumes that the basic multiplication operator
+ * yields constant-time code.
+ */
+#define MUL(x, y) ((uint64_t)(x) * (uint64_t)(y))
+
+#if BR_CT_MUL31
+
+/*
+ * Alternate implementation of MUL31, that will be constant-time on some
+ * (old) platforms where the default MUL31 is not. Unfortunately, it is
+ * also substantially slower, and yields larger code, on more modern
+ * platforms, which is why it is deactivated by default.
+ *
+ * MUL31_lo() must do some extra work because on some platforms, the
+ * _signed_ multiplication may return early if the top bits are 1.
+ * Simply truncating (casting) the output of MUL31() would not be
+ * sufficient, because the compiler may notice that we keep only the low
+ * word, and then replace automatically the unsigned multiplication with
+ * a signed multiplication opcode.
+ */
+#define MUL31(x, y) ((uint64_t)((x) | (uint32_t)0x80000000) \
+ * (uint64_t)((y) | (uint32_t)0x80000000) \
+ - ((uint64_t)(x) << 31) - ((uint64_t)(y) << 31) \
+ - ((uint64_t)1 << 62))
+static inline uint32_t
+MUL31_lo(uint32_t x, uint32_t y)
+{
+ uint32_t xl, xh;
+ uint32_t yl, yh;
+
+ xl = (x & 0xFFFF) | (uint32_t)0x80000000;
+ xh = (x >> 16) | (uint32_t)0x80000000;
+ yl = (y & 0xFFFF) | (uint32_t)0x80000000;
+ yh = (y >> 16) | (uint32_t)0x80000000;
+ return (xl * yl + ((xl * yh + xh * yl) << 16)) & (uint32_t)0x7FFFFFFF;
+}
+
+#else
+
+/*
+ * Multiply two 31-bit integers, with a 62-bit result. This default
+ * implementation assumes that the basic multiplication operator
+ * yields constant-time code.
+ * The MUL31_lo() macro returns only the low 31 bits of the product.
+ */
+#define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y))
+#define MUL31_lo(x, y) (((uint32_t)(x) * (uint32_t)(y)) & (uint32_t)0x7FFFFFFF)
+
+#endif
+
+/*
+ * Multiply two words together; the sum of the lengths of the two
+ * operands must not exceed 31 (for instance, one operand may use 16
+ * bits if the other fits on 15). If BR_CT_MUL15 is non-zero, then the
+ * macro will contain some extra operations that help in making the
+ * operation constant-time on some platforms, where the basic 32-bit
+ * multiplication is not constant-time.
+ */
+#if BR_CT_MUL15
+#define MUL15(x, y) (((uint32_t)(x) | (uint32_t)0x80000000) \
+ * ((uint32_t)(y) | (uint32_t)0x80000000) \
+ & (uint32_t)0x7FFFFFFF)
+#else
+#define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y))
+#endif
+
+/*
+ * Arithmetic right shift (sign bit is copied). What happens when
+ * right-shifting a negative value is _implementation-defined_, so it
+ * does not trigger undefined behaviour, but it is still up to each
+ * compiler to define (and document) what it does. Most/all compilers
+ * will do an arithmetic shift, the sign bit being used to fill the
+ * holes; this is a native operation on the underlying CPU, and it would
+ * make little sense for the compiler to do otherwise. GCC explicitly
+ * documents that it follows that convention.
+ *
+ * Still, if BR_NO_ARITH_SHIFT is defined (and non-zero), then an
+ * alternate version will be used, that does not rely on such
+ * implementation-defined behaviour. Unfortunately, it is also slower
+ * and yields bigger code, which is why it is deactivated by default.
+ */
+#if BR_NO_ARITH_SHIFT
+#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
+ | ((-((uint32_t)(x) >> 31)) << (32 - (n))))
+#else
+#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
+#endif
+
+/*
+ * Constant-time division. The dividend hi:lo is divided by the
+ * divisor d; the quotient is returned and the remainder is written
+ * in *r. If hi == d, then the quotient does not fit on 32 bits;
+ * returned value is thus truncated. If hi > d, returned values are
+ * indeterminate.
+ */
+uint32_t br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r);
+
+/*
+ * Wrapper for br_divrem(); the remainder is returned, and the quotient
+ * is discarded.
+ */
+static inline uint32_t
+br_rem(uint32_t hi, uint32_t lo, uint32_t d)
+{
+ uint32_t r;
+
+ br_divrem(hi, lo, d, &r);
+ return r;
+}
+
+/*
+ * Wrapper for br_divrem(); the quotient is returned, and the remainder
+ * is discarded.
+ */
+static inline uint32_t
+br_div(uint32_t hi, uint32_t lo, uint32_t d)
+{
+ uint32_t r;
+
+ return br_divrem(hi, lo, d, &r);
+}
+
+/* ==================================================================== */
+
+/*
+ * Integers 'i32'
+ * --------------
+ *
+ * The 'i32' functions implement computations on big integers using
+ * an internal representation as an array of 32-bit integers. For
+ * an array x[]:
+ * -- x[0] contains the "announced bit length" of the integer
+ * -- x[1], x[2]... contain the value in little-endian order (x[1]
+ * contains the least significant 32 bits)
+ *
+ * Multiplications rely on the elementary 32x32->64 multiplication.
+ *
+ * The announced bit length specifies the number of bits that are
+ * significant in the subsequent 32-bit words. Unused bits in the
+ * last (most significant) word are set to 0; subsequent words are
+ * uninitialized and need not exist at all.
+ *
+ * The execution time and memory access patterns of all computations
+ * depend on the announced bit length, but not on the actual word
+ * values. For modular integers, the announced bit length of any integer
+ * modulo n is equal to the actual bit length of n; thus, computations
+ * on modular integers are "constant-time" (only the modulus length may
+ * leak).
+ */
+
+/*
+ * Compute the actual bit length of an integer. The argument x should
+ * point to the first (least significant) value word of the integer.
+ * The len 'xlen' contains the number of 32-bit words to access.
+ *
+ * CT: value or length of x does not leak.
+ */
+uint32_t br_i32_bit_length(uint32_t *x, size_t xlen);
+
+/*
+ * Decode an integer from its big-endian unsigned representation. The
+ * "true" bit length of the integer is computed, but all words of x[]
+ * corresponding to the full 'len' bytes of the source are set.
+ *
+ * CT: value or length of x does not leak.
+ */
+void br_i32_decode(uint32_t *x, const void *src, size_t len);
+
+/*
+ * Decode an integer from its big-endian unsigned representation. The
+ * integer MUST be lower than m[]; the announced bit length written in
+ * x[] will be equal to that of m[]. All 'len' bytes from the source are
+ * read.
+ *
+ * Returned value is 1 if the decode value fits within the modulus, 0
+ * otherwise. In the latter case, the x[] buffer will be set to 0 (but
+ * still with the announced bit length of m[]).
+ *
+ * CT: value or length of x does not leak. Memory access pattern depends
+ * only of 'len' and the announced bit length of m. Whether x fits or
+ * not does not leak either.
+ */
+uint32_t br_i32_decode_mod(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m);
+
+/*
+ * Reduce an integer (a[]) modulo another (m[]). The result is written
+ * in x[] and its announced bit length is set to be equal to that of m[].
+ *
+ * x[] MUST be distinct from a[] and m[].
+ *
+ * CT: only announced bit lengths leak, not values of x, a or m.
+ */
+void br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m);
+
+/*
+ * Decode an integer from its big-endian unsigned representation, and
+ * reduce it modulo the provided modulus m[]. The announced bit length
+ * of the result is set to be equal to that of the modulus.
+ *
+ * x[] MUST be distinct from m[].
+ */
+void br_i32_decode_reduce(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m);
+
+/*
+ * Encode an integer into its big-endian unsigned representation. The
+ * output length in bytes is provided (parameter 'len'); if the length
+ * is too short then the integer is appropriately truncated; if it is
+ * too long then the extra bytes are set to 0.
+ */
+void br_i32_encode(void *dst, size_t len, const uint32_t *x);
+
+/*
+ * Multiply x[] by 2^32 and then add integer z, modulo m[]. This
+ * function assumes that x[] and m[] have the same announced bit
+ * length, and the announced bit length of m[] matches its true
+ * bit length.
+ *
+ * x[] and m[] MUST be distinct arrays.
+ *
+ * CT: only the common announced bit length of x and m leaks, not
+ * the values of x, z or m.
+ */
+void br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m);
+
+/*
+ * Extract one word from an integer. The offset is counted in bits.
+ * The word MUST entirely fit within the word elements corresponding
+ * to the announced bit length of a[].
+ */
+static inline uint32_t
+br_i32_word(const uint32_t *a, uint32_t off)
+{
+ size_t u;
+ unsigned j;
+
+ u = (size_t)(off >> 5) + 1;
+ j = (unsigned)off & 31;
+ if (j == 0) {
+ return a[u];
+ } else {
+ return (a[u] >> j) | (a[u + 1] << (32 - j));
+ }
+}
+
+/*
+ * Test whether an integer is zero.
+ */
+uint32_t br_i32_iszero(const uint32_t *x);
+
+/*
+ * Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[]
+ * is unmodified, but the carry is still computed and returned. The
+ * arrays a[] and b[] MUST have the same announced bit length.
+ *
+ * a[] and b[] MAY be the same array, but partial overlap is not allowed.
+ */
+uint32_t br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl);
+
+/*
+ * Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0,
+ * then a[] is unmodified, but the carry is still computed and returned.
+ * The arrays a[] and b[] MUST have the same announced bit length.
+ *
+ * a[] and b[] MAY be the same array, but partial overlap is not allowed.
+ */
+uint32_t br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl);
+
+/*
+ * Compute d+a*b, result in d. The initial announced bit length of d[]
+ * MUST match that of a[]. The d[] array MUST be large enough to
+ * accommodate the full result, plus (possibly) an extra word. The
+ * resulting announced bit length of d[] will be the sum of the announced
+ * bit lengths of a[] and b[] (therefore, it may be larger than the actual
+ * bit length of the numerical result).
+ *
+ * a[] and b[] may be the same array. d[] must be disjoint from both a[]
+ * and b[].
+ */
+void br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
+
+/*
+ * Zeroize an integer. The announced bit length is set to the provided
+ * value, and the corresponding words are set to 0.
+ */
+static inline void
+br_i32_zero(uint32_t *x, uint32_t bit_len)
+{
+ *x ++ = bit_len;
+ memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x);
+}
+
+/*
+ * Compute -(1/x) mod 2^32. If x is even, then this function returns 0.
+ */
+uint32_t br_i32_ninv32(uint32_t x);
+
+/*
+ * Convert a modular integer to Montgomery representation. The integer x[]
+ * MUST be lower than m[], but with the same announced bit length.
+ */
+void br_i32_to_monty(uint32_t *x, const uint32_t *m);
+
+/*
+ * Convert a modular integer back from Montgomery representation. The
+ * integer x[] MUST be lower than m[], but with the same announced bit
+ * length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is
+ * the least significant value word of m[] (this works only if m[] is
+ * an odd integer).
+ */
+void br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i);
+
+/*
+ * Compute a modular Montgomery multiplication. d[] is filled with the
+ * value of x*y/R modulo m[] (where R is the Montgomery factor). The
+ * array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be
+ * numerically lower than m[]. x[] and y[] MAY be the same array. The
+ * "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least
+ * significant value word of m[] (this works only if m[] is an odd
+ * integer).
+ */
+void br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
+ const uint32_t *m, uint32_t m0i);
+
+/*
+ * Compute a modular exponentiation. x[] MUST be an integer modulo m[]
+ * (same announced bit length, lower value). m[] MUST be odd. The
+ * exponent is in big-endian unsigned notation, over 'elen' bytes. The
+ * "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least
+ * significant value word of m[] (this works only if m[] is an odd
+ * integer). The t1[] and t2[] parameters must be temporary arrays,
+ * each large enough to accommodate an integer with the same size as m[].
+ */
+void br_i32_modpow(uint32_t *x, const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2);
+
+/* ==================================================================== */
+
+/*
+ * Integers 'i31'
+ * --------------
+ *
+ * The 'i31' functions implement computations on big integers using
+ * an internal representation as an array of 32-bit integers. For
+ * an array x[]:
+ * -- x[0] encodes the array length and the "announced bit length"
+ * of the integer: namely, if the announced bit length is k,
+ * then x[0] = ((k / 31) << 5) + (k % 31).
+ * -- x[1], x[2]... contain the value in little-endian order, 31
+ * bits per word (x[1] contains the least significant 31 bits).
+ * The upper bit of each word is 0.
+ *
+ * Multiplications rely on the elementary 32x32->64 multiplication.
+ *
+ * The announced bit length specifies the number of bits that are
+ * significant in the subsequent 32-bit words. Unused bits in the
+ * last (most significant) word are set to 0; subsequent words are
+ * uninitialized and need not exist at all.
+ *
+ * The execution time and memory access patterns of all computations
+ * depend on the announced bit length, but not on the actual word
+ * values. For modular integers, the announced bit length of any integer
+ * modulo n is equal to the actual bit length of n; thus, computations
+ * on modular integers are "constant-time" (only the modulus length may
+ * leak).
+ */
+
+/*
+ * Test whether an integer is zero.
+ */
+uint32_t br_i31_iszero(const uint32_t *x);
+
+/*
+ * Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[]
+ * is unmodified, but the carry is still computed and returned. The
+ * arrays a[] and b[] MUST have the same announced bit length.
+ *
+ * a[] and b[] MAY be the same array, but partial overlap is not allowed.
+ */
+uint32_t br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl);
+
+/*
+ * Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0,
+ * then a[] is unmodified, but the carry is still computed and returned.
+ * The arrays a[] and b[] MUST have the same announced bit length.
+ *
+ * a[] and b[] MAY be the same array, but partial overlap is not allowed.
+ */
+uint32_t br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl);
+
+/*
+ * Compute the ENCODED actual bit length of an integer. The argument x
+ * should point to the first (least significant) value word of the
+ * integer. The len 'xlen' contains the number of 32-bit words to
+ * access. The upper bit of each value word MUST be 0.
+ * Returned value is ((k / 31) << 5) + (k % 31) if the bit length is k.
+ *
+ * CT: value or length of x does not leak.
+ */
+uint32_t br_i31_bit_length(uint32_t *x, size_t xlen);
+
+/*
+ * Decode an integer from its big-endian unsigned representation. The
+ * "true" bit length of the integer is computed and set in the encoded
+ * announced bit length (x[0]), but all words of x[] corresponding to
+ * the full 'len' bytes of the source are set.
+ *
+ * CT: value or length of x does not leak.
+ */
+void br_i31_decode(uint32_t *x, const void *src, size_t len);
+
+/*
+ * Decode an integer from its big-endian unsigned representation. The
+ * integer MUST be lower than m[]; the (encoded) announced bit length
+ * written in x[] will be equal to that of m[]. All 'len' bytes from the
+ * source are read.
+ *
+ * Returned value is 1 if the decode value fits within the modulus, 0
+ * otherwise. In the latter case, the x[] buffer will be set to 0 (but
+ * still with the announced bit length of m[]).
+ *
+ * CT: value or length of x does not leak. Memory access pattern depends
+ * only of 'len' and the announced bit length of m. Whether x fits or
+ * not does not leak either.
+ */
+uint32_t br_i31_decode_mod(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m);
+
+/*
+ * Zeroize an integer. The announced bit length is set to the provided
+ * value, and the corresponding words are set to 0. The ENCODED bit length
+ * is expected here.
+ */
+static inline void
+br_i31_zero(uint32_t *x, uint32_t bit_len)
+{
+ *x ++ = bit_len;
+ memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x);
+}
+
+/*
+ * Right-shift an integer. The shift amount must be lower than 31
+ * bits.
+ */
+void br_i31_rshift(uint32_t *x, int count);
+
+/*
+ * Reduce an integer (a[]) modulo another (m[]). The result is written
+ * in x[] and its announced bit length is set to be equal to that of m[].
+ *
+ * x[] MUST be distinct from a[] and m[].
+ *
+ * CT: only announced bit lengths leak, not values of x, a or m.
+ */
+void br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m);
+
+/*
+ * Decode an integer from its big-endian unsigned representation, and
+ * reduce it modulo the provided modulus m[]. The announced bit length
+ * of the result is set to be equal to that of the modulus.
+ *
+ * x[] MUST be distinct from m[].
+ */
+void br_i31_decode_reduce(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m);
+
+/*
+ * Multiply x[] by 2^31 and then add integer z, modulo m[]. This
+ * function assumes that x[] and m[] have the same announced bit
+ * length, the announced bit length of m[] matches its true
+ * bit length.
+ *
+ * x[] and m[] MUST be distinct arrays. z MUST fit in 31 bits (upper
+ * bit set to 0).
+ *
+ * CT: only the common announced bit length of x and m leaks, not
+ * the values of x, z or m.
+ */
+void br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m);
+
+/*
+ * Encode an integer into its big-endian unsigned representation. The
+ * output length in bytes is provided (parameter 'len'); if the length
+ * is too short then the integer is appropriately truncated; if it is
+ * too long then the extra bytes are set to 0.
+ */
+void br_i31_encode(void *dst, size_t len, const uint32_t *x);
+
+/*
+ * Compute -(1/x) mod 2^31. If x is even, then this function returns 0.
+ */
+uint32_t br_i31_ninv31(uint32_t x);
+
+/*
+ * Compute a modular Montgomery multiplication. d[] is filled with the
+ * value of x*y/R modulo m[] (where R is the Montgomery factor). The
+ * array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be
+ * numerically lower than m[]. x[] and y[] MAY be the same array. The
+ * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
+ * significant value word of m[] (this works only if m[] is an odd
+ * integer).
+ */
+void br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
+ const uint32_t *m, uint32_t m0i);
+
+/*
+ * Convert a modular integer to Montgomery representation. The integer x[]
+ * MUST be lower than m[], but with the same announced bit length.
+ */
+void br_i31_to_monty(uint32_t *x, const uint32_t *m);
+
+/*
+ * Convert a modular integer back from Montgomery representation. The
+ * integer x[] MUST be lower than m[], but with the same announced bit
+ * length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is
+ * the least significant value word of m[] (this works only if m[] is
+ * an odd integer).
+ */
+void br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i);
+
+/*
+ * Compute a modular exponentiation. x[] MUST be an integer modulo m[]
+ * (same announced bit length, lower value). m[] MUST be odd. The
+ * exponent is in big-endian unsigned notation, over 'elen' bytes. The
+ * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
+ * significant value word of m[] (this works only if m[] is an odd
+ * integer). The t1[] and t2[] parameters must be temporary arrays,
+ * each large enough to accommodate an integer with the same size as m[].
+ */
+void br_i31_modpow(uint32_t *x, const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2);
+
+/*
+ * Compute a modular exponentiation. x[] MUST be an integer modulo m[]
+ * (same announced bit length, lower value). m[] MUST be odd. The
+ * exponent is in big-endian unsigned notation, over 'elen' bytes. The
+ * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
+ * significant value word of m[] (this works only if m[] is an odd
+ * integer). The tmp[] array is used for temporaries, and has size
+ * 'twlen' words; it must be large enough to accommodate at least two
+ * temporary values with the same size as m[] (including the leading
+ * "bit length" word). If there is room for more temporaries, then this
+ * function may use the extra room for window-based optimisation,
+ * resulting in faster computations.
+ *
+ * Returned value is 1 on success, 0 on error. An error is reported if
+ * the provided tmp[] array is too short.
+ */
+uint32_t br_i31_modpow_opt(uint32_t *x, const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
+
+/*
+ * Compute d+a*b, result in d. The initial announced bit length of d[]
+ * MUST match that of a[]. The d[] array MUST be large enough to
+ * accommodate the full result, plus (possibly) an extra word. The
+ * resulting announced bit length of d[] will be the sum of the announced
+ * bit lengths of a[] and b[] (therefore, it may be larger than the actual
+ * bit length of the numerical result).
+ *
+ * a[] and b[] may be the same array. d[] must be disjoint from both a[]
+ * and b[].
+ */
+void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
+
+/*
+ * Compute x/y mod m, result in x. Values x and y must be between 0 and
+ * m-1, and have the same announced bit length as m. Modulus m must be
+ * odd. The "m0i" parameter is equal to -1/m mod 2^31. The array 't'
+ * must point to a temporary area that can hold at least three integers
+ * of the size of m.
+ *
+ * m may not overlap x and y. x and y may overlap each other (this can
+ * be useful to test whether a value is invertible modulo m). t must be
+ * disjoint from all other arrays.
+ *
+ * Returned value is 1 on success, 0 otherwise. Success is attained if
+ * y is invertible modulo m.
+ */
+uint32_t br_i31_moddiv(uint32_t *x, const uint32_t *y,
+ const uint32_t *m, uint32_t m0i, uint32_t *t);
+
+/* ==================================================================== */
+
+/*
+ * FIXME: document "i15" functions.
+ */
+
+static inline void
+br_i15_zero(uint16_t *x, uint16_t bit_len)
+{
+ *x ++ = bit_len;
+ memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x);
+}
+
+uint32_t br_i15_iszero(const uint16_t *x);
+
+uint16_t br_i15_ninv15(uint16_t x);
+
+uint32_t br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl);
+
+uint32_t br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl);
+
+void br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m);
+
+void br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
+ const uint16_t *m, uint16_t m0i);
+
+void br_i15_to_monty(uint16_t *x, const uint16_t *m);
+
+void br_i15_modpow(uint16_t *x, const unsigned char *e, size_t elen,
+ const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2);
+
+uint32_t br_i15_modpow_opt(uint16_t *x, const unsigned char *e, size_t elen,
+ const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen);
+
+void br_i15_encode(void *dst, size_t len, const uint16_t *x);
+
+uint32_t br_i15_decode_mod(uint16_t *x,
+ const void *src, size_t len, const uint16_t *m);
+
+void br_i15_rshift(uint16_t *x, int count);
+
+uint32_t br_i15_bit_length(uint16_t *x, size_t xlen);
+
+void br_i15_decode(uint16_t *x, const void *src, size_t len);
+
+void br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i);
+
+void br_i15_decode_reduce(uint16_t *x,
+ const void *src, size_t len, const uint16_t *m);
+
+void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m);
+
+void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b);
+
+uint32_t br_i15_moddiv(uint16_t *x, const uint16_t *y,
+ const uint16_t *m, uint16_t m0i, uint16_t *t);
+
+/*
+ * Variant of br_i31_modpow_opt() that internally uses 64x64->128
+ * multiplications. It expects the same parameters as br_i31_modpow_opt(),
+ * except that the temporaries should be 64-bit integers, not 32-bit
+ * integers.
+ */
+uint32_t br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen,
+ const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen);
+
+/*
+ * Type for a function with the same API as br_i31_modpow_opt() (some
+ * implementations of this type may have stricter alignment requirements
+ * on the temporaries).
+ */
+typedef uint32_t (*br_i31_modpow_opt_type)(uint32_t *x,
+ const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
+
+/*
+ * Wrapper for br_i62_modpow_opt() that uses the same type as
+ * br_i31_modpow_opt(); however, it requires its 'tmp' argument to the
+ * 64-bit aligned.
+ */
+uint32_t br_i62_modpow_opt_as_i31(uint32_t *x,
+ const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
+
+/* ==================================================================== */
+
+static inline size_t
+br_digest_size(const br_hash_class *digest_class)
+{
+ return (size_t)(digest_class->desc >> BR_HASHDESC_OUT_OFF)
+ & BR_HASHDESC_OUT_MASK;
+}
+
+/*
+ * Get the output size (in bytes) of a hash function.
+ */
+size_t br_digest_size_by_ID(int digest_id);
+
+/*
+ * Get the OID (encoded OBJECT IDENTIFIER value, without tag and length)
+ * for a hash function. If digest_id is not a supported digest identifier
+ * (in particular if it is equal to 0, i.e. br_md5sha1_ID), then NULL is
+ * returned and *len is set to 0.
+ */
+const unsigned char *br_digest_OID(int digest_id, size_t *len);
+
+/* ==================================================================== */
+/*
+ * DES support functions.
+ */
+
+/*
+ * Apply DES Initial Permutation.
+ */
+void br_des_do_IP(uint32_t *xl, uint32_t *xr);
+
+/*
+ * Apply DES Final Permutation (inverse of IP).
+ */
+void br_des_do_invIP(uint32_t *xl, uint32_t *xr);
+
+/*
+ * Key schedule unit: for a DES key (8 bytes), compute 16 subkeys. Each
+ * subkey is two 28-bit words represented as two 32-bit words; the PC-2
+ * bit extration is NOT applied.
+ */
+void br_des_keysched_unit(uint32_t *skey, const void *key);
+
+/*
+ * Reversal of 16 DES sub-keys (for decryption).
+ */
+void br_des_rev_skey(uint32_t *skey);
+
+/*
+ * DES/3DES key schedule for 'des_tab' (encryption direction). Returned
+ * value is the number of rounds.
+ */
+unsigned br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len);
+
+/*
+ * DES/3DES key schedule for 'des_ct' (encryption direction). Returned
+ * value is the number of rounds.
+ */
+unsigned br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len);
+
+/*
+ * DES/3DES subkey decompression (from the compressed bitsliced subkeys).
+ */
+void br_des_ct_skey_expand(uint32_t *sk_exp,
+ unsigned num_rounds, const uint32_t *skey);
+
+/*
+ * DES/3DES block encryption/decryption ('des_tab').
+ */
+void br_des_tab_process_block(unsigned num_rounds,
+ const uint32_t *skey, void *block);
+
+/*
+ * DES/3DES block encryption/decryption ('des_ct').
+ */
+void br_des_ct_process_block(unsigned num_rounds,
+ const uint32_t *skey, void *block);
+
+/* ==================================================================== */
+/*
+ * AES support functions.
+ */
+
+/*
+ * The AES S-box (256-byte table).
+ */
+extern const unsigned char br_aes_S[];
+
+/*
+ * AES key schedule. skey[] is filled with n+1 128-bit subkeys, where n
+ * is the number of rounds (10 to 14, depending on key size). The number
+ * of rounds is returned. If the key size is invalid (not 16, 24 or 32),
+ * then 0 is returned.
+ *
+ * This implementation uses a 256-byte table and is NOT constant-time.
+ */
+unsigned br_aes_keysched(uint32_t *skey, const void *key, size_t key_len);
+
+/*
+ * AES key schedule for decryption ('aes_big' implementation).
+ */
+unsigned br_aes_big_keysched_inv(uint32_t *skey,
+ const void *key, size_t key_len);
+
+/*
+ * AES block encryption with the 'aes_big' implementation (fast, but
+ * not constant-time). This function encrypts a single block "in place".
+ */
+void br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data);
+
+/*
+ * AES block decryption with the 'aes_big' implementation (fast, but
+ * not constant-time). This function decrypts a single block "in place".
+ */
+void br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data);
+
+/*
+ * AES block encryption with the 'aes_small' implementation (small, but
+ * slow and not constant-time). This function encrypts a single block
+ * "in place".
+ */
+void br_aes_small_encrypt(unsigned num_rounds,
+ const uint32_t *skey, void *data);
+
+/*
+ * AES block decryption with the 'aes_small' implementation (small, but
+ * slow and not constant-time). This function decrypts a single block
+ * "in place".
+ */
+void br_aes_small_decrypt(unsigned num_rounds,
+ const uint32_t *skey, void *data);
+
+/*
+ * The constant-time implementation is "bitsliced": the 128-bit state is
+ * split over eight 32-bit words q* in the following way:
+ *
+ * -- Input block consists in 16 bytes:
+ * a00 a10 a20 a30 a01 a11 a21 a31 a02 a12 a22 a32 a03 a13 a23 a33
+ * In the terminology of FIPS 197, this is a 4x4 matrix which is read
+ * column by column.
+ *
+ * -- Each byte is split into eight bits which are distributed over the
+ * eight words, at the same rank. Thus, for a byte x at rank k, bit 0
+ * (least significant) of x will be at rank k in q0 (if that bit is b,
+ * then it contributes "b << k" to the value of q0), bit 1 of x will be
+ * at rank k in q1, and so on.
+ *
+ * -- Ranks given to bits are in "row order" and are either all even, or
+ * all odd. Two independent AES states are thus interleaved, one using
+ * the even ranks, the other the odd ranks. Row order means:
+ * a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 a30 a31 a32 a33
+ *
+ * Converting input bytes from two AES blocks to bitslice representation
+ * is done in the following way:
+ * -- Decode first block into the four words q0 q2 q4 q6, in that order,
+ * using little-endian convention.
+ * -- Decode second block into the four words q1 q3 q5 q7, in that order,
+ * using little-endian convention.
+ * -- Call br_aes_ct_ortho().
+ *
+ * Converting back to bytes is done by using the reverse operations. Note
+ * that br_aes_ct_ortho() is its own inverse.
+ */
+
+/*
+ * Perform bytewise orthogonalization of eight 32-bit words. Bytes
+ * of q0..q7 are spread over all words: for a byte x that occurs
+ * at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit
+ * of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j.
+ *
+ * This operation is an involution.
+ */
+void br_aes_ct_ortho(uint32_t *q);
+
+/*
+ * The AES S-box, as a bitsliced constant-time version. The input array
+ * consists in eight 32-bit words; 32 S-box instances are computed in
+ * parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant)
+ * are spread over the words 0 to 7, at the same rank.
+ */
+void br_aes_ct_bitslice_Sbox(uint32_t *q);
+
+/*
+ * Like br_aes_bitslice_Sbox(), but for the inverse S-box.
+ */
+void br_aes_ct_bitslice_invSbox(uint32_t *q);
+
+/*
+ * Compute AES encryption on bitsliced data. Since input is stored on
+ * eight 32-bit words, two block encryptions are actually performed
+ * in parallel.
+ */
+void br_aes_ct_bitslice_encrypt(unsigned num_rounds,
+ const uint32_t *skey, uint32_t *q);
+
+/*
+ * Compute AES decryption on bitsliced data. Since input is stored on
+ * eight 32-bit words, two block decryptions are actually performed
+ * in parallel.
+ */
+void br_aes_ct_bitslice_decrypt(unsigned num_rounds,
+ const uint32_t *skey, uint32_t *q);
+
+/*
+ * AES key schedule, constant-time version. skey[] is filled with n+1
+ * 128-bit subkeys, where n is the number of rounds (10 to 14, depending
+ * on key size). The number of rounds is returned. If the key size is
+ * invalid (not 16, 24 or 32), then 0 is returned.
+ */
+unsigned br_aes_ct_keysched(uint32_t *comp_skey,
+ const void *key, size_t key_len);
+
+/*
+ * Expand AES subkeys as produced by br_aes_ct_keysched(), into
+ * a larger array suitable for br_aes_ct_bitslice_encrypt() and
+ * br_aes_ct_bitslice_decrypt().
+ */
+void br_aes_ct_skey_expand(uint32_t *skey,
+ unsigned num_rounds, const uint32_t *comp_skey);
+
+/*
+ * For the ct64 implementation, the same bitslicing technique is used,
+ * but four instances are interleaved. First instance uses bits 0, 4,
+ * 8, 12,... of each word; second instance uses bits 1, 5, 9, 13,...
+ * and so on.
+ */
+
+/*
+ * Perform bytewise orthogonalization of eight 64-bit words. Bytes
+ * of q0..q7 are spread over all words: for a byte x that occurs
+ * at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit
+ * of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j.
+ *
+ * This operation is an involution.
+ */
+void br_aes_ct64_ortho(uint64_t *q);
+
+/*
+ * Interleave bytes for an AES input block. If input bytes are
+ * denoted 0123456789ABCDEF, and have been decoded with little-endian
+ * convention (w[0] contains 0123, with '3' being most significant;
+ * w[1] contains 4567, and so on), then output word q0 will be
+ * set to 08192A3B (again little-endian convention) and q1 will
+ * be set to 4C5D6E7F.
+ */
+void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w);
+
+/*
+ * Perform the opposite of br_aes_ct64_interleave_in().
+ */
+void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1);
+
+/*
+ * The AES S-box, as a bitsliced constant-time version. The input array
+ * consists in eight 64-bit words; 64 S-box instances are computed in
+ * parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant)
+ * are spread over the words 0 to 7, at the same rank.
+ */
+void br_aes_ct64_bitslice_Sbox(uint64_t *q);
+
+/*
+ * Like br_aes_bitslice_Sbox(), but for the inverse S-box.
+ */
+void br_aes_ct64_bitslice_invSbox(uint64_t *q);
+
+/*
+ * Compute AES encryption on bitsliced data. Since input is stored on
+ * eight 64-bit words, four block encryptions are actually performed
+ * in parallel.
+ */
+void br_aes_ct64_bitslice_encrypt(unsigned num_rounds,
+ const uint64_t *skey, uint64_t *q);
+
+/*
+ * Compute AES decryption on bitsliced data. Since input is stored on
+ * eight 64-bit words, four block decryptions are actually performed
+ * in parallel.
+ */
+void br_aes_ct64_bitslice_decrypt(unsigned num_rounds,
+ const uint64_t *skey, uint64_t *q);
+
+/*
+ * AES key schedule, constant-time version. skey[] is filled with n+1
+ * 128-bit subkeys, where n is the number of rounds (10 to 14, depending
+ * on key size). The number of rounds is returned. If the key size is
+ * invalid (not 16, 24 or 32), then 0 is returned.
+ */
+unsigned br_aes_ct64_keysched(uint64_t *comp_skey,
+ const void *key, size_t key_len);
+
+/*
+ * Expand AES subkeys as produced by br_aes_ct64_keysched(), into
+ * a larger array suitable for br_aes_ct64_bitslice_encrypt() and
+ * br_aes_ct64_bitslice_decrypt().
+ */
+void br_aes_ct64_skey_expand(uint64_t *skey,
+ unsigned num_rounds, const uint64_t *comp_skey);
+
+/*
+ * Test support for AES-NI opcodes.
+ */
+int br_aes_x86ni_supported(void);
+
+/*
+ * AES key schedule, using x86 AES-NI instructions. This yields the
+ * subkeys in the encryption direction. Number of rounds is returned.
+ * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
+ */
+unsigned br_aes_x86ni_keysched_enc(unsigned char *skni,
+ const void *key, size_t len);
+
+/*
+ * AES key schedule, using x86 AES-NI instructions. This yields the
+ * subkeys in the decryption direction. Number of rounds is returned.
+ * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
+ */
+unsigned br_aes_x86ni_keysched_dec(unsigned char *skni,
+ const void *key, size_t len);
+
+/*
+ * Test support for AES POWER8 opcodes.
+ */
+int br_aes_pwr8_supported(void);
+
+/*
+ * AES key schedule, using POWER8 instructions. This yields the
+ * subkeys in the encryption direction. Number of rounds is returned.
+ * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
+ */
+unsigned br_aes_pwr8_keysched(unsigned char *skni,
+ const void *key, size_t len);
+
+/* ==================================================================== */
+/*
+ * RSA.
+ */
+
+/*
+ * Apply proper PKCS#1 v1.5 padding (for signatures). 'hash_oid' is
+ * the encoded hash function OID, or NULL.
+ */
+uint32_t br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ uint32_t n_bitlen, unsigned char *x);
+
+/*
+ * Check PKCS#1 v1.5 padding (for signatures). 'hash_oid' is the encoded
+ * hash function OID, or NULL. The provided 'sig' value is _after_ the
+ * modular exponentiation, i.e. it should be the padded hash. On
+ * success, the hashed message is extracted.
+ */
+uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len,
+ const unsigned char *hash_oid, size_t hash_len,
+ unsigned char *hash_out);
+
+/*
+ * Apply proper PSS padding. The 'x' buffer is output only: it
+ * receives the value that is to be exponentiated.
+ */
+uint32_t br_rsa_pss_sig_pad(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ uint32_t n_bitlen, unsigned char *x);
+
+/*
+ * Check PSS padding. The provided value is the one _after_
+ * the modular exponentiation; it is modified by this function.
+ * This function infers the signature length from the public key
+ * size, i.e. it assumes that this has already been verified (as
+ * part of the exponentiation).
+ */
+uint32_t br_rsa_pss_sig_unpad(
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_public_key *pk, unsigned char *x);
+
+/*
+ * Apply OAEP padding. Returned value is the actual padded string length,
+ * or zero on error.
+ */
+size_t br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len, const br_rsa_public_key *pk,
+ void *dst, size_t dst_nax_len, const void *src, size_t src_len);
+
+/*
+ * Unravel and check OAEP padding. If the padding is correct, then 1 is
+ * returned, '*len' is adjusted to the length of the message, and the
+ * data is moved to the start of the 'data' buffer. If the padding is
+ * incorrect, then 0 is returned and '*len' is untouched. Either way,
+ * the complete buffer contents are altered.
+ */
+uint32_t br_rsa_oaep_unpad(const br_hash_class *dig,
+ const void *label, size_t label_len, void *data, size_t *len);
+
+/*
+ * Compute MGF1 for a given seed, and XOR the output into the provided
+ * buffer.
+ */
+void br_mgf1_xor(void *data, size_t len,
+ const br_hash_class *dig, const void *seed, size_t seed_len);
+
+/*
+ * Inner function for RSA key generation; used by the "i31" and "i62"
+ * implementations.
+ */
+uint32_t br_rsa_i31_keygen_inner(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31);
+
+/* ==================================================================== */
+/*
+ * Elliptic curves.
+ */
+
+/*
+ * Type for generic EC parameters: curve order (unsigned big-endian
+ * encoding) and encoded conventional generator.
+ */
+typedef struct {
+ int curve;
+ const unsigned char *order;
+ size_t order_len;
+ const unsigned char *generator;
+ size_t generator_len;
+} br_ec_curve_def;
+
+extern const br_ec_curve_def br_secp256r1;
+extern const br_ec_curve_def br_secp384r1;
+extern const br_ec_curve_def br_secp521r1;
+
+/*
+ * For Curve25519, the advertised "order" really is 2^255-1, since the
+ * point multipliction function really works over arbitrary 255-bit
+ * scalars. This value is only meant as a hint for ECDH key generation;
+ * only ECDSA uses the exact curve order, and ECDSA is not used with
+ * that specific curve.
+ */
+extern const br_ec_curve_def br_curve25519;
+
+/*
+ * Decode some bytes as an i31 integer, with truncation (corresponding
+ * to the 'bits2int' operation in RFC 6979). The target ENCODED bit
+ * length is provided as last parameter. The resulting value will have
+ * this declared bit length, and consists the big-endian unsigned decoding
+ * of exactly that many bits in the source (capped at the source length).
+ */
+void br_ecdsa_i31_bits2int(uint32_t *x,
+ const void *src, size_t len, uint32_t ebitlen);
+
+/*
+ * Decode some bytes as an i15 integer, with truncation (corresponding
+ * to the 'bits2int' operation in RFC 6979). The target ENCODED bit
+ * length is provided as last parameter. The resulting value will have
+ * this declared bit length, and consists the big-endian unsigned decoding
+ * of exactly that many bits in the source (capped at the source length).
+ */
+void br_ecdsa_i15_bits2int(uint16_t *x,
+ const void *src, size_t len, uint32_t ebitlen);
+
+/* ==================================================================== */
+/*
+ * ASN.1 support functions.
+ */
+
+/*
+ * A br_asn1_uint structure contains encoding information about an
+ * INTEGER nonnegative value: pointer to the integer contents (unsigned
+ * big-endian representation), length of the integer contents,
+ * and length of the encoded value. The data shall have minimal length:
+ * - If the integer value is zero, then 'len' must be zero.
+ * - If the integer value is not zero, then data[0] must be non-zero.
+ *
+ * Under these conditions, 'asn1len' is necessarily equal to either len
+ * or len+1.
+ */
+typedef struct {
+ const unsigned char *data;
+ size_t len;
+ size_t asn1len;
+} br_asn1_uint;
+
+/*
+ * Given an encoded integer (unsigned big-endian, with possible leading
+ * bytes of value 0), returned the "prepared INTEGER" structure.
+ */
+br_asn1_uint br_asn1_uint_prepare(const void *xdata, size_t xlen);
+
+/*
+ * Encode an ASN.1 length. The length of the encoded length is returned.
+ * If 'dest' is NULL, then no encoding is performed, but the length of
+ * the encoded length is still computed and returned.
+ */
+size_t br_asn1_encode_length(void *dest, size_t len);
+
+/*
+ * Convenient macro for computing lengths of lengths.
+ */
+#define len_of_len(len) br_asn1_encode_length(NULL, len)
+
+/*
+ * Encode a (prepared) ASN.1 INTEGER. The encoded length is returned.
+ * If 'dest' is NULL, then no encoding is performed, but the length of
+ * the encoded integer is still computed and returned.
+ */
+size_t br_asn1_encode_uint(void *dest, br_asn1_uint pp);
+
+/*
+ * Get the OID that identifies an elliptic curve. Returned value is
+ * the DER-encoded OID, with the length (always one byte) but without
+ * the tag. Thus, the first byte of the returned buffer contains the
+ * number of subsequent bytes in the value. If the curve is not
+ * recognised, NULL is returned.
+ */
+const unsigned char *br_get_curve_OID(int curve);
+
+/*
+ * Inner function for EC private key encoding. This is equivalent to
+ * the API function br_encode_ec_raw_der(), except for an extra
+ * parameter: if 'include_curve_oid' is zero, then the curve OID is
+ * _not_ included in the output blob (this is for PKCS#8 support).
+ */
+size_t br_encode_ec_raw_der_inner(void *dest,
+ const br_ec_private_key *sk, const br_ec_public_key *pk,
+ int include_curve_oid);
+
+/* ==================================================================== */
+/*
+ * SSL/TLS support functions.
+ */
+
+/*
+ * Record types.
+ */
+#define BR_SSL_CHANGE_CIPHER_SPEC 20
+#define BR_SSL_ALERT 21
+#define BR_SSL_HANDSHAKE 22
+#define BR_SSL_APPLICATION_DATA 23
+
+/*
+ * Handshake message types.
+ */
+#define BR_SSL_HELLO_REQUEST 0
+#define BR_SSL_CLIENT_HELLO 1
+#define BR_SSL_SERVER_HELLO 2
+#define BR_SSL_CERTIFICATE 11
+#define BR_SSL_SERVER_KEY_EXCHANGE 12
+#define BR_SSL_CERTIFICATE_REQUEST 13
+#define BR_SSL_SERVER_HELLO_DONE 14
+#define BR_SSL_CERTIFICATE_VERIFY 15
+#define BR_SSL_CLIENT_KEY_EXCHANGE 16
+#define BR_SSL_FINISHED 20
+
+/*
+ * Alert levels.
+ */
+#define BR_LEVEL_WARNING 1
+#define BR_LEVEL_FATAL 2
+
+/*
+ * Low-level I/O state.
+ */
+#define BR_IO_FAILED 0
+#define BR_IO_IN 1
+#define BR_IO_OUT 2
+#define BR_IO_INOUT 3
+
+/*
+ * Mark a SSL engine as failed. The provided error code is recorded if
+ * the engine was not already marked as failed. If 'err' is 0, then the
+ * engine is marked as closed (without error).
+ */
+void br_ssl_engine_fail(br_ssl_engine_context *cc, int err);
+
+/*
+ * Test whether the engine is closed (normally or as a failure).
+ */
+static inline int
+br_ssl_engine_closed(const br_ssl_engine_context *cc)
+{
+ return cc->iomode == BR_IO_FAILED;
+}
+
+/*
+ * Configure a new maximum fragment length. If possible, the maximum
+ * length for outgoing records is immediately adjusted (if there are
+ * not already too many buffered bytes for that).
+ */
+void br_ssl_engine_new_max_frag_len(
+ br_ssl_engine_context *rc, unsigned max_frag_len);
+
+/*
+ * Test whether the current incoming record has been fully received
+ * or not. This functions returns 0 only if a complete record header
+ * has been received, but some of the (possibly encrypted) payload
+ * has not yet been obtained.
+ */
+int br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc);
+
+/*
+ * Flush the current record (if not empty). This is meant to be called
+ * from the handshake processor only.
+ */
+void br_ssl_engine_flush_record(br_ssl_engine_context *cc);
+
+/*
+ * Test whether there is some accumulated payload to send.
+ */
+static inline int
+br_ssl_engine_has_pld_to_send(const br_ssl_engine_context *rc)
+{
+ return rc->oxa != rc->oxb && rc->oxa != rc->oxc;
+}
+
+/*
+ * Initialize RNG in engine. Returned value is 1 on success, 0 on error.
+ * This function will try to use the OS-provided RNG, if available. If
+ * there is no OS-provided RNG, or if it failed, and no entropy was
+ * injected by the caller, then a failure will be reported. On error,
+ * the context error code is set.
+ */
+int br_ssl_engine_init_rand(br_ssl_engine_context *cc);
+
+/*
+ * Reset the handshake-related parts of the engine.
+ */
+void br_ssl_engine_hs_reset(br_ssl_engine_context *cc,
+ void (*hsinit)(void *), void (*hsrun)(void *));
+
+/*
+ * Get the PRF to use for this context, for the provided PRF hash
+ * function ID.
+ */
+br_tls_prf_impl br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id);
+
+/*
+ * Consume the provided pre-master secret and compute the corresponding
+ * master secret. The 'prf_id' is the ID of the hash function to use
+ * with the TLS 1.2 PRF (ignored if the version is TLS 1.0 or 1.1).
+ */
+void br_ssl_engine_compute_master(br_ssl_engine_context *cc,
+ int prf_id, const void *pms, size_t len);
+
+/*
+ * Switch to CBC decryption for incoming records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF (ignored if not TLS 1.2+)
+ * mac_id id of hash function for HMAC
+ * bc_impl block cipher implementation (CBC decryption)
+ * cipher_key_len block cipher key length (in bytes)
+ */
+void br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id, int mac_id,
+ const br_block_cbcdec_class *bc_impl, size_t cipher_key_len);
+
+/*
+ * Switch to CBC encryption for outgoing records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF (ignored if not TLS 1.2+)
+ * mac_id id of hash function for HMAC
+ * bc_impl block cipher implementation (CBC encryption)
+ * cipher_key_len block cipher key length (in bytes)
+ */
+void br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id, int mac_id,
+ const br_block_cbcenc_class *bc_impl, size_t cipher_key_len);
+
+/*
+ * Switch to GCM decryption for incoming records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF
+ * bc_impl block cipher implementation (CTR)
+ * cipher_key_len block cipher key length (in bytes)
+ */
+void br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctr_class *bc_impl, size_t cipher_key_len);
+
+/*
+ * Switch to GCM encryption for outgoing records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF
+ * bc_impl block cipher implementation (CTR)
+ * cipher_key_len block cipher key length (in bytes)
+ */
+void br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctr_class *bc_impl, size_t cipher_key_len);
+
+/*
+ * Switch to ChaCha20+Poly1305 decryption for incoming records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF
+ */
+void br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id);
+
+/*
+ * Switch to ChaCha20+Poly1305 encryption for outgoing records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF
+ */
+void br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id);
+
+/*
+ * Switch to CCM decryption for incoming records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF
+ * bc_impl block cipher implementation (CTR+CBC)
+ * cipher_key_len block cipher key length (in bytes)
+ * tag_len tag length (in bytes)
+ */
+void br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctrcbc_class *bc_impl,
+ size_t cipher_key_len, size_t tag_len);
+
+/*
+ * Switch to GCM encryption for outgoing records.
+ * cc the engine context
+ * is_client non-zero for a client, zero for a server
+ * prf_id id of hash function for PRF
+ * bc_impl block cipher implementation (CTR+CBC)
+ * cipher_key_len block cipher key length (in bytes)
+ * tag_len tag length (in bytes)
+ */
+void br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctrcbc_class *bc_impl,
+ size_t cipher_key_len, size_t tag_len);
+
+/*
+ * Calls to T0-generated code.
+ */
+void br_ssl_hs_client_init_main(void *ctx);
+void br_ssl_hs_client_run(void *ctx);
+void br_ssl_hs_server_init_main(void *ctx);
+void br_ssl_hs_server_run(void *ctx);
+
+/*
+ * Get the hash function to use for signatures, given a bit mask of
+ * supported hash functions. This implements a strict choice order
+ * (namely SHA-256, SHA-384, SHA-512, SHA-224, SHA-1). If the mask
+ * does not document support of any of these hash functions, then this
+ * functions returns 0.
+ */
+int br_ssl_choose_hash(unsigned bf);
+
+/* ==================================================================== */
+
+/*
+ * PowerPC / POWER assembly stuff. The special BR_POWER_ASM_MACROS macro
+ * must be defined before including this file; this is done by source
+ * files that use some inline assembly for PowerPC / POWER machines.
+ */
+
+#if BR_POWER_ASM_MACROS
+
+#define lxvw4x(xt, ra, rb) lxvw4x_(xt, ra, rb)
+#define stxvw4x(xt, ra, rb) stxvw4x_(xt, ra, rb)
+
+#define bdnz(foo) bdnz_(foo)
+#define bdz(foo) bdz_(foo)
+#define beq(foo) beq_(foo)
+
+#define li(rx, value) li_(rx, value)
+#define addi(rx, ra, imm) addi_(rx, ra, imm)
+#define cmpldi(rx, imm) cmpldi_(rx, imm)
+#define mtctr(rx) mtctr_(rx)
+#define vspltb(vrt, vrb, uim) vspltb_(vrt, vrb, uim)
+#define vspltw(vrt, vrb, uim) vspltw_(vrt, vrb, uim)
+#define vspltisb(vrt, imm) vspltisb_(vrt, imm)
+#define vspltisw(vrt, imm) vspltisw_(vrt, imm)
+#define vrlw(vrt, vra, vrb) vrlw_(vrt, vra, vrb)
+#define vsbox(vrt, vra) vsbox_(vrt, vra)
+#define vxor(vrt, vra, vrb) vxor_(vrt, vra, vrb)
+#define vand(vrt, vra, vrb) vand_(vrt, vra, vrb)
+#define vsro(vrt, vra, vrb) vsro_(vrt, vra, vrb)
+#define vsl(vrt, vra, vrb) vsl_(vrt, vra, vrb)
+#define vsldoi(vt, va, vb, sh) vsldoi_(vt, va, vb, sh)
+#define vsr(vrt, vra, vrb) vsr_(vrt, vra, vrb)
+#define vaddcuw(vrt, vra, vrb) vaddcuw_(vrt, vra, vrb)
+#define vadduwm(vrt, vra, vrb) vadduwm_(vrt, vra, vrb)
+#define vsububm(vrt, vra, vrb) vsububm_(vrt, vra, vrb)
+#define vsubuwm(vrt, vra, vrb) vsubuwm_(vrt, vra, vrb)
+#define vsrw(vrt, vra, vrb) vsrw_(vrt, vra, vrb)
+#define vcipher(vt, va, vb) vcipher_(vt, va, vb)
+#define vcipherlast(vt, va, vb) vcipherlast_(vt, va, vb)
+#define vncipher(vt, va, vb) vncipher_(vt, va, vb)
+#define vncipherlast(vt, va, vb) vncipherlast_(vt, va, vb)
+#define vperm(vt, va, vb, vc) vperm_(vt, va, vb, vc)
+#define vpmsumd(vt, va, vb) vpmsumd_(vt, va, vb)
+#define xxpermdi(vt, va, vb, d) xxpermdi_(vt, va, vb, d)
+
+#define lxvw4x_(xt, ra, rb) "\tlxvw4x\t" #xt "," #ra "," #rb "\n"
+#define stxvw4x_(xt, ra, rb) "\tstxvw4x\t" #xt "," #ra "," #rb "\n"
+
+#define label(foo) #foo "%=:\n"
+#define bdnz_(foo) "\tbdnz\t" #foo "%=\n"
+#define bdz_(foo) "\tbdz\t" #foo "%=\n"
+#define beq_(foo) "\tbeq\t" #foo "%=\n"
+
+#define li_(rx, value) "\tli\t" #rx "," #value "\n"
+#define addi_(rx, ra, imm) "\taddi\t" #rx "," #ra "," #imm "\n"
+#define cmpldi_(rx, imm) "\tcmpldi\t" #rx "," #imm "\n"
+#define mtctr_(rx) "\tmtctr\t" #rx "\n"
+#define vspltb_(vrt, vrb, uim) "\tvspltb\t" #vrt "," #vrb "," #uim "\n"
+#define vspltw_(vrt, vrb, uim) "\tvspltw\t" #vrt "," #vrb "," #uim "\n"
+#define vspltisb_(vrt, imm) "\tvspltisb\t" #vrt "," #imm "\n"
+#define vspltisw_(vrt, imm) "\tvspltisw\t" #vrt "," #imm "\n"
+#define vrlw_(vrt, vra, vrb) "\tvrlw\t" #vrt "," #vra "," #vrb "\n"
+#define vsbox_(vrt, vra) "\tvsbox\t" #vrt "," #vra "\n"
+#define vxor_(vrt, vra, vrb) "\tvxor\t" #vrt "," #vra "," #vrb "\n"
+#define vand_(vrt, vra, vrb) "\tvand\t" #vrt "," #vra "," #vrb "\n"
+#define vsro_(vrt, vra, vrb) "\tvsro\t" #vrt "," #vra "," #vrb "\n"
+#define vsl_(vrt, vra, vrb) "\tvsl\t" #vrt "," #vra "," #vrb "\n"
+#define vsldoi_(vt, va, vb, sh) "\tvsldoi\t" #vt "," #va "," #vb "," #sh "\n"
+#define vsr_(vrt, vra, vrb) "\tvsr\t" #vrt "," #vra "," #vrb "\n"
+#define vaddcuw_(vrt, vra, vrb) "\tvaddcuw\t" #vrt "," #vra "," #vrb "\n"
+#define vadduwm_(vrt, vra, vrb) "\tvadduwm\t" #vrt "," #vra "," #vrb "\n"
+#define vsububm_(vrt, vra, vrb) "\tvsububm\t" #vrt "," #vra "," #vrb "\n"
+#define vsubuwm_(vrt, vra, vrb) "\tvsubuwm\t" #vrt "," #vra "," #vrb "\n"
+#define vsrw_(vrt, vra, vrb) "\tvsrw\t" #vrt "," #vra "," #vrb "\n"
+#define vcipher_(vt, va, vb) "\tvcipher\t" #vt "," #va "," #vb "\n"
+#define vcipherlast_(vt, va, vb) "\tvcipherlast\t" #vt "," #va "," #vb "\n"
+#define vncipher_(vt, va, vb) "\tvncipher\t" #vt "," #va "," #vb "\n"
+#define vncipherlast_(vt, va, vb) "\tvncipherlast\t" #vt "," #va "," #vb "\n"
+#define vperm_(vt, va, vb, vc) "\tvperm\t" #vt "," #va "," #vb "," #vc "\n"
+#define vpmsumd_(vt, va, vb) "\tvpmsumd\t" #vt "," #va "," #vb "\n"
+#define xxpermdi_(vt, va, vb, d) "\txxpermdi\t" #vt "," #va "," #vb "," #d "\n"
+
+#endif
+
+/* ==================================================================== */
+/*
+ * Special "activate intrinsics" code, needed for some compiler versions.
+ * This is defined at the end of this file, so that it won't impact any
+ * of the inline functions defined previously; and it is controlled by
+ * a specific macro defined in the caller code.
+ *
+ * Calling code conventions:
+ *
+ * - Caller must define BR_ENABLE_INTRINSICS before including "inner.h".
+ * - Functions that use intrinsics must be enclosed in an "enabled"
+ * region (between BR_TARGETS_X86_UP and BR_TARGETS_X86_DOWN).
+ * - Functions that use intrinsics must be tagged with the appropriate
+ * BR_TARGET().
+ */
+
+#if BR_ENABLE_INTRINSICS && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005)
+
+/*
+ * x86 intrinsics (both 32-bit and 64-bit).
+ */
+#if BR_i386 || BR_amd64
+
+/*
+ * On GCC before version 5.0, we need to use the pragma to enable the
+ * target options globally, because the 'target' function attribute
+ * appears to be unreliable. Before 4.6 we must also avoid the
+ * push_options / pop_options mechanism, because it tends to trigger
+ * some internal compiler errors.
+ */
+#if BR_GCC && !BR_GCC_5_0
+#if BR_GCC_4_6
+#define BR_TARGETS_X86_UP \
+ _Pragma("GCC push_options") \
+ _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul,rdrnd\")")
+#define BR_TARGETS_X86_DOWN \
+ _Pragma("GCC pop_options")
+#else
+#define BR_TARGETS_X86_UP \
+ _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul\")")
+#define BR_TARGETS_X86_DOWN
+#endif
+#pragma GCC diagnostic ignored "-Wpsabi"
+#endif
+
+#if BR_CLANG && !BR_CLANG_3_8
+#undef __SSE2__
+#undef __SSE3__
+#undef __SSSE3__
+#undef __SSE4_1__
+#undef __AES__
+#undef __PCLMUL__
+#undef __RDRND__
+#define __SSE2__ 1
+#define __SSE3__ 1
+#define __SSSE3__ 1
+#define __SSE4_1__ 1
+#define __AES__ 1
+#define __PCLMUL__ 1
+#define __RDRND__ 1
+#endif
+
+#ifndef BR_TARGETS_X86_UP
+#define BR_TARGETS_X86_UP
+#endif
+#ifndef BR_TARGETS_X86_DOWN
+#define BR_TARGETS_X86_DOWN
+#endif
+
+#if BR_GCC || BR_CLANG
+BR_TARGETS_X86_UP
+#include <x86intrin.h>
+#include <cpuid.h>
+#define br_bswap32 __builtin_bswap32
+BR_TARGETS_X86_DOWN
+#endif
+
+#if BR_MSC
+#include <stdlib.h>
+#include <intrin.h>
+#include <immintrin.h>
+#define br_bswap32 _byteswap_ulong
+#endif
+
+static inline int
+br_cpuid(uint32_t mask_eax, uint32_t mask_ebx,
+ uint32_t mask_ecx, uint32_t mask_edx)
+{
+#if BR_GCC || BR_CLANG
+ unsigned eax, ebx, ecx, edx;
+
+ if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
+ if ((eax & mask_eax) == mask_eax
+ && (ebx & mask_ebx) == mask_ebx
+ && (ecx & mask_ecx) == mask_ecx
+ && (edx & mask_edx) == mask_edx)
+ {
+ return 1;
+ }
+ }
+#elif BR_MSC
+ int info[4];
+
+ __cpuid(info, 1);
+ if (((uint32_t)info[0] & mask_eax) == mask_eax
+ && ((uint32_t)info[1] & mask_ebx) == mask_ebx
+ && ((uint32_t)info[2] & mask_ecx) == mask_ecx
+ && ((uint32_t)info[3] & mask_edx) == mask_edx)
+ {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+#endif
+
+#endif
+
+/* ==================================================================== */
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/inner.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_add.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_add.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_add.c (revision 346145)
@@ -0,0 +1,46 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl)
+{
+ uint32_t cc;
+ size_t u, m;
+
+ cc = 0;
+ m = (a[0] + 31) >> 4;
+ for (u = 1; u < m; u ++) {
+ uint32_t aw, bw, naw;
+
+ aw = a[u];
+ bw = b[u];
+ naw = aw + bw + cc;
+ cc = naw >> 15;
+ a[u] = MUX(ctl, naw & 0x7FFF, aw);
+ }
+ return cc;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_add.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_bitlen.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_bitlen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_bitlen.c (revision 346145)
@@ -0,0 +1,44 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_i15_bit_length(uint16_t *x, size_t xlen)
+{
+ uint32_t tw, twk;
+
+ tw = 0;
+ twk = 0;
+ while (xlen -- > 0) {
+ uint32_t w, c;
+
+ c = EQ(tw, 0);
+ w = x[xlen];
+ tw = MUX(c, w, tw);
+ twk = MUX(c, (uint32_t)xlen, twk);
+ }
+ return (twk << 4) + BIT_LENGTH(tw);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_bitlen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_decmod.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_decmod.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_decmod.c (revision 346145)
@@ -0,0 +1,124 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_i15_decode_mod(uint16_t *x, const void *src, size_t len, const uint16_t *m)
+{
+ /*
+ * Two-pass algorithm: in the first pass, we determine whether the
+ * value fits; in the second pass, we do the actual write.
+ *
+ * During the first pass, 'r' contains the comparison result so
+ * far:
+ * 0x00000000 value is equal to the modulus
+ * 0x00000001 value is greater than the modulus
+ * 0xFFFFFFFF value is lower than the modulus
+ *
+ * Since we iterate starting with the least significant bytes (at
+ * the end of src[]), each new comparison overrides the previous
+ * except when the comparison yields 0 (equal).
+ *
+ * During the second pass, 'r' is either 0xFFFFFFFF (value fits)
+ * or 0x00000000 (value does not fit).
+ *
+ * We must iterate over all bytes of the source, _and_ possibly
+ * some extra virtual bytes (with value 0) so as to cover the
+ * complete modulus as well. We also add 4 such extra bytes beyond
+ * the modulus length because it then guarantees that no accumulated
+ * partial word remains to be processed.
+ */
+ const unsigned char *buf;
+ size_t mlen, tlen;
+ int pass;
+ uint32_t r;
+
+ buf = src;
+ mlen = (m[0] + 15) >> 4;
+ tlen = (mlen << 1);
+ if (tlen < len) {
+ tlen = len;
+ }
+ tlen += 4;
+ r = 0;
+ for (pass = 0; pass < 2; pass ++) {
+ size_t u, v;
+ uint32_t acc;
+ int acc_len;
+
+ v = 1;
+ acc = 0;
+ acc_len = 0;
+ for (u = 0; u < tlen; u ++) {
+ uint32_t b;
+
+ if (u < len) {
+ b = buf[len - 1 - u];
+ } else {
+ b = 0;
+ }
+ acc |= (b << acc_len);
+ acc_len += 8;
+ if (acc_len >= 15) {
+ uint32_t xw;
+
+ xw = acc & (uint32_t)0x7FFF;
+ acc_len -= 15;
+ acc = b >> (8 - acc_len);
+ if (v <= mlen) {
+ if (pass) {
+ x[v] = r & xw;
+ } else {
+ uint32_t cc;
+
+ cc = (uint32_t)CMP(xw, m[v]);
+ r = MUX(EQ(cc, 0), r, cc);
+ }
+ } else {
+ if (!pass) {
+ r = MUX(EQ(xw, 0), r, 1);
+ }
+ }
+ v ++;
+ }
+ }
+
+ /*
+ * When we reach this point at the end of the first pass:
+ * r is either 0, 1 or -1; we want to set r to 0 if it
+ * is equal to 0 or 1, and leave it to -1 otherwise.
+ *
+ * When we reach this point at the end of the second pass:
+ * r is either 0 or -1; we want to leave that value
+ * untouched. This is a subcase of the previous.
+ */
+ r >>= 1;
+ r |= (r << 1);
+ }
+
+ x[0] = m[0];
+ return r & (uint32_t)1;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_decmod.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_decode.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_decode.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_decode.c (revision 346145)
@@ -0,0 +1,56 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_decode(uint16_t *x, const void *src, size_t len)
+{
+ const unsigned char *buf;
+ size_t v;
+ uint32_t acc;
+ int acc_len;
+
+ buf = src;
+ v = 1;
+ acc = 0;
+ acc_len = 0;
+ while (len -- > 0) {
+ uint32_t b;
+
+ b = buf[len];
+ acc |= (b << acc_len);
+ acc_len += 8;
+ if (acc_len >= 15) {
+ x[v ++] = acc & 0x7FFF;
+ acc_len -= 15;
+ acc >>= 15;
+ }
+ }
+ if (acc_len != 0) {
+ x[v ++] = acc;
+ }
+ x[0] = br_i15_bit_length(x + 1, v - 1);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_decode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_decred.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_decred.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_decred.c (revision 346145)
@@ -0,0 +1,100 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_decode_reduce(uint16_t *x,
+ const void *src, size_t len, const uint16_t *m)
+{
+ uint32_t m_ebitlen, m_rbitlen;
+ size_t mblen, k;
+ const unsigned char *buf;
+ uint32_t acc;
+ int acc_len;
+
+ /*
+ * Get the encoded bit length.
+ */
+ m_ebitlen = m[0];
+
+ /*
+ * Special case for an invalid (null) modulus.
+ */
+ if (m_ebitlen == 0) {
+ x[0] = 0;
+ return;
+ }
+
+ /*
+ * Clear the destination.
+ */
+ br_i15_zero(x, m_ebitlen);
+
+ /*
+ * First decode directly as many bytes as possible. This requires
+ * computing the actual bit length.
+ */
+ m_rbitlen = m_ebitlen >> 4;
+ m_rbitlen = (m_ebitlen & 15) + (m_rbitlen << 4) - m_rbitlen;
+ mblen = (m_rbitlen + 7) >> 3;
+ k = mblen - 1;
+ if (k >= len) {
+ br_i15_decode(x, src, len);
+ x[0] = m_ebitlen;
+ return;
+ }
+ buf = src;
+ br_i15_decode(x, buf, k);
+ x[0] = m_ebitlen;
+
+ /*
+ * Input remaining bytes, using 15-bit words.
+ */
+ acc = 0;
+ acc_len = 0;
+ while (k < len) {
+ uint32_t v;
+
+ v = buf[k ++];
+ acc = (acc << 8) | v;
+ acc_len += 8;
+ if (acc_len >= 15) {
+ br_i15_muladd_small(x, acc >> (acc_len - 15), m);
+ acc_len -= 15;
+ acc &= ~((uint32_t)-1 << acc_len);
+ }
+ }
+
+ /*
+ * We may have some bits accumulated. We then perform a shift to
+ * be able to inject these bits as a full 15-bit word.
+ */
+ if (acc_len != 0) {
+ acc = (acc | (x[1] << acc_len)) & 0x7FFF;
+ br_i15_rshift(x, 15 - acc_len);
+ br_i15_muladd_small(x, acc, m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_decred.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_encode.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_encode.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_encode.c (revision 346145)
@@ -0,0 +1,56 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_encode(void *dst, size_t len, const uint16_t *x)
+{
+ unsigned char *buf;
+ size_t u, xlen;
+ uint32_t acc;
+ int acc_len;
+
+ xlen = (x[0] + 15) >> 4;
+ if (xlen == 0) {
+ memset(dst, 0, len);
+ return;
+ }
+ u = 1;
+ acc = 0;
+ acc_len = 0;
+ buf = dst;
+ while (len -- > 0) {
+ if (acc_len < 8) {
+ if (u <= xlen) {
+ acc += (uint32_t)x[u ++] << acc_len;
+ }
+ acc_len += 15;
+ }
+ buf[len] = (unsigned char)acc;
+ acc >>= 8;
+ acc_len -= 8;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_encode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_fmont.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_fmont.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_fmont.c (revision 346145)
@@ -0,0 +1,59 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i)
+{
+ size_t len, u, v;
+
+ len = (m[0] + 15) >> 4;
+ for (u = 0; u < len; u ++) {
+ uint32_t f, cc;
+
+ f = MUL15(x[1], m0i) & 0x7FFF;
+ cc = 0;
+ for (v = 0; v < len; v ++) {
+ uint32_t z;
+
+ z = (uint32_t)x[v + 1] + MUL15(f, m[v + 1]) + cc;
+ cc = z >> 15;
+ if (v != 0) {
+ x[v] = z & 0x7FFF;
+ }
+ }
+ x[len] = cc;
+ }
+
+ /*
+ * We may have to do an extra subtraction, but only if the
+ * value in x[] is indeed greater than or equal to that of m[],
+ * which is why we must do two calls (first call computes the
+ * carry, second call performs the subtraction only if the carry
+ * is 0).
+ */
+ br_i15_sub(x, m, NOT(br_i15_sub(x, m, 0)));
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_fmont.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_iszero.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_iszero.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_iszero.c (revision 346145)
@@ -0,0 +1,39 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_i15_iszero(const uint16_t *x)
+{
+ uint32_t z;
+ size_t u;
+
+ z = 0;
+ for (u = (x[0] + 15) >> 4; u > 0; u --) {
+ z |= x[u];
+ }
+ return ~(z | -z) >> 31;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_iszero.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_moddiv.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_moddiv.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_moddiv.c (revision 346145)
@@ -0,0 +1,465 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * In this file, we handle big integers with a custom format, i.e.
+ * without the usual one-word header. Value is split into 15-bit words,
+ * each stored in a 16-bit slot (top bit is zero) in little-endian
+ * order. The length (in words) is provided explicitly. In some cases,
+ * the value can be negative (using two's complement representation). In
+ * some cases, the top word is allowed to have a 16th bit.
+ */
+
+/*
+ * Negate big integer conditionally. The value consists of 'len' words,
+ * with 15 bits in each word (the top bit of each word should be 0,
+ * except possibly for the last word). If 'ctl' is 1, the negation is
+ * computed; otherwise, if 'ctl' is 0, then the value is unchanged.
+ */
+static void
+cond_negate(uint16_t *a, size_t len, uint32_t ctl)
+{
+ size_t k;
+ uint32_t cc, xm;
+
+ cc = ctl;
+ xm = 0x7FFF & -ctl;
+ for (k = 0; k < len; k ++) {
+ uint32_t aw;
+
+ aw = a[k];
+ aw = (aw ^ xm) + cc;
+ a[k] = aw & 0x7FFF;
+ cc = (aw >> 15) & 1;
+ }
+}
+
+/*
+ * Finish modular reduction. Rules on input parameters:
+ *
+ * if neg = 1, then -m <= a < 0
+ * if neg = 0, then 0 <= a < 2*m
+ *
+ * If neg = 0, then the top word of a[] may use 16 bits.
+ *
+ * Also, modulus m must be odd.
+ */
+static void
+finish_mod(uint16_t *a, size_t len, const uint16_t *m, uint32_t neg)
+{
+ size_t k;
+ uint32_t cc, xm, ym;
+
+ /*
+ * First pass: compare a (assumed nonnegative) with m.
+ */
+ cc = 0;
+ for (k = 0; k < len; k ++) {
+ uint32_t aw, mw;
+
+ aw = a[k];
+ mw = m[k];
+ cc = (aw - mw - cc) >> 31;
+ }
+
+ /*
+ * At this point:
+ * if neg = 1, then we must add m (regardless of cc)
+ * if neg = 0 and cc = 0, then we must subtract m
+ * if neg = 0 and cc = 1, then we must do nothing
+ */
+ xm = 0x7FFF & -neg;
+ ym = -(neg | (1 - cc));
+ cc = neg;
+ for (k = 0; k < len; k ++) {
+ uint32_t aw, mw;
+
+ aw = a[k];
+ mw = (m[k] ^ xm) & ym;
+ aw = aw - mw - cc;
+ a[k] = aw & 0x7FFF;
+ cc = aw >> 31;
+ }
+}
+
+/*
+ * Compute:
+ * a <- (a*pa+b*pb)/(2^15)
+ * b <- (a*qa+b*qb)/(2^15)
+ * The division is assumed to be exact (i.e. the low word is dropped).
+ * If the final a is negative, then it is negated. Similarly for b.
+ * Returned value is the combination of two bits:
+ * bit 0: 1 if a had to be negated, 0 otherwise
+ * bit 1: 1 if b had to be negated, 0 otherwise
+ *
+ * Factors pa, pb, qa and qb must be at most 2^15 in absolute value.
+ * Source integers a and b must be nonnegative; top word is not allowed
+ * to contain an extra 16th bit.
+ */
+static uint32_t
+co_reduce(uint16_t *a, uint16_t *b, size_t len,
+ int32_t pa, int32_t pb, int32_t qa, int32_t qb)
+{
+ size_t k;
+ int32_t cca, ccb;
+ uint32_t nega, negb;
+
+ cca = 0;
+ ccb = 0;
+ for (k = 0; k < len; k ++) {
+ uint32_t wa, wb, za, zb;
+ uint16_t tta, ttb;
+
+ /*
+ * Since:
+ * |pa| <= 2^15
+ * |pb| <= 2^15
+ * 0 <= wa <= 2^15 - 1
+ * 0 <= wb <= 2^15 - 1
+ * |cca| <= 2^16 - 1
+ * Then:
+ * |za| <= (2^15-1)*(2^16) + (2^16-1) = 2^31 - 1
+ *
+ * Thus, the new value of cca is such that |cca| <= 2^16 - 1.
+ * The same applies to ccb.
+ */
+ wa = a[k];
+ wb = b[k];
+ za = wa * (uint32_t)pa + wb * (uint32_t)pb + (uint32_t)cca;
+ zb = wa * (uint32_t)qa + wb * (uint32_t)qb + (uint32_t)ccb;
+ if (k > 0) {
+ a[k - 1] = za & 0x7FFF;
+ b[k - 1] = zb & 0x7FFF;
+ }
+ tta = za >> 15;
+ ttb = zb >> 15;
+ cca = *(int16_t *)&tta;
+ ccb = *(int16_t *)&ttb;
+ }
+ a[len - 1] = (uint16_t)cca;
+ b[len - 1] = (uint16_t)ccb;
+ nega = (uint32_t)cca >> 31;
+ negb = (uint32_t)ccb >> 31;
+ cond_negate(a, len, nega);
+ cond_negate(b, len, negb);
+ return nega | (negb << 1);
+}
+
+/*
+ * Compute:
+ * a <- (a*pa+b*pb)/(2^15) mod m
+ * b <- (a*qa+b*qb)/(2^15) mod m
+ *
+ * m0i is equal to -1/m[0] mod 2^15.
+ *
+ * Factors pa, pb, qa and qb must be at most 2^15 in absolute value.
+ * Source integers a and b must be nonnegative; top word is not allowed
+ * to contain an extra 16th bit.
+ */
+static void
+co_reduce_mod(uint16_t *a, uint16_t *b, size_t len,
+ int32_t pa, int32_t pb, int32_t qa, int32_t qb,
+ const uint16_t *m, uint16_t m0i)
+{
+ size_t k;
+ int32_t cca, ccb, fa, fb;
+
+ cca = 0;
+ ccb = 0;
+ fa = ((a[0] * (uint32_t)pa + b[0] * (uint32_t)pb) * m0i) & 0x7FFF;
+ fb = ((a[0] * (uint32_t)qa + b[0] * (uint32_t)qb) * m0i) & 0x7FFF;
+ for (k = 0; k < len; k ++) {
+ uint32_t wa, wb, za, zb;
+ uint32_t tta, ttb;
+
+ /*
+ * In this loop, carries 'cca' and 'ccb' always fit on
+ * 17 bits (in absolute value).
+ */
+ wa = a[k];
+ wb = b[k];
+ za = wa * (uint32_t)pa + wb * (uint32_t)pb
+ + m[k] * (uint32_t)fa + (uint32_t)cca;
+ zb = wa * (uint32_t)qa + wb * (uint32_t)qb
+ + m[k] * (uint32_t)fb + (uint32_t)ccb;
+ if (k > 0) {
+ a[k - 1] = za & 0x7FFF;
+ b[k - 1] = zb & 0x7FFF;
+ }
+
+ /*
+ * The XOR-and-sub construction below does an arithmetic
+ * right shift in a portable way (technically, right-shifting
+ * a negative signed value is implementation-defined in C).
+ */
+#define M ((uint32_t)1 << 16)
+ tta = za >> 15;
+ ttb = zb >> 15;
+ tta = (tta ^ M) - M;
+ ttb = (ttb ^ M) - M;
+ cca = *(int32_t *)&tta;
+ ccb = *(int32_t *)&ttb;
+#undef M
+ }
+ a[len - 1] = (uint32_t)cca;
+ b[len - 1] = (uint32_t)ccb;
+
+ /*
+ * At this point:
+ * -m <= a < 2*m
+ * -m <= b < 2*m
+ * (this is a case of Montgomery reduction)
+ * The top word of 'a' and 'b' may have a 16-th bit set.
+ * We may have to add or subtract the modulus.
+ */
+ finish_mod(a, len, m, (uint32_t)cca >> 31);
+ finish_mod(b, len, m, (uint32_t)ccb >> 31);
+}
+
+/* see inner.h */
+uint32_t
+br_i15_moddiv(uint16_t *x, const uint16_t *y, const uint16_t *m, uint16_t m0i,
+ uint16_t *t)
+{
+ /*
+ * Algorithm is an extended binary GCD. We maintain four values
+ * a, b, u and v, with the following invariants:
+ *
+ * a * x = y * u mod m
+ * b * x = y * v mod m
+ *
+ * Starting values are:
+ *
+ * a = y
+ * b = m
+ * u = x
+ * v = 0
+ *
+ * The formal definition of the algorithm is a sequence of steps:
+ *
+ * - If a is even, then a <- a/2 and u <- u/2 mod m.
+ * - Otherwise, if b is even, then b <- b/2 and v <- v/2 mod m.
+ * - Otherwise, if a > b, then a <- (a-b)/2 and u <- (u-v)/2 mod m.
+ * - Otherwise, b <- (b-a)/2 and v <- (v-u)/2 mod m.
+ *
+ * Algorithm stops when a = b. At that point, they both are equal
+ * to GCD(y,m); the modular division succeeds if that value is 1.
+ * The result of the modular division is then u (or v: both are
+ * equal at that point).
+ *
+ * Each step makes either a or b shrink by at least one bit; hence,
+ * if m has bit length k bits, then 2k-2 steps are sufficient.
+ *
+ *
+ * Though complexity is quadratic in the size of m, the bit-by-bit
+ * processing is not very efficient. We can speed up processing by
+ * remarking that the decisions are taken based only on observation
+ * of the top and low bits of a and b.
+ *
+ * In the loop below, at each iteration, we use the two top words
+ * of a and b, and the low words of a and b, to compute reduction
+ * parameters pa, pb, qa and qb such that the new values for a
+ * and b are:
+ *
+ * a' = (a*pa + b*pb) / (2^15)
+ * b' = (a*qa + b*qb) / (2^15)
+ *
+ * the division being exact.
+ *
+ * Since the choices are based on the top words, they may be slightly
+ * off, requiring an optional correction: if a' < 0, then we replace
+ * pa with -pa, and pb with -pb. The total length of a and b is
+ * thus reduced by at least 14 bits at each iteration.
+ *
+ * The stopping conditions are still the same, though: when a
+ * and b become equal, they must be both odd (since m is odd,
+ * the GCD cannot be even), therefore the next operation is a
+ * subtraction, and one of the values becomes 0. At that point,
+ * nothing else happens, i.e. one value is stuck at 0, and the
+ * other one is the GCD.
+ */
+ size_t len, k;
+ uint16_t *a, *b, *u, *v;
+ uint32_t num, r;
+
+ len = (m[0] + 15) >> 4;
+ a = t;
+ b = a + len;
+ u = x + 1;
+ v = b + len;
+ memcpy(a, y + 1, len * sizeof *y);
+ memcpy(b, m + 1, len * sizeof *m);
+ memset(v, 0, len * sizeof *v);
+
+ /*
+ * Loop below ensures that a and b are reduced by some bits each,
+ * for a total of at least 14 bits.
+ */
+ for (num = ((m[0] - (m[0] >> 4)) << 1) + 14; num >= 14; num -= 14) {
+ size_t j;
+ uint32_t c0, c1;
+ uint32_t a0, a1, b0, b1;
+ uint32_t a_hi, b_hi, a_lo, b_lo;
+ int32_t pa, pb, qa, qb;
+ int i;
+
+ /*
+ * Extract top words of a and b. If j is the highest
+ * index >= 1 such that a[j] != 0 or b[j] != 0, then we want
+ * (a[j] << 15) + a[j - 1], and (b[j] << 15) + b[j - 1].
+ * If a and b are down to one word each, then we use a[0]
+ * and b[0].
+ */
+ c0 = (uint32_t)-1;
+ c1 = (uint32_t)-1;
+ a0 = 0;
+ a1 = 0;
+ b0 = 0;
+ b1 = 0;
+ j = len;
+ while (j -- > 0) {
+ uint32_t aw, bw;
+
+ aw = a[j];
+ bw = b[j];
+ a0 ^= (a0 ^ aw) & c0;
+ a1 ^= (a1 ^ aw) & c1;
+ b0 ^= (b0 ^ bw) & c0;
+ b1 ^= (b1 ^ bw) & c1;
+ c1 = c0;
+ c0 &= (((aw | bw) + 0xFFFF) >> 16) - (uint32_t)1;
+ }
+
+ /*
+ * If c1 = 0, then we grabbed two words for a and b.
+ * If c1 != 0 but c0 = 0, then we grabbed one word. It
+ * is not possible that c1 != 0 and c0 != 0, because that
+ * would mean that both integers are zero.
+ */
+ a1 |= a0 & c1;
+ a0 &= ~c1;
+ b1 |= b0 & c1;
+ b0 &= ~c1;
+ a_hi = (a0 << 15) + a1;
+ b_hi = (b0 << 15) + b1;
+ a_lo = a[0];
+ b_lo = b[0];
+
+ /*
+ * Compute reduction factors:
+ *
+ * a' = a*pa + b*pb
+ * b' = a*qa + b*qb
+ *
+ * such that a' and b' are both multiple of 2^15, but are
+ * only marginally larger than a and b.
+ */
+ pa = 1;
+ pb = 0;
+ qa = 0;
+ qb = 1;
+ for (i = 0; i < 15; i ++) {
+ /*
+ * At each iteration:
+ *
+ * a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi
+ * b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi
+ * a <- a/2 if: a is even
+ * b <- b/2 if: a is odd, b is even
+ *
+ * We multiply a_lo and b_lo by 2 at each
+ * iteration, thus a division by 2 really is a
+ * non-multiplication by 2.
+ */
+ uint32_t r, oa, ob, cAB, cBA, cA;
+
+ /*
+ * cAB = 1 if b must be subtracted from a
+ * cBA = 1 if a must be subtracted from b
+ * cA = 1 if a is divided by 2, 0 otherwise
+ *
+ * Rules:
+ *
+ * cAB and cBA cannot be both 1.
+ * if a is not divided by 2, b is.
+ */
+ r = GT(a_hi, b_hi);
+ oa = (a_lo >> i) & 1;
+ ob = (b_lo >> i) & 1;
+ cAB = oa & ob & r;
+ cBA = oa & ob & NOT(r);
+ cA = cAB | NOT(oa);
+
+ /*
+ * Conditional subtractions.
+ */
+ a_lo -= b_lo & -cAB;
+ a_hi -= b_hi & -cAB;
+ pa -= qa & -(int32_t)cAB;
+ pb -= qb & -(int32_t)cAB;
+ b_lo -= a_lo & -cBA;
+ b_hi -= a_hi & -cBA;
+ qa -= pa & -(int32_t)cBA;
+ qb -= pb & -(int32_t)cBA;
+
+ /*
+ * Shifting.
+ */
+ a_lo += a_lo & (cA - 1);
+ pa += pa & ((int32_t)cA - 1);
+ pb += pb & ((int32_t)cA - 1);
+ a_hi ^= (a_hi ^ (a_hi >> 1)) & -cA;
+ b_lo += b_lo & -cA;
+ qa += qa & -(int32_t)cA;
+ qb += qb & -(int32_t)cA;
+ b_hi ^= (b_hi ^ (b_hi >> 1)) & (cA - 1);
+ }
+
+ /*
+ * Replace a and b with new values a' and b'.
+ */
+ r = co_reduce(a, b, len, pa, pb, qa, qb);
+ pa -= pa * ((r & 1) << 1);
+ pb -= pb * ((r & 1) << 1);
+ qa -= qa * (r & 2);
+ qb -= qb * (r & 2);
+ co_reduce_mod(u, v, len, pa, pb, qa, qb, m + 1, m0i);
+ }
+
+ /*
+ * Now one of the arrays should be 0, and the other contains
+ * the GCD. If a is 0, then u is 0 as well, and v contains
+ * the division result.
+ * Result is correct if and only if GCD is 1.
+ */
+ r = (a[0] | b[0]) ^ 1;
+ u[0] |= v[0];
+ for (k = 1; k < len; k ++) {
+ r |= a[k] | b[k];
+ u[k] |= v[k];
+ }
+ return EQ0(r);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_moddiv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_modpow.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_modpow.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_modpow.c (revision 346145)
@@ -0,0 +1,50 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_modpow(uint16_t *x,
+ const unsigned char *e, size_t elen,
+ const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2)
+{
+ size_t mlen;
+ unsigned k;
+
+ mlen = ((m[0] + 31) >> 4) * sizeof m[0];
+ memcpy(t1, x, mlen);
+ br_i15_to_monty(t1, m);
+ br_i15_zero(x, m[0]);
+ x[1] = 1;
+ for (k = 0; k < ((unsigned)elen << 3); k ++) {
+ uint32_t ctl;
+
+ ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1;
+ br_i15_montymul(t2, x, t1, m, m0i);
+ CCOPY(ctl, x, t2, mlen);
+ br_i15_montymul(t2, t1, t1, m, m0i);
+ memcpy(t1, t2, mlen);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_modpow.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_modpow2.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_modpow2.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_modpow2.c (revision 346145)
@@ -0,0 +1,160 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_i15_modpow_opt(uint16_t *x,
+ const unsigned char *e, size_t elen,
+ const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen)
+{
+ size_t mlen, mwlen;
+ uint16_t *t1, *t2, *base;
+ size_t u, v;
+ uint32_t acc;
+ int acc_len, win_len;
+
+ /*
+ * Get modulus size.
+ */
+ mwlen = (m[0] + 31) >> 4;
+ mlen = mwlen * sizeof m[0];
+ mwlen += (mwlen & 1);
+ t1 = tmp;
+ t2 = tmp + mwlen;
+
+ /*
+ * Compute possible window size, with a maximum of 5 bits.
+ * When the window has size 1 bit, we use a specific code
+ * that requires only two temporaries. Otherwise, for a
+ * window of k bits, we need 2^k+1 temporaries.
+ */
+ if (twlen < (mwlen << 1)) {
+ return 0;
+ }
+ for (win_len = 5; win_len > 1; win_len --) {
+ if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) {
+ break;
+ }
+ }
+
+ /*
+ * Everything is done in Montgomery representation.
+ */
+ br_i15_to_monty(x, m);
+
+ /*
+ * Compute window contents. If the window has size one bit only,
+ * then t2 is set to x; otherwise, t2[0] is left untouched, and
+ * t2[k] is set to x^k (for k >= 1).
+ */
+ if (win_len == 1) {
+ memcpy(t2, x, mlen);
+ } else {
+ memcpy(t2 + mwlen, x, mlen);
+ base = t2 + mwlen;
+ for (u = 2; u < ((unsigned)1 << win_len); u ++) {
+ br_i15_montymul(base + mwlen, base, x, m, m0i);
+ base += mwlen;
+ }
+ }
+
+ /*
+ * We need to set x to 1, in Montgomery representation. This can
+ * be done efficiently by setting the high word to 1, then doing
+ * one word-sized shift.
+ */
+ br_i15_zero(x, m[0]);
+ x[(m[0] + 15) >> 4] = 1;
+ br_i15_muladd_small(x, 0, m);
+
+ /*
+ * We process bits from most to least significant. At each
+ * loop iteration, we have acc_len bits in acc.
+ */
+ acc = 0;
+ acc_len = 0;
+ while (acc_len > 0 || elen > 0) {
+ int i, k;
+ uint32_t bits;
+
+ /*
+ * Get the next bits.
+ */
+ k = win_len;
+ if (acc_len < win_len) {
+ if (elen > 0) {
+ acc = (acc << 8) | *e ++;
+ elen --;
+ acc_len += 8;
+ } else {
+ k = acc_len;
+ }
+ }
+ bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1);
+ acc_len -= k;
+
+ /*
+ * We could get exactly k bits. Compute k squarings.
+ */
+ for (i = 0; i < k; i ++) {
+ br_i15_montymul(t1, x, x, m, m0i);
+ memcpy(x, t1, mlen);
+ }
+
+ /*
+ * Window lookup: we want to set t2 to the window
+ * lookup value, assuming the bits are non-zero. If
+ * the window length is 1 bit only, then t2 is
+ * already set; otherwise, we do a constant-time lookup.
+ */
+ if (win_len > 1) {
+ br_i15_zero(t2, m[0]);
+ base = t2 + mwlen;
+ for (u = 1; u < ((uint32_t)1 << k); u ++) {
+ uint32_t mask;
+
+ mask = -EQ(u, bits);
+ for (v = 1; v < mwlen; v ++) {
+ t2[v] |= mask & base[v];
+ }
+ base += mwlen;
+ }
+ }
+
+ /*
+ * Multiply with the looked-up value. We keep the
+ * product only if the exponent bits are not all-zero.
+ */
+ br_i15_montymul(t1, x, t2, m, m0i);
+ CCOPY(NEQ(bits, 0), x, t1, mlen);
+ }
+
+ /*
+ * Convert back from Montgomery representation, and exit.
+ */
+ br_i15_from_monty(x, m, m0i);
+ return 1;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_modpow2.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_montmul.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_montmul.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_montmul.c (revision 346145)
@@ -0,0 +1,184 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
+ const uint16_t *m, uint16_t m0i)
+{
+ size_t len, len4, u, v;
+ uint32_t dh;
+
+ len = (m[0] + 15) >> 4;
+ len4 = len & ~(size_t)3;
+ br_i15_zero(d, m[0]);
+ dh = 0;
+ for (u = 0; u < len; u ++) {
+ uint32_t f, xu, r, zh;
+
+ xu = x[u + 1];
+ f = MUL15((d[1] + MUL15(x[u + 1], y[1])) & 0x7FFF, m0i)
+ & 0x7FFF;
+#if BR_ARMEL_CORTEXM_GCC
+ if (len4 != 0) {
+ uint16_t *limit;
+
+ limit = d + len4;
+ asm volatile (
+"\n\
+ @ carry: r=r2 \n\
+ @ multipliers: xu=r3 f=r4 \n\
+ @ base registers: d+v=r5 y+v=r6 m+v=r7 \n\
+ @ r8 contains 0x7FFF \n\
+ @ r9 contains d+len4 \n\
+ ldr r0, %[limit] \n\
+ ldr r3, %[xu] \n\
+ mov r9, r0 \n\
+ ldr r4, %[f] \n\
+ eor r2, r2 \n\
+ ldr r5, %[d] \n\
+ sub r1, r2, #1 \n\
+ ldr r6, %[y] \n\
+ lsr r1, r1, #17 \n\
+ ldr r7, %[m] \n\
+ mov r8, r1 \n\
+loop%=: \n\
+ ldrh r0, [r6, #2] \n\
+ ldrh r1, [r7, #2] \n\
+ mul r0, r3 \n\
+ mul r1, r4 \n\
+ add r2, r0, r2 \n\
+ ldrh r0, [r5, #2] \n\
+ add r2, r1, r2 \n\
+ mov r1, r8 \n\
+ add r2, r0, r2 \n\
+ and r1, r2 \n\
+ lsr r2, r2, #15 \n\
+ strh r1, [r5, #0] \n\
+ \n\
+ ldrh r0, [r6, #4] \n\
+ ldrh r1, [r7, #4] \n\
+ mul r0, r3 \n\
+ mul r1, r4 \n\
+ add r2, r0, r2 \n\
+ ldrh r0, [r5, #4] \n\
+ add r2, r1, r2 \n\
+ mov r1, r8 \n\
+ add r2, r0, r2 \n\
+ and r1, r2 \n\
+ lsr r2, r2, #15 \n\
+ strh r1, [r5, #2] \n\
+ \n\
+ ldrh r0, [r6, #6] \n\
+ ldrh r1, [r7, #6] \n\
+ mul r0, r3 \n\
+ mul r1, r4 \n\
+ add r2, r0, r2 \n\
+ ldrh r0, [r5, #6] \n\
+ add r2, r1, r2 \n\
+ mov r1, r8 \n\
+ add r2, r0, r2 \n\
+ and r1, r2 \n\
+ lsr r2, r2, #15 \n\
+ strh r1, [r5, #4] \n\
+ \n\
+ ldrh r0, [r6, #8] \n\
+ ldrh r1, [r7, #8] \n\
+ mul r0, r3 \n\
+ mul r1, r4 \n\
+ add r2, r0, r2 \n\
+ ldrh r0, [r5, #8] \n\
+ add r2, r1, r2 \n\
+ mov r1, r8 \n\
+ add r2, r0, r2 \n\
+ and r1, r2 \n\
+ lsr r2, r2, #15 \n\
+ strh r1, [r5, #6] \n\
+ \n\
+ add r5, r5, #8 \n\
+ add r6, r6, #8 \n\
+ add r7, r7, #8 \n\
+ cmp r5, r9 \n\
+ bne loop%= \n\
+ \n\
+ str r2, %[carry] \n\
+"
+: [carry] "=m" (r)
+: [xu] "m" (xu), [f] "m" (f), [d] "m" (d), [y] "m" (y),
+ [m] "m" (m), [limit] "m" (limit)
+: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+ } else {
+ r = 0;
+ }
+ v = len4;
+#else
+ r = 0;
+ for (v = 0; v < len4; v += 4) {
+ uint32_t z;
+
+ z = d[v + 1] + MUL15(xu, y[v + 1])
+ + MUL15(f, m[v + 1]) + r;
+ r = z >> 15;
+ d[v + 0] = z & 0x7FFF;
+ z = d[v + 2] + MUL15(xu, y[v + 2])
+ + MUL15(f, m[v + 2]) + r;
+ r = z >> 15;
+ d[v + 1] = z & 0x7FFF;
+ z = d[v + 3] + MUL15(xu, y[v + 3])
+ + MUL15(f, m[v + 3]) + r;
+ r = z >> 15;
+ d[v + 2] = z & 0x7FFF;
+ z = d[v + 4] + MUL15(xu, y[v + 4])
+ + MUL15(f, m[v + 4]) + r;
+ r = z >> 15;
+ d[v + 3] = z & 0x7FFF;
+ }
+#endif
+ for (; v < len; v ++) {
+ uint32_t z;
+
+ z = d[v + 1] + MUL15(xu, y[v + 1])
+ + MUL15(f, m[v + 1]) + r;
+ r = z >> 15;
+ d[v + 0] = z & 0x7FFF;
+ }
+
+ zh = dh + r;
+ d[len] = zh & 0x7FFF;
+ dh = zh >> 15;
+ }
+
+ /*
+ * Restore the bit length (it was overwritten in the loop above).
+ */
+ d[0] = m[0];
+
+ /*
+ * d[] may be greater than m[], but it is still lower than twice
+ * the modulus.
+ */
+ br_i15_sub(d, m, NEQ(dh, 0) | NOT(br_i15_sub(d, m, 0)));
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_montmul.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_mulacc.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_mulacc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_mulacc.c (revision 346145)
@@ -0,0 +1,61 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b)
+{
+ size_t alen, blen, u;
+ unsigned dl, dh;
+
+ alen = (a[0] + 15) >> 4;
+ blen = (b[0] + 15) >> 4;
+
+ /*
+ * Announced bit length of d[] will be the sum of the announced
+ * bit lengths of a[] and b[]; but the lengths are encoded.
+ */
+ dl = (a[0] & 15) + (b[0] & 15);
+ dh = (a[0] >> 4) + (b[0] >> 4);
+ d[0] = (dh << 4) + dl + (~(uint32_t)(dl - 15) >> 31);
+
+ for (u = 0; u < blen; u ++) {
+ uint32_t f;
+ size_t v;
+ uint32_t cc;
+
+ f = b[1 + u];
+ cc = 0;
+ for (v = 0; v < alen; v ++) {
+ uint32_t z;
+
+ z = (uint32_t)d[1 + u + v] + MUL15(f, a[1 + v]) + cc;
+ cc = z >> 15;
+ d[1 + u + v] = z & 0x7FFF;
+ }
+ d[1 + u + alen] = cc;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_mulacc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_muladd.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_muladd.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_muladd.c (revision 346145)
@@ -0,0 +1,173 @@
+/*
+ * 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"
+
+/*
+ * Constant-time division. The divisor must not be larger than 16 bits,
+ * and the quotient must fit on 17 bits.
+ */
+static uint32_t
+divrem16(uint32_t x, uint32_t d, uint32_t *r)
+{
+ int i;
+ uint32_t q;
+
+ q = 0;
+ d <<= 16;
+ for (i = 16; i >= 0; i --) {
+ uint32_t ctl;
+
+ ctl = LE(d, x);
+ q |= ctl << i;
+ x -= (-ctl) & d;
+ d >>= 1;
+ }
+ if (r != NULL) {
+ *r = x;
+ }
+ return q;
+}
+
+/* see inner.h */
+void
+br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m)
+{
+ /*
+ * Constant-time: we accept to leak the exact bit length of the
+ * modulus m.
+ */
+ unsigned m_bitlen, mblr;
+ size_t u, mlen;
+ uint32_t hi, a0, a, b, q;
+ uint32_t cc, tb, over, under;
+
+ /*
+ * Simple case: the modulus fits on one word.
+ */
+ m_bitlen = m[0];
+ if (m_bitlen == 0) {
+ return;
+ }
+ if (m_bitlen <= 15) {
+ uint32_t rem;
+
+ divrem16(((uint32_t)x[1] << 15) | z, m[1], &rem);
+ x[1] = rem;
+ return;
+ }
+ mlen = (m_bitlen + 15) >> 4;
+ mblr = m_bitlen & 15;
+
+ /*
+ * Principle: we estimate the quotient (x*2^15+z)/m by
+ * doing a 30/15 division with the high words.
+ *
+ * Let:
+ * w = 2^15
+ * a = (w*a0 + a1) * w^N + a2
+ * b = b0 * w^N + b2
+ * such that:
+ * 0 <= a0 < w
+ * 0 <= a1 < w
+ * 0 <= a2 < w^N
+ * w/2 <= b0 < w
+ * 0 <= b2 < w^N
+ * a < w*b
+ * I.e. the two top words of a are a0:a1, the top word of b is
+ * b0, we ensured that b0 is "full" (high bit set), and a is
+ * such that the quotient q = a/b fits on one word (0 <= q < w).
+ *
+ * If a = b*q + r (with 0 <= r < q), then we can estimate q by
+ * using a division on the top words:
+ * a0*w + a1 = b0*u + v (with 0 <= v < b0)
+ * Then the following holds:
+ * 0 <= u <= w
+ * u-2 <= q <= u
+ */
+ hi = x[mlen];
+ if (mblr == 0) {
+ a0 = x[mlen];
+ memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
+ x[1] = z;
+ a = (a0 << 15) + x[mlen];
+ b = m[mlen];
+ } else {
+ a0 = (x[mlen] << (15 - mblr)) | (x[mlen - 1] >> mblr);
+ memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
+ x[1] = z;
+ a = (a0 << 15) | (((x[mlen] << (15 - mblr))
+ | (x[mlen - 1] >> mblr)) & 0x7FFF);
+ b = (m[mlen] << (15 - mblr)) | (m[mlen - 1] >> mblr);
+ }
+ q = divrem16(a, b, NULL);
+
+ /*
+ * We computed an estimate for q, but the real one may be q,
+ * q-1 or q-2; moreover, the division may have returned a value
+ * 8000 or even 8001 if the two high words were identical, and
+ * we want to avoid values beyond 7FFF. We thus adjust q so
+ * that the "true" multiplier will be q+1, q or q-1, and q is
+ * in the 0000..7FFF range.
+ */
+ q = MUX(EQ(b, a0), 0x7FFF, q - 1 + ((q - 1) >> 31));
+
+ /*
+ * We subtract q*m from x (x has an extra high word of value 'hi').
+ * Since q may be off by 1 (in either direction), we may have to
+ * add or subtract m afterwards.
+ *
+ * The 'tb' flag will be true (1) at the end of the loop if the
+ * result is greater than or equal to the modulus (not counting
+ * 'hi' or the carry).
+ */
+ cc = 0;
+ tb = 1;
+ for (u = 1; u <= mlen; u ++) {
+ uint32_t mw, zl, xw, nxw;
+
+ mw = m[u];
+ zl = MUL15(mw, q) + cc;
+ cc = zl >> 15;
+ zl &= 0x7FFF;
+ xw = x[u];
+ nxw = xw - zl;
+ cc += nxw >> 31;
+ nxw &= 0x7FFF;
+ x[u] = nxw;
+ tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw));
+ }
+
+ /*
+ * If we underestimated q, then either cc < hi (one extra bit
+ * beyond the top array word), or cc == hi and tb is true (no
+ * extra bit, but the result is not lower than the modulus).
+ *
+ * If we overestimated q, then cc > hi.
+ */
+ over = GT(cc, hi);
+ under = ~over & (tb | LT(cc, hi));
+ br_i15_add(x, m, over);
+ br_i15_sub(x, m, under);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_muladd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_ninv15.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_ninv15.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_ninv15.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+uint16_t
+br_i15_ninv15(uint16_t x)
+{
+ uint32_t y;
+
+ y = 2 - x;
+ y = MUL15(y, 2 - MUL15(x, y));
+ y = MUL15(y, 2 - MUL15(x, y));
+ y = MUL15(y, 2 - MUL15(x, y));
+ return MUX(x & 1, -y, 0) & 0x7FFF;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_ninv15.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_reduce.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_reduce.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_reduce.c (revision 346145)
@@ -0,0 +1,66 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m)
+{
+ uint32_t m_bitlen, a_bitlen;
+ size_t mlen, alen, u;
+
+ m_bitlen = m[0];
+ mlen = (m_bitlen + 15) >> 4;
+
+ x[0] = m_bitlen;
+ if (m_bitlen == 0) {
+ return;
+ }
+
+ /*
+ * If the source is shorter, then simply copy all words from a[]
+ * and zero out the upper words.
+ */
+ a_bitlen = a[0];
+ alen = (a_bitlen + 15) >> 4;
+ if (a_bitlen < m_bitlen) {
+ memcpy(x + 1, a + 1, alen * sizeof *a);
+ for (u = alen; u < mlen; u ++) {
+ x[u + 1] = 0;
+ }
+ return;
+ }
+
+ /*
+ * The source length is at least equal to that of the modulus.
+ * We must thus copy N-1 words, and input the remaining words
+ * one by one.
+ */
+ memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a);
+ x[mlen] = 0;
+ for (u = 1 + alen - mlen; u > 0; u --) {
+ br_i15_muladd_small(x, a[u], m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_reduce.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_rshift.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_rshift.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_rshift.c (revision 346145)
@@ -0,0 +1,47 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_rshift(uint16_t *x, int count)
+{
+ size_t u, len;
+ unsigned r;
+
+ len = (x[0] + 15) >> 4;
+ if (len == 0) {
+ return;
+ }
+ r = x[1] >> count;
+ for (u = 2; u <= len; u ++) {
+ unsigned w;
+
+ w = x[u];
+ x[u - 1] = ((w << (15 - count)) | r) & 0x7FFF;
+ r = w >> count;
+ }
+ x[len] = r;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_rshift.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_sub.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_sub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_sub.c (revision 346145)
@@ -0,0 +1,46 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl)
+{
+ uint32_t cc;
+ size_t u, m;
+
+ cc = 0;
+ m = (a[0] + 31) >> 4;
+ for (u = 1; u < m; u ++) {
+ uint32_t aw, bw, naw;
+
+ aw = a[u];
+ bw = b[u];
+ naw = aw - bw - cc;
+ cc = naw >> 31;
+ a[u] = MUX(ctl, naw & 0x7FFF, aw);
+ }
+ return cc;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_sub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i15_tmont.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i15_tmont.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i15_tmont.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+/* see inner.h */
+void
+br_i15_to_monty(uint16_t *x, const uint16_t *m)
+{
+ unsigned k;
+
+ for (k = (m[0] + 15) >> 4; k > 0; k --) {
+ br_i15_muladd_small(x, 0, m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i15_tmont.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_add.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_add.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_add.c (revision 346145)
@@ -0,0 +1,46 @@
+/*
+ * 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 */
+uint32_t
+br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl)
+{
+ uint32_t cc;
+ size_t u, m;
+
+ cc = 0;
+ m = (a[0] + 63) >> 5;
+ for (u = 1; u < m; u ++) {
+ uint32_t aw, bw, naw;
+
+ aw = a[u];
+ bw = b[u];
+ naw = aw + bw + cc;
+ cc = naw >> 31;
+ a[u] = MUX(ctl, naw & (uint32_t)0x7FFFFFFF, aw);
+ }
+ return cc;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_add.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_bitlen.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_bitlen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_bitlen.c (revision 346145)
@@ -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 */
+uint32_t
+br_i31_bit_length(uint32_t *x, size_t xlen)
+{
+ uint32_t tw, twk;
+
+ tw = 0;
+ twk = 0;
+ while (xlen -- > 0) {
+ uint32_t w, c;
+
+ c = EQ(tw, 0);
+ w = x[xlen];
+ tw = MUX(c, w, tw);
+ twk = MUX(c, (uint32_t)xlen, twk);
+ }
+ return (twk << 5) + BIT_LENGTH(tw);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_bitlen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_decmod.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_decmod.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_decmod.c (revision 346145)
@@ -0,0 +1,124 @@
+/*
+ * 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 */
+uint32_t
+br_i31_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m)
+{
+ /*
+ * Two-pass algorithm: in the first pass, we determine whether the
+ * value fits; in the second pass, we do the actual write.
+ *
+ * During the first pass, 'r' contains the comparison result so
+ * far:
+ * 0x00000000 value is equal to the modulus
+ * 0x00000001 value is greater than the modulus
+ * 0xFFFFFFFF value is lower than the modulus
+ *
+ * Since we iterate starting with the least significant bytes (at
+ * the end of src[]), each new comparison overrides the previous
+ * except when the comparison yields 0 (equal).
+ *
+ * During the second pass, 'r' is either 0xFFFFFFFF (value fits)
+ * or 0x00000000 (value does not fit).
+ *
+ * We must iterate over all bytes of the source, _and_ possibly
+ * some extra virtual bytes (with value 0) so as to cover the
+ * complete modulus as well. We also add 4 such extra bytes beyond
+ * the modulus length because it then guarantees that no accumulated
+ * partial word remains to be processed.
+ */
+ const unsigned char *buf;
+ size_t mlen, tlen;
+ int pass;
+ uint32_t r;
+
+ buf = src;
+ mlen = (m[0] + 31) >> 5;
+ tlen = (mlen << 2);
+ if (tlen < len) {
+ tlen = len;
+ }
+ tlen += 4;
+ r = 0;
+ for (pass = 0; pass < 2; pass ++) {
+ size_t u, v;
+ uint32_t acc;
+ int acc_len;
+
+ v = 1;
+ acc = 0;
+ acc_len = 0;
+ for (u = 0; u < tlen; u ++) {
+ uint32_t b;
+
+ if (u < len) {
+ b = buf[len - 1 - u];
+ } else {
+ b = 0;
+ }
+ acc |= (b << acc_len);
+ acc_len += 8;
+ if (acc_len >= 31) {
+ uint32_t xw;
+
+ xw = acc & (uint32_t)0x7FFFFFFF;
+ acc_len -= 31;
+ acc = b >> (8 - acc_len);
+ if (v <= mlen) {
+ if (pass) {
+ x[v] = r & xw;
+ } else {
+ uint32_t cc;
+
+ cc = (uint32_t)CMP(xw, m[v]);
+ r = MUX(EQ(cc, 0), r, cc);
+ }
+ } else {
+ if (!pass) {
+ r = MUX(EQ(xw, 0), r, 1);
+ }
+ }
+ v ++;
+ }
+ }
+
+ /*
+ * When we reach this point at the end of the first pass:
+ * r is either 0, 1 or -1; we want to set r to 0 if it
+ * is equal to 0 or 1, and leave it to -1 otherwise.
+ *
+ * When we reach this point at the end of the second pass:
+ * r is either 0 or -1; we want to leave that value
+ * untouched. This is a subcase of the previous.
+ */
+ r >>= 1;
+ r |= (r << 1);
+ }
+
+ x[0] = m[0];
+ return r & (uint32_t)1;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_decmod.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_decode.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_decode.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_decode.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_i31_decode(uint32_t *x, const void *src, size_t len)
+{
+ const unsigned char *buf;
+ size_t u, v;
+ uint32_t acc;
+ int acc_len;
+
+ buf = src;
+ u = len;
+ v = 1;
+ acc = 0;
+ acc_len = 0;
+ while (u -- > 0) {
+ uint32_t b;
+
+ b = buf[u];
+ acc |= (b << acc_len);
+ acc_len += 8;
+ if (acc_len >= 31) {
+ x[v ++] = acc & (uint32_t)0x7FFFFFFF;
+ acc_len -= 31;
+ acc = b >> (8 - acc_len);
+ }
+ }
+ if (acc_len != 0) {
+ x[v ++] = acc;
+ }
+ x[0] = br_i31_bit_length(x + 1, v - 1);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_decode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_decred.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_decred.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_decred.c (revision 346145)
@@ -0,0 +1,103 @@
+/*
+ * 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_i31_decode_reduce(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m)
+{
+ uint32_t m_ebitlen, m_rbitlen;
+ size_t mblen, k;
+ const unsigned char *buf;
+ uint32_t acc;
+ int acc_len;
+
+ /*
+ * Get the encoded bit length.
+ */
+ m_ebitlen = m[0];
+
+ /*
+ * Special case for an invalid (null) modulus.
+ */
+ if (m_ebitlen == 0) {
+ x[0] = 0;
+ return;
+ }
+
+ /*
+ * Clear the destination.
+ */
+ br_i31_zero(x, m_ebitlen);
+
+ /*
+ * First decode directly as many bytes as possible. This requires
+ * computing the actual bit length.
+ */
+ m_rbitlen = m_ebitlen >> 5;
+ m_rbitlen = (m_ebitlen & 31) + (m_rbitlen << 5) - m_rbitlen;
+ mblen = (m_rbitlen + 7) >> 3;
+ k = mblen - 1;
+ if (k >= len) {
+ br_i31_decode(x, src, len);
+ x[0] = m_ebitlen;
+ return;
+ }
+ buf = src;
+ br_i31_decode(x, buf, k);
+ x[0] = m_ebitlen;
+
+ /*
+ * Input remaining bytes, using 31-bit words.
+ */
+ acc = 0;
+ acc_len = 0;
+ while (k < len) {
+ uint32_t v;
+
+ v = buf[k ++];
+ if (acc_len >= 23) {
+ acc_len -= 23;
+ acc <<= (8 - acc_len);
+ acc |= v >> acc_len;
+ br_i31_muladd_small(x, acc, m);
+ acc = v & (0xFF >> (8 - acc_len));
+ } else {
+ acc = (acc << 8) | v;
+ acc_len += 8;
+ }
+ }
+
+ /*
+ * We may have some bits accumulated. We then perform a shift to
+ * be able to inject these bits as a full 31-bit word.
+ */
+ if (acc_len != 0) {
+ acc = (acc | (x[1] << acc_len)) & 0x7FFFFFFF;
+ br_i31_rshift(x, 31 - acc_len);
+ br_i31_muladd_small(x, acc, m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_decred.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_encode.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_encode.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_encode.c (revision 346145)
@@ -0,0 +1,79 @@
+/*
+ * 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_i31_encode(void *dst, size_t len, const uint32_t *x)
+{
+ unsigned char *buf;
+ size_t k, xlen;
+ uint32_t acc;
+ int acc_len;
+
+ xlen = (x[0] + 31) >> 5;
+ if (xlen == 0) {
+ memset(dst, 0, len);
+ return;
+ }
+ buf = (unsigned char *)dst + len;
+ k = 1;
+ acc = 0;
+ acc_len = 0;
+ while (len != 0) {
+ uint32_t w;
+
+ w = (k <= xlen) ? x[k] : 0;
+ k ++;
+ if (acc_len == 0) {
+ acc = w;
+ acc_len = 31;
+ } else {
+ uint32_t z;
+
+ z = acc | (w << acc_len);
+ acc_len --;
+ acc = w >> (31 - acc_len);
+ if (len >= 4) {
+ buf -= 4;
+ len -= 4;
+ br_enc32be(buf, z);
+ } else {
+ switch (len) {
+ case 3:
+ buf[-3] = (unsigned char)(z >> 16);
+ /* fall through */
+ case 2:
+ buf[-2] = (unsigned char)(z >> 8);
+ /* fall through */
+ case 1:
+ buf[-1] = (unsigned char)z;
+ break;
+ }
+ return;
+ }
+ }
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_encode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_fmont.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_fmont.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_fmont.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i)
+{
+ size_t len, u, v;
+
+ len = (m[0] + 31) >> 5;
+ for (u = 0; u < len; u ++) {
+ uint32_t f;
+ uint64_t cc;
+
+ f = MUL31_lo(x[1], m0i);
+ cc = 0;
+ for (v = 0; v < len; v ++) {
+ uint64_t z;
+
+ z = (uint64_t)x[v + 1] + MUL31(f, m[v + 1]) + cc;
+ cc = z >> 31;
+ if (v != 0) {
+ x[v] = (uint32_t)z & 0x7FFFFFFF;
+ }
+ }
+ x[len] = (uint32_t)cc;
+ }
+
+ /*
+ * We may have to do an extra subtraction, but only if the
+ * value in x[] is indeed greater than or equal to that of m[],
+ * which is why we must do two calls (first call computes the
+ * carry, second call performs the subtraction only if the carry
+ * is 0).
+ */
+ br_i31_sub(x, m, NOT(br_i31_sub(x, m, 0)));
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_fmont.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_iszero.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_iszero.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_iszero.c (revision 346145)
@@ -0,0 +1,39 @@
+/*
+ * 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 */
+uint32_t
+br_i31_iszero(const uint32_t *x)
+{
+ uint32_t z;
+ size_t u;
+
+ z = 0;
+ for (u = (x[0] + 31) >> 5; u > 0; u --) {
+ z |= x[u];
+ }
+ return ~(z | -z) >> 31;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_iszero.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_moddiv.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_moddiv.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_moddiv.c (revision 346145)
@@ -0,0 +1,488 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * In this file, we handle big integers with a custom format, i.e.
+ * without the usual one-word header. Value is split into 31-bit words,
+ * each stored in a 32-bit slot (top bit is zero) in little-endian
+ * order. The length (in words) is provided explicitly. In some cases,
+ * the value can be negative (using two's complement representation). In
+ * some cases, the top word is allowed to have a 32th bit.
+ */
+
+/*
+ * Negate big integer conditionally. The value consists of 'len' words,
+ * with 31 bits in each word (the top bit of each word should be 0,
+ * except possibly for the last word). If 'ctl' is 1, the negation is
+ * computed; otherwise, if 'ctl' is 0, then the value is unchanged.
+ */
+static void
+cond_negate(uint32_t *a, size_t len, uint32_t ctl)
+{
+ size_t k;
+ uint32_t cc, xm;
+
+ cc = ctl;
+ xm = -ctl >> 1;
+ for (k = 0; k < len; k ++) {
+ uint32_t aw;
+
+ aw = a[k];
+ aw = (aw ^ xm) + cc;
+ a[k] = aw & 0x7FFFFFFF;
+ cc = aw >> 31;
+ }
+}
+
+/*
+ * Finish modular reduction. Rules on input parameters:
+ *
+ * if neg = 1, then -m <= a < 0
+ * if neg = 0, then 0 <= a < 2*m
+ *
+ * If neg = 0, then the top word of a[] may use 32 bits.
+ *
+ * Also, modulus m must be odd.
+ */
+static void
+finish_mod(uint32_t *a, size_t len, const uint32_t *m, uint32_t neg)
+{
+ size_t k;
+ uint32_t cc, xm, ym;
+
+ /*
+ * First pass: compare a (assumed nonnegative) with m.
+ * Note that if the final word uses the top extra bit, then
+ * subtracting m must yield a value less than 2^31, since we
+ * assumed that a < 2*m.
+ */
+ cc = 0;
+ for (k = 0; k < len; k ++) {
+ uint32_t aw, mw;
+
+ aw = a[k];
+ mw = m[k];
+ cc = (aw - mw - cc) >> 31;
+ }
+
+ /*
+ * At this point:
+ * if neg = 1, then we must add m (regardless of cc)
+ * if neg = 0 and cc = 0, then we must subtract m
+ * if neg = 0 and cc = 1, then we must do nothing
+ */
+ xm = -neg >> 1;
+ ym = -(neg | (1 - cc));
+ cc = neg;
+ for (k = 0; k < len; k ++) {
+ uint32_t aw, mw;
+
+ aw = a[k];
+ mw = (m[k] ^ xm) & ym;
+ aw = aw - mw - cc;
+ a[k] = aw & 0x7FFFFFFF;
+ cc = aw >> 31;
+ }
+}
+
+/*
+ * Compute:
+ * a <- (a*pa+b*pb)/(2^31)
+ * b <- (a*qa+b*qb)/(2^31)
+ * The division is assumed to be exact (i.e. the low word is dropped).
+ * If the final a is negative, then it is negated. Similarly for b.
+ * Returned value is the combination of two bits:
+ * bit 0: 1 if a had to be negated, 0 otherwise
+ * bit 1: 1 if b had to be negated, 0 otherwise
+ *
+ * Factors pa, pb, qa and qb must be at most 2^31 in absolute value.
+ * Source integers a and b must be nonnegative; top word is not allowed
+ * to contain an extra 32th bit.
+ */
+static uint32_t
+co_reduce(uint32_t *a, uint32_t *b, size_t len,
+ int64_t pa, int64_t pb, int64_t qa, int64_t qb)
+{
+ size_t k;
+ int64_t cca, ccb;
+ uint32_t nega, negb;
+
+ cca = 0;
+ ccb = 0;
+ for (k = 0; k < len; k ++) {
+ uint32_t wa, wb;
+ uint64_t za, zb;
+ uint64_t tta, ttb;
+
+ /*
+ * Since:
+ * |pa| <= 2^31
+ * |pb| <= 2^31
+ * 0 <= wa <= 2^31 - 1
+ * 0 <= wb <= 2^31 - 1
+ * |cca| <= 2^32 - 1
+ * Then:
+ * |za| <= (2^31-1)*(2^32) + (2^32-1) = 2^63 - 1
+ *
+ * Thus, the new value of cca is such that |cca| <= 2^32 - 1.
+ * The same applies to ccb.
+ */
+ wa = a[k];
+ wb = b[k];
+ za = wa * (uint64_t)pa + wb * (uint64_t)pb + (uint64_t)cca;
+ zb = wa * (uint64_t)qa + wb * (uint64_t)qb + (uint64_t)ccb;
+ if (k > 0) {
+ a[k - 1] = za & 0x7FFFFFFF;
+ b[k - 1] = zb & 0x7FFFFFFF;
+ }
+
+ /*
+ * For the new values of cca and ccb, we need a signed
+ * right-shift; since, in C, right-shifting a signed
+ * negative value is implementation-defined, we use a
+ * custom portable sign extension expression.
+ */
+#define M ((uint64_t)1 << 32)
+ tta = za >> 31;
+ ttb = zb >> 31;
+ tta = (tta ^ M) - M;
+ ttb = (ttb ^ M) - M;
+ cca = *(int64_t *)&tta;
+ ccb = *(int64_t *)&ttb;
+#undef M
+ }
+ a[len - 1] = (uint32_t)cca;
+ b[len - 1] = (uint32_t)ccb;
+
+ nega = (uint32_t)((uint64_t)cca >> 63);
+ negb = (uint32_t)((uint64_t)ccb >> 63);
+ cond_negate(a, len, nega);
+ cond_negate(b, len, negb);
+ return nega | (negb << 1);
+}
+
+/*
+ * Compute:
+ * a <- (a*pa+b*pb)/(2^31) mod m
+ * b <- (a*qa+b*qb)/(2^31) mod m
+ *
+ * m0i is equal to -1/m[0] mod 2^31.
+ *
+ * Factors pa, pb, qa and qb must be at most 2^31 in absolute value.
+ * Source integers a and b must be nonnegative; top word is not allowed
+ * to contain an extra 32th bit.
+ */
+static void
+co_reduce_mod(uint32_t *a, uint32_t *b, size_t len,
+ int64_t pa, int64_t pb, int64_t qa, int64_t qb,
+ const uint32_t *m, uint32_t m0i)
+{
+ size_t k;
+ int64_t cca, ccb;
+ uint32_t fa, fb;
+
+ cca = 0;
+ ccb = 0;
+ fa = ((a[0] * (uint32_t)pa + b[0] * (uint32_t)pb) * m0i) & 0x7FFFFFFF;
+ fb = ((a[0] * (uint32_t)qa + b[0] * (uint32_t)qb) * m0i) & 0x7FFFFFFF;
+ for (k = 0; k < len; k ++) {
+ uint32_t wa, wb;
+ uint64_t za, zb;
+ uint64_t tta, ttb;
+
+ /*
+ * In this loop, carries 'cca' and 'ccb' always fit on
+ * 33 bits (in absolute value).
+ */
+ wa = a[k];
+ wb = b[k];
+ za = wa * (uint64_t)pa + wb * (uint64_t)pb
+ + m[k] * (uint64_t)fa + (uint64_t)cca;
+ zb = wa * (uint64_t)qa + wb * (uint64_t)qb
+ + m[k] * (uint64_t)fb + (uint64_t)ccb;
+ if (k > 0) {
+ a[k - 1] = (uint32_t)za & 0x7FFFFFFF;
+ b[k - 1] = (uint32_t)zb & 0x7FFFFFFF;
+ }
+
+#define M ((uint64_t)1 << 32)
+ tta = za >> 31;
+ ttb = zb >> 31;
+ tta = (tta ^ M) - M;
+ ttb = (ttb ^ M) - M;
+ cca = *(int64_t *)&tta;
+ ccb = *(int64_t *)&ttb;
+#undef M
+ }
+ a[len - 1] = (uint32_t)cca;
+ b[len - 1] = (uint32_t)ccb;
+
+ /*
+ * At this point:
+ * -m <= a < 2*m
+ * -m <= b < 2*m
+ * (this is a case of Montgomery reduction)
+ * The top word of 'a' and 'b' may have a 32-th bit set.
+ * We may have to add or subtract the modulus.
+ */
+ finish_mod(a, len, m, (uint32_t)((uint64_t)cca >> 63));
+ finish_mod(b, len, m, (uint32_t)((uint64_t)ccb >> 63));
+}
+
+/* see inner.h */
+uint32_t
+br_i31_moddiv(uint32_t *x, const uint32_t *y, const uint32_t *m, uint32_t m0i,
+ uint32_t *t)
+{
+ /*
+ * Algorithm is an extended binary GCD. We maintain four values
+ * a, b, u and v, with the following invariants:
+ *
+ * a * x = y * u mod m
+ * b * x = y * v mod m
+ *
+ * Starting values are:
+ *
+ * a = y
+ * b = m
+ * u = x
+ * v = 0
+ *
+ * The formal definition of the algorithm is a sequence of steps:
+ *
+ * - If a is even, then a <- a/2 and u <- u/2 mod m.
+ * - Otherwise, if b is even, then b <- b/2 and v <- v/2 mod m.
+ * - Otherwise, if a > b, then a <- (a-b)/2 and u <- (u-v)/2 mod m.
+ * - Otherwise, b <- (b-a)/2 and v <- (v-u)/2 mod m.
+ *
+ * Algorithm stops when a = b. At that point, they both are equal
+ * to GCD(y,m); the modular division succeeds if that value is 1.
+ * The result of the modular division is then u (or v: both are
+ * equal at that point).
+ *
+ * Each step makes either a or b shrink by at least one bit; hence,
+ * if m has bit length k bits, then 2k-2 steps are sufficient.
+ *
+ *
+ * Though complexity is quadratic in the size of m, the bit-by-bit
+ * processing is not very efficient. We can speed up processing by
+ * remarking that the decisions are taken based only on observation
+ * of the top and low bits of a and b.
+ *
+ * In the loop below, at each iteration, we use the two top words
+ * of a and b, and the low words of a and b, to compute reduction
+ * parameters pa, pb, qa and qb such that the new values for a
+ * and b are:
+ *
+ * a' = (a*pa + b*pb) / (2^31)
+ * b' = (a*qa + b*qb) / (2^31)
+ *
+ * the division being exact.
+ *
+ * Since the choices are based on the top words, they may be slightly
+ * off, requiring an optional correction: if a' < 0, then we replace
+ * pa with -pa, and pb with -pb. The total length of a and b is
+ * thus reduced by at least 30 bits at each iteration.
+ *
+ * The stopping conditions are still the same, though: when a
+ * and b become equal, they must be both odd (since m is odd,
+ * the GCD cannot be even), therefore the next operation is a
+ * subtraction, and one of the values becomes 0. At that point,
+ * nothing else happens, i.e. one value is stuck at 0, and the
+ * other one is the GCD.
+ */
+ size_t len, k;
+ uint32_t *a, *b, *u, *v;
+ uint32_t num, r;
+
+ len = (m[0] + 31) >> 5;
+ a = t;
+ b = a + len;
+ u = x + 1;
+ v = b + len;
+ memcpy(a, y + 1, len * sizeof *y);
+ memcpy(b, m + 1, len * sizeof *m);
+ memset(v, 0, len * sizeof *v);
+
+ /*
+ * Loop below ensures that a and b are reduced by some bits each,
+ * for a total of at least 30 bits.
+ */
+ for (num = ((m[0] - (m[0] >> 5)) << 1) + 30; num >= 30; num -= 30) {
+ size_t j;
+ uint32_t c0, c1;
+ uint32_t a0, a1, b0, b1;
+ uint64_t a_hi, b_hi;
+ uint32_t a_lo, b_lo;
+ int64_t pa, pb, qa, qb;
+ int i;
+
+ /*
+ * Extract top words of a and b. If j is the highest
+ * index >= 1 such that a[j] != 0 or b[j] != 0, then we want
+ * (a[j] << 31) + a[j - 1], and (b[j] << 31) + b[j - 1].
+ * If a and b are down to one word each, then we use a[0]
+ * and b[0].
+ */
+ c0 = (uint32_t)-1;
+ c1 = (uint32_t)-1;
+ a0 = 0;
+ a1 = 0;
+ b0 = 0;
+ b1 = 0;
+ j = len;
+ while (j -- > 0) {
+ uint32_t aw, bw;
+
+ aw = a[j];
+ bw = b[j];
+ a0 ^= (a0 ^ aw) & c0;
+ a1 ^= (a1 ^ aw) & c1;
+ b0 ^= (b0 ^ bw) & c0;
+ b1 ^= (b1 ^ bw) & c1;
+ c1 = c0;
+ c0 &= (((aw | bw) + 0x7FFFFFFF) >> 31) - (uint32_t)1;
+ }
+
+ /*
+ * If c1 = 0, then we grabbed two words for a and b.
+ * If c1 != 0 but c0 = 0, then we grabbed one word. It
+ * is not possible that c1 != 0 and c0 != 0, because that
+ * would mean that both integers are zero.
+ */
+ a1 |= a0 & c1;
+ a0 &= ~c1;
+ b1 |= b0 & c1;
+ b0 &= ~c1;
+ a_hi = ((uint64_t)a0 << 31) + a1;
+ b_hi = ((uint64_t)b0 << 31) + b1;
+ a_lo = a[0];
+ b_lo = b[0];
+
+ /*
+ * Compute reduction factors:
+ *
+ * a' = a*pa + b*pb
+ * b' = a*qa + b*qb
+ *
+ * such that a' and b' are both multiple of 2^31, but are
+ * only marginally larger than a and b.
+ */
+ pa = 1;
+ pb = 0;
+ qa = 0;
+ qb = 1;
+ for (i = 0; i < 31; i ++) {
+ /*
+ * At each iteration:
+ *
+ * a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi
+ * b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi
+ * a <- a/2 if: a is even
+ * b <- b/2 if: a is odd, b is even
+ *
+ * We multiply a_lo and b_lo by 2 at each
+ * iteration, thus a division by 2 really is a
+ * non-multiplication by 2.
+ */
+ uint32_t r, oa, ob, cAB, cBA, cA;
+ uint64_t rz;
+
+ /*
+ * r = GT(a_hi, b_hi)
+ * But the GT() function works on uint32_t operands,
+ * so we inline a 64-bit version here.
+ */
+ rz = b_hi - a_hi;
+ r = (uint32_t)((rz ^ ((a_hi ^ b_hi)
+ & (a_hi ^ rz))) >> 63);
+
+ /*
+ * cAB = 1 if b must be subtracted from a
+ * cBA = 1 if a must be subtracted from b
+ * cA = 1 if a is divided by 2, 0 otherwise
+ *
+ * Rules:
+ *
+ * cAB and cBA cannot be both 1.
+ * if a is not divided by 2, b is.
+ */
+ oa = (a_lo >> i) & 1;
+ ob = (b_lo >> i) & 1;
+ cAB = oa & ob & r;
+ cBA = oa & ob & NOT(r);
+ cA = cAB | NOT(oa);
+
+ /*
+ * Conditional subtractions.
+ */
+ a_lo -= b_lo & -cAB;
+ a_hi -= b_hi & -(uint64_t)cAB;
+ pa -= qa & -(int64_t)cAB;
+ pb -= qb & -(int64_t)cAB;
+ b_lo -= a_lo & -cBA;
+ b_hi -= a_hi & -(uint64_t)cBA;
+ qa -= pa & -(int64_t)cBA;
+ qb -= pb & -(int64_t)cBA;
+
+ /*
+ * Shifting.
+ */
+ a_lo += a_lo & (cA - 1);
+ pa += pa & ((int64_t)cA - 1);
+ pb += pb & ((int64_t)cA - 1);
+ a_hi ^= (a_hi ^ (a_hi >> 1)) & -(uint64_t)cA;
+ b_lo += b_lo & -cA;
+ qa += qa & -(int64_t)cA;
+ qb += qb & -(int64_t)cA;
+ b_hi ^= (b_hi ^ (b_hi >> 1)) & ((uint64_t)cA - 1);
+ }
+
+ /*
+ * Replace a and b with new values a' and b'.
+ */
+ r = co_reduce(a, b, len, pa, pb, qa, qb);
+ pa -= pa * ((r & 1) << 1);
+ pb -= pb * ((r & 1) << 1);
+ qa -= qa * (r & 2);
+ qb -= qb * (r & 2);
+ co_reduce_mod(u, v, len, pa, pb, qa, qb, m + 1, m0i);
+ }
+
+ /*
+ * Now one of the arrays should be 0, and the other contains
+ * the GCD. If a is 0, then u is 0 as well, and v contains
+ * the division result.
+ * Result is correct if and only if GCD is 1.
+ */
+ r = (a[0] | b[0]) ^ 1;
+ u[0] |= v[0];
+ for (k = 1; k < len; k ++) {
+ r |= a[k] | b[k];
+ u[k] |= v[k];
+ }
+ return EQ0(r);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_moddiv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_modpow.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_modpow.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_modpow.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_i31_modpow(uint32_t *x,
+ const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2)
+{
+ size_t mlen;
+ uint32_t k;
+
+ /*
+ * 'mlen' is the length of m[] expressed in bytes (including
+ * the "bit length" first field).
+ */
+ mlen = ((m[0] + 63) >> 5) * sizeof m[0];
+
+ /*
+ * Throughout the algorithm:
+ * -- t1[] is in Montgomery representation; it contains x, x^2,
+ * x^4, x^8...
+ * -- The result is accumulated, in normal representation, in
+ * the x[] array.
+ * -- t2[] is used as destination buffer for each multiplication.
+ *
+ * Note that there is no need to call br_i32_from_monty().
+ */
+ memcpy(t1, x, mlen);
+ br_i31_to_monty(t1, m);
+ br_i31_zero(x, m[0]);
+ x[1] = 1;
+ for (k = 0; k < ((uint32_t)elen << 3); k ++) {
+ uint32_t ctl;
+
+ ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1;
+ br_i31_montymul(t2, x, t1, m, m0i);
+ CCOPY(ctl, x, t2, mlen);
+ br_i31_montymul(t2, t1, t1, m, m0i);
+ memcpy(t1, t2, mlen);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_modpow.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_modpow2.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_modpow2.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_modpow2.c (revision 346145)
@@ -0,0 +1,160 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_i31_modpow_opt(uint32_t *x,
+ const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen)
+{
+ size_t mlen, mwlen;
+ uint32_t *t1, *t2, *base;
+ size_t u, v;
+ uint32_t acc;
+ int acc_len, win_len;
+
+ /*
+ * Get modulus size.
+ */
+ mwlen = (m[0] + 63) >> 5;
+ mlen = mwlen * sizeof m[0];
+ mwlen += (mwlen & 1);
+ t1 = tmp;
+ t2 = tmp + mwlen;
+
+ /*
+ * Compute possible window size, with a maximum of 5 bits.
+ * When the window has size 1 bit, we use a specific code
+ * that requires only two temporaries. Otherwise, for a
+ * window of k bits, we need 2^k+1 temporaries.
+ */
+ if (twlen < (mwlen << 1)) {
+ return 0;
+ }
+ for (win_len = 5; win_len > 1; win_len --) {
+ if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) {
+ break;
+ }
+ }
+
+ /*
+ * Everything is done in Montgomery representation.
+ */
+ br_i31_to_monty(x, m);
+
+ /*
+ * Compute window contents. If the window has size one bit only,
+ * then t2 is set to x; otherwise, t2[0] is left untouched, and
+ * t2[k] is set to x^k (for k >= 1).
+ */
+ if (win_len == 1) {
+ memcpy(t2, x, mlen);
+ } else {
+ memcpy(t2 + mwlen, x, mlen);
+ base = t2 + mwlen;
+ for (u = 2; u < ((unsigned)1 << win_len); u ++) {
+ br_i31_montymul(base + mwlen, base, x, m, m0i);
+ base += mwlen;
+ }
+ }
+
+ /*
+ * We need to set x to 1, in Montgomery representation. This can
+ * be done efficiently by setting the high word to 1, then doing
+ * one word-sized shift.
+ */
+ br_i31_zero(x, m[0]);
+ x[(m[0] + 31) >> 5] = 1;
+ br_i31_muladd_small(x, 0, m);
+
+ /*
+ * We process bits from most to least significant. At each
+ * loop iteration, we have acc_len bits in acc.
+ */
+ acc = 0;
+ acc_len = 0;
+ while (acc_len > 0 || elen > 0) {
+ int i, k;
+ uint32_t bits;
+
+ /*
+ * Get the next bits.
+ */
+ k = win_len;
+ if (acc_len < win_len) {
+ if (elen > 0) {
+ acc = (acc << 8) | *e ++;
+ elen --;
+ acc_len += 8;
+ } else {
+ k = acc_len;
+ }
+ }
+ bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1);
+ acc_len -= k;
+
+ /*
+ * We could get exactly k bits. Compute k squarings.
+ */
+ for (i = 0; i < k; i ++) {
+ br_i31_montymul(t1, x, x, m, m0i);
+ memcpy(x, t1, mlen);
+ }
+
+ /*
+ * Window lookup: we want to set t2 to the window
+ * lookup value, assuming the bits are non-zero. If
+ * the window length is 1 bit only, then t2 is
+ * already set; otherwise, we do a constant-time lookup.
+ */
+ if (win_len > 1) {
+ br_i31_zero(t2, m[0]);
+ base = t2 + mwlen;
+ for (u = 1; u < ((uint32_t)1 << k); u ++) {
+ uint32_t mask;
+
+ mask = -EQ(u, bits);
+ for (v = 1; v < mwlen; v ++) {
+ t2[v] |= mask & base[v];
+ }
+ base += mwlen;
+ }
+ }
+
+ /*
+ * Multiply with the looked-up value. We keep the
+ * product only if the exponent bits are not all-zero.
+ */
+ br_i31_montymul(t1, x, t2, m, m0i);
+ CCOPY(NEQ(bits, 0), x, t1, mlen);
+ }
+
+ /*
+ * Convert back from Montgomery representation, and exit.
+ */
+ br_i31_from_monty(x, m, m0i);
+ return 1;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_modpow2.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_montmul.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_montmul.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_montmul.c (revision 346145)
@@ -0,0 +1,127 @@
+/*
+ * 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_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
+ const uint32_t *m, uint32_t m0i)
+{
+ /*
+ * Each outer loop iteration computes:
+ * d <- (d + xu*y + f*m) / 2^31
+ * We have xu <= 2^31-1 and f <= 2^31-1.
+ * Thus, if d <= 2*m-1 on input, then:
+ * 2*m-1 + 2*(2^31-1)*m <= (2^32)*m-1
+ * and the new d value is less than 2*m.
+ *
+ * We represent d over 31-bit words, with an extra word 'dh'
+ * which can thus be only 0 or 1.
+ */
+ size_t len, len4, u, v;
+ uint32_t dh;
+
+ len = (m[0] + 31) >> 5;
+ len4 = len & ~(size_t)3;
+ br_i31_zero(d, m[0]);
+ dh = 0;
+ for (u = 0; u < len; u ++) {
+ /*
+ * The carry for each operation fits on 32 bits:
+ * d[v+1] <= 2^31-1
+ * xu*y[v+1] <= (2^31-1)*(2^31-1)
+ * f*m[v+1] <= (2^31-1)*(2^31-1)
+ * r <= 2^32-1
+ * (2^31-1) + 2*(2^31-1)*(2^31-1) + (2^32-1) = 2^63 - 2^31
+ * After division by 2^31, the new r is then at most 2^32-1
+ *
+ * Using a 32-bit carry has performance benefits on 32-bit
+ * systems; however, on 64-bit architectures, we prefer to
+ * keep the carry (r) in a 64-bit register, thus avoiding some
+ * "clear high bits" operations.
+ */
+ uint32_t f, xu;
+#if BR_64
+ uint64_t r;
+#else
+ uint32_t r;
+#endif
+
+ xu = x[u + 1];
+ f = MUL31_lo((d[1] + MUL31_lo(x[u + 1], y[1])), m0i);
+
+ r = 0;
+ for (v = 0; v < len4; v += 4) {
+ uint64_t z;
+
+ z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1])
+ + MUL31(f, m[v + 1]) + r;
+ r = z >> 31;
+ d[v + 0] = (uint32_t)z & 0x7FFFFFFF;
+ z = (uint64_t)d[v + 2] + MUL31(xu, y[v + 2])
+ + MUL31(f, m[v + 2]) + r;
+ r = z >> 31;
+ d[v + 1] = (uint32_t)z & 0x7FFFFFFF;
+ z = (uint64_t)d[v + 3] + MUL31(xu, y[v + 3])
+ + MUL31(f, m[v + 3]) + r;
+ r = z >> 31;
+ d[v + 2] = (uint32_t)z & 0x7FFFFFFF;
+ z = (uint64_t)d[v + 4] + MUL31(xu, y[v + 4])
+ + MUL31(f, m[v + 4]) + r;
+ r = z >> 31;
+ d[v + 3] = (uint32_t)z & 0x7FFFFFFF;
+ }
+ for (; v < len; v ++) {
+ uint64_t z;
+
+ z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1])
+ + MUL31(f, m[v + 1]) + r;
+ r = z >> 31;
+ d[v] = (uint32_t)z & 0x7FFFFFFF;
+ }
+
+ /*
+ * Since the new dh can only be 0 or 1, the addition of
+ * the old dh with the carry MUST fit on 32 bits, and
+ * thus can be done into dh itself.
+ */
+ dh += r;
+ d[len] = dh & 0x7FFFFFFF;
+ dh >>= 31;
+ }
+
+ /*
+ * We must write back the bit length because it was overwritten in
+ * the loop (not overwriting it would require a test in the loop,
+ * which would yield bigger and slower code).
+ */
+ d[0] = m[0];
+
+ /*
+ * d[] may still be greater than m[] at that point; notably, the
+ * 'dh' word may be non-zero.
+ */
+ br_i31_sub(d, m, NEQ(dh, 0) | NOT(br_i31_sub(d, m, 0)));
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_montmul.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_mulacc.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_mulacc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_mulacc.c (revision 346145)
@@ -0,0 +1,74 @@
+/*
+ * 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_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ size_t alen, blen, u;
+ uint32_t dl, dh;
+
+ alen = (a[0] + 31) >> 5;
+ blen = (b[0] + 31) >> 5;
+
+ /*
+ * We want to add the two bit lengths, but these are encoded,
+ * which requires some extra care.
+ */
+ dl = (a[0] & 31) + (b[0] & 31);
+ dh = (a[0] >> 5) + (b[0] >> 5);
+ d[0] = (dh << 5) + dl + (~(uint32_t)(dl - 31) >> 31);
+
+ for (u = 0; u < blen; u ++) {
+ uint32_t f;
+ size_t v;
+
+ /*
+ * Carry always fits on 31 bits; we want to keep it in a
+ * 32-bit register on 32-bit architectures (on a 64-bit
+ * architecture, cast down from 64 to 32 bits means
+ * clearing the high bits, which is not free; on a 32-bit
+ * architecture, the same operation really means ignoring
+ * the top register, which has negative or zero cost).
+ */
+#if BR_64
+ uint64_t cc;
+#else
+ uint32_t cc;
+#endif
+
+ f = b[1 + u];
+ cc = 0;
+ for (v = 0; v < alen; v ++) {
+ uint64_t z;
+
+ z = (uint64_t)d[1 + u + v] + MUL31(f, a[1 + v]) + cc;
+ cc = z >> 31;
+ d[1 + u + v] = (uint32_t)z & 0x7FFFFFFF;
+ }
+ d[1 + u + alen] = (uint32_t)cc;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_mulacc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_muladd.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_muladd.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_muladd.c (revision 346145)
@@ -0,0 +1,157 @@
+/*
+ * 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_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m)
+{
+ uint32_t m_bitlen;
+ unsigned mblr;
+ size_t u, mlen;
+ uint32_t a0, a1, b0, hi, g, q, tb;
+ uint32_t under, over;
+ uint32_t cc;
+
+ /*
+ * We can test on the modulus bit length since we accept to
+ * leak that length.
+ */
+ m_bitlen = m[0];
+ if (m_bitlen == 0) {
+ return;
+ }
+ if (m_bitlen <= 31) {
+ uint32_t lo;
+
+ hi = x[1] >> 1;
+ lo = (x[1] << 31) | z;
+ x[1] = br_rem(hi, lo, m[1]);
+ return;
+ }
+ mlen = (m_bitlen + 31) >> 5;
+ mblr = (unsigned)m_bitlen & 31;
+
+ /*
+ * Principle: we estimate the quotient (x*2^31+z)/m by
+ * doing a 64/32 division with the high words.
+ *
+ * Let:
+ * w = 2^31
+ * a = (w*a0 + a1) * w^N + a2
+ * b = b0 * w^N + b2
+ * such that:
+ * 0 <= a0 < w
+ * 0 <= a1 < w
+ * 0 <= a2 < w^N
+ * w/2 <= b0 < w
+ * 0 <= b2 < w^N
+ * a < w*b
+ * I.e. the two top words of a are a0:a1, the top word of b is
+ * b0, we ensured that b0 is "full" (high bit set), and a is
+ * such that the quotient q = a/b fits on one word (0 <= q < w).
+ *
+ * If a = b*q + r (with 0 <= r < q), we can estimate q by
+ * doing an Euclidean division on the top words:
+ * a0*w+a1 = b0*u + v (with 0 <= v < b0)
+ * Then the following holds:
+ * 0 <= u <= w
+ * u-2 <= q <= u
+ */
+ hi = x[mlen];
+ if (mblr == 0) {
+ a0 = x[mlen];
+ memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
+ x[1] = z;
+ a1 = x[mlen];
+ b0 = m[mlen];
+ } else {
+ a0 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr))
+ & 0x7FFFFFFF;
+ memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
+ x[1] = z;
+ a1 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr))
+ & 0x7FFFFFFF;
+ b0 = ((m[mlen] << (31 - mblr)) | (m[mlen - 1] >> mblr))
+ & 0x7FFFFFFF;
+ }
+
+ /*
+ * We estimate a divisor q. If the quotient returned by br_div()
+ * is g:
+ * -- If a0 == b0 then g == 0; we want q = 0x7FFFFFFF.
+ * -- Otherwise:
+ * -- if g == 0 then we set q = 0;
+ * -- otherwise, we set q = g - 1.
+ * The properties described above then ensure that the true
+ * quotient is q-1, q or q+1.
+ *
+ * Take care that a0, a1 and b0 are 31-bit words, not 32-bit. We
+ * must adjust the parameters to br_div() accordingly.
+ */
+ g = br_div(a0 >> 1, a1 | (a0 << 31), b0);
+ q = MUX(EQ(a0, b0), 0x7FFFFFFF, MUX(EQ(g, 0), 0, g - 1));
+
+ /*
+ * We subtract q*m from x (with the extra high word of value 'hi').
+ * Since q may be off by 1 (in either direction), we may have to
+ * add or subtract m afterwards.
+ *
+ * The 'tb' flag will be true (1) at the end of the loop if the
+ * result is greater than or equal to the modulus (not counting
+ * 'hi' or the carry).
+ */
+ cc = 0;
+ tb = 1;
+ for (u = 1; u <= mlen; u ++) {
+ uint32_t mw, zw, xw, nxw;
+ uint64_t zl;
+
+ mw = m[u];
+ zl = MUL31(mw, q) + cc;
+ cc = (uint32_t)(zl >> 31);
+ zw = (uint32_t)zl & (uint32_t)0x7FFFFFFF;
+ xw = x[u];
+ nxw = xw - zw;
+ cc += nxw >> 31;
+ nxw &= 0x7FFFFFFF;
+ x[u] = nxw;
+ tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw));
+ }
+
+ /*
+ * If we underestimated q, then either cc < hi (one extra bit
+ * beyond the top array word), or cc == hi and tb is true (no
+ * extra bit, but the result is not lower than the modulus). In
+ * these cases we must subtract m once.
+ *
+ * Otherwise, we may have overestimated, which will show as
+ * cc > hi (thus a negative result). Correction is adding m once.
+ */
+ over = GT(cc, hi);
+ under = ~over & (tb | LT(cc, hi));
+ br_i31_add(x, m, over);
+ br_i31_sub(x, m, under);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_muladd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_ninv31.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_ninv31.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_ninv31.c (revision 346145)
@@ -0,0 +1,39 @@
+/*
+ * 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 */
+uint32_t
+br_i31_ninv31(uint32_t x)
+{
+ uint32_t y;
+
+ y = 2 - x;
+ y *= 2 - y * x;
+ y *= 2 - y * x;
+ y *= 2 - y * x;
+ y *= 2 - y * x;
+ return MUX(x & 1, -y, 0) & 0x7FFFFFFF;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_ninv31.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_reduce.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_reduce.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_reduce.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m)
+{
+ uint32_t m_bitlen, a_bitlen;
+ size_t mlen, alen, u;
+
+ m_bitlen = m[0];
+ mlen = (m_bitlen + 31) >> 5;
+
+ x[0] = m_bitlen;
+ if (m_bitlen == 0) {
+ return;
+ }
+
+ /*
+ * If the source is shorter, then simply copy all words from a[]
+ * and zero out the upper words.
+ */
+ a_bitlen = a[0];
+ alen = (a_bitlen + 31) >> 5;
+ if (a_bitlen < m_bitlen) {
+ memcpy(x + 1, a + 1, alen * sizeof *a);
+ for (u = alen; u < mlen; u ++) {
+ x[u + 1] = 0;
+ }
+ return;
+ }
+
+ /*
+ * The source length is at least equal to that of the modulus.
+ * We must thus copy N-1 words, and input the remaining words
+ * one by one.
+ */
+ memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a);
+ x[mlen] = 0;
+ for (u = 1 + alen - mlen; u > 0; u --) {
+ br_i31_muladd_small(x, a[u], m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_reduce.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_rshift.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_rshift.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_rshift.c (revision 346145)
@@ -0,0 +1,47 @@
+/*
+ * 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_i31_rshift(uint32_t *x, int count)
+{
+ size_t u, len;
+ uint32_t r;
+
+ len = (x[0] + 31) >> 5;
+ if (len == 0) {
+ return;
+ }
+ r = x[1] >> count;
+ for (u = 2; u <= len; u ++) {
+ uint32_t w;
+
+ w = x[u];
+ x[u - 1] = ((w << (31 - count)) | r) & 0x7FFFFFFF;
+ r = w >> count;
+ }
+ x[len] = r;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_rshift.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_sub.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_sub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_sub.c (revision 346145)
@@ -0,0 +1,46 @@
+/*
+ * 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 */
+uint32_t
+br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl)
+{
+ uint32_t cc;
+ size_t u, m;
+
+ cc = 0;
+ m = (a[0] + 63) >> 5;
+ for (u = 1; u < m; u ++) {
+ uint32_t aw, bw, naw;
+
+ aw = a[u];
+ bw = b[u];
+ naw = aw - bw - cc;
+ cc = naw >> 31;
+ a[u] = MUX(ctl, naw & 0x7FFFFFFF, aw);
+ }
+ return cc;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_sub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i31_tmont.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i31_tmont.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i31_tmont.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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_i31_to_monty(uint32_t *x, const uint32_t *m)
+{
+ uint32_t k;
+
+ for (k = (m[0] + 31) >> 5; k > 0; k --) {
+ br_i31_muladd_small(x, 0, m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i31_tmont.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_add.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_add.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_add.c (revision 346145)
@@ -0,0 +1,51 @@
+/*
+ * 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 */
+uint32_t
+br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl)
+{
+ uint32_t cc;
+ size_t u, m;
+
+ cc = 0;
+ m = (a[0] + 63) >> 5;
+ for (u = 1; u < m; u ++) {
+ uint32_t aw, bw, naw;
+
+ aw = a[u];
+ bw = b[u];
+ naw = aw + bw + cc;
+
+ /*
+ * Carry is 1 if naw < aw. Carry is also 1 if naw == aw
+ * AND the carry was already 1.
+ */
+ cc = (cc & EQ(naw, aw)) | LT(naw, aw);
+ a[u] = MUX(ctl, naw, aw);
+ }
+ return cc;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_add.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_bitlen.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_bitlen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_bitlen.c (revision 346145)
@@ -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 */
+uint32_t
+br_i32_bit_length(uint32_t *x, size_t xlen)
+{
+ uint32_t tw, twk;
+
+ tw = 0;
+ twk = 0;
+ while (xlen -- > 0) {
+ uint32_t w, c;
+
+ c = EQ(tw, 0);
+ w = x[xlen];
+ tw = MUX(c, w, tw);
+ twk = MUX(c, (uint32_t)xlen, twk);
+ }
+ return (twk << 5) + BIT_LENGTH(tw);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_bitlen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_decmod.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_decmod.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_decmod.c (revision 346145)
@@ -0,0 +1,77 @@
+/*
+ * 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 */
+uint32_t
+br_i32_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m)
+{
+ const unsigned char *buf;
+ uint32_t r;
+ size_t u, v, mlen;
+
+ buf = src;
+
+ /*
+ * First pass: determine whether the value fits. The 'r' value
+ * will contain the comparison result, as 0x00000000 (value is
+ * equal to the modulus), 0x00000001 (value is greater than the
+ * modulus), or 0xFFFFFFFF (value is lower than the modulus).
+ */
+ mlen = (m[0] + 7) >> 3;
+ r = 0;
+ for (u = (mlen > len) ? mlen : len; u > 0; u --) {
+ uint32_t mb, xb;
+
+ v = u - 1;
+ if (v >= mlen) {
+ mb = 0;
+ } else {
+ mb = (m[1 + (v >> 2)] >> ((v & 3) << 3)) & 0xFF;
+ }
+ if (v >= len) {
+ xb = 0;
+ } else {
+ xb = buf[len - u];
+ }
+ r = MUX(EQ(r, 0), (uint32_t)CMP(xb, mb), r);
+ }
+
+ /*
+ * Only r == 0xFFFFFFFF is acceptable. We want to set r to 0xFF if
+ * the value fits, 0x00 otherwise.
+ */
+ r >>= 24;
+ br_i32_zero(x, m[0]);
+ u = (mlen > len) ? len : mlen;
+ while (u > 0) {
+ uint32_t xb;
+
+ xb = buf[len - u] & r;
+ u --;
+ x[1 + (u >> 2)] |= xb << ((u & 3) << 3);
+ }
+ return r >> 7;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_decmod.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_decode.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_decode.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_decode.c (revision 346145)
@@ -0,0 +1,63 @@
+/*
+ * 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_i32_decode(uint32_t *x, const void *src, size_t len)
+{
+ const unsigned char *buf;
+ size_t u, v;
+
+ buf = src;
+ u = len;
+ v = 1;
+ for (;;) {
+ if (u < 4) {
+ uint32_t w;
+
+ if (u < 2) {
+ if (u == 0) {
+ break;
+ } else {
+ w = buf[0];
+ }
+ } else {
+ if (u == 2) {
+ w = br_dec16be(buf);
+ } else {
+ w = ((uint32_t)buf[0] << 16)
+ | br_dec16be(buf + 1);
+ }
+ }
+ x[v ++] = w;
+ break;
+ } else {
+ u -= 4;
+ x[v ++] = br_dec32be(buf + u);
+ }
+ }
+ x[0] = br_i32_bit_length(x + 1, v - 1);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_decode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_decred.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_decred.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_decred.c (revision 346145)
@@ -0,0 +1,107 @@
+/*
+ * 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_i32_decode_reduce(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m)
+{
+ uint32_t m_bitlen;
+ size_t mblen, k, q;
+ const unsigned char *buf;
+
+ m_bitlen = m[0];
+
+ /*
+ * Special case for an invalid modulus.
+ */
+ if (m_bitlen == 0) {
+ x[0] = 0;
+ return;
+ }
+
+ /*
+ * Clear the destination.
+ */
+ br_i32_zero(x, m_bitlen);
+
+ /*
+ * First decode directly as many bytes as possible without
+ * reduction, taking care to leave a number of bytes which
+ * is a multiple of 4.
+ */
+ mblen = (m_bitlen + 7) >> 3;
+ k = mblen - 1;
+
+ /*
+ * Up to k bytes can be safely decoded.
+ */
+ if (k >= len) {
+ br_i32_decode(x, src, len);
+ x[0] = m_bitlen;
+ return;
+ }
+
+ /*
+ * We want to first inject some bytes with direct decoding,
+ * then extra bytes by whole 32-bit words. First compute
+ * the size that should be injected that way.
+ */
+ buf = src;
+ q = (len - k + 3) & ~(size_t)3;
+
+ /*
+ * It may happen that this is more than what we already have
+ * (by at most 3 bytes). Such a case may happen only with
+ * a very short modulus. In that case, we must process the first
+ * bytes "manually".
+ */
+ if (q > len) {
+ int i;
+ uint32_t w;
+
+ w = 0;
+ for (i = 0; i < 4; i ++) {
+ w <<= 8;
+ if (q <= len) {
+ w |= buf[len - q];
+ }
+ q --;
+ }
+ br_i32_muladd_small(x, w, m);
+ } else {
+ br_i32_decode(x, buf, len - q);
+ x[0] = m_bitlen;
+ }
+
+ /*
+ * At that point, we have exactly q bytes to inject, and q is
+ * a multiple of 4.
+ */
+ for (k = len - q; k < len; k += 4) {
+ br_i32_muladd_small(x, br_dec32be(buf + k), m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_decred.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_div32.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_div32.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_div32.c (revision 346145)
@@ -0,0 +1,56 @@
+/*
+ * 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 */
+uint32_t
+br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r)
+{
+ /* TODO: optimize this */
+ uint32_t q;
+ uint32_t ch, cf;
+ int k;
+
+ q = 0;
+ ch = EQ(hi, d);
+ hi = MUX(ch, 0, hi);
+ for (k = 31; k > 0; k --) {
+ int j;
+ uint32_t w, ctl, hi2, lo2;
+
+ j = 32 - k;
+ w = (hi << j) | (lo >> k);
+ ctl = GE(w, d) | (hi >> k);
+ hi2 = (w - d) >> j;
+ lo2 = lo - (d << k);
+ hi = MUX(ctl, hi2, hi);
+ lo = MUX(ctl, lo2, lo);
+ q |= ctl << k;
+ }
+ cf = GE(lo, d) | hi;
+ q |= cf;
+ *r = MUX(cf, lo - d, lo);
+ return q;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_div32.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_encode.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_encode.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_encode.c (revision 346145)
@@ -0,0 +1,72 @@
+/*
+ * 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_i32_encode(void *dst, size_t len, const uint32_t *x)
+{
+ unsigned char *buf;
+ size_t k;
+
+ buf = dst;
+
+ /*
+ * Compute the announced size of x in bytes; extra bytes are
+ * filled with zeros.
+ */
+ k = (x[0] + 7) >> 3;
+ while (len > k) {
+ *buf ++ = 0;
+ len --;
+ }
+
+ /*
+ * Now we use k as index within x[]. That index starts at 1;
+ * we initialize it to the topmost complete word, and process
+ * any remaining incomplete word.
+ */
+ k = (len + 3) >> 2;
+ switch (len & 3) {
+ case 3:
+ *buf ++ = x[k] >> 16;
+ /* fall through */
+ case 2:
+ *buf ++ = x[k] >> 8;
+ /* fall through */
+ case 1:
+ *buf ++ = x[k];
+ k --;
+ }
+
+ /*
+ * Encode all complete words.
+ */
+ while (k > 0) {
+ br_enc32be(buf, x[k]);
+ k --;
+ buf += 4;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_encode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_fmont.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_fmont.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_fmont.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i)
+{
+ size_t len, u, v;
+
+ len = (m[0] + 31) >> 5;
+ for (u = 0; u < len; u ++) {
+ uint32_t f;
+ uint64_t cc;
+
+ f = x[1] * m0i;
+ cc = 0;
+ for (v = 0; v < len; v ++) {
+ uint64_t z;
+
+ z = (uint64_t)x[v + 1] + MUL(f, m[v + 1]) + cc;
+ cc = z >> 32;
+ if (v != 0) {
+ x[v] = (uint32_t)z;
+ }
+ }
+ x[len] = (uint32_t)cc;
+ }
+
+ /*
+ * We may have to do an extra subtraction, but only if the
+ * value in x[] is indeed greater than or equal to that of m[],
+ * which is why we must do two calls (first call computes the
+ * carry, second call performs the subtraction only if the carry
+ * is 0).
+ */
+ br_i32_sub(x, m, NOT(br_i32_sub(x, m, 0)));
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_fmont.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_iszero.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_iszero.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_iszero.c (revision 346145)
@@ -0,0 +1,39 @@
+/*
+ * 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 */
+uint32_t
+br_i32_iszero(const uint32_t *x)
+{
+ uint32_t z;
+ size_t u;
+
+ z = 0;
+ for (u = (x[0] + 31) >> 5; u > 0; u --) {
+ z |= x[u];
+ }
+ return ~(z | -z) >> 31;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_iszero.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_modpow.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_modpow.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_modpow.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_i32_modpow(uint32_t *x,
+ const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2)
+{
+ size_t mlen;
+ uint32_t k;
+
+ /*
+ * 'mlen' is the length of m[] expressed in bytes (including
+ * the "bit length" first field).
+ */
+ mlen = ((m[0] + 63) >> 5) * sizeof m[0];
+
+ /*
+ * Throughout the algorithm:
+ * -- t1[] is in Montgomery representation; it contains x, x^2,
+ * x^4, x^8...
+ * -- The result is accumulated, in normal representation, in
+ * the x[] array.
+ * -- t2[] is used as destination buffer for each multiplication.
+ *
+ * Note that there is no need to call br_i32_from_monty().
+ */
+ memcpy(t1, x, mlen);
+ br_i32_to_monty(t1, m);
+ br_i32_zero(x, m[0]);
+ x[1] = 1;
+ for (k = 0; k < ((uint32_t)elen << 3); k ++) {
+ uint32_t ctl;
+
+ ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1;
+ br_i32_montymul(t2, x, t1, m, m0i);
+ CCOPY(ctl, x, t2, mlen);
+ br_i32_montymul(t2, t1, t1, m, m0i);
+ memcpy(t1, t2, mlen);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_modpow.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_montmul.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_montmul.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_montmul.c (revision 346145)
@@ -0,0 +1,69 @@
+/*
+ * 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_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
+ const uint32_t *m, uint32_t m0i)
+{
+ size_t len, u, v;
+ uint64_t dh;
+
+ len = (m[0] + 31) >> 5;
+ br_i32_zero(d, m[0]);
+ dh = 0;
+ for (u = 0; u < len; u ++) {
+ uint32_t f, xu;
+ uint64_t r1, r2, zh;
+
+ xu = x[u + 1];
+ f = (d[1] + x[u + 1] * y[1]) * m0i;
+ r1 = 0;
+ r2 = 0;
+ for (v = 0; v < len; v ++) {
+ uint64_t z;
+ uint32_t t;
+
+ z = (uint64_t)d[v + 1] + MUL(xu, y[v + 1]) + r1;
+ r1 = z >> 32;
+ t = (uint32_t)z;
+ z = (uint64_t)t + MUL(f, m[v + 1]) + r2;
+ r2 = z >> 32;
+ if (v != 0) {
+ d[v] = (uint32_t)z;
+ }
+ }
+ zh = dh + r1 + r2;
+ d[len] = (uint32_t)zh;
+ dh = zh >> 32;
+ }
+
+ /*
+ * d[] may still be greater than m[] at that point; notably, the
+ * 'dh' word may be non-zero.
+ */
+ br_i32_sub(d, m, NEQ(dh, 0) | NOT(br_i32_sub(d, m, 0)));
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_montmul.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_mulacc.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_mulacc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_mulacc.c (revision 346145)
@@ -0,0 +1,56 @@
+/*
+ * 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_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b)
+{
+ size_t alen, blen, u;
+
+ alen = (a[0] + 31) >> 5;
+ blen = (b[0] + 31) >> 5;
+ d[0] = a[0] + b[0];
+ for (u = 0; u < blen; u ++) {
+ uint32_t f;
+ size_t v;
+#if BR_64
+ uint64_t cc;
+#else
+ uint32_t cc;
+#endif
+
+ f = b[1 + u];
+ cc = 0;
+ for (v = 0; v < alen; v ++) {
+ uint64_t z;
+
+ z = (uint64_t)d[1 + u + v] + MUL(f, a[1 + v]) + cc;
+ cc = z >> 32;
+ d[1 + u + v] = (uint32_t)z;
+ }
+ d[1 + u + alen] = (uint32_t)cc;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_mulacc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_muladd.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_muladd.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_muladd.c (revision 346145)
@@ -0,0 +1,138 @@
+/*
+ * 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_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m)
+{
+ uint32_t m_bitlen;
+ size_t u, mlen;
+ uint32_t a0, a1, b0, hi, g, q, tb;
+ uint32_t chf, clow, under, over;
+ uint64_t cc;
+
+ /*
+ * We can test on the modulus bit length since we accept to
+ * leak that length.
+ */
+ m_bitlen = m[0];
+ if (m_bitlen == 0) {
+ return;
+ }
+ if (m_bitlen <= 32) {
+ x[1] = br_rem(x[1], z, m[1]);
+ return;
+ }
+ mlen = (m_bitlen + 31) >> 5;
+
+ /*
+ * Principle: we estimate the quotient (x*2^32+z)/m by
+ * doing a 64/32 division with the high words.
+ *
+ * Let:
+ * w = 2^32
+ * a = (w*a0 + a1) * w^N + a2
+ * b = b0 * w^N + b2
+ * such that:
+ * 0 <= a0 < w
+ * 0 <= a1 < w
+ * 0 <= a2 < w^N
+ * w/2 <= b0 < w
+ * 0 <= b2 < w^N
+ * a < w*b
+ * I.e. the two top words of a are a0:a1, the top word of b is
+ * b0, we ensured that b0 is "full" (high bit set), and a is
+ * such that the quotient q = a/b fits on one word (0 <= q < w).
+ *
+ * If a = b*q + r (with 0 <= r < q), we can estimate q by
+ * doing an Euclidean division on the top words:
+ * a0*w+a1 = b0*u + v (with 0 <= v < w)
+ * Then the following holds:
+ * 0 <= u <= w
+ * u-2 <= q <= u
+ */
+ a0 = br_i32_word(x, m_bitlen - 32);
+ hi = x[mlen];
+ memmove(x + 2, x + 1, (mlen - 1) * sizeof *x);
+ x[1] = z;
+ a1 = br_i32_word(x, m_bitlen - 32);
+ b0 = br_i32_word(m, m_bitlen - 32);
+
+ /*
+ * We estimate a divisor q. If the quotient returned by br_div()
+ * is g:
+ * -- If a0 == b0 then g == 0; we want q = 0xFFFFFFFF.
+ * -- Otherwise:
+ * -- if g == 0 then we set q = 0;
+ * -- otherwise, we set q = g - 1.
+ * The properties described above then ensure that the true
+ * quotient is q-1, q or q+1.
+ */
+ g = br_div(a0, a1, b0);
+ q = MUX(EQ(a0, b0), 0xFFFFFFFF, MUX(EQ(g, 0), 0, g - 1));
+
+ /*
+ * We subtract q*m from x (with the extra high word of value 'hi').
+ * Since q may be off by 1 (in either direction), we may have to
+ * add or subtract m afterwards.
+ *
+ * The 'tb' flag will be true (1) at the end of the loop if the
+ * result is greater than or equal to the modulus (not counting
+ * 'hi' or the carry).
+ */
+ cc = 0;
+ tb = 1;
+ for (u = 1; u <= mlen; u ++) {
+ uint32_t mw, zw, xw, nxw;
+ uint64_t zl;
+
+ mw = m[u];
+ zl = MUL(mw, q) + cc;
+ cc = (uint32_t)(zl >> 32);
+ zw = (uint32_t)zl;
+ xw = x[u];
+ nxw = xw - zw;
+ cc += (uint64_t)GT(nxw, xw);
+ x[u] = nxw;
+ tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw));
+ }
+
+ /*
+ * If we underestimated q, then either cc < hi (one extra bit
+ * beyond the top array word), or cc == hi and tb is true (no
+ * extra bit, but the result is not lower than the modulus). In
+ * these cases we must subtract m once.
+ *
+ * Otherwise, we may have overestimated, which will show as
+ * cc > hi (thus a negative result). Correction is adding m once.
+ */
+ chf = (uint32_t)(cc >> 32);
+ clow = (uint32_t)cc;
+ over = chf | GT(clow, hi);
+ under = ~over & (tb | (~chf & LT(clow, hi)));
+ br_i32_add(x, m, over);
+ br_i32_sub(x, m, under);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_muladd.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_ninv32.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_ninv32.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_ninv32.c (revision 346145)
@@ -0,0 +1,39 @@
+/*
+ * 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 */
+uint32_t
+br_i32_ninv32(uint32_t x)
+{
+ uint32_t y;
+
+ y = 2 - x;
+ y *= 2 - y * x;
+ y *= 2 - y * x;
+ y *= 2 - y * x;
+ y *= 2 - y * x;
+ return MUX(x & 1, -y, 0);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_ninv32.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_reduce.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_reduce.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_reduce.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m)
+{
+ uint32_t m_bitlen, a_bitlen;
+ size_t mlen, alen, u;
+
+ m_bitlen = m[0];
+ mlen = (m_bitlen + 31) >> 5;
+
+ x[0] = m_bitlen;
+ if (m_bitlen == 0) {
+ return;
+ }
+
+ /*
+ * If the source is shorter, then simply copy all words from a[]
+ * and zero out the upper words.
+ */
+ a_bitlen = a[0];
+ alen = (a_bitlen + 31) >> 5;
+ if (a_bitlen < m_bitlen) {
+ memcpy(x + 1, a + 1, alen * sizeof *a);
+ for (u = alen; u < mlen; u ++) {
+ x[u + 1] = 0;
+ }
+ return;
+ }
+
+ /*
+ * The source length is at least equal to that of the modulus.
+ * We must thus copy N-1 words, and input the remaining words
+ * one by one.
+ */
+ memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a);
+ x[mlen] = 0;
+ for (u = 1 + alen - mlen; u > 0; u --) {
+ br_i32_muladd_small(x, a[u], m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_reduce.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_sub.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_sub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_sub.c (revision 346145)
@@ -0,0 +1,51 @@
+/*
+ * 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 */
+uint32_t
+br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl)
+{
+ uint32_t cc;
+ size_t u, m;
+
+ cc = 0;
+ m = (a[0] + 63) >> 5;
+ for (u = 1; u < m; u ++) {
+ uint32_t aw, bw, naw;
+
+ aw = a[u];
+ bw = b[u];
+ naw = aw - bw - cc;
+
+ /*
+ * Carry is 1 if naw > aw. Carry is 1 also if naw == aw
+ * AND the carry was already 1.
+ */
+ cc = (cc & EQ(naw, aw)) | GT(naw, aw);
+ a[u] = MUX(ctl, naw, aw);
+ }
+ return cc;
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_sub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i32_tmont.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i32_tmont.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i32_tmont.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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_i32_to_monty(uint32_t *x, const uint32_t *m)
+{
+ uint32_t k;
+
+ for (k = (m[0] + 31) >> 5; k > 0; k --) {
+ br_i32_muladd_small(x, 0, m);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/int/i32_tmont.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/int/i62_modpow2.c
===================================================================
--- stable/12/contrib/bearssl/src/int/i62_modpow2.c (nonexistent)
+++ stable/12/contrib/bearssl/src/int/i62_modpow2.c (revision 346145)
@@ -0,0 +1,493 @@
+/*
+ * 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"
+
+#if BR_INT128 || BR_UMUL128
+
+#if BR_INT128
+
+/*
+ * Compute x*y+v1+v2. Operands are 64-bit, and result is 128-bit, with
+ * high word in "hi" and low word in "lo".
+ */
+#define FMA1(hi, lo, x, y, v1, v2) do { \
+ unsigned __int128 fmaz; \
+ fmaz = (unsigned __int128)(x) * (unsigned __int128)(y) \
+ + (unsigned __int128)(v1) + (unsigned __int128)(v2); \
+ (hi) = (uint64_t)(fmaz >> 64); \
+ (lo) = (uint64_t)fmaz; \
+ } while (0)
+
+/*
+ * Compute x1*y1+x2*y2+v1+v2. Operands are 64-bit, and result is 128-bit,
+ * with high word in "hi" and low word in "lo".
+ *
+ * Callers should ensure that the two inner products, and the v1 and v2
+ * operands, are multiple of 4 (this is not used by this specific definition
+ * but may help other implementations).
+ */
+#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \
+ unsigned __int128 fmaz; \
+ fmaz = (unsigned __int128)(x1) * (unsigned __int128)(y1) \
+ + (unsigned __int128)(x2) * (unsigned __int128)(y2) \
+ + (unsigned __int128)(v1) + (unsigned __int128)(v2); \
+ (hi) = (uint64_t)(fmaz >> 64); \
+ (lo) = (uint64_t)fmaz; \
+ } while (0)
+
+#elif BR_UMUL128
+
+#include <intrin.h>
+
+#define FMA1(hi, lo, x, y, v1, v2) do { \
+ uint64_t fmahi, fmalo; \
+ unsigned char fmacc; \
+ fmalo = _umul128((x), (y), &fmahi); \
+ fmacc = _addcarry_u64(0, fmalo, (v1), &fmalo); \
+ _addcarry_u64(fmacc, fmahi, 0, &fmahi); \
+ fmacc = _addcarry_u64(0, fmalo, (v2), &(lo)); \
+ _addcarry_u64(fmacc, fmahi, 0, &(hi)); \
+ } while (0)
+
+/*
+ * Normally we should use _addcarry_u64() for FMA2 too, but it makes
+ * Visual Studio crash. Instead we use this version, which leverages
+ * the fact that the vx operands, and the products, are multiple of 4.
+ * This is unfortunately slower.
+ */
+#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \
+ uint64_t fma1hi, fma1lo; \
+ uint64_t fma2hi, fma2lo; \
+ uint64_t fmatt; \
+ fma1lo = _umul128((x1), (y1), &fma1hi); \
+ fma2lo = _umul128((x2), (y2), &fma2hi); \
+ fmatt = (fma1lo >> 2) + (fma2lo >> 2) \
+ + ((v1) >> 2) + ((v2) >> 2); \
+ (lo) = fmatt << 2; \
+ (hi) = fma1hi + fma2hi + (fmatt >> 62); \
+ } while (0)
+
+/*
+ * The FMA2 macro definition we would prefer to use, but it triggers
+ * an internal compiler error in Visual Studio 2015.
+ *
+#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \
+ uint64_t fma1hi, fma1lo; \
+ uint64_t fma2hi, fma2lo; \
+ unsigned char fmacc; \
+ fma1lo = _umul128((x1), (y1), &fma1hi); \
+ fma2lo = _umul128((x2), (y2), &fma2hi); \
+ fmacc = _addcarry_u64(0, fma1lo, (v1), &fma1lo); \
+ _addcarry_u64(fmacc, fma1hi, 0, &fma1hi); \
+ fmacc = _addcarry_u64(0, fma2lo, (v2), &fma2lo); \
+ _addcarry_u64(fmacc, fma2hi, 0, &fma2hi); \
+ fmacc = _addcarry_u64(0, fma1lo, fma2lo, &(lo)); \
+ _addcarry_u64(fmacc, fma1hi, fma2hi, &(hi)); \
+ } while (0)
+ */
+
+#endif
+
+#define MASK62 ((uint64_t)0x3FFFFFFFFFFFFFFF)
+#define MUL62_lo(x, y) (((uint64_t)(x) * (uint64_t)(y)) & MASK62)
+
+/*
+ * Subtract b from a, and return the final carry. If 'ctl32' is 0, then
+ * a[] is kept unmodified, but the final carry is still computed and
+ * returned.
+ */
+static uint32_t
+i62_sub(uint64_t *a, const uint64_t *b, size_t num, uint32_t ctl32)
+{
+ uint64_t cc, mask;
+ size_t u;
+
+ cc = 0;
+ ctl32 = -ctl32;
+ mask = (uint64_t)ctl32 | ((uint64_t)ctl32 << 32);
+ for (u = 0; u < num; u ++) {
+ uint64_t aw, bw, dw;
+
+ aw = a[u];
+ bw = b[u];
+ dw = aw - bw - cc;
+ cc = dw >> 63;
+ dw &= MASK62;
+ a[u] = aw ^ (mask & (dw ^ aw));
+ }
+ return (uint32_t)cc;
+}
+
+/*
+ * Montgomery multiplication, over arrays of 62-bit values. The
+ * destination array (d) must be distinct from the other operands
+ * (x, y and m). All arrays are in little-endian format (least
+ * significant word comes first) over 'num' words.
+ */
+static void
+montymul(uint64_t *d, const uint64_t *x, const uint64_t *y,
+ const uint64_t *m, size_t num, uint64_t m0i)
+{
+ uint64_t dh;
+ size_t u, num4;
+
+ num4 = 1 + ((num - 1) & ~(size_t)3);
+ memset(d, 0, num * sizeof *d);
+ dh = 0;
+ for (u = 0; u < num; u ++) {
+ size_t v;
+ uint64_t f, xu;
+ uint64_t r, zh;
+ uint64_t hi, lo;
+
+ xu = x[u] << 2;
+ f = MUL62_lo(d[0] + MUL62_lo(x[u], y[0]), m0i) << 2;
+
+ FMA2(hi, lo, xu, y[0], f, m[0], d[0] << 2, 0);
+ r = hi;
+
+ for (v = 1; v < num4; v += 4) {
+ FMA2(hi, lo, xu, y[v + 0],
+ f, m[v + 0], d[v + 0] << 2, r << 2);
+ r = hi + (r >> 62);
+ d[v - 1] = lo >> 2;
+ FMA2(hi, lo, xu, y[v + 1],
+ f, m[v + 1], d[v + 1] << 2, r << 2);
+ r = hi + (r >> 62);
+ d[v + 0] = lo >> 2;
+ FMA2(hi, lo, xu, y[v + 2],
+ f, m[v + 2], d[v + 2] << 2, r << 2);
+ r = hi + (r >> 62);
+ d[v + 1] = lo >> 2;
+ FMA2(hi, lo, xu, y[v + 3],
+ f, m[v + 3], d[v + 3] << 2, r << 2);
+ r = hi + (r >> 62);
+ d[v + 2] = lo >> 2;
+ }
+ for (; v < num; v ++) {
+ FMA2(hi, lo, xu, y[v], f, m[v], d[v] << 2, r << 2);
+ r = hi + (r >> 62);
+ d[v - 1] = lo >> 2;
+ }
+
+ zh = dh + r;
+ d[num - 1] = zh & MASK62;
+ dh = zh >> 62;
+ }
+ i62_sub(d, m, num, (uint32_t)dh | NOT(i62_sub(d, m, num, 0)));
+}
+
+/*
+ * Conversion back from Montgomery representation.
+ */
+static void
+frommonty(uint64_t *x, const uint64_t *m, size_t num, uint64_t m0i)
+{
+ size_t u, v;
+
+ for (u = 0; u < num; u ++) {
+ uint64_t f, cc;
+
+ f = MUL62_lo(x[0], m0i) << 2;
+ cc = 0;
+ for (v = 0; v < num; v ++) {
+ uint64_t hi, lo;
+
+ FMA1(hi, lo, f, m[v], x[v] << 2, cc);
+ cc = hi << 2;
+ if (v != 0) {
+ x[v - 1] = lo >> 2;
+ }
+ }
+ x[num - 1] = cc >> 2;
+ }
+ i62_sub(x, m, num, NOT(i62_sub(x, m, num, 0)));
+}
+
+/* see inner.h */
+uint32_t
+br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen,
+ const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen)
+{
+ size_t u, mw31num, mw62num;
+ uint64_t *x, *m, *t1, *t2;
+ uint64_t m0i;
+ uint32_t acc;
+ int win_len, acc_len;
+
+ /*
+ * Get modulus size, in words.
+ */
+ mw31num = (m31[0] + 31) >> 5;
+ mw62num = (mw31num + 1) >> 1;
+
+ /*
+ * In order to apply this function, we must have enough room to
+ * copy the operand and modulus into the temporary array, along
+ * with at least two temporaries. If there is not enough room,
+ * switch to br_i31_modpow(). We also use br_i31_modpow() if the
+ * modulus length is not at least four words (94 bits or more).
+ */
+ if (mw31num < 4 || (mw62num << 2) > twlen) {
+ /*
+ * We assume here that we can split an aligned uint64_t
+ * into two properly aligned uint32_t. Since both types
+ * are supposed to have an exact width with no padding,
+ * then this property must hold.
+ */
+ size_t txlen;
+
+ txlen = mw31num + 1;
+ if (twlen < txlen) {
+ return 0;
+ }
+ br_i31_modpow(x31, e, elen, m31, m0i31,
+ (uint32_t *)tmp, (uint32_t *)tmp + txlen);
+ return 1;
+ }
+
+ /*
+ * Convert x to Montgomery representation: this means that
+ * we replace x with x*2^z mod m, where z is the smallest multiple
+ * of the word size such that 2^z >= m. We want to reuse the 31-bit
+ * functions here (for constant-time operation), but we need z
+ * for a 62-bit word size.
+ */
+ for (u = 0; u < mw62num; u ++) {
+ br_i31_muladd_small(x31, 0, m31);
+ br_i31_muladd_small(x31, 0, m31);
+ }
+
+ /*
+ * Assemble operands into arrays of 62-bit words. Note that
+ * all the arrays of 62-bit words that we will handle here
+ * are without any leading size word.
+ *
+ * We also adjust tmp and twlen to account for the words used
+ * for these extra arrays.
+ */
+ m = tmp;
+ x = tmp + mw62num;
+ tmp += (mw62num << 1);
+ twlen -= (mw62num << 1);
+ for (u = 0; u < mw31num; u += 2) {
+ size_t v;
+
+ v = u >> 1;
+ if ((u + 1) == mw31num) {
+ m[v] = (uint64_t)m31[u + 1];
+ x[v] = (uint64_t)x31[u + 1];
+ } else {
+ m[v] = (uint64_t)m31[u + 1]
+ + ((uint64_t)m31[u + 2] << 31);
+ x[v] = (uint64_t)x31[u + 1]
+ + ((uint64_t)x31[u + 2] << 31);
+ }
+ }
+
+ /*
+ * Compute window size. We support windows up to 5 bits; for a
+ * window of size k bits, we need 2^k+1 temporaries (for k = 1,
+ * we use special code that uses only 2 temporaries).
+ */
+ for (win_len = 5; win_len > 1; win_len --) {
+ if ((((uint32_t)1 << win_len) + 1) * mw62num <= twlen) {
+ break;
+ }
+ }
+
+ t1 = tmp;
+ t2 = tmp + mw62num;
+
+ /*
+ * Compute m0i, which is equal to -(1/m0) mod 2^62. We were
+ * provided with m0i31, which already fulfills this property
+ * modulo 2^31; the single expression below is then sufficient.
+ */
+ m0i = (uint64_t)m0i31;
+ m0i = MUL62_lo(m0i, (uint64_t)2 + MUL62_lo(m0i, m[0]));
+
+ /*
+ * Compute window contents. If the window has size one bit only,
+ * then t2 is set to x; otherwise, t2[0] is left untouched, and
+ * t2[k] is set to x^k (for k >= 1).
+ */
+ if (win_len == 1) {
+ memcpy(t2, x, mw62num * sizeof *x);
+ } else {
+ uint64_t *base;
+
+ memcpy(t2 + mw62num, x, mw62num * sizeof *x);
+ base = t2 + mw62num;
+ for (u = 2; u < ((unsigned)1 << win_len); u ++) {
+ montymul(base + mw62num, base, x, m, mw62num, m0i);
+ base += mw62num;
+ }
+ }
+
+ /*
+ * Set x to 1, in Montgomery representation. We again use the
+ * 31-bit code.
+ */
+ br_i31_zero(x31, m31[0]);
+ x31[(m31[0] + 31) >> 5] = 1;
+ br_i31_muladd_small(x31, 0, m31);
+ if (mw31num & 1) {
+ br_i31_muladd_small(x31, 0, m31);
+ }
+ for (u = 0; u < mw31num; u += 2) {
+ size_t v;
+
+ v = u >> 1;
+ if ((u + 1) == mw31num) {
+ x[v] = (uint64_t)x31[u + 1];
+ } else {
+ x[v] = (uint64_t)x31[u + 1]
+ + ((uint64_t)x31[u + 2] << 31);
+ }
+ }
+
+ /*
+ * We process bits from most to least significant. At each
+ * loop iteration, we have acc_len bits in acc.
+ */
+ acc = 0;
+ acc_len = 0;
+ while (acc_len > 0 || elen > 0) {
+ int i, k;
+ uint32_t bits;
+ uint64_t mask1, mask2;
+
+ /*
+ * Get the next bits.
+ */
+ k = win_len;
+ if (acc_len < win_len) {
+ if (elen > 0) {
+ acc = (acc << 8) | *e ++;
+ elen --;
+ acc_len += 8;
+ } else {
+ k = acc_len;
+ }
+ }
+ bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1);
+ acc_len -= k;
+
+ /*
+ * We could get exactly k bits. Compute k squarings.
+ */
+ for (i = 0; i < k; i ++) {
+ montymul(t1, x, x, m, mw62num, m0i);
+ memcpy(x, t1, mw62num * sizeof *x);
+ }
+
+ /*
+ * Window lookup: we want to set t2 to the window
+ * lookup value, assuming the bits are non-zero. If
+ * the window length is 1 bit only, then t2 is
+ * already set; otherwise, we do a constant-time lookup.
+ */
+ if (win_len > 1) {
+ uint64_t *base;
+
+ memset(t2, 0, mw62num * sizeof *t2);
+ base = t2 + mw62num;
+ for (u = 1; u < ((uint32_t)1 << k); u ++) {
+ uint64_t mask;
+ size_t v;
+
+ mask = -(uint64_t)EQ(u, bits);
+ for (v = 0; v < mw62num; v ++) {
+ t2[v] |= mask & base[v];
+ }
+ base += mw62num;
+ }
+ }
+
+ /*
+ * Multiply with the looked-up value. We keep the product
+ * only if the exponent bits are not all-zero.
+ */
+ montymul(t1, x, t2, m, mw62num, m0i);
+ mask1 = -(uint64_t)EQ(bits, 0);
+ mask2 = ~mask1;
+ for (u = 0; u < mw62num; u ++) {
+ x[u] = (mask1 & x[u]) | (mask2 & t1[u]);
+ }
+ }
+
+ /*
+ * Convert back from Montgomery representation.
+ */
+ frommonty(x, m, mw62num, m0i);
+
+ /*
+ * Convert result into 31-bit words.
+ */
+ for (u = 0; u < mw31num; u += 2) {
+ uint64_t zw;
+
+ zw = x[u >> 1];
+ x31[u + 1] = (uint32_t)zw & 0x7FFFFFFF;
+ if ((u + 1) < mw31num) {
+ x31[u + 2] = (uint32_t)(zw >> 31);
+ }
+ }
+ return 1;
+}
+
+#else
+
+/* see inner.h */
+uint32_t
+br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen,
+ const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen)
+{
+ size_t mwlen;
+
+ mwlen = (m31[0] + 63) >> 5;
+ if (twlen < mwlen) {
+ return 0;
+ }
+ return br_i31_modpow_opt(x31, e, elen, m31, m0i31,
+ (uint32_t *)tmp, twlen << 1);
+}
+
+#endif
+
+/* see inner.h */
+uint32_t
+br_i62_modpow_opt_as_i31(uint32_t *x31, const unsigned char *e, size_t elen,
+ const uint32_t *m31, uint32_t m0i31, uint32_t *tmp, size_t twlen)
+{
+ /*
+ * As documented, this function expects the 'tmp' argument to be
+ * 64-bit aligned. This is OK since this function is internal (it
+ * is not part of BearSSL's public API).
+ */
+ return br_i62_modpow_opt(x31, e, elen, m31, m0i31,
+ (uint64_t *)tmp, twlen >> 1);
+}
Property changes on: stable/12/contrib/bearssl/src/int/i62_modpow2.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/kdf/hkdf.c
===================================================================
--- stable/12/contrib/bearssl/src/kdf/hkdf.c (nonexistent)
+++ stable/12/contrib/bearssl/src/kdf/hkdf.c (revision 346145)
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+const unsigned char br_hkdf_no_salt = 0;
+
+/* see bearssl_kdf.h */
+void
+br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable,
+ const void *salt, size_t salt_len)
+{
+ br_hmac_key_context kc;
+ unsigned char tmp[64];
+
+ if (salt == BR_HKDF_NO_SALT) {
+ salt = tmp;
+ salt_len = br_digest_size(digest_vtable);
+ memset(tmp, 0, salt_len);
+ }
+ br_hmac_key_init(&kc, digest_vtable, salt, salt_len);
+ br_hmac_init(&hc->u.hmac_ctx, &kc, 0);
+ hc->dig_len = br_hmac_size(&hc->u.hmac_ctx);
+}
+
+/* see bearssl_kdf.h */
+void
+br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len)
+{
+ br_hmac_update(&hc->u.hmac_ctx, ikm, ikm_len);
+}
+
+/* see bearssl_kdf.h */
+void
+br_hkdf_flip(br_hkdf_context *hc)
+{
+ unsigned char tmp[64];
+
+ br_hmac_out(&hc->u.hmac_ctx, tmp);
+ br_hmac_key_init(&hc->u.prk_ctx,
+ br_hmac_get_digest(&hc->u.hmac_ctx), tmp, hc->dig_len);
+ hc->ptr = hc->dig_len;
+ hc->chunk_num = 0;
+}
+
+/* see bearssl_kdf.h */
+size_t
+br_hkdf_produce(br_hkdf_context *hc,
+ const void *info, size_t info_len, void *out, size_t out_len)
+{
+ size_t tlen;
+
+ tlen = 0;
+ while (out_len > 0) {
+ size_t clen;
+
+ if (hc->ptr == hc->dig_len) {
+ br_hmac_context hmac_ctx;
+ unsigned char x;
+
+ hc->chunk_num ++;
+ if (hc->chunk_num == 256) {
+ return tlen;
+ }
+ x = hc->chunk_num;
+ br_hmac_init(&hmac_ctx, &hc->u.prk_ctx, 0);
+ if (x != 1) {
+ br_hmac_update(&hmac_ctx, hc->buf, hc->dig_len);
+ }
+ br_hmac_update(&hmac_ctx, info, info_len);
+ br_hmac_update(&hmac_ctx, &x, 1);
+ br_hmac_out(&hmac_ctx, hc->buf);
+ hc->ptr = 0;
+ }
+ clen = hc->dig_len - hc->ptr;
+ if (clen > out_len) {
+ clen = out_len;
+ }
+ memcpy(out, hc->buf + hc->ptr, clen);
+ out = (unsigned char *)out + clen;
+ out_len -= clen;
+ hc->ptr += clen;
+ tlen += clen;
+ }
+ return tlen;
+}
Property changes on: stable/12/contrib/bearssl/src/kdf/hkdf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/kdf/shake.c
===================================================================
--- stable/12/contrib/bearssl/src/kdf/shake.c (nonexistent)
+++ stable/12/contrib/bearssl/src/kdf/shake.c (revision 346145)
@@ -0,0 +1,590 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Round constants.
+ */
+static const uint64_t RC[] = {
+ 0x0000000000000001, 0x0000000000008082,
+ 0x800000000000808A, 0x8000000080008000,
+ 0x000000000000808B, 0x0000000080000001,
+ 0x8000000080008081, 0x8000000000008009,
+ 0x000000000000008A, 0x0000000000000088,
+ 0x0000000080008009, 0x000000008000000A,
+ 0x000000008000808B, 0x800000000000008B,
+ 0x8000000000008089, 0x8000000000008003,
+ 0x8000000000008002, 0x8000000000000080,
+ 0x000000000000800A, 0x800000008000000A,
+ 0x8000000080008081, 0x8000000000008080,
+ 0x0000000080000001, 0x8000000080008008
+};
+
+/*
+ * XOR a block of data into the provided state. This supports only
+ * blocks whose length is a multiple of 64 bits.
+ */
+static void
+xor_block(uint64_t *A, const void *data, size_t rate)
+{
+ size_t u;
+
+ for (u = 0; u < rate; u += 8) {
+ A[u >> 3] ^= br_dec64le((const unsigned char *)data + u);
+ }
+}
+
+/*
+ * Process a block with the provided data. The data length must be a
+ * multiple of 8 (in bytes); normally, this is the "rate".
+ */
+static void
+process_block(uint64_t *A)
+{
+ uint64_t t0, t1, t2, t3, t4;
+ uint64_t tt0, tt1, tt2, tt3;
+ uint64_t t, kt;
+ uint64_t c0, c1, c2, c3, c4, bnn;
+ int j;
+
+ /*
+ * Compute the 24 rounds. This loop is partially unrolled (each
+ * iteration computes two rounds).
+ */
+ for (j = 0; j < 24; j += 2) {
+
+ tt0 = A[ 1] ^ A[ 6];
+ tt1 = A[11] ^ A[16];
+ tt0 ^= A[21] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[ 4] ^ A[ 9];
+ tt3 = A[14] ^ A[19];
+ tt0 ^= A[24];
+ tt2 ^= tt3;
+ t0 = tt0 ^ tt2;
+
+ tt0 = A[ 2] ^ A[ 7];
+ tt1 = A[12] ^ A[17];
+ tt0 ^= A[22] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[ 0] ^ A[ 5];
+ tt3 = A[10] ^ A[15];
+ tt0 ^= A[20];
+ tt2 ^= tt3;
+ t1 = tt0 ^ tt2;
+
+ tt0 = A[ 3] ^ A[ 8];
+ tt1 = A[13] ^ A[18];
+ tt0 ^= A[23] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[ 1] ^ A[ 6];
+ tt3 = A[11] ^ A[16];
+ tt0 ^= A[21];
+ tt2 ^= tt3;
+ t2 = tt0 ^ tt2;
+
+ tt0 = A[ 4] ^ A[ 9];
+ tt1 = A[14] ^ A[19];
+ tt0 ^= A[24] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[ 2] ^ A[ 7];
+ tt3 = A[12] ^ A[17];
+ tt0 ^= A[22];
+ tt2 ^= tt3;
+ t3 = tt0 ^ tt2;
+
+ tt0 = A[ 0] ^ A[ 5];
+ tt1 = A[10] ^ A[15];
+ tt0 ^= A[20] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[ 3] ^ A[ 8];
+ tt3 = A[13] ^ A[18];
+ tt0 ^= A[23];
+ tt2 ^= tt3;
+ t4 = tt0 ^ tt2;
+
+ A[ 0] = A[ 0] ^ t0;
+ A[ 5] = A[ 5] ^ t0;
+ A[10] = A[10] ^ t0;
+ A[15] = A[15] ^ t0;
+ A[20] = A[20] ^ t0;
+ A[ 1] = A[ 1] ^ t1;
+ A[ 6] = A[ 6] ^ t1;
+ A[11] = A[11] ^ t1;
+ A[16] = A[16] ^ t1;
+ A[21] = A[21] ^ t1;
+ A[ 2] = A[ 2] ^ t2;
+ A[ 7] = A[ 7] ^ t2;
+ A[12] = A[12] ^ t2;
+ A[17] = A[17] ^ t2;
+ A[22] = A[22] ^ t2;
+ A[ 3] = A[ 3] ^ t3;
+ A[ 8] = A[ 8] ^ t3;
+ A[13] = A[13] ^ t3;
+ A[18] = A[18] ^ t3;
+ A[23] = A[23] ^ t3;
+ A[ 4] = A[ 4] ^ t4;
+ A[ 9] = A[ 9] ^ t4;
+ A[14] = A[14] ^ t4;
+ A[19] = A[19] ^ t4;
+ A[24] = A[24] ^ t4;
+ A[ 5] = (A[ 5] << 36) | (A[ 5] >> (64 - 36));
+ A[10] = (A[10] << 3) | (A[10] >> (64 - 3));
+ A[15] = (A[15] << 41) | (A[15] >> (64 - 41));
+ A[20] = (A[20] << 18) | (A[20] >> (64 - 18));
+ A[ 1] = (A[ 1] << 1) | (A[ 1] >> (64 - 1));
+ A[ 6] = (A[ 6] << 44) | (A[ 6] >> (64 - 44));
+ A[11] = (A[11] << 10) | (A[11] >> (64 - 10));
+ A[16] = (A[16] << 45) | (A[16] >> (64 - 45));
+ A[21] = (A[21] << 2) | (A[21] >> (64 - 2));
+ A[ 2] = (A[ 2] << 62) | (A[ 2] >> (64 - 62));
+ A[ 7] = (A[ 7] << 6) | (A[ 7] >> (64 - 6));
+ A[12] = (A[12] << 43) | (A[12] >> (64 - 43));
+ A[17] = (A[17] << 15) | (A[17] >> (64 - 15));
+ A[22] = (A[22] << 61) | (A[22] >> (64 - 61));
+ A[ 3] = (A[ 3] << 28) | (A[ 3] >> (64 - 28));
+ A[ 8] = (A[ 8] << 55) | (A[ 8] >> (64 - 55));
+ A[13] = (A[13] << 25) | (A[13] >> (64 - 25));
+ A[18] = (A[18] << 21) | (A[18] >> (64 - 21));
+ A[23] = (A[23] << 56) | (A[23] >> (64 - 56));
+ A[ 4] = (A[ 4] << 27) | (A[ 4] >> (64 - 27));
+ A[ 9] = (A[ 9] << 20) | (A[ 9] >> (64 - 20));
+ A[14] = (A[14] << 39) | (A[14] >> (64 - 39));
+ A[19] = (A[19] << 8) | (A[19] >> (64 - 8));
+ A[24] = (A[24] << 14) | (A[24] >> (64 - 14));
+ bnn = ~A[12];
+ kt = A[ 6] | A[12];
+ c0 = A[ 0] ^ kt;
+ kt = bnn | A[18];
+ c1 = A[ 6] ^ kt;
+ kt = A[18] & A[24];
+ c2 = A[12] ^ kt;
+ kt = A[24] | A[ 0];
+ c3 = A[18] ^ kt;
+ kt = A[ 0] & A[ 6];
+ c4 = A[24] ^ kt;
+ A[ 0] = c0;
+ A[ 6] = c1;
+ A[12] = c2;
+ A[18] = c3;
+ A[24] = c4;
+ bnn = ~A[22];
+ kt = A[ 9] | A[10];
+ c0 = A[ 3] ^ kt;
+ kt = A[10] & A[16];
+ c1 = A[ 9] ^ kt;
+ kt = A[16] | bnn;
+ c2 = A[10] ^ kt;
+ kt = A[22] | A[ 3];
+ c3 = A[16] ^ kt;
+ kt = A[ 3] & A[ 9];
+ c4 = A[22] ^ kt;
+ A[ 3] = c0;
+ A[ 9] = c1;
+ A[10] = c2;
+ A[16] = c3;
+ A[22] = c4;
+ bnn = ~A[19];
+ kt = A[ 7] | A[13];
+ c0 = A[ 1] ^ kt;
+ kt = A[13] & A[19];
+ c1 = A[ 7] ^ kt;
+ kt = bnn & A[20];
+ c2 = A[13] ^ kt;
+ kt = A[20] | A[ 1];
+ c3 = bnn ^ kt;
+ kt = A[ 1] & A[ 7];
+ c4 = A[20] ^ kt;
+ A[ 1] = c0;
+ A[ 7] = c1;
+ A[13] = c2;
+ A[19] = c3;
+ A[20] = c4;
+ bnn = ~A[17];
+ kt = A[ 5] & A[11];
+ c0 = A[ 4] ^ kt;
+ kt = A[11] | A[17];
+ c1 = A[ 5] ^ kt;
+ kt = bnn | A[23];
+ c2 = A[11] ^ kt;
+ kt = A[23] & A[ 4];
+ c3 = bnn ^ kt;
+ kt = A[ 4] | A[ 5];
+ c4 = A[23] ^ kt;
+ A[ 4] = c0;
+ A[ 5] = c1;
+ A[11] = c2;
+ A[17] = c3;
+ A[23] = c4;
+ bnn = ~A[ 8];
+ kt = bnn & A[14];
+ c0 = A[ 2] ^ kt;
+ kt = A[14] | A[15];
+ c1 = bnn ^ kt;
+ kt = A[15] & A[21];
+ c2 = A[14] ^ kt;
+ kt = A[21] | A[ 2];
+ c3 = A[15] ^ kt;
+ kt = A[ 2] & A[ 8];
+ c4 = A[21] ^ kt;
+ A[ 2] = c0;
+ A[ 8] = c1;
+ A[14] = c2;
+ A[15] = c3;
+ A[21] = c4;
+ A[ 0] = A[ 0] ^ RC[j + 0];
+
+ tt0 = A[ 6] ^ A[ 9];
+ tt1 = A[ 7] ^ A[ 5];
+ tt0 ^= A[ 8] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[24] ^ A[22];
+ tt3 = A[20] ^ A[23];
+ tt0 ^= A[21];
+ tt2 ^= tt3;
+ t0 = tt0 ^ tt2;
+
+ tt0 = A[12] ^ A[10];
+ tt1 = A[13] ^ A[11];
+ tt0 ^= A[14] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[ 0] ^ A[ 3];
+ tt3 = A[ 1] ^ A[ 4];
+ tt0 ^= A[ 2];
+ tt2 ^= tt3;
+ t1 = tt0 ^ tt2;
+
+ tt0 = A[18] ^ A[16];
+ tt1 = A[19] ^ A[17];
+ tt0 ^= A[15] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[ 6] ^ A[ 9];
+ tt3 = A[ 7] ^ A[ 5];
+ tt0 ^= A[ 8];
+ tt2 ^= tt3;
+ t2 = tt0 ^ tt2;
+
+ tt0 = A[24] ^ A[22];
+ tt1 = A[20] ^ A[23];
+ tt0 ^= A[21] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[12] ^ A[10];
+ tt3 = A[13] ^ A[11];
+ tt0 ^= A[14];
+ tt2 ^= tt3;
+ t3 = tt0 ^ tt2;
+
+ tt0 = A[ 0] ^ A[ 3];
+ tt1 = A[ 1] ^ A[ 4];
+ tt0 ^= A[ 2] ^ tt1;
+ tt0 = (tt0 << 1) | (tt0 >> 63);
+ tt2 = A[18] ^ A[16];
+ tt3 = A[19] ^ A[17];
+ tt0 ^= A[15];
+ tt2 ^= tt3;
+ t4 = tt0 ^ tt2;
+
+ A[ 0] = A[ 0] ^ t0;
+ A[ 3] = A[ 3] ^ t0;
+ A[ 1] = A[ 1] ^ t0;
+ A[ 4] = A[ 4] ^ t0;
+ A[ 2] = A[ 2] ^ t0;
+ A[ 6] = A[ 6] ^ t1;
+ A[ 9] = A[ 9] ^ t1;
+ A[ 7] = A[ 7] ^ t1;
+ A[ 5] = A[ 5] ^ t1;
+ A[ 8] = A[ 8] ^ t1;
+ A[12] = A[12] ^ t2;
+ A[10] = A[10] ^ t2;
+ A[13] = A[13] ^ t2;
+ A[11] = A[11] ^ t2;
+ A[14] = A[14] ^ t2;
+ A[18] = A[18] ^ t3;
+ A[16] = A[16] ^ t3;
+ A[19] = A[19] ^ t3;
+ A[17] = A[17] ^ t3;
+ A[15] = A[15] ^ t3;
+ A[24] = A[24] ^ t4;
+ A[22] = A[22] ^ t4;
+ A[20] = A[20] ^ t4;
+ A[23] = A[23] ^ t4;
+ A[21] = A[21] ^ t4;
+ A[ 3] = (A[ 3] << 36) | (A[ 3] >> (64 - 36));
+ A[ 1] = (A[ 1] << 3) | (A[ 1] >> (64 - 3));
+ A[ 4] = (A[ 4] << 41) | (A[ 4] >> (64 - 41));
+ A[ 2] = (A[ 2] << 18) | (A[ 2] >> (64 - 18));
+ A[ 6] = (A[ 6] << 1) | (A[ 6] >> (64 - 1));
+ A[ 9] = (A[ 9] << 44) | (A[ 9] >> (64 - 44));
+ A[ 7] = (A[ 7] << 10) | (A[ 7] >> (64 - 10));
+ A[ 5] = (A[ 5] << 45) | (A[ 5] >> (64 - 45));
+ A[ 8] = (A[ 8] << 2) | (A[ 8] >> (64 - 2));
+ A[12] = (A[12] << 62) | (A[12] >> (64 - 62));
+ A[10] = (A[10] << 6) | (A[10] >> (64 - 6));
+ A[13] = (A[13] << 43) | (A[13] >> (64 - 43));
+ A[11] = (A[11] << 15) | (A[11] >> (64 - 15));
+ A[14] = (A[14] << 61) | (A[14] >> (64 - 61));
+ A[18] = (A[18] << 28) | (A[18] >> (64 - 28));
+ A[16] = (A[16] << 55) | (A[16] >> (64 - 55));
+ A[19] = (A[19] << 25) | (A[19] >> (64 - 25));
+ A[17] = (A[17] << 21) | (A[17] >> (64 - 21));
+ A[15] = (A[15] << 56) | (A[15] >> (64 - 56));
+ A[24] = (A[24] << 27) | (A[24] >> (64 - 27));
+ A[22] = (A[22] << 20) | (A[22] >> (64 - 20));
+ A[20] = (A[20] << 39) | (A[20] >> (64 - 39));
+ A[23] = (A[23] << 8) | (A[23] >> (64 - 8));
+ A[21] = (A[21] << 14) | (A[21] >> (64 - 14));
+ bnn = ~A[13];
+ kt = A[ 9] | A[13];
+ c0 = A[ 0] ^ kt;
+ kt = bnn | A[17];
+ c1 = A[ 9] ^ kt;
+ kt = A[17] & A[21];
+ c2 = A[13] ^ kt;
+ kt = A[21] | A[ 0];
+ c3 = A[17] ^ kt;
+ kt = A[ 0] & A[ 9];
+ c4 = A[21] ^ kt;
+ A[ 0] = c0;
+ A[ 9] = c1;
+ A[13] = c2;
+ A[17] = c3;
+ A[21] = c4;
+ bnn = ~A[14];
+ kt = A[22] | A[ 1];
+ c0 = A[18] ^ kt;
+ kt = A[ 1] & A[ 5];
+ c1 = A[22] ^ kt;
+ kt = A[ 5] | bnn;
+ c2 = A[ 1] ^ kt;
+ kt = A[14] | A[18];
+ c3 = A[ 5] ^ kt;
+ kt = A[18] & A[22];
+ c4 = A[14] ^ kt;
+ A[18] = c0;
+ A[22] = c1;
+ A[ 1] = c2;
+ A[ 5] = c3;
+ A[14] = c4;
+ bnn = ~A[23];
+ kt = A[10] | A[19];
+ c0 = A[ 6] ^ kt;
+ kt = A[19] & A[23];
+ c1 = A[10] ^ kt;
+ kt = bnn & A[ 2];
+ c2 = A[19] ^ kt;
+ kt = A[ 2] | A[ 6];
+ c3 = bnn ^ kt;
+ kt = A[ 6] & A[10];
+ c4 = A[ 2] ^ kt;
+ A[ 6] = c0;
+ A[10] = c1;
+ A[19] = c2;
+ A[23] = c3;
+ A[ 2] = c4;
+ bnn = ~A[11];
+ kt = A[ 3] & A[ 7];
+ c0 = A[24] ^ kt;
+ kt = A[ 7] | A[11];
+ c1 = A[ 3] ^ kt;
+ kt = bnn | A[15];
+ c2 = A[ 7] ^ kt;
+ kt = A[15] & A[24];
+ c3 = bnn ^ kt;
+ kt = A[24] | A[ 3];
+ c4 = A[15] ^ kt;
+ A[24] = c0;
+ A[ 3] = c1;
+ A[ 7] = c2;
+ A[11] = c3;
+ A[15] = c4;
+ bnn = ~A[16];
+ kt = bnn & A[20];
+ c0 = A[12] ^ kt;
+ kt = A[20] | A[ 4];
+ c1 = bnn ^ kt;
+ kt = A[ 4] & A[ 8];
+ c2 = A[20] ^ kt;
+ kt = A[ 8] | A[12];
+ c3 = A[ 4] ^ kt;
+ kt = A[12] & A[16];
+ c4 = A[ 8] ^ kt;
+ A[12] = c0;
+ A[16] = c1;
+ A[20] = c2;
+ A[ 4] = c3;
+ A[ 8] = c4;
+ A[ 0] = A[ 0] ^ RC[j + 1];
+ t = A[ 5];
+ A[ 5] = A[18];
+ A[18] = A[11];
+ A[11] = A[10];
+ A[10] = A[ 6];
+ A[ 6] = A[22];
+ A[22] = A[20];
+ A[20] = A[12];
+ A[12] = A[19];
+ A[19] = A[15];
+ A[15] = A[24];
+ A[24] = A[ 8];
+ A[ 8] = t;
+ t = A[ 1];
+ A[ 1] = A[ 9];
+ A[ 9] = A[14];
+ A[14] = A[ 2];
+ A[ 2] = A[13];
+ A[13] = A[23];
+ A[23] = A[ 4];
+ A[ 4] = A[21];
+ A[21] = A[16];
+ A[16] = A[ 3];
+ A[ 3] = A[17];
+ A[17] = A[ 7];
+ A[ 7] = t;
+ }
+}
+
+/* see bearssl_kdf.h */
+void
+br_shake_init(br_shake_context *sc, int security_level)
+{
+ sc->rate = 200 - (size_t)(security_level >> 2);
+ sc->dptr = 0;
+ memset(sc->A, 0, sizeof sc->A);
+ sc->A[ 1] = ~(uint64_t)0;
+ sc->A[ 2] = ~(uint64_t)0;
+ sc->A[ 8] = ~(uint64_t)0;
+ sc->A[12] = ~(uint64_t)0;
+ sc->A[17] = ~(uint64_t)0;
+ sc->A[20] = ~(uint64_t)0;
+}
+
+/* see bearssl_kdf.h */
+void
+br_shake_inject(br_shake_context *sc, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ size_t rate, dptr;
+
+ buf = data;
+ rate = sc->rate;
+ dptr = sc->dptr;
+ while (len > 0) {
+ size_t clen;
+
+ clen = rate - dptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(sc->dbuf + dptr, buf, clen);
+ dptr += clen;
+ buf += clen;
+ len -= clen;
+ if (dptr == rate) {
+ xor_block(sc->A, sc->dbuf, rate);
+ process_block(sc->A);
+ dptr = 0;
+ }
+ }
+ sc->dptr = dptr;
+}
+
+/* see bearssl_kdf.h */
+void
+br_shake_flip(br_shake_context *sc)
+{
+ /*
+ * We apply padding and pre-XOR the value into the state. We
+ * set dptr to the end of the buffer, so that first call to
+ * shake_extract() will process the block.
+ */
+ if ((sc->dptr + 1) == sc->rate) {
+ sc->dbuf[sc->dptr ++] = 0x9F;
+ } else {
+ sc->dbuf[sc->dptr ++] = 0x1F;
+ memset(sc->dbuf + sc->dptr, 0x00, sc->rate - sc->dptr - 1);
+ sc->dbuf[sc->rate - 1] = 0x80;
+ sc->dptr = sc->rate;
+ }
+ xor_block(sc->A, sc->dbuf, sc->rate);
+}
+
+/* see bearssl_kdf.h */
+void
+br_shake_produce(br_shake_context *sc, void *out, size_t len)
+{
+ unsigned char *buf;
+ size_t dptr, rate;
+
+ buf = out;
+ dptr = sc->dptr;
+ rate = sc->rate;
+ while (len > 0) {
+ size_t clen;
+
+ if (dptr == rate) {
+ unsigned char *dbuf;
+ uint64_t *A;
+
+ A = sc->A;
+ dbuf = sc->dbuf;
+ process_block(A);
+ br_enc64le(dbuf + 0, A[ 0]);
+ br_enc64le(dbuf + 8, ~A[ 1]);
+ br_enc64le(dbuf + 16, ~A[ 2]);
+ br_enc64le(dbuf + 24, A[ 3]);
+ br_enc64le(dbuf + 32, A[ 4]);
+ br_enc64le(dbuf + 40, A[ 5]);
+ br_enc64le(dbuf + 48, A[ 6]);
+ br_enc64le(dbuf + 56, A[ 7]);
+ br_enc64le(dbuf + 64, ~A[ 8]);
+ br_enc64le(dbuf + 72, A[ 9]);
+ br_enc64le(dbuf + 80, A[10]);
+ br_enc64le(dbuf + 88, A[11]);
+ br_enc64le(dbuf + 96, ~A[12]);
+ br_enc64le(dbuf + 104, A[13]);
+ br_enc64le(dbuf + 112, A[14]);
+ br_enc64le(dbuf + 120, A[15]);
+ br_enc64le(dbuf + 128, A[16]);
+ br_enc64le(dbuf + 136, ~A[17]);
+ br_enc64le(dbuf + 144, A[18]);
+ br_enc64le(dbuf + 152, A[19]);
+ br_enc64le(dbuf + 160, ~A[20]);
+ br_enc64le(dbuf + 168, A[21]);
+ br_enc64le(dbuf + 176, A[22]);
+ br_enc64le(dbuf + 184, A[23]);
+ br_enc64le(dbuf + 192, A[24]);
+ dptr = 0;
+ }
+ clen = rate - dptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(buf, sc->dbuf + dptr, clen);
+ dptr += clen;
+ buf += clen;
+ len -= clen;
+ }
+ sc->dptr = dptr;
+}
Property changes on: stable/12/contrib/bearssl/src/kdf/shake.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/mac/hmac.c
===================================================================
--- stable/12/contrib/bearssl/src/mac/hmac.c (nonexistent)
+++ stable/12/contrib/bearssl/src/mac/hmac.c (revision 346145)
@@ -0,0 +1,122 @@
+/*
+ * 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"
+
+static inline size_t
+block_size(const br_hash_class *dig)
+{
+ unsigned ls;
+
+ ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF)
+ & BR_HASHDESC_LBLEN_MASK;
+ return (size_t)1 << ls;
+}
+
+static void
+process_key(const br_hash_class **hc, void *ks,
+ const void *key, size_t key_len, unsigned bb)
+{
+ unsigned char tmp[256];
+ size_t blen, u;
+
+ blen = block_size(*hc);
+ memcpy(tmp, key, key_len);
+ for (u = 0; u < key_len; u ++) {
+ tmp[u] ^= (unsigned char)bb;
+ }
+ memset(tmp + key_len, bb, blen - key_len);
+ (*hc)->init(hc);
+ (*hc)->update(hc, tmp, blen);
+ (*hc)->state(hc, ks);
+}
+
+/* see bearssl.h */
+void
+br_hmac_key_init(br_hmac_key_context *kc,
+ const br_hash_class *dig, const void *key, size_t key_len)
+{
+ br_hash_compat_context hc;
+ unsigned char kbuf[64];
+
+ kc->dig_vtable = dig;
+ hc.vtable = dig;
+ if (key_len > block_size(dig)) {
+ dig->init(&hc.vtable);
+ dig->update(&hc.vtable, key, key_len);
+ dig->out(&hc.vtable, kbuf);
+ key = kbuf;
+ key_len = br_digest_size(dig);
+ }
+ process_key(&hc.vtable, kc->ksi, key, key_len, 0x36);
+ process_key(&hc.vtable, kc->kso, key, key_len, 0x5C);
+}
+
+/* see bearssl.h */
+void
+br_hmac_init(br_hmac_context *ctx,
+ const br_hmac_key_context *kc, size_t out_len)
+{
+ const br_hash_class *dig;
+ size_t blen, hlen;
+
+ dig = kc->dig_vtable;
+ blen = block_size(dig);
+ dig->init(&ctx->dig.vtable);
+ dig->set_state(&ctx->dig.vtable, kc->ksi, (uint64_t)blen);
+ memcpy(ctx->kso, kc->kso, sizeof kc->kso);
+ hlen = br_digest_size(dig);
+ if (out_len > 0 && out_len < hlen) {
+ hlen = out_len;
+ }
+ ctx->out_len = hlen;
+}
+
+/* see bearssl.h */
+void
+br_hmac_update(br_hmac_context *ctx, const void *data, size_t len)
+{
+ ctx->dig.vtable->update(&ctx->dig.vtable, data, len);
+}
+
+/* see bearssl.h */
+size_t
+br_hmac_out(const br_hmac_context *ctx, void *out)
+{
+ const br_hash_class *dig;
+ br_hash_compat_context hc;
+ unsigned char tmp[64];
+ size_t blen, hlen;
+
+ dig = ctx->dig.vtable;
+ dig->out(&ctx->dig.vtable, tmp);
+ blen = block_size(dig);
+ dig->init(&hc.vtable);
+ dig->set_state(&hc.vtable, ctx->kso, (uint64_t)blen);
+ hlen = br_digest_size(dig);
+ dig->update(&hc.vtable, tmp, hlen);
+ dig->out(&hc.vtable, tmp);
+ memcpy(out, tmp, ctx->out_len);
+ return ctx->out_len;
+}
Property changes on: stable/12/contrib/bearssl/src/mac/hmac.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/mac/hmac_ct.c
===================================================================
--- stable/12/contrib/bearssl/src/mac/hmac_ct.c (nonexistent)
+++ stable/12/contrib/bearssl/src/mac/hmac_ct.c (revision 346145)
@@ -0,0 +1,193 @@
+/*
+ * 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"
+
+static inline size_t
+hash_size(const br_hash_class *dig)
+{
+ return (unsigned)(dig->desc >> BR_HASHDESC_OUT_OFF)
+ & BR_HASHDESC_OUT_MASK;
+}
+
+static inline size_t
+block_size(const br_hash_class *dig)
+{
+ unsigned ls;
+
+ ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF)
+ & BR_HASHDESC_LBLEN_MASK;
+ return (size_t)1 << ls;
+}
+
+/* see bearssl.h */
+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)
+{
+ /*
+ * Method implemented here is inspired from the descriptions on:
+ * https://www.imperialviolet.org/2013/02/04/luckythirteen.html
+ *
+ * Principle: we input bytes one by one. We use a MUX to push
+ * padding bytes instead of data bytes when appropriate. At each
+ * block limit, we get the current hash function state: this is
+ * a potential output, since we handle MD padding ourselves.
+ *
+ * be 1 for big-endian, 0 for little-endian
+ * po minimal MD padding length
+ * bs block size (always a power of 2)
+ * hlen hash output size
+ */
+
+ const br_hash_class *dig;
+ br_hash_compat_context hc;
+ int be;
+ uint32_t po, bs;
+ uint32_t kr, km, kl, kz, u;
+ uint64_t count, ncount, bit_len;
+ unsigned char tmp1[64], tmp2[64];
+ size_t hlen;
+
+ /*
+ * Copy the current hash context.
+ */
+ hc = ctx->dig;
+
+ /*
+ * Get function-specific information.
+ */
+ dig = hc.vtable;
+ be = (dig->desc & BR_HASHDESC_MD_PADDING_BE) != 0;
+ po = 9;
+ if (dig->desc & BR_HASHDESC_MD_PADDING_128) {
+ po += 8;
+ }
+ bs = block_size(dig);
+ hlen = hash_size(dig);
+
+ /*
+ * Get current input length and compute total bit length.
+ */
+ count = dig->state(&hc.vtable, tmp1);
+ bit_len = (count + (uint64_t)len) << 3;
+
+ /*
+ * We can input the blocks that we are sure we will use.
+ * This offers better performance (no MUX for these blocks)
+ * and also ensures that the remaining lengths fit on 32 bits.
+ */
+ ncount = (count + (uint64_t)min_len) & ~(uint64_t)(bs - 1);
+ if (ncount > count) {
+ size_t zlen;
+
+ zlen = (size_t)(ncount - count);
+ dig->update(&hc.vtable, data, zlen);
+ data = (const unsigned char *)data + zlen;
+ len -= zlen;
+ max_len -= zlen;
+ count = ncount;
+ }
+
+ /*
+ * At that point:
+ * -- 'count' contains the number of bytes already processed
+ * (in total).
+ * -- We must input 'len' bytes. 'min_len' is unimportant: we
+ * used it to know how many full blocks we could process
+ * directly. Now only len and max_len matter.
+ *
+ * We compute kr, kl, kz and km.
+ * kr number of input bytes already in the current block
+ * km index of the first byte after the end of the last padding
+ * block, if length is max_len
+ * kz index of the last byte of the actual last padding block
+ * kl index of the start of the encoded length
+ *
+ * km, kz and kl are counted from the current offset in the
+ * input data.
+ */
+ kr = (uint32_t)count & (bs - 1);
+ kz = ((kr + (uint32_t)len + po + bs - 1) & ~(bs - 1)) - 1 - kr;
+ kl = kz - 7;
+ km = ((kr + (uint32_t)max_len + po + bs - 1) & ~(bs - 1)) - kr;
+
+ /*
+ * We must now process km bytes. For index u from 0 to km-1:
+ * d is from data[] if u < max_len, 0x00 otherwise
+ * e is an encoded length byte or 0x00, depending on u
+ * The tests for d and e need not be constant-time, since
+ * they relate only to u and max_len, not to the actual length.
+ *
+ * Actual input length is then:
+ * d if u < len
+ * 0x80 if u == len
+ * 0x00 if u > len and u < kl
+ * e if u >= kl
+ *
+ * Hash state is obtained whenever we reach a full block. This
+ * is the result we want if and only if u == kz.
+ */
+ memset(tmp2, 0, sizeof tmp2);
+ for (u = 0; u < km; u ++) {
+ uint32_t v;
+ uint32_t d, e, x0, x1;
+ unsigned char x[1];
+
+ d = (u < max_len) ? ((const unsigned char *)data)[u] : 0x00;
+ v = (kr + u) & (bs - 1);
+ if (v >= (bs - 8)) {
+ unsigned j;
+
+ j = (v - (bs - 8)) << 3;
+ if (be) {
+ e = (uint32_t)(bit_len >> (56 - j));
+ } else {
+ e = (uint32_t)(bit_len >> j);
+ }
+ e &= 0xFF;
+ } else {
+ e = 0x00;
+ }
+ x0 = MUX(EQ(u, (uint32_t)len), 0x80, d);
+ x1 = MUX(LT(u, kl), 0x00, e);
+ x[0] = MUX(LE(u, (uint32_t)len), x0, x1);
+ dig->update(&hc.vtable, x, 1);
+ if (v == (bs - 1)) {
+ dig->state(&hc.vtable, tmp1);
+ CCOPY(EQ(u, kz), tmp2, tmp1, hlen);
+ }
+ }
+
+ /*
+ * Inner hash output is in tmp2[]; we finish processing.
+ */
+ dig->init(&hc.vtable);
+ dig->set_state(&hc.vtable, ctx->kso, (uint64_t)bs);
+ dig->update(&hc.vtable, tmp2, hlen);
+ dig->out(&hc.vtable, tmp2);
+ memcpy(out, tmp2, ctx->out_len);
+ return ctx->out_len;
+}
Property changes on: stable/12/contrib/bearssl/src/mac/hmac_ct.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rand/aesctr_drbg.c
===================================================================
--- stable/12/contrib/bearssl/src/rand/aesctr_drbg.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rand/aesctr_drbg.c (revision 346145)
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rand.h */
+void
+br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
+ const br_block_ctr_class *aesctr,
+ const void *seed, size_t len)
+{
+ unsigned char tmp[16];
+
+ ctx->vtable = &br_aesctr_drbg_vtable;
+ memset(tmp, 0, sizeof tmp);
+ aesctr->init(&ctx->sk.vtable, tmp, 16);
+ ctx->cc = 0;
+ br_aesctr_drbg_update(ctx, seed, len);
+}
+
+/* see bearssl_rand.h */
+void
+br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len)
+{
+ unsigned char *buf;
+ unsigned char iv[12];
+
+ buf = out;
+ memset(iv, 0, sizeof iv);
+ while (len > 0) {
+ size_t clen;
+
+ /*
+ * We generate data by blocks of at most 65280 bytes. This
+ * allows for unambiguously testing the counter overflow
+ * condition; also, it should work on 16-bit architectures
+ * (where 'size_t' is 16 bits only).
+ */
+ clen = len;
+ if (clen > 65280) {
+ clen = 65280;
+ }
+
+ /*
+ * We make sure that the counter won't exceed the configured
+ * limit.
+ */
+ if ((uint32_t)(ctx->cc + ((clen + 15) >> 4)) > 32768) {
+ clen = (32768 - ctx->cc) << 4;
+ if (clen > len) {
+ clen = len;
+ }
+ }
+
+ /*
+ * Run CTR.
+ */
+ memset(buf, 0, clen);
+ ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable,
+ iv, ctx->cc, buf, clen);
+ buf += clen;
+ len -= clen;
+
+ /*
+ * Every 32768 blocks, we force a state update.
+ */
+ if (ctx->cc >= 32768) {
+ br_aesctr_drbg_update(ctx, NULL, 0);
+ }
+ }
+}
+
+/* see bearssl_rand.h */
+void
+br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len)
+{
+ /*
+ * We use a Hirose construction on AES-256 to make a hash function.
+ * Function definition:
+ * - running state consists in two 16-byte blocks G and H
+ * - initial values of G and H are conventional
+ * - there is a fixed block-sized constant C
+ * - for next data block m:
+ * set AES key to H||m
+ * G' = E(G) xor G
+ * H' = E(G xor C) xor G xor C
+ * G <- G', H <- H'
+ * - once all blocks have been processed, output is H||G
+ *
+ * Constants:
+ * G_init = B6 B6 ... B6
+ * H_init = A5 A5 ... A5
+ * C = 01 00 ... 00
+ *
+ * With this hash function h(), we compute the new state as
+ * follows:
+ * - produce a state-dependent value s as encryption of an
+ * all-one block with AES and the current key
+ * - compute the new key as the first 128 bits of h(s||seed)
+ *
+ * Original Hirose article:
+ * https://www.iacr.org/archive/fse2006/40470213/40470213.pdf
+ */
+
+ unsigned char s[16], iv[12];
+ unsigned char G[16], H[16];
+ int first;
+
+ /*
+ * Use an all-one IV to get a fresh output block that depends on the
+ * current seed.
+ */
+ memset(iv, 0xFF, sizeof iv);
+ memset(s, 0, 16);
+ ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16);
+
+ /*
+ * Set G[] and H[] to conventional start values.
+ */
+ memset(G, 0xB6, sizeof G);
+ memset(H, 0x5A, sizeof H);
+
+ /*
+ * Process the concatenation of the current state and the seed
+ * with the custom hash function.
+ */
+ first = 1;
+ for (;;) {
+ unsigned char tmp[32];
+ unsigned char newG[16];
+
+ /*
+ * Assemble new key H||m into tmp[].
+ */
+ memcpy(tmp, H, 16);
+ if (first) {
+ memcpy(tmp + 16, s, 16);
+ first = 0;
+ } else {
+ size_t clen;
+
+ if (len == 0) {
+ break;
+ }
+ clen = len < 16 ? len : 16;
+ memcpy(tmp + 16, seed, clen);
+ memset(tmp + 16 + clen, 0, 16 - clen);
+ seed = (const unsigned char *)seed + clen;
+ len -= clen;
+ }
+ ctx->sk.vtable->init(&ctx->sk.vtable, tmp, 32);
+
+ /*
+ * Compute new G and H values.
+ */
+ memcpy(iv, G, 12);
+ memcpy(newG, G, 16);
+ ctx->sk.vtable->run(&ctx->sk.vtable, iv,
+ br_dec32be(G + 12), newG, 16);
+ iv[0] ^= 0x01;
+ memcpy(H, G, 16);
+ H[0] ^= 0x01;
+ ctx->sk.vtable->run(&ctx->sk.vtable, iv,
+ br_dec32be(G + 12), H, 16);
+ memcpy(G, newG, 16);
+ }
+
+ /*
+ * Output hash value is H||G. We truncate it to its first 128 bits,
+ * i.e. H; that's our new AES key.
+ */
+ ctx->sk.vtable->init(&ctx->sk.vtable, H, 16);
+ ctx->cc = 0;
+}
+
+/* see bearssl_rand.h */
+const br_prng_class br_aesctr_drbg_vtable = {
+ sizeof(br_aesctr_drbg_context),
+ (void (*)(const br_prng_class **, const void *, const void *, size_t))
+ &br_aesctr_drbg_init,
+ (void (*)(const br_prng_class **, void *, size_t))
+ &br_aesctr_drbg_generate,
+ (void (*)(const br_prng_class **, const void *, size_t))
+ &br_aesctr_drbg_update
+};
Property changes on: stable/12/contrib/bearssl/src/rand/aesctr_drbg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rand/hmac_drbg.c
===================================================================
--- stable/12/contrib/bearssl/src/rand/hmac_drbg.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rand/hmac_drbg.c (revision 346145)
@@ -0,0 +1,157 @@
+/*
+ * 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 bearssl.h */
+void
+br_hmac_drbg_init(br_hmac_drbg_context *ctx,
+ const br_hash_class *digest_class, const void *seed, size_t len)
+{
+ size_t hlen;
+
+ ctx->vtable = &br_hmac_drbg_vtable;
+ hlen = br_digest_size(digest_class);
+ memset(ctx->K, 0x00, hlen);
+ memset(ctx->V, 0x01, hlen);
+ ctx->digest_class = digest_class;
+ br_hmac_drbg_update(ctx, seed, len);
+}
+
+/* see bearssl.h */
+void
+br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len)
+{
+ const br_hash_class *dig;
+ br_hmac_key_context kc;
+ br_hmac_context hc;
+ size_t hlen;
+ unsigned char *buf;
+ unsigned char x;
+
+ dig = ctx->digest_class;
+ hlen = br_digest_size(dig);
+ br_hmac_key_init(&kc, dig, ctx->K, hlen);
+ buf = out;
+ while (len > 0) {
+ size_t clen;
+
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, ctx->V, hlen);
+ br_hmac_out(&hc, ctx->V);
+ clen = hlen;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(buf, ctx->V, clen);
+ buf += clen;
+ len -= clen;
+ }
+
+ /*
+ * To prepare the state for the next request, we should call
+ * br_hmac_drbg_update() with an empty additional seed. However,
+ * we already have an initialized HMAC context with the right
+ * initial key, and we don't want to push another one on the
+ * stack, so we inline that update() call here.
+ */
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, ctx->V, hlen);
+ x = 0x00;
+ br_hmac_update(&hc, &x, 1);
+ br_hmac_out(&hc, ctx->K);
+ br_hmac_key_init(&kc, dig, ctx->K, hlen);
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, ctx->V, hlen);
+ br_hmac_out(&hc, ctx->V);
+}
+
+/* see bearssl.h */
+void
+br_hmac_drbg_update(br_hmac_drbg_context *ctx, const void *seed, size_t len)
+{
+ const br_hash_class *dig;
+ br_hmac_key_context kc;
+ br_hmac_context hc;
+ size_t hlen;
+ unsigned char x;
+
+ dig = ctx->digest_class;
+ hlen = br_digest_size(dig);
+
+ /*
+ * 1. K = HMAC(K, V || 0x00 || seed)
+ */
+ br_hmac_key_init(&kc, dig, ctx->K, hlen);
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, ctx->V, hlen);
+ x = 0x00;
+ br_hmac_update(&hc, &x, 1);
+ br_hmac_update(&hc, seed, len);
+ br_hmac_out(&hc, ctx->K);
+ br_hmac_key_init(&kc, dig, ctx->K, hlen);
+
+ /*
+ * 2. V = HMAC(K, V)
+ */
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, ctx->V, hlen);
+ br_hmac_out(&hc, ctx->V);
+
+ /*
+ * 3. If the additional seed is empty, then stop here.
+ */
+ if (len == 0) {
+ return;
+ }
+
+ /*
+ * 4. K = HMAC(K, V || 0x01 || seed)
+ */
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, ctx->V, hlen);
+ x = 0x01;
+ br_hmac_update(&hc, &x, 1);
+ br_hmac_update(&hc, seed, len);
+ br_hmac_out(&hc, ctx->K);
+ br_hmac_key_init(&kc, dig, ctx->K, hlen);
+
+ /*
+ * 5. V = HMAC(K, V)
+ */
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, ctx->V, hlen);
+ br_hmac_out(&hc, ctx->V);
+}
+
+/* see bearssl.h */
+const br_prng_class br_hmac_drbg_vtable = {
+ sizeof(br_hmac_drbg_context),
+ (void (*)(const br_prng_class **, const void *, const void *, size_t))
+ &br_hmac_drbg_init,
+ (void (*)(const br_prng_class **, void *, size_t))
+ &br_hmac_drbg_generate,
+ (void (*)(const br_prng_class **, const void *, size_t))
+ &br_hmac_drbg_update
+};
Property changes on: stable/12/contrib/bearssl/src/rand/hmac_drbg.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rand/sysrng.c
===================================================================
--- stable/12/contrib/bearssl/src/rand/sysrng.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rand/sysrng.c (revision 346145)
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+#if BR_USE_URANDOM
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+
+#if BR_USE_WIN32_RAND
+#include <windows.h>
+#include <wincrypt.h>
+#pragma comment(lib, "advapi32")
+#endif
+
+#if BR_RDRAND
+BR_TARGETS_X86_UP
+BR_TARGET("rdrnd")
+static int
+seeder_rdrand(const br_prng_class **ctx)
+{
+ unsigned char tmp[32];
+ size_t u;
+
+ for (u = 0; u < sizeof tmp; u += sizeof(uint32_t)) {
+ int j;
+ uint32_t x;
+
+ /*
+ * We use the 32-bit intrinsic so that code is compatible
+ * with both 32-bit and 64-bit architectures.
+ *
+ * Intel recommends trying at least 10 times in case of
+ * failure.
+ */
+ for (j = 0; j < 10; j ++) {
+ if (_rdrand32_step(&x)) {
+ goto next_word;
+ }
+ }
+ return 0;
+ next_word:
+ br_enc32le(tmp + u, x);
+ }
+ (*ctx)->update(ctx, tmp, sizeof tmp);
+ return 1;
+}
+BR_TARGETS_X86_DOWN
+
+static int
+rdrand_supported(void)
+{
+ /*
+ * The RDRND support is bit 30 of ECX, as returned by CPUID.
+ */
+ return br_cpuid(0, 0, 0x40000000, 0);
+}
+
+#endif
+
+#if BR_USE_URANDOM
+static int
+seeder_urandom(const br_prng_class **ctx)
+{
+ int f;
+
+ f = open("/dev/urandom", O_RDONLY);
+ if (f >= 0) {
+ unsigned char tmp[32];
+ size_t u;
+
+ for (u = 0; u < sizeof tmp;) {
+ ssize_t len;
+
+ len = read(f, tmp + u, (sizeof tmp) - u);
+ if (len < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ break;
+ }
+ u += (size_t)len;
+ }
+ close(f);
+ if (u == sizeof tmp) {
+ (*ctx)->update(ctx, tmp, sizeof tmp);
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+#if BR_USE_WIN32_RAND
+static int
+seeder_win32(const br_prng_class **ctx)
+{
+ HCRYPTPROV hp;
+
+ if (CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ {
+ BYTE buf[32];
+ BOOL r;
+
+ r = CryptGenRandom(hp, sizeof buf, buf);
+ CryptReleaseContext(hp, 0);
+ if (r) {
+ (*ctx)->update(ctx, buf, sizeof buf);
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+/* see bearssl_rand.h */
+br_prng_seeder
+br_prng_seeder_system(const char **name)
+{
+#if BR_RDRAND
+ if (rdrand_supported()) {
+ if (name != NULL) {
+ *name = "rdrand";
+ }
+ return &seeder_rdrand;
+ }
+#endif
+#if BR_USE_URANDOM
+ if (name != NULL) {
+ *name = "urandom";
+ }
+ return &seeder_urandom;
+#elif BR_USE_WIN32_RAND
+ if (name != NULL) {
+ *name = "win32";
+ }
+ return &seeder_win32;
+#else
+ if (name != NULL) {
+ *name = "none";
+ }
+ return 0;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rand/sysrng.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_keygen.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_keygen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_keygen.c (revision 346145)
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_keygen
+br_rsa_keygen_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_keygen;
+#elif BR_LOMUL
+ return &br_rsa_i15_keygen;
+#else
+ return &br_rsa_i31_keygen;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_keygen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_modulus.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_modulus.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_modulus.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_compute_modulus
+br_rsa_compute_modulus_get_default(void)
+{
+#if BR_LOMUL
+ return &br_rsa_i15_compute_modulus;
+#else
+ return &br_rsa_i31_compute_modulus;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_modulus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_decrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_decrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_decrypt.c (revision 346145)
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_decrypt
+br_rsa_oaep_decrypt_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_oaep_decrypt;
+#elif BR_LOMUL
+ return &br_rsa_i15_oaep_decrypt;
+#else
+ return &br_rsa_i31_oaep_decrypt;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_decrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_encrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_encrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_encrypt.c (revision 346145)
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_encrypt
+br_rsa_oaep_encrypt_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_oaep_encrypt;
+#elif BR_LOMUL
+ return &br_rsa_i15_oaep_encrypt;
+#else
+ return &br_rsa_i31_oaep_encrypt;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_oaep_encrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_sign.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_sign
+br_rsa_pkcs1_sign_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pkcs1_sign;
+#elif BR_LOMUL
+ return &br_rsa_i15_pkcs1_sign;
+#else
+ return &br_rsa_i31_pkcs1_sign;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_vrfy.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_vrfy
+br_rsa_pkcs1_vrfy_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pkcs1_vrfy;
+#elif BR_LOMUL
+ return &br_rsa_i15_pkcs1_vrfy;
+#else
+ return &br_rsa_i31_pkcs1_vrfy;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_pkcs1_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_priv.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_priv.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_priv.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_private
+br_rsa_private_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_private;
+#elif BR_LOMUL
+ return &br_rsa_i15_private;
+#else
+ return &br_rsa_i31_private;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_priv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_privexp.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_privexp.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_privexp.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_compute_privexp
+br_rsa_compute_privexp_get_default(void)
+{
+#if BR_LOMUL
+ return &br_rsa_i15_compute_privexp;
+#else
+ return &br_rsa_i31_compute_privexp;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_privexp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_pss_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_pss_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_pss_sign.c (revision 346145)
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pss_sign
+br_rsa_pss_sign_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pss_sign;
+#elif BR_LOMUL
+ return &br_rsa_i15_pss_sign;
+#else
+ return &br_rsa_i31_pss_sign;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_pss_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_pss_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_pss_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_pss_vrfy.c (revision 346145)
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_pss_vrfy
+br_rsa_pss_vrfy_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_pss_vrfy;
+#elif BR_LOMUL
+ return &br_rsa_i15_pss_vrfy;
+#else
+ return &br_rsa_i31_pss_vrfy;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_pss_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_pub.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_pub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_pub.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_public
+br_rsa_public_get_default(void)
+{
+#if BR_INT128 || BR_UMUL128
+ return &br_rsa_i62_public;
+#elif BR_LOMUL
+ return &br_rsa_i15_public;
+#else
+ return &br_rsa_i31_public;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_pub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_default_pubexp.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_default_pubexp.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_default_pubexp.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+br_rsa_compute_pubexp
+br_rsa_compute_pubexp_get_default(void)
+{
+#if BR_LOMUL
+ return &br_rsa_i15_compute_pubexp;
+#else
+ return &br_rsa_i31_compute_pubexp;
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_default_pubexp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_keygen.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_keygen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_keygen.c (revision 346145)
@@ -0,0 +1,583 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Make a random integer of the provided size. The size is encoded.
+ * The header word is untouched.
+ */
+static void
+mkrand(const br_prng_class **rng, uint16_t *x, uint32_t esize)
+{
+ size_t u, len;
+ unsigned m;
+
+ len = (esize + 15) >> 4;
+ (*rng)->generate(rng, x + 1, len * sizeof(uint16_t));
+ for (u = 1; u < len; u ++) {
+ x[u] &= 0x7FFF;
+ }
+ m = esize & 15;
+ if (m == 0) {
+ x[len] &= 0x7FFF;
+ } else {
+ x[len] &= 0x7FFF >> (15 - m);
+ }
+}
+
+/*
+ * This is the big-endian unsigned representation of the product of
+ * all small primes from 13 to 1481.
+ */
+static const unsigned char SMALL_PRIMES[] = {
+ 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A,
+ 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7,
+ 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37,
+ 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5,
+ 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E,
+ 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6,
+ 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C,
+ 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40,
+ 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50,
+ 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7,
+ 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3,
+ 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E,
+ 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC,
+ 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08,
+ 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B,
+ 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22,
+ 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77,
+ 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E,
+ 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80,
+ 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8,
+ 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2,
+ 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC,
+ 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54,
+ 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74,
+ 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C,
+ 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD
+};
+
+/*
+ * We need temporary values for at least 7 integers of the same size
+ * as a factor (including header word); more space helps with performance
+ * (in modular exponentiations), but we much prefer to remain under
+ * 2 kilobytes in total, to save stack space. The macro TEMPS below
+ * exceeds 1024 (which is a count in 16-bit words) when BR_MAX_RSA_SIZE
+ * is greater than 4350 (default value is 4096, so the 2-kB limit is
+ * maintained unless BR_MAX_RSA_SIZE was modified).
+ */
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define TEMPS MAX(1024, 7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 29) / 15))
+
+/*
+ * Perform trial division on a candidate prime. This computes
+ * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The
+ * br_i15_moddiv() function will report an error if y is not invertible
+ * modulo x. Returned value is 1 on success (none of the small primes
+ * divides x), 0 on error (a non-trivial GCD is obtained).
+ *
+ * This function assumes that x is odd.
+ */
+static uint32_t
+trial_divisions(const uint16_t *x, uint16_t *t)
+{
+ uint16_t *y;
+ uint16_t x0i;
+
+ y = t;
+ t += 1 + ((x[0] + 15) >> 4);
+ x0i = br_i15_ninv15(x[1]);
+ br_i15_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x);
+ return br_i15_moddiv(y, y, x, x0i, t);
+}
+
+/*
+ * Perform n rounds of Miller-Rabin on the candidate prime x. This
+ * function assumes that x = 3 mod 4.
+ *
+ * Returned value is 1 on success (all rounds completed successfully),
+ * 0 otherwise.
+ */
+static uint32_t
+miller_rabin(const br_prng_class **rng, const uint16_t *x, int n,
+ uint16_t *t, size_t tlen)
+{
+ /*
+ * Since x = 3 mod 4, the Miller-Rabin test is simple:
+ * - get a random base a (such that 1 < a < x-1)
+ * - compute z = a^((x-1)/2) mod x
+ * - if z != 1 and z != x-1, the number x is composite
+ *
+ * We generate bases 'a' randomly with a size which is
+ * one bit less than x, which ensures that a < x-1. It
+ * is not useful to verify that a > 1 because the probability
+ * that we get a value a equal to 0 or 1 is much smaller
+ * than the probability of our Miller-Rabin tests not to
+ * detect a composite, which is already quite smaller than the
+ * probability of the hardware misbehaving and return a
+ * composite integer because of some glitch (e.g. bad RAM
+ * or ill-timed cosmic ray).
+ */
+ unsigned char *xm1d2;
+ size_t xlen, xm1d2_len, xm1d2_len_u16, u;
+ uint32_t asize;
+ unsigned cc;
+ uint16_t x0i;
+
+ /*
+ * Compute (x-1)/2 (encoded).
+ */
+ xm1d2 = (unsigned char *)t;
+ xm1d2_len = ((x[0] - (x[0] >> 4)) + 7) >> 3;
+ br_i15_encode(xm1d2, xm1d2_len, x);
+ cc = 0;
+ for (u = 0; u < xm1d2_len; u ++) {
+ unsigned w;
+
+ w = xm1d2[u];
+ xm1d2[u] = (unsigned char)((w >> 1) | cc);
+ cc = w << 7;
+ }
+
+ /*
+ * We used some words of the provided buffer for (x-1)/2.
+ */
+ xm1d2_len_u16 = (xm1d2_len + 1) >> 1;
+ t += xm1d2_len_u16;
+ tlen -= xm1d2_len_u16;
+
+ xlen = (x[0] + 15) >> 4;
+ asize = x[0] - 1 - EQ0(x[0] & 15);
+ x0i = br_i15_ninv15(x[1]);
+ while (n -- > 0) {
+ uint16_t *a;
+ uint32_t eq1, eqm1;
+
+ /*
+ * Generate a random base. We don't need the base to be
+ * really uniform modulo x, so we just get a random
+ * number which is one bit shorter than x.
+ */
+ a = t;
+ a[0] = x[0];
+ a[xlen] = 0;
+ mkrand(rng, a, asize);
+
+ /*
+ * Compute a^((x-1)/2) mod x. We assume here that the
+ * function will not fail (the temporary array is large
+ * enough).
+ */
+ br_i15_modpow_opt(a, xm1d2, xm1d2_len,
+ x, x0i, t + 1 + xlen, tlen - 1 - xlen);
+
+ /*
+ * We must obtain either 1 or x-1. Note that x is odd,
+ * hence x-1 differs from x only in its low word (no
+ * carry).
+ */
+ eq1 = a[1] ^ 1;
+ eqm1 = a[1] ^ (x[1] - 1);
+ for (u = 2; u <= xlen; u ++) {
+ eq1 |= a[u];
+ eqm1 |= a[u] ^ x[u];
+ }
+
+ if ((EQ0(eq1) | EQ0(eqm1)) == 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Create a random prime of the provided size. 'size' is the _encoded_
+ * bit length. The two top bits and the two bottom bits are set to 1.
+ */
+static void
+mkprime(const br_prng_class **rng, uint16_t *x, uint32_t esize,
+ uint32_t pubexp, uint16_t *t, size_t tlen)
+{
+ size_t len;
+
+ x[0] = esize;
+ len = (esize + 15) >> 4;
+ for (;;) {
+ size_t u;
+ uint32_t m3, m5, m7, m11;
+ int rounds;
+
+ /*
+ * Generate random bits. We force the two top bits and the
+ * two bottom bits to 1.
+ */
+ mkrand(rng, x, esize);
+ if ((esize & 15) == 0) {
+ x[len] |= 0x6000;
+ } else if ((esize & 15) == 1) {
+ x[len] |= 0x0001;
+ x[len - 1] |= 0x4000;
+ } else {
+ x[len] |= 0x0003 << ((esize & 15) - 2);
+ }
+ x[1] |= 0x0003;
+
+ /*
+ * Trial division with low primes (3, 5, 7 and 11). We
+ * use the following properties:
+ *
+ * 2^2 = 1 mod 3
+ * 2^4 = 1 mod 5
+ * 2^3 = 1 mod 7
+ * 2^10 = 1 mod 11
+ */
+ m3 = 0;
+ m5 = 0;
+ m7 = 0;
+ m11 = 0;
+ for (u = 0; u < len; u ++) {
+ uint32_t w;
+
+ w = x[1 + u];
+ m3 += w << (u & 1);
+ m3 = (m3 & 0xFF) + (m3 >> 8);
+ m5 += w << ((4 - u) & 3);
+ m5 = (m5 & 0xFF) + (m5 >> 8);
+ m7 += w;
+ m7 = (m7 & 0x1FF) + (m7 >> 9);
+ m11 += w << (5 & -(u & 1));
+ m11 = (m11 & 0x3FF) + (m11 >> 10);
+ }
+
+ /*
+ * Maximum values of m* at this point:
+ * m3: 511
+ * m5: 2310
+ * m7: 510
+ * m11: 2047
+ * We use the same properties to make further reductions.
+ */
+
+ m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 46 */
+ m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 16 */
+ m3 = ((m3 * 43) >> 5) & 3;
+
+ m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 263 */
+ m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 30 */
+ m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 15 */
+ m5 -= 10 & -GT(m5, 9);
+ m5 -= 5 & -GT(m5, 4);
+
+ m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 69 */
+ m7 = (m7 & 7) + (m7 >> 3); /* max: 14 */
+ m7 = ((m7 * 147) >> 7) & 7;
+
+ /*
+ * 2^5 = 32 = -1 mod 11.
+ */
+ m11 = (m11 & 0x1F) + 66 - (m11 >> 5); /* max: 97 */
+ m11 -= 88 & -GT(m11, 87);
+ m11 -= 44 & -GT(m11, 43);
+ m11 -= 22 & -GT(m11, 21);
+ m11 -= 11 & -GT(m11, 10);
+
+ /*
+ * If any of these modulo is 0, then the candidate is
+ * not prime. Also, if pubexp is 3, 5, 7 or 11, and the
+ * corresponding modulus is 1, then the candidate must
+ * be rejected, because we need e to be invertible
+ * modulo p-1. We can use simple comparisons here
+ * because they won't leak information on a candidate
+ * that we keep, only on one that we reject (and is thus
+ * not secret).
+ */
+ if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) {
+ continue;
+ }
+ if ((pubexp == 3 && m3 == 1)
+ || (pubexp == 5 && m5 == 5)
+ || (pubexp == 7 && m5 == 7)
+ || (pubexp == 11 && m5 == 11))
+ {
+ continue;
+ }
+
+ /*
+ * More trial divisions.
+ */
+ if (!trial_divisions(x, t)) {
+ continue;
+ }
+
+ /*
+ * Miller-Rabin algorithm. Since we selected a random
+ * integer, not a maliciously crafted integer, we can use
+ * relatively few rounds to lower the risk of a false
+ * positive (i.e. declaring prime a non-prime) under
+ * 2^(-80). It is not useful to lower the probability much
+ * below that, since that would be substantially below
+ * the probability of the hardware misbehaving. Sufficient
+ * numbers of rounds are extracted from the Handbook of
+ * Applied Cryptography, note 4.49 (page 149).
+ *
+ * Since we work on the encoded size (esize), we need to
+ * compare with encoded thresholds.
+ */
+ if (esize < 320) {
+ rounds = 12;
+ } else if (esize < 480) {
+ rounds = 9;
+ } else if (esize < 693) {
+ rounds = 6;
+ } else if (esize < 906) {
+ rounds = 4;
+ } else if (esize < 1386) {
+ rounds = 3;
+ } else {
+ rounds = 2;
+ }
+
+ if (miller_rabin(rng, x, rounds, t, tlen)) {
+ return;
+ }
+ }
+}
+
+/*
+ * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided
+ * as parameter (with announced bit length equal to that of p). This
+ * function computes d = 1/e mod p-1 (for an odd integer e). Returned
+ * value is 1 on success, 0 on error (an error is reported if e is not
+ * invertible modulo p-1).
+ *
+ * The temporary buffer (t) must have room for at least 4 integers of
+ * the size of p.
+ */
+static uint32_t
+invert_pubexp(uint16_t *d, const uint16_t *m, uint32_t e, uint16_t *t)
+{
+ uint16_t *f;
+ uint32_t r;
+
+ f = t;
+ t += 1 + ((m[0] + 15) >> 4);
+
+ /*
+ * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd.
+ */
+ br_i15_zero(d, m[0]);
+ d[1] = 1;
+ br_i15_zero(f, m[0]);
+ f[1] = e & 0x7FFF;
+ f[2] = (e >> 15) & 0x7FFF;
+ f[3] = e >> 30;
+ r = br_i15_moddiv(d, f, m, br_i15_ninv15(m[1]), t);
+
+ /*
+ * We really want d = 1/e mod p-1, with p = 2m. By the CRT,
+ * the result is either the d we got, or d + m.
+ *
+ * Let's write e*d = 1 + k*m, for some integer k. Integers e
+ * and m are odd. If d is odd, then e*d is odd, which implies
+ * that k must be even; in that case, e*d = 1 + (k/2)*2m, and
+ * thus d is already fine. Conversely, if d is even, then k
+ * is odd, and we must add m to d in order to get the correct
+ * result.
+ */
+ br_i15_add(d, m, (uint32_t)(1 - (d[1] & 1)));
+
+ return r;
+}
+
+/*
+ * Swap two buffers in RAM. They must be disjoint.
+ */
+static void
+bufswap(void *b1, void *b2, size_t len)
+{
+ size_t u;
+ unsigned char *buf1, *buf2;
+
+ buf1 = b1;
+ buf2 = b2;
+ for (u = 0; u < len; u ++) {
+ unsigned w;
+
+ w = buf1[u];
+ buf1[u] = buf2[u];
+ buf2[u] = w;
+ }
+}
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_keygen(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp)
+{
+ uint32_t esize_p, esize_q;
+ size_t plen, qlen, tlen;
+ uint16_t *p, *q, *t;
+ uint16_t tmp[TEMPS];
+ uint32_t r;
+
+ if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) {
+ return 0;
+ }
+ if (pubexp == 0) {
+ pubexp = 3;
+ } else if (pubexp == 1 || (pubexp & 1) == 0) {
+ return 0;
+ }
+
+ esize_p = (size + 1) >> 1;
+ esize_q = size - esize_p;
+ sk->n_bitlen = size;
+ sk->p = kbuf_priv;
+ sk->plen = (esize_p + 7) >> 3;
+ sk->q = sk->p + sk->plen;
+ sk->qlen = (esize_q + 7) >> 3;
+ sk->dp = sk->q + sk->qlen;
+ sk->dplen = sk->plen;
+ sk->dq = sk->dp + sk->dplen;
+ sk->dqlen = sk->qlen;
+ sk->iq = sk->dq + sk->dqlen;
+ sk->iqlen = sk->plen;
+
+ if (pk != NULL) {
+ pk->n = kbuf_pub;
+ pk->nlen = (size + 7) >> 3;
+ pk->e = pk->n + pk->nlen;
+ pk->elen = 4;
+ br_enc32be(pk->e, pubexp);
+ while (*pk->e == 0) {
+ pk->e ++;
+ pk->elen --;
+ }
+ }
+
+ /*
+ * We now switch to encoded sizes.
+ *
+ * floor((x * 17477) / (2^18)) is equal to floor(x/15) for all
+ * integers x from 0 to 23833.
+ */
+ esize_p += MUL15(esize_p, 17477) >> 18;
+ esize_q += MUL15(esize_q, 17477) >> 18;
+ plen = (esize_p + 15) >> 4;
+ qlen = (esize_q + 15) >> 4;
+ p = tmp;
+ q = p + 1 + plen;
+ t = q + 1 + qlen;
+ tlen = ((sizeof tmp) / sizeof(uint16_t)) - (2 + plen + qlen);
+
+ /*
+ * When looking for primes p and q, we temporarily divide
+ * candidates by 2, in order to compute the inverse of the
+ * public exponent.
+ */
+
+ for (;;) {
+ mkprime(rng, p, esize_p, pubexp, t, tlen);
+ br_i15_rshift(p, 1);
+ if (invert_pubexp(t, p, pubexp, t + 1 + plen)) {
+ br_i15_add(p, p, 1);
+ p[1] |= 1;
+ br_i15_encode(sk->p, sk->plen, p);
+ br_i15_encode(sk->dp, sk->dplen, t);
+ break;
+ }
+ }
+
+ for (;;) {
+ mkprime(rng, q, esize_q, pubexp, t, tlen);
+ br_i15_rshift(q, 1);
+ if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) {
+ br_i15_add(q, q, 1);
+ q[1] |= 1;
+ br_i15_encode(sk->q, sk->qlen, q);
+ br_i15_encode(sk->dq, sk->dqlen, t);
+ break;
+ }
+ }
+
+ /*
+ * If p and q have the same size, then it is possible that q > p
+ * (when the target modulus size is odd, we generate p with a
+ * greater bit length than q). If q > p, we want to swap p and q
+ * (and also dp and dq) for two reasons:
+ * - The final step below (inversion of q modulo p) is easier if
+ * p > q.
+ * - While BearSSL's RSA code is perfectly happy with RSA keys such
+ * that p < q, some other implementations have restrictions and
+ * require p > q.
+ *
+ * Note that we can do a simple non-constant-time swap here,
+ * because the only information we leak here is that we insist on
+ * returning p and q such that p > q, which is not a secret.
+ */
+ if (esize_p == esize_q && br_i15_sub(p, q, 0) == 1) {
+ bufswap(p, q, (1 + plen) * sizeof *p);
+ bufswap(sk->p, sk->q, sk->plen);
+ bufswap(sk->dp, sk->dq, sk->dplen);
+ }
+
+ /*
+ * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p.
+ *
+ * We ensured that p >= q, so this is just a matter of updating the
+ * header word for q (and possibly adding an extra word).
+ *
+ * Theoretically, the call below may fail, in case we were
+ * extraordinarily unlucky, and p = q. Another failure case is if
+ * Miller-Rabin failed us _twice_, and p and q are non-prime and
+ * have a factor is common. We report the error mostly because it
+ * is cheap and we can, but in practice this never happens (or, at
+ * least, it happens way less often than hardware glitches).
+ */
+ q[0] = p[0];
+ if (plen > qlen) {
+ q[plen] = 0;
+ t ++;
+ tlen --;
+ }
+ br_i15_zero(t, p[0]);
+ t[1] = 1;
+ r = br_i15_moddiv(t, q, p, br_i15_ninv15(p[1]), t + 1 + plen);
+ br_i15_encode(sk->iq, sk->iqlen, t);
+
+ /*
+ * Compute the public modulus too, if required.
+ */
+ if (pk != NULL) {
+ br_i15_zero(t, p[0]);
+ br_i15_mulacc(t, p, q);
+ br_i15_encode(pk->n, pk->nlen, t);
+ }
+
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_keygen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_modulus.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_modulus.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_modulus.c (revision 346145)
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk)
+{
+ uint16_t tmp[2 * ((BR_MAX_RSA_SIZE + 14) / 15) + 5];
+ uint16_t *t, *p, *q;
+ const unsigned char *pbuf, *qbuf;
+ size_t nlen, plen, qlen, tlen;
+
+ /*
+ * Compute actual byte and lengths for p and q.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+
+ t = tmp;
+ tlen = (sizeof tmp) / (sizeof tmp[0]);
+
+ /*
+ * Decode p.
+ */
+ if ((15 * tlen) < (plen << 3) + 15) {
+ return 0;
+ }
+ br_i15_decode(t, pbuf, plen);
+ p = t;
+ plen = (p[0] + 31) >> 4;
+ t += plen;
+ tlen -= plen;
+
+ /*
+ * Decode q.
+ */
+ if ((15 * tlen) < (qlen << 3) + 15) {
+ return 0;
+ }
+ br_i15_decode(t, qbuf, qlen);
+ q = t;
+ qlen = (q[0] + 31) >> 4;
+ t += qlen;
+ tlen -= qlen;
+
+ /*
+ * Computation can proceed only if we have enough room for the
+ * modulus.
+ */
+ if (tlen < (plen + qlen + 1)) {
+ return 0;
+ }
+
+ /*
+ * Private key already contains the modulus bit length, from which
+ * we can infer the output length. Even if n is NULL, we still had
+ * to decode p and q to make sure that the product can be computed.
+ */
+ nlen = (sk->n_bitlen + 7) >> 3;
+ if (n != NULL) {
+ br_i15_zero(t, p[0]);
+ br_i15_mulacc(t, p, q);
+ br_i15_encode(n, nlen, t);
+ }
+ return nlen;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_modulus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_decrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_decrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_decrypt.c (revision 346145)
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i15_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_decrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_encrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_encrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_encrypt.c (revision 346145)
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i15_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i15_public(dst, dlen, pk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_oaep_encrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_sign.c (revision 346145)
@@ -0,0 +1,37 @@
+/*
+ * 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"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i15_private(x, sk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_vrfy.c (revision 346145)
@@ -0,0 +1,43 @@
+/*
+ * 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"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i15_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_pkcs1_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_priv.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_priv.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_priv.c (revision 346145)
@@ -0,0 +1,209 @@
+/*
+ * 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"
+
+#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15))
+#define TLEN (8 * U)
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ size_t fwlen;
+ uint16_t p0i, q0i;
+ size_t xlen, u;
+ uint16_t tmp[1 + TLEN];
+ long z;
+ uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t r;
+
+ /*
+ * Compute the actual lengths of p and q, in bytes.
+ * These lengths are not considered secret (we cannot really hide
+ * them anyway in constant-time code).
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+
+ /*
+ * Compute the maximum factor length, in words.
+ */
+ z = (long)(plen > qlen ? plen : qlen) << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 15;
+ fwlen ++;
+ }
+ /*
+ * Round up the word length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * We need to fit at least 6 values in the stack buffer.
+ */
+ if (6 * fwlen > TLEN) {
+ return 0;
+ }
+
+ /*
+ * Compute signature length (in bytes).
+ */
+ xlen = (sk->n_bitlen + 7) >> 3;
+
+ /*
+ * Ensure 32-bit alignment for value words.
+ */
+ mq = tmp;
+ if (((uintptr_t)mq & 2) == 0) {
+ mq ++;
+ }
+
+ /*
+ * Decode q.
+ */
+ br_i15_decode(mq, q, qlen);
+
+ /*
+ * Decode p.
+ */
+ t1 = mq + fwlen;
+ br_i15_decode(t1, p, plen);
+
+ /*
+ * Compute the modulus (product of the two factors), to compare
+ * it with the source value. We use br_i15_mulacc(), since it's
+ * already used later on.
+ */
+ t2 = mq + 2 * fwlen;
+ br_i15_zero(t2, mq[0]);
+ br_i15_mulacc(t2, mq, t1);
+
+ /*
+ * We encode the modulus into bytes, to perform the comparison
+ * with bytes. We know that the product length, in bytes, is
+ * exactly xlen.
+ * The comparison actually computes the carry when subtracting
+ * the modulus from the source value; that carry must be 1 for
+ * a value in the correct range. We keep it in r, which is our
+ * accumulator for the error code.
+ */
+ t3 = mq + 4 * fwlen;
+ br_i15_encode(t3, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)t3)[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Move the decoded p to another temporary buffer.
+ */
+ mp = mq + 2 * fwlen;
+ memmove(mp, t1, fwlen * sizeof *t1);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i15_ninv15(mq[1]);
+ s2 = mq + fwlen;
+ br_i15_decode_reduce(s2, x, xlen, mq);
+ r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
+ mq + 3 * fwlen, TLEN - 3 * fwlen);
+
+ /*
+ * Compute s1 = x^dq mod q.
+ */
+ p0i = br_i15_ninv15(mp[1]);
+ s1 = mq + 3 * fwlen;
+ br_i15_decode_reduce(s1, x, xlen, mp);
+ r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
+ mq + 4 * fwlen, TLEN - 4 * fwlen);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i15_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ t1 = mq + 4 * fwlen;
+ t2 = mq + 5 * fwlen;
+ br_i15_reduce(t2, s2, mp);
+ br_i15_add(s1, mp, br_i15_sub(s1, t2, 1));
+ br_i15_to_monty(s1, mp);
+ br_i15_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i15_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed, so we can
+ * reuse them for t3. Moreover, the first step of the computation
+ * is to copy s2 into t3, after which s2 is not needed. Right
+ * now, mq is in slot 0, s2 is in slot 1, and t2 in slot 5.
+ * Therefore, we have ample room for t3 by simply using s2.
+ */
+ t3 = s2;
+ br_i15_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i15_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_priv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_privexp.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_privexp.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_privexp.c (revision 346145)
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i15_compute_privexp(void *d,
+ const br_rsa_private_key *sk, uint32_t e)
+{
+ /*
+ * We want to invert e modulo phi = (p-1)(q-1). This first
+ * requires computing phi, which is easy since we have the factors
+ * p and q in the private key structure.
+ *
+ * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer.
+ * We could invert e modulo phi/4 then patch the result to
+ * modulo phi, but this would involve assembling three modulus-wide
+ * values (phi/4, 1 and e) and calling moddiv, that requires
+ * three more temporaries, for a total of six big integers, or
+ * slightly more than 3 kB of stack space for RSA-4096. This
+ * exceeds our stack requirements.
+ *
+ * Instead, we first use one step of the extended GCD:
+ *
+ * - We compute phi = k*e + r (Euclidean division of phi by e).
+ * If public exponent e is correct, then r != 0 (e must be
+ * invertible modulo phi). We also have k != 0 since we
+ * enforce non-ridiculously-small factors.
+ *
+ * - We find small u, v such that u*e - v*r = 1 (using a
+ * binary GCD; we can arrange for u < r and v < e, i.e. all
+ * values fit on 32 bits).
+ *
+ * - Solution is: d = u + v*k
+ * This last computation is exact: since u < r and v < e,
+ * the above implies d < r + e*((phi-r)/e) = phi
+ */
+
+ uint16_t tmp[4 * ((BR_MAX_RSA_FACTOR + 14) / 15) + 12];
+ uint16_t *p, *q, *k, *m, *z, *phi;
+ const unsigned char *pbuf, *qbuf;
+ size_t plen, qlen, u, len, dlen;
+ uint32_t r, a, b, u0, v0, u1, v1, he, hr;
+ int i;
+
+ /*
+ * Check that e is correct.
+ */
+ if (e < 3 || (e & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Check lengths of p and q, and that they are both odd.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)
+ || (pbuf[plen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+ if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8)
+ || (qbuf[qlen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+
+ /*
+ * Output length is that of the modulus.
+ */
+ dlen = (sk->n_bitlen + 7) >> 3;
+ if (d == NULL) {
+ return dlen;
+ }
+
+ p = tmp;
+ br_i15_decode(p, pbuf, plen);
+ plen = (p[0] + 15) >> 4;
+ q = p + 1 + plen;
+ br_i15_decode(q, qbuf, qlen);
+ qlen = (q[0] + 15) >> 4;
+
+ /*
+ * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that
+ * we do not need anymore). The mulacc function sets the announced
+ * bit length of t to be the sum of the announced bit lengths of
+ * p-1 and q-1, which is usually exact but may overshoot by one 1
+ * bit in some cases; we readjust it to its true length.
+ */
+ p[1] --;
+ q[1] --;
+ phi = q + 1 + qlen;
+ br_i15_zero(phi, p[0]);
+ br_i15_mulacc(phi, p, q);
+ len = (phi[0] + 15) >> 4;
+ memmove(tmp, phi, (1 + len) * sizeof *phi);
+ phi = tmp;
+ phi[0] = br_i15_bit_length(phi + 1, len);
+ len = (phi[0] + 15) >> 4;
+
+ /*
+ * Divide phi by public exponent e. The final remainder r must be
+ * non-zero (otherwise, the key is invalid). The quotient is k,
+ * which we write over phi, since we don't need phi after that.
+ */
+ r = 0;
+ for (u = len; u >= 1; u --) {
+ /*
+ * Upon entry, r < e, and phi[u] < 2^15; hence,
+ * hi:lo < e*2^15. Thus, the produced word k[u]
+ * must be lower than 2^15, and the new remainder r
+ * is lower than e.
+ */
+ uint32_t hi, lo;
+
+ hi = r >> 17;
+ lo = (r << 15) + phi[u];
+ phi[u] = br_divrem(hi, lo, e, &r);
+ }
+ if (r == 0) {
+ return 0;
+ }
+ k = phi;
+
+ /*
+ * Compute u and v such that u*e - v*r = GCD(e,r). We use
+ * a binary GCD algorithm, with 6 extra integers a, b,
+ * u0, u1, v0 and v1. Initial values are:
+ * a = e u0 = 1 v0 = 0
+ * b = r u1 = r v1 = e-1
+ * The following invariants are maintained:
+ * a = u0*e - v0*r
+ * b = u1*e - v1*r
+ * 0 < a <= e
+ * 0 < b <= r
+ * 0 <= u0 <= r
+ * 0 <= v0 <= e
+ * 0 <= u1 <= r
+ * 0 <= v1 <= e
+ *
+ * At each iteration, we reduce either a or b by one bit, and
+ * adjust u0, u1, v0 and v1 to maintain the invariants:
+ * - if a is even, then a <- a/2
+ * - otherwise, if b is even, then b <- b/2
+ * - otherwise, if a > b, then a <- (a-b)/2
+ * - otherwise, if b > a, then b <- (b-a)/2
+ * Algorithm stops when a = b. At that point, the common value
+ * is the GCD of e and r; it must be 1 (otherwise, the private
+ * key or public exponent is not valid). The (u0,v0) or (u1,v1)
+ * pairs are the solution we are looking for.
+ *
+ * Since either a or b is reduced by at least 1 bit at each
+ * iteration, 62 iterations are enough to reach the end
+ * condition.
+ *
+ * To maintain the invariants, we must compute the same operations
+ * on the u* and v* values that we do on a and b:
+ * - When a is divided by 2, u0 and v0 must be divided by 2.
+ * - When b is divided by 2, u1 and v1 must be divided by 2.
+ * - When b is subtracted from a, u1 and v1 are subtracted from
+ * u0 and v0, respectively.
+ * - When a is subtracted from b, u0 and v0 are subtracted from
+ * u1 and v1, respectively.
+ *
+ * However, we want to keep the u* and v* values in their proper
+ * ranges. The following remarks apply:
+ *
+ * - When a is divided by 2, then a is even. Therefore:
+ *
+ * * If r is odd, then u0 and v0 must have the same parity;
+ * if they are both odd, then adding r to u0 and e to v0
+ * makes them both even, and the division by 2 brings them
+ * back to the proper range.
+ *
+ * * If r is even, then u0 must be even; if v0 is odd, then
+ * adding r to u0 and e to v0 makes them both even, and the
+ * division by 2 brings them back to the proper range.
+ *
+ * Thus, all we need to do is to look at the parity of v0,
+ * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid
+ * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the
+ * division (r+1 does not overflow since r < e; and (e/2)+1
+ * is equal to (e+1)/2 since e is odd).
+ *
+ * - When we subtract b from a, three cases may occur:
+ *
+ * * u1 <= u0 and v1 <= v0: just do the subtractions
+ *
+ * * u1 > u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * * u1 <= u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * The fourth case (u1 > u0 and v1 <= v0) is not possible
+ * because it would contradict "b < a" (which is the reason
+ * why we subtract b from a).
+ *
+ * The tricky case is the third one: from the equations, it
+ * seems that u0 may go out of range. However, the invariants
+ * and ranges of other values imply that, in that case, the
+ * new u0 does not actually exceed the range.
+ *
+ * We can thus handle the subtraction by adding (r,e) based
+ * solely on the comparison between v0 and v1.
+ */
+ a = e;
+ b = r;
+ u0 = 1;
+ v0 = 0;
+ u1 = r;
+ v1 = e - 1;
+ hr = (r + 1) >> 1;
+ he = (e >> 1) + 1;
+ for (i = 0; i < 62; i ++) {
+ uint32_t oa, ob, agtb, bgta;
+ uint32_t sab, sba, da, db;
+ uint32_t ctl;
+
+ oa = a & 1; /* 1 if a is odd */
+ ob = b & 1; /* 1 if b is odd */
+ agtb = GT(a, b); /* 1 if a > b */
+ bgta = GT(b, a); /* 1 if b > a */
+
+ sab = oa & ob & agtb; /* 1 if a <- a-b */
+ sba = oa & ob & bgta; /* 1 if b <- b-a */
+
+ /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */
+ ctl = GT(v1, v0);
+ a -= b & -sab;
+ u0 -= (u1 - (r & -ctl)) & -sab;
+ v0 -= (v1 - (e & -ctl)) & -sab;
+
+ /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */
+ ctl = GT(v0, v1);
+ b -= a & -sba;
+ u1 -= (u0 - (r & -ctl)) & -sba;
+ v1 -= (v0 - (e & -ctl)) & -sba;
+
+ da = NOT(oa) | sab; /* 1 if a <- a/2 */
+ db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */
+
+ /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */
+ ctl = v0 & 1;
+ a ^= (a ^ (a >> 1)) & -da;
+ u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da;
+ v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da;
+
+ /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */
+ ctl = v1 & 1;
+ b ^= (b ^ (b >> 1)) & -db;
+ u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db;
+ v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db;
+ }
+
+ /*
+ * Check that the GCD is indeed 1. If not, then the key is invalid
+ * (and there's no harm in leaking that piece of information).
+ */
+ if (a != 1) {
+ return 0;
+ }
+
+ /*
+ * Now we have u0*e - v0*r = 1. Let's compute the result as:
+ * d = u0 + v0*k
+ * We still have k in the tmp[] array, and its announced bit
+ * length is that of phi.
+ */
+ m = k + 1 + len;
+ m[0] = (2 << 4) + 2; /* bit length is 32 bits, encoded */
+ m[1] = v0 & 0x7FFF;
+ m[2] = (v0 >> 15) & 0x7FFF;
+ m[3] = v0 >> 30;
+ z = m + 4;
+ br_i15_zero(z, k[0]);
+ z[1] = u0 & 0x7FFF;
+ z[2] = (u0 >> 15) & 0x7FFF;
+ z[3] = u0 >> 30;
+ br_i15_mulacc(z, k, m);
+
+ /*
+ * Encode the result.
+ */
+ br_i15_encode(d, dlen, z);
+ return dlen;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_privexp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_sign.c (revision 346145)
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i15_private(x, sk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_vrfy.c (revision 346145)
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i15_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_pss_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_pub.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_pub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_pub.c (revision 346145)
@@ -0,0 +1,113 @@
+/*
+ * 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"
+
+/*
+ * As a strict minimum, we need four buffers that can hold a
+ * modular integer.
+ */
+#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 14) / 15)))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint16_t tmp[1 + TLEN];
+ uint16_t *m, *a, *t;
+ size_t fwlen;
+ long z;
+ uint16_t m0i;
+ uint32_t r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ z = (long)nlen << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 15;
+ fwlen ++;
+ }
+ /*
+ * Round up length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * The modulus gets decoded into m[].
+ * The value to exponentiate goes into a[].
+ * The temporaries for modular exponentiations are in t[].
+ *
+ * We want the first value word of each integer to be aligned
+ * on a 32-bit boundary.
+ */
+ m = tmp;
+ if (((uintptr_t)m & 2) == 0) {
+ m ++;
+ }
+ a = m + fwlen;
+ t = m + 2 * fwlen;
+
+ /*
+ * Decode the modulus.
+ */
+ br_i15_decode(m, n, nlen);
+ m0i = br_i15_ninv15(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i15_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i15_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen);
+
+ /*
+ * Encode the result.
+ */
+ br_i15_encode(x, xlen, a);
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_pub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i15_pubexp.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i15_pubexp.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i15_pubexp.c (revision 346145)
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Recompute public exponent, based on factor p and reduced private
+ * exponent dp.
+ */
+static uint32_t
+get_pubexp(const unsigned char *pbuf, size_t plen,
+ const unsigned char *dpbuf, size_t dplen)
+{
+ /*
+ * dp is the inverse of e modulo p-1. If p = 3 mod 4, then
+ * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1;
+ * thus, dp must be odd.
+ *
+ * We compute the inverse of dp modulo (p-1)/2. This requires
+ * first reducing dp modulo (p-1)/2 (this can be done with a
+ * conditional subtract, no need to use the generic modular
+ * reduction function); then, we use moddiv.
+ */
+
+ uint16_t tmp[6 * ((BR_MAX_RSA_FACTOR + 29) / 15)];
+ uint16_t *p, *dp, *x;
+ size_t len;
+ uint32_t e;
+
+ /*
+ * Compute actual factor length (in bytes) and check that it fits
+ * under our size constraints.
+ */
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) {
+ return 0;
+ }
+
+ /*
+ * Compute actual reduced exponent length (in bytes) and check that
+ * it is not longer than p.
+ */
+ while (dplen > 0 && *dpbuf == 0) {
+ dpbuf ++;
+ dplen --;
+ }
+ if (dplen > plen || dplen == 0
+ || (dplen == plen && dpbuf[0] > pbuf[0]))
+ {
+ return 0;
+ }
+
+ /*
+ * Verify that p = 3 mod 4 and that dp is odd.
+ */
+ if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) {
+ return 0;
+ }
+
+ /*
+ * Decode p and compute (p-1)/2.
+ */
+ p = tmp;
+ br_i15_decode(p, pbuf, plen);
+ len = (p[0] + 31) >> 4;
+ br_i15_rshift(p, 1);
+
+ /*
+ * Decode dp and make sure its announced bit length matches that of
+ * p (we already know that the size of dp, in bits, does not exceed
+ * the size of p, so we just have to copy the header word).
+ */
+ dp = p + len;
+ memset(dp, 0, len * sizeof *dp);
+ br_i15_decode(dp, dpbuf, dplen);
+ dp[0] = p[0];
+
+ /*
+ * Subtract (p-1)/2 from dp if necessary.
+ */
+ br_i15_sub(dp, p, NOT(br_i15_sub(dp, p, 0)));
+
+ /*
+ * If another subtraction is needed, then this means that the
+ * value was invalid. We don't care to leak information about
+ * invalid keys.
+ */
+ if (br_i15_sub(dp, p, 0) == 0) {
+ return 0;
+ }
+
+ /*
+ * Invert dp modulo (p-1)/2. If the inversion fails, then the
+ * key value was invalid.
+ */
+ x = dp + len;
+ br_i15_zero(x, p[0]);
+ x[1] = 1;
+ if (br_i15_moddiv(x, dp, p, br_i15_ninv15(p[1]), x + len) == 0) {
+ return 0;
+ }
+
+ /*
+ * We now have an inverse. We must set it to zero (error) if its
+ * length is greater than 32 bits and/or if it is an even integer.
+ * Take care that the bit_length function returns an encoded
+ * bit length.
+ */
+ e = (uint32_t)x[1] | ((uint32_t)x[2] << 15) | ((uint32_t)x[3] << 30);
+ e &= -LT(br_i15_bit_length(x + 1, len - 1), 35);
+ e &= -(e & 1);
+ return e;
+}
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk)
+{
+ /*
+ * Get the public exponent from both p and q. This is the right
+ * exponent if we get twice the same value.
+ */
+ uint32_t ep, eq;
+
+ ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen);
+ eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen);
+ return ep & -EQ(ep, eq);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i15_pubexp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen.c (revision 346145)
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_keygen(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp)
+{
+ return br_rsa_i31_keygen_inner(rng,
+ sk, kbuf_priv, pk, kbuf_pub, size, pubexp,
+ &br_i31_modpow_opt);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen_inner.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen_inner.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen_inner.c (revision 346145)
@@ -0,0 +1,608 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Make a random integer of the provided size. The size is encoded.
+ * The header word is untouched.
+ */
+static void
+mkrand(const br_prng_class **rng, uint32_t *x, uint32_t esize)
+{
+ size_t u, len;
+ unsigned m;
+
+ len = (esize + 31) >> 5;
+ (*rng)->generate(rng, x + 1, len * sizeof(uint32_t));
+ for (u = 1; u < len; u ++) {
+ x[u] &= 0x7FFFFFFF;
+ }
+ m = esize & 31;
+ if (m == 0) {
+ x[len] &= 0x7FFFFFFF;
+ } else {
+ x[len] &= 0x7FFFFFFF >> (31 - m);
+ }
+}
+
+/*
+ * This is the big-endian unsigned representation of the product of
+ * all small primes from 13 to 1481.
+ */
+static const unsigned char SMALL_PRIMES[] = {
+ 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A,
+ 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7,
+ 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37,
+ 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5,
+ 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E,
+ 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6,
+ 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C,
+ 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40,
+ 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50,
+ 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7,
+ 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3,
+ 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E,
+ 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC,
+ 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08,
+ 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B,
+ 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22,
+ 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77,
+ 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E,
+ 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80,
+ 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8,
+ 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2,
+ 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC,
+ 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54,
+ 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74,
+ 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C,
+ 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD
+};
+
+/*
+ * We need temporary values for at least 7 integers of the same size
+ * as a factor (including header word); more space helps with performance
+ * (in modular exponentiations), but we much prefer to remain under
+ * 2 kilobytes in total, to save stack space. The macro TEMPS below
+ * exceeds 512 (which is a count in 32-bit words) when BR_MAX_RSA_SIZE
+ * is greater than 4464 (default value is 4096, so the 2-kB limit is
+ * maintained unless BR_MAX_RSA_SIZE was modified).
+ */
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define ROUND2(x) ((((x) + 1) >> 1) << 1)
+
+#define TEMPS MAX(512, ROUND2(7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 61) / 31)))
+
+/*
+ * Perform trial division on a candidate prime. This computes
+ * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The
+ * br_i31_moddiv() function will report an error if y is not invertible
+ * modulo x. Returned value is 1 on success (none of the small primes
+ * divides x), 0 on error (a non-trivial GCD is obtained).
+ *
+ * This function assumes that x is odd.
+ */
+static uint32_t
+trial_divisions(const uint32_t *x, uint32_t *t)
+{
+ uint32_t *y;
+ uint32_t x0i;
+
+ y = t;
+ t += 1 + ((x[0] + 31) >> 5);
+ x0i = br_i31_ninv31(x[1]);
+ br_i31_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x);
+ return br_i31_moddiv(y, y, x, x0i, t);
+}
+
+/*
+ * Perform n rounds of Miller-Rabin on the candidate prime x. This
+ * function assumes that x = 3 mod 4.
+ *
+ * Returned value is 1 on success (all rounds completed successfully),
+ * 0 otherwise.
+ */
+static uint32_t
+miller_rabin(const br_prng_class **rng, const uint32_t *x, int n,
+ uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31)
+{
+ /*
+ * Since x = 3 mod 4, the Miller-Rabin test is simple:
+ * - get a random base a (such that 1 < a < x-1)
+ * - compute z = a^((x-1)/2) mod x
+ * - if z != 1 and z != x-1, the number x is composite
+ *
+ * We generate bases 'a' randomly with a size which is
+ * one bit less than x, which ensures that a < x-1. It
+ * is not useful to verify that a > 1 because the probability
+ * that we get a value a equal to 0 or 1 is much smaller
+ * than the probability of our Miller-Rabin tests not to
+ * detect a composite, which is already quite smaller than the
+ * probability of the hardware misbehaving and return a
+ * composite integer because of some glitch (e.g. bad RAM
+ * or ill-timed cosmic ray).
+ */
+ unsigned char *xm1d2;
+ size_t xlen, xm1d2_len, xm1d2_len_u32, u;
+ uint32_t asize;
+ unsigned cc;
+ uint32_t x0i;
+
+ /*
+ * Compute (x-1)/2 (encoded).
+ */
+ xm1d2 = (unsigned char *)t;
+ xm1d2_len = ((x[0] - (x[0] >> 5)) + 7) >> 3;
+ br_i31_encode(xm1d2, xm1d2_len, x);
+ cc = 0;
+ for (u = 0; u < xm1d2_len; u ++) {
+ unsigned w;
+
+ w = xm1d2[u];
+ xm1d2[u] = (unsigned char)((w >> 1) | cc);
+ cc = w << 7;
+ }
+
+ /*
+ * We used some words of the provided buffer for (x-1)/2.
+ */
+ xm1d2_len_u32 = (xm1d2_len + 3) >> 2;
+ t += xm1d2_len_u32;
+ tlen -= xm1d2_len_u32;
+
+ xlen = (x[0] + 31) >> 5;
+ asize = x[0] - 1 - EQ0(x[0] & 31);
+ x0i = br_i31_ninv31(x[1]);
+ while (n -- > 0) {
+ uint32_t *a, *t2;
+ uint32_t eq1, eqm1;
+ size_t t2len;
+
+ /*
+ * Generate a random base. We don't need the base to be
+ * really uniform modulo x, so we just get a random
+ * number which is one bit shorter than x.
+ */
+ a = t;
+ a[0] = x[0];
+ a[xlen] = 0;
+ mkrand(rng, a, asize);
+
+ /*
+ * Compute a^((x-1)/2) mod x. We assume here that the
+ * function will not fail (the temporary array is large
+ * enough).
+ */
+ t2 = t + 1 + xlen;
+ t2len = tlen - 1 - xlen;
+ if ((t2len & 1) != 0) {
+ /*
+ * Since the source array is 64-bit aligned and
+ * has an even number of elements (TEMPS), we
+ * can use the parity of the remaining length to
+ * detect and adjust alignment.
+ */
+ t2 ++;
+ t2len --;
+ }
+ mp31(a, xm1d2, xm1d2_len, x, x0i, t2, t2len);
+
+ /*
+ * We must obtain either 1 or x-1. Note that x is odd,
+ * hence x-1 differs from x only in its low word (no
+ * carry).
+ */
+ eq1 = a[1] ^ 1;
+ eqm1 = a[1] ^ (x[1] - 1);
+ for (u = 2; u <= xlen; u ++) {
+ eq1 |= a[u];
+ eqm1 |= a[u] ^ x[u];
+ }
+
+ if ((EQ0(eq1) | EQ0(eqm1)) == 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Create a random prime of the provided size. 'size' is the _encoded_
+ * bit length. The two top bits and the two bottom bits are set to 1.
+ */
+static void
+mkprime(const br_prng_class **rng, uint32_t *x, uint32_t esize,
+ uint32_t pubexp, uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31)
+{
+ size_t len;
+
+ x[0] = esize;
+ len = (esize + 31) >> 5;
+ for (;;) {
+ size_t u;
+ uint32_t m3, m5, m7, m11;
+ int rounds, s7, s11;
+
+ /*
+ * Generate random bits. We force the two top bits and the
+ * two bottom bits to 1.
+ */
+ mkrand(rng, x, esize);
+ if ((esize & 31) == 0) {
+ x[len] |= 0x60000000;
+ } else if ((esize & 31) == 1) {
+ x[len] |= 0x00000001;
+ x[len - 1] |= 0x40000000;
+ } else {
+ x[len] |= 0x00000003 << ((esize & 31) - 2);
+ }
+ x[1] |= 0x00000003;
+
+ /*
+ * Trial division with low primes (3, 5, 7 and 11). We
+ * use the following properties:
+ *
+ * 2^2 = 1 mod 3
+ * 2^4 = 1 mod 5
+ * 2^3 = 1 mod 7
+ * 2^10 = 1 mod 11
+ */
+ m3 = 0;
+ m5 = 0;
+ m7 = 0;
+ m11 = 0;
+ s7 = 0;
+ s11 = 0;
+ for (u = 0; u < len; u ++) {
+ uint32_t w, w3, w5, w7, w11;
+
+ w = x[1 + u];
+ w3 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */
+ w5 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */
+ w7 = (w & 0x7FFF) + (w >> 15); /* max: 98302 */
+ w11 = (w & 0xFFFFF) + (w >> 20); /* max: 1050622 */
+
+ m3 += w3 << (u & 1);
+ m3 = (m3 & 0xFF) + (m3 >> 8); /* max: 1025 */
+
+ m5 += w5 << ((4 - u) & 3);
+ m5 = (m5 & 0xFFF) + (m5 >> 12); /* max: 4479 */
+
+ m7 += w7 << s7;
+ m7 = (m7 & 0x1FF) + (m7 >> 9); /* max: 1280 */
+ if (++ s7 == 3) {
+ s7 = 0;
+ }
+
+ m11 += w11 << s11;
+ if (++ s11 == 10) {
+ s11 = 0;
+ }
+ m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 526847 */
+ }
+
+ m3 = (m3 & 0x3F) + (m3 >> 6); /* max: 78 */
+ m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 18 */
+ m3 = ((m3 * 43) >> 5) & 3;
+
+ m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 271 */
+ m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 31 */
+ m5 -= 20 & -GT(m5, 19);
+ m5 -= 10 & -GT(m5, 9);
+ m5 -= 5 & -GT(m5, 4);
+
+ m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 82 */
+ m7 = (m7 & 0x07) + (m7 >> 3); /* max: 16 */
+ m7 = ((m7 * 147) >> 7) & 7;
+
+ /*
+ * 2^5 = 32 = -1 mod 11.
+ */
+ m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1536 */
+ m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1023 */
+ m11 = (m11 & 0x1F) + 33 - (m11 >> 5); /* max: 64 */
+ m11 -= 44 & -GT(m11, 43);
+ m11 -= 22 & -GT(m11, 21);
+ m11 -= 11 & -GT(m11, 10);
+
+ /*
+ * If any of these modulo is 0, then the candidate is
+ * not prime. Also, if pubexp is 3, 5, 7 or 11, and the
+ * corresponding modulus is 1, then the candidate must
+ * be rejected, because we need e to be invertible
+ * modulo p-1. We can use simple comparisons here
+ * because they won't leak information on a candidate
+ * that we keep, only on one that we reject (and is thus
+ * not secret).
+ */
+ if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) {
+ continue;
+ }
+ if ((pubexp == 3 && m3 == 1)
+ || (pubexp == 5 && m5 == 5)
+ || (pubexp == 7 && m5 == 7)
+ || (pubexp == 11 && m5 == 11))
+ {
+ continue;
+ }
+
+ /*
+ * More trial divisions.
+ */
+ if (!trial_divisions(x, t)) {
+ continue;
+ }
+
+ /*
+ * Miller-Rabin algorithm. Since we selected a random
+ * integer, not a maliciously crafted integer, we can use
+ * relatively few rounds to lower the risk of a false
+ * positive (i.e. declaring prime a non-prime) under
+ * 2^(-80). It is not useful to lower the probability much
+ * below that, since that would be substantially below
+ * the probability of the hardware misbehaving. Sufficient
+ * numbers of rounds are extracted from the Handbook of
+ * Applied Cryptography, note 4.49 (page 149).
+ *
+ * Since we work on the encoded size (esize), we need to
+ * compare with encoded thresholds.
+ */
+ if (esize < 309) {
+ rounds = 12;
+ } else if (esize < 464) {
+ rounds = 9;
+ } else if (esize < 670) {
+ rounds = 6;
+ } else if (esize < 877) {
+ rounds = 4;
+ } else if (esize < 1341) {
+ rounds = 3;
+ } else {
+ rounds = 2;
+ }
+
+ if (miller_rabin(rng, x, rounds, t, tlen, mp31)) {
+ return;
+ }
+ }
+}
+
+/*
+ * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided
+ * as parameter (with announced bit length equal to that of p). This
+ * function computes d = 1/e mod p-1 (for an odd integer e). Returned
+ * value is 1 on success, 0 on error (an error is reported if e is not
+ * invertible modulo p-1).
+ *
+ * The temporary buffer (t) must have room for at least 4 integers of
+ * the size of p.
+ */
+static uint32_t
+invert_pubexp(uint32_t *d, const uint32_t *m, uint32_t e, uint32_t *t)
+{
+ uint32_t *f;
+ uint32_t r;
+
+ f = t;
+ t += 1 + ((m[0] + 31) >> 5);
+
+ /*
+ * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd.
+ */
+ br_i31_zero(d, m[0]);
+ d[1] = 1;
+ br_i31_zero(f, m[0]);
+ f[1] = e & 0x7FFFFFFF;
+ f[2] = e >> 31;
+ r = br_i31_moddiv(d, f, m, br_i31_ninv31(m[1]), t);
+
+ /*
+ * We really want d = 1/e mod p-1, with p = 2m. By the CRT,
+ * the result is either the d we got, or d + m.
+ *
+ * Let's write e*d = 1 + k*m, for some integer k. Integers e
+ * and m are odd. If d is odd, then e*d is odd, which implies
+ * that k must be even; in that case, e*d = 1 + (k/2)*2m, and
+ * thus d is already fine. Conversely, if d is even, then k
+ * is odd, and we must add m to d in order to get the correct
+ * result.
+ */
+ br_i31_add(d, m, (uint32_t)(1 - (d[1] & 1)));
+
+ return r;
+}
+
+/*
+ * Swap two buffers in RAM. They must be disjoint.
+ */
+static void
+bufswap(void *b1, void *b2, size_t len)
+{
+ size_t u;
+ unsigned char *buf1, *buf2;
+
+ buf1 = b1;
+ buf2 = b2;
+ for (u = 0; u < len; u ++) {
+ unsigned w;
+
+ w = buf1[u];
+ buf1[u] = buf2[u];
+ buf2[u] = w;
+ }
+}
+
+/* see inner.h */
+uint32_t
+br_rsa_i31_keygen_inner(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31)
+{
+ uint32_t esize_p, esize_q;
+ size_t plen, qlen, tlen;
+ uint32_t *p, *q, *t;
+ union {
+ uint32_t t32[TEMPS];
+ uint64_t t64[TEMPS >> 1]; /* for 64-bit alignment */
+ } tmp;
+ uint32_t r;
+
+ if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) {
+ return 0;
+ }
+ if (pubexp == 0) {
+ pubexp = 3;
+ } else if (pubexp == 1 || (pubexp & 1) == 0) {
+ return 0;
+ }
+
+ esize_p = (size + 1) >> 1;
+ esize_q = size - esize_p;
+ sk->n_bitlen = size;
+ sk->p = kbuf_priv;
+ sk->plen = (esize_p + 7) >> 3;
+ sk->q = sk->p + sk->plen;
+ sk->qlen = (esize_q + 7) >> 3;
+ sk->dp = sk->q + sk->qlen;
+ sk->dplen = sk->plen;
+ sk->dq = sk->dp + sk->dplen;
+ sk->dqlen = sk->qlen;
+ sk->iq = sk->dq + sk->dqlen;
+ sk->iqlen = sk->plen;
+
+ if (pk != NULL) {
+ pk->n = kbuf_pub;
+ pk->nlen = (size + 7) >> 3;
+ pk->e = pk->n + pk->nlen;
+ pk->elen = 4;
+ br_enc32be(pk->e, pubexp);
+ while (*pk->e == 0) {
+ pk->e ++;
+ pk->elen --;
+ }
+ }
+
+ /*
+ * We now switch to encoded sizes.
+ *
+ * floor((x * 16913) / (2^19)) is equal to floor(x/31) for all
+ * integers x from 0 to 34966; the intermediate product fits on
+ * 30 bits, thus we can use MUL31().
+ */
+ esize_p += MUL31(esize_p, 16913) >> 19;
+ esize_q += MUL31(esize_q, 16913) >> 19;
+ plen = (esize_p + 31) >> 5;
+ qlen = (esize_q + 31) >> 5;
+ p = tmp.t32;
+ q = p + 1 + plen;
+ t = q + 1 + qlen;
+ tlen = ((sizeof tmp.t32) / sizeof(uint32_t)) - (2 + plen + qlen);
+
+ /*
+ * When looking for primes p and q, we temporarily divide
+ * candidates by 2, in order to compute the inverse of the
+ * public exponent.
+ */
+
+ for (;;) {
+ mkprime(rng, p, esize_p, pubexp, t, tlen, mp31);
+ br_i31_rshift(p, 1);
+ if (invert_pubexp(t, p, pubexp, t + 1 + plen)) {
+ br_i31_add(p, p, 1);
+ p[1] |= 1;
+ br_i31_encode(sk->p, sk->plen, p);
+ br_i31_encode(sk->dp, sk->dplen, t);
+ break;
+ }
+ }
+
+ for (;;) {
+ mkprime(rng, q, esize_q, pubexp, t, tlen, mp31);
+ br_i31_rshift(q, 1);
+ if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) {
+ br_i31_add(q, q, 1);
+ q[1] |= 1;
+ br_i31_encode(sk->q, sk->qlen, q);
+ br_i31_encode(sk->dq, sk->dqlen, t);
+ break;
+ }
+ }
+
+ /*
+ * If p and q have the same size, then it is possible that q > p
+ * (when the target modulus size is odd, we generate p with a
+ * greater bit length than q). If q > p, we want to swap p and q
+ * (and also dp and dq) for two reasons:
+ * - The final step below (inversion of q modulo p) is easier if
+ * p > q.
+ * - While BearSSL's RSA code is perfectly happy with RSA keys such
+ * that p < q, some other implementations have restrictions and
+ * require p > q.
+ *
+ * Note that we can do a simple non-constant-time swap here,
+ * because the only information we leak here is that we insist on
+ * returning p and q such that p > q, which is not a secret.
+ */
+ if (esize_p == esize_q && br_i31_sub(p, q, 0) == 1) {
+ bufswap(p, q, (1 + plen) * sizeof *p);
+ bufswap(sk->p, sk->q, sk->plen);
+ bufswap(sk->dp, sk->dq, sk->dplen);
+ }
+
+ /*
+ * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p.
+ *
+ * We ensured that p >= q, so this is just a matter of updating the
+ * header word for q (and possibly adding an extra word).
+ *
+ * Theoretically, the call below may fail, in case we were
+ * extraordinarily unlucky, and p = q. Another failure case is if
+ * Miller-Rabin failed us _twice_, and p and q are non-prime and
+ * have a factor is common. We report the error mostly because it
+ * is cheap and we can, but in practice this never happens (or, at
+ * least, it happens way less often than hardware glitches).
+ */
+ q[0] = p[0];
+ if (plen > qlen) {
+ q[plen] = 0;
+ t ++;
+ tlen --;
+ }
+ br_i31_zero(t, p[0]);
+ t[1] = 1;
+ r = br_i31_moddiv(t, q, p, br_i31_ninv31(p[1]), t + 1 + plen);
+ br_i31_encode(sk->iq, sk->iqlen, t);
+
+ /*
+ * Compute the public modulus too, if required.
+ */
+ if (pk != NULL) {
+ br_i31_zero(t, p[0]);
+ br_i31_mulacc(t, p, q);
+ br_i31_encode(pk->n, pk->nlen, t);
+ }
+
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_keygen_inner.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_modulus.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_modulus.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_modulus.c (revision 346145)
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk)
+{
+ uint32_t tmp[2 * ((BR_MAX_RSA_SIZE + 30) / 31) + 5];
+ uint32_t *t, *p, *q;
+ const unsigned char *pbuf, *qbuf;
+ size_t nlen, plen, qlen, tlen;
+
+ /*
+ * Compute actual byte and lengths for p and q.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+
+ t = tmp;
+ tlen = (sizeof tmp) / (sizeof tmp[0]);
+
+ /*
+ * Decode p.
+ */
+ if ((31 * tlen) < (plen << 3) + 31) {
+ return 0;
+ }
+ br_i31_decode(t, pbuf, plen);
+ p = t;
+ plen = (p[0] + 63) >> 5;
+ t += plen;
+ tlen -= plen;
+
+ /*
+ * Decode q.
+ */
+ if ((31 * tlen) < (qlen << 3) + 31) {
+ return 0;
+ }
+ br_i31_decode(t, qbuf, qlen);
+ q = t;
+ qlen = (q[0] + 63) >> 5;
+ t += qlen;
+ tlen -= qlen;
+
+ /*
+ * Computation can proceed only if we have enough room for the
+ * modulus.
+ */
+ if (tlen < (plen + qlen + 1)) {
+ return 0;
+ }
+
+ /*
+ * Private key already contains the modulus bit length, from which
+ * we can infer the output length. Even if n is NULL, we still had
+ * to decode p and q to make sure that the product can be computed.
+ */
+ nlen = (sk->n_bitlen + 7) >> 3;
+ if (n != NULL) {
+ br_i31_zero(t, p[0]);
+ br_i31_mulacc(t, p, q);
+ br_i31_encode(n, nlen, t);
+ }
+ return nlen;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_modulus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_decrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_decrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_decrypt.c (revision 346145)
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i31_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_decrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_encrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_encrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_encrypt.c (revision 346145)
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i31_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i31_public(dst, dlen, pk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_oaep_encrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_sign.c (revision 346145)
@@ -0,0 +1,37 @@
+/*
+ * 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 bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i31_private(x, sk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_vrfy.c (revision 346145)
@@ -0,0 +1,43 @@
+/*
+ * 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 bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i31_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_pkcs1_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_priv.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_priv.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_priv.c (revision 346145)
@@ -0,0 +1,203 @@
+/*
+ * 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"
+
+#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31))
+#define TLEN (8 * U)
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ size_t fwlen;
+ uint32_t p0i, q0i;
+ size_t xlen, u;
+ uint32_t tmp[1 + TLEN];
+ long z;
+ uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t r;
+
+ /*
+ * Compute the actual lengths of p and q, in bytes.
+ * These lengths are not considered secret (we cannot really hide
+ * them anyway in constant-time code).
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+
+ /*
+ * Compute the maximum factor length, in words.
+ */
+ z = (long)(plen > qlen ? plen : qlen) << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+
+ /*
+ * Round up the word length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * We need to fit at least 6 values in the stack buffer.
+ */
+ if (6 * fwlen > TLEN) {
+ return 0;
+ }
+
+ /*
+ * Compute modulus length (in bytes).
+ */
+ xlen = (sk->n_bitlen + 7) >> 3;
+
+ /*
+ * Decode q.
+ */
+ mq = tmp;
+ br_i31_decode(mq, q, qlen);
+
+ /*
+ * Decode p.
+ */
+ t1 = mq + fwlen;
+ br_i31_decode(t1, p, plen);
+
+ /*
+ * Compute the modulus (product of the two factors), to compare
+ * it with the source value. We use br_i31_mulacc(), since it's
+ * already used later on.
+ */
+ t2 = mq + 2 * fwlen;
+ br_i31_zero(t2, mq[0]);
+ br_i31_mulacc(t2, mq, t1);
+
+ /*
+ * We encode the modulus into bytes, to perform the comparison
+ * with bytes. We know that the product length, in bytes, is
+ * exactly xlen.
+ * The comparison actually computes the carry when subtracting
+ * the modulus from the source value; that carry must be 1 for
+ * a value in the correct range. We keep it in r, which is our
+ * accumulator for the error code.
+ */
+ t3 = mq + 4 * fwlen;
+ br_i31_encode(t3, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)t3)[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Move the decoded p to another temporary buffer.
+ */
+ mp = mq + 2 * fwlen;
+ memmove(mp, t1, fwlen * sizeof *t1);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i31_ninv31(mq[1]);
+ s2 = mq + fwlen;
+ br_i31_decode_reduce(s2, x, xlen, mq);
+ r &= br_i31_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
+ mq + 3 * fwlen, TLEN - 3 * fwlen);
+
+ /*
+ * Compute s1 = x^dp mod p.
+ */
+ p0i = br_i31_ninv31(mp[1]);
+ s1 = mq + 3 * fwlen;
+ br_i31_decode_reduce(s1, x, xlen, mp);
+ r &= br_i31_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
+ mq + 4 * fwlen, TLEN - 4 * fwlen);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i31_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ t1 = mq + 4 * fwlen;
+ t2 = mq + 5 * fwlen;
+ br_i31_reduce(t2, s2, mp);
+ br_i31_add(s1, mp, br_i31_sub(s1, t2, 1));
+ br_i31_to_monty(s1, mp);
+ br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i31_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed, so we can
+ * reuse them for t3. Moreover, the first step of the computation
+ * is to copy s2 into t3, after which s2 is not needed. Right
+ * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5.
+ * Therefore, we have ample room for t3 by simply using s2.
+ */
+ t3 = s2;
+ br_i31_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i31_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_priv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_privexp.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_privexp.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_privexp.c (revision 346145)
@@ -0,0 +1,318 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i31_compute_privexp(void *d,
+ const br_rsa_private_key *sk, uint32_t e)
+{
+ /*
+ * We want to invert e modulo phi = (p-1)(q-1). This first
+ * requires computing phi, which is easy since we have the factors
+ * p and q in the private key structure.
+ *
+ * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer.
+ * We could invert e modulo phi/4 then patch the result to
+ * modulo phi, but this would involve assembling three modulus-wide
+ * values (phi/4, 1 and e) and calling moddiv, that requires
+ * three more temporaries, for a total of six big integers, or
+ * slightly more than 3 kB of stack space for RSA-4096. This
+ * exceeds our stack requirements.
+ *
+ * Instead, we first use one step of the extended GCD:
+ *
+ * - We compute phi = k*e + r (Euclidean division of phi by e).
+ * If public exponent e is correct, then r != 0 (e must be
+ * invertible modulo phi). We also have k != 0 since we
+ * enforce non-ridiculously-small factors.
+ *
+ * - We find small u, v such that u*e - v*r = 1 (using a
+ * binary GCD; we can arrange for u < r and v < e, i.e. all
+ * values fit on 32 bits).
+ *
+ * - Solution is: d = u + v*k
+ * This last computation is exact: since u < r and v < e,
+ * the above implies d < r + e*((phi-r)/e) = phi
+ */
+
+ uint32_t tmp[4 * ((BR_MAX_RSA_FACTOR + 30) / 31) + 12];
+ uint32_t *p, *q, *k, *m, *z, *phi;
+ const unsigned char *pbuf, *qbuf;
+ size_t plen, qlen, u, len, dlen;
+ uint32_t r, a, b, u0, v0, u1, v1, he, hr;
+ int i;
+
+ /*
+ * Check that e is correct.
+ */
+ if (e < 3 || (e & 1) == 0) {
+ return 0;
+ }
+
+ /*
+ * Check lengths of p and q, and that they are both odd.
+ */
+ pbuf = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)
+ || (pbuf[plen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+ qbuf = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *qbuf == 0) {
+ qbuf ++;
+ qlen --;
+ }
+ if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8)
+ || (qbuf[qlen - 1] & 1) != 1)
+ {
+ return 0;
+ }
+
+ /*
+ * Output length is that of the modulus.
+ */
+ dlen = (sk->n_bitlen + 7) >> 3;
+ if (d == NULL) {
+ return dlen;
+ }
+
+ p = tmp;
+ br_i31_decode(p, pbuf, plen);
+ plen = (p[0] + 31) >> 5;
+ q = p + 1 + plen;
+ br_i31_decode(q, qbuf, qlen);
+ qlen = (q[0] + 31) >> 5;
+
+ /*
+ * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that
+ * we do not need anymore). The mulacc function sets the announced
+ * bit length of t to be the sum of the announced bit lengths of
+ * p-1 and q-1, which is usually exact but may overshoot by one 1
+ * bit in some cases; we readjust it to its true length.
+ */
+ p[1] --;
+ q[1] --;
+ phi = q + 1 + qlen;
+ br_i31_zero(phi, p[0]);
+ br_i31_mulacc(phi, p, q);
+ len = (phi[0] + 31) >> 5;
+ memmove(tmp, phi, (1 + len) * sizeof *phi);
+ phi = tmp;
+ phi[0] = br_i31_bit_length(phi + 1, len);
+ len = (phi[0] + 31) >> 5;
+
+ /*
+ * Divide phi by public exponent e. The final remainder r must be
+ * non-zero (otherwise, the key is invalid). The quotient is k,
+ * which we write over phi, since we don't need phi after that.
+ */
+ r = 0;
+ for (u = len; u >= 1; u --) {
+ /*
+ * Upon entry, r < e, and phi[u] < 2^31; hence,
+ * hi:lo < e*2^31. Thus, the produced word k[u]
+ * must be lower than 2^31, and the new remainder r
+ * is lower than e.
+ */
+ uint32_t hi, lo;
+
+ hi = r >> 1;
+ lo = (r << 31) + phi[u];
+ phi[u] = br_divrem(hi, lo, e, &r);
+ }
+ if (r == 0) {
+ return 0;
+ }
+ k = phi;
+
+ /*
+ * Compute u and v such that u*e - v*r = GCD(e,r). We use
+ * a binary GCD algorithm, with 6 extra integers a, b,
+ * u0, u1, v0 and v1. Initial values are:
+ * a = e u0 = 1 v0 = 0
+ * b = r u1 = r v1 = e-1
+ * The following invariants are maintained:
+ * a = u0*e - v0*r
+ * b = u1*e - v1*r
+ * 0 < a <= e
+ * 0 < b <= r
+ * 0 <= u0 <= r
+ * 0 <= v0 <= e
+ * 0 <= u1 <= r
+ * 0 <= v1 <= e
+ *
+ * At each iteration, we reduce either a or b by one bit, and
+ * adjust u0, u1, v0 and v1 to maintain the invariants:
+ * - if a is even, then a <- a/2
+ * - otherwise, if b is even, then b <- b/2
+ * - otherwise, if a > b, then a <- (a-b)/2
+ * - otherwise, if b > a, then b <- (b-a)/2
+ * Algorithm stops when a = b. At that point, the common value
+ * is the GCD of e and r; it must be 1 (otherwise, the private
+ * key or public exponent is not valid). The (u0,v0) or (u1,v1)
+ * pairs are the solution we are looking for.
+ *
+ * Since either a or b is reduced by at least 1 bit at each
+ * iteration, 62 iterations are enough to reach the end
+ * condition.
+ *
+ * To maintain the invariants, we must compute the same operations
+ * on the u* and v* values that we do on a and b:
+ * - When a is divided by 2, u0 and v0 must be divided by 2.
+ * - When b is divided by 2, u1 and v1 must be divided by 2.
+ * - When b is subtracted from a, u1 and v1 are subtracted from
+ * u0 and v0, respectively.
+ * - When a is subtracted from b, u0 and v0 are subtracted from
+ * u1 and v1, respectively.
+ *
+ * However, we want to keep the u* and v* values in their proper
+ * ranges. The following remarks apply:
+ *
+ * - When a is divided by 2, then a is even. Therefore:
+ *
+ * * If r is odd, then u0 and v0 must have the same parity;
+ * if they are both odd, then adding r to u0 and e to v0
+ * makes them both even, and the division by 2 brings them
+ * back to the proper range.
+ *
+ * * If r is even, then u0 must be even; if v0 is odd, then
+ * adding r to u0 and e to v0 makes them both even, and the
+ * division by 2 brings them back to the proper range.
+ *
+ * Thus, all we need to do is to look at the parity of v0,
+ * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid
+ * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the
+ * division (r+1 does not overflow since r < e; and (e/2)+1
+ * is equal to (e+1)/2 since e is odd).
+ *
+ * - When we subtract b from a, three cases may occur:
+ *
+ * * u1 <= u0 and v1 <= v0: just do the subtractions
+ *
+ * * u1 > u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * * u1 <= u0 and v1 > v0: compute:
+ * (u0, v0) <- (u0 + r - u1, v0 + e - v1)
+ *
+ * The fourth case (u1 > u0 and v1 <= v0) is not possible
+ * because it would contradict "b < a" (which is the reason
+ * why we subtract b from a).
+ *
+ * The tricky case is the third one: from the equations, it
+ * seems that u0 may go out of range. However, the invariants
+ * and ranges of other values imply that, in that case, the
+ * new u0 does not actually exceed the range.
+ *
+ * We can thus handle the subtraction by adding (r,e) based
+ * solely on the comparison between v0 and v1.
+ */
+ a = e;
+ b = r;
+ u0 = 1;
+ v0 = 0;
+ u1 = r;
+ v1 = e - 1;
+ hr = (r + 1) >> 1;
+ he = (e >> 1) + 1;
+ for (i = 0; i < 62; i ++) {
+ uint32_t oa, ob, agtb, bgta;
+ uint32_t sab, sba, da, db;
+ uint32_t ctl;
+
+ oa = a & 1; /* 1 if a is odd */
+ ob = b & 1; /* 1 if b is odd */
+ agtb = GT(a, b); /* 1 if a > b */
+ bgta = GT(b, a); /* 1 if b > a */
+
+ sab = oa & ob & agtb; /* 1 if a <- a-b */
+ sba = oa & ob & bgta; /* 1 if b <- b-a */
+
+ /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */
+ ctl = GT(v1, v0);
+ a -= b & -sab;
+ u0 -= (u1 - (r & -ctl)) & -sab;
+ v0 -= (v1 - (e & -ctl)) & -sab;
+
+ /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */
+ ctl = GT(v0, v1);
+ b -= a & -sba;
+ u1 -= (u0 - (r & -ctl)) & -sba;
+ v1 -= (v0 - (e & -ctl)) & -sba;
+
+ da = NOT(oa) | sab; /* 1 if a <- a/2 */
+ db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */
+
+ /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */
+ ctl = v0 & 1;
+ a ^= (a ^ (a >> 1)) & -da;
+ u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da;
+ v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da;
+
+ /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */
+ ctl = v1 & 1;
+ b ^= (b ^ (b >> 1)) & -db;
+ u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db;
+ v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db;
+ }
+
+ /*
+ * Check that the GCD is indeed 1. If not, then the key is invalid
+ * (and there's no harm in leaking that piece of information).
+ */
+ if (a != 1) {
+ return 0;
+ }
+
+ /*
+ * Now we have u0*e - v0*r = 1. Let's compute the result as:
+ * d = u0 + v0*k
+ * We still have k in the tmp[] array, and its announced bit
+ * length is that of phi.
+ */
+ m = k + 1 + len;
+ m[0] = (1 << 5) + 1; /* bit length is 32 bits, encoded */
+ m[1] = v0 & 0x7FFFFFFF;
+ m[2] = v0 >> 31;
+ z = m + 3;
+ br_i31_zero(z, k[0]);
+ z[1] = u0 & 0x7FFFFFFF;
+ z[2] = u0 >> 31;
+ br_i31_mulacc(z, k, m);
+
+ /*
+ * Encode the result.
+ */
+ br_i31_encode(d, dlen, z);
+ return dlen;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_privexp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_sign.c (revision 346145)
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i31_private(x, sk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_vrfy.c (revision 346145)
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i31_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_pss_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_pub.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_pub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_pub.c (revision 346145)
@@ -0,0 +1,106 @@
+/*
+ * 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"
+
+/*
+ * As a strict minimum, we need four buffers that can hold a
+ * modular integer.
+ */
+#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31)))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint32_t tmp[1 + TLEN];
+ uint32_t *m, *a, *t;
+ size_t fwlen;
+ long z;
+ uint32_t m0i, r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ z = (long)nlen << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+ /*
+ * Round up length to an even number.
+ */
+ fwlen += (fwlen & 1);
+
+ /*
+ * The modulus gets decoded into m[].
+ * The value to exponentiate goes into a[].
+ * The temporaries for modular exponentiation are in t[].
+ */
+ m = tmp;
+ a = m + fwlen;
+ t = m + 2 * fwlen;
+
+ /*
+ * Decode the modulus.
+ */
+ br_i31_decode(m, n, nlen);
+ m0i = br_i31_ninv31(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i31_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i31_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen);
+
+ /*
+ * Encode the result.
+ */
+ br_i31_encode(x, xlen, a);
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_pub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i31_pubexp.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i31_pubexp.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i31_pubexp.c (revision 346145)
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Recompute public exponent, based on factor p and reduced private
+ * exponent dp.
+ */
+static uint32_t
+get_pubexp(const unsigned char *pbuf, size_t plen,
+ const unsigned char *dpbuf, size_t dplen)
+{
+ /*
+ * dp is the inverse of e modulo p-1. If p = 3 mod 4, then
+ * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1;
+ * thus, dp must be odd.
+ *
+ * We compute the inverse of dp modulo (p-1)/2. This requires
+ * first reducing dp modulo (p-1)/2 (this can be done with a
+ * conditional subtract, no need to use the generic modular
+ * reduction function); then, we use moddiv.
+ */
+
+ uint32_t tmp[6 * ((BR_MAX_RSA_FACTOR + 61) / 31)];
+ uint32_t *p, *dp, *x;
+ size_t len;
+ uint32_t e;
+
+ /*
+ * Compute actual factor length (in bytes) and check that it fits
+ * under our size constraints.
+ */
+ while (plen > 0 && *pbuf == 0) {
+ pbuf ++;
+ plen --;
+ }
+ if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) {
+ return 0;
+ }
+
+ /*
+ * Compute actual reduced exponent length (in bytes) and check that
+ * it is not longer than p.
+ */
+ while (dplen > 0 && *dpbuf == 0) {
+ dpbuf ++;
+ dplen --;
+ }
+ if (dplen > plen || dplen == 0
+ || (dplen == plen && dpbuf[0] > pbuf[0]))
+ {
+ return 0;
+ }
+
+ /*
+ * Verify that p = 3 mod 4 and that dp is odd.
+ */
+ if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) {
+ return 0;
+ }
+
+ /*
+ * Decode p and compute (p-1)/2.
+ */
+ p = tmp;
+ br_i31_decode(p, pbuf, plen);
+ len = (p[0] + 63) >> 5;
+ br_i31_rshift(p, 1);
+
+ /*
+ * Decode dp and make sure its announced bit length matches that of
+ * p (we already know that the size of dp, in bits, does not exceed
+ * the size of p, so we just have to copy the header word).
+ */
+ dp = p + len;
+ memset(dp, 0, len * sizeof *dp);
+ br_i31_decode(dp, dpbuf, dplen);
+ dp[0] = p[0];
+
+ /*
+ * Subtract (p-1)/2 from dp if necessary.
+ */
+ br_i31_sub(dp, p, NOT(br_i31_sub(dp, p, 0)));
+
+ /*
+ * If another subtraction is needed, then this means that the
+ * value was invalid. We don't care to leak information about
+ * invalid keys.
+ */
+ if (br_i31_sub(dp, p, 0) == 0) {
+ return 0;
+ }
+
+ /*
+ * Invert dp modulo (p-1)/2. If the inversion fails, then the
+ * key value was invalid.
+ */
+ x = dp + len;
+ br_i31_zero(x, p[0]);
+ x[1] = 1;
+ if (br_i31_moddiv(x, dp, p, br_i31_ninv31(p[1]), x + len) == 0) {
+ return 0;
+ }
+
+ /*
+ * We now have an inverse. We must set it to zero (error) if its
+ * length is greater than 32 bits and/or if it is an even integer.
+ * Take care that the bit_length function returns an encoded
+ * bit length.
+ */
+ e = (uint32_t)x[1] | ((uint32_t)x[2] << 31);
+ e &= -LT(br_i31_bit_length(x + 1, len - 1), 34);
+ e &= -(e & 1);
+ return e;
+}
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk)
+{
+ /*
+ * Get the public exponent from both p and q. This is the right
+ * exponent if we get twice the same value.
+ */
+ uint32_t ep, eq;
+
+ ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen);
+ eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen);
+ return ep & -EQ(ep, eq);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i31_pubexp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_decrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_decrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_decrypt.c (revision 346145)
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i32_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_decrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_encrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_encrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_encrypt.c (revision 346145)
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i32_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i32_public(dst, dlen, pk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_oaep_encrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_sign.c (revision 346145)
@@ -0,0 +1,37 @@
+/*
+ * 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 bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i32_private(x, sk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_vrfy.c (revision 346145)
@@ -0,0 +1,43 @@
+/*
+ * 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 bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i32_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_pkcs1_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_priv.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_priv.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_priv.c (revision 346145)
@@ -0,0 +1,160 @@
+/*
+ * 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"
+
+#define U (1 + (BR_MAX_RSA_FACTOR >> 5))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ uint32_t tmp[6 * U];
+ uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t p0i, q0i;
+ size_t xlen, u;
+ uint32_t r;
+
+ /*
+ * All our temporary buffers are from the tmp[] array.
+ *
+ * The mp, mq, s1, s2, t1 and t2 buffers are large enough to
+ * contain a RSA factor. The t3 buffer can contain a complete
+ * RSA modulus. t3 shares its storage space with s2, s1 and t1,
+ * in that order (this is important, see below).
+ */
+ mq = tmp;
+ mp = tmp + U;
+ t2 = tmp + 2 * U;
+ s2 = tmp + 3 * U;
+ s1 = tmp + 4 * U;
+ t1 = tmp + 5 * U;
+ t3 = s2;
+
+ /*
+ * Compute the actual lengths (in bytes) of p and q, and check
+ * that they fit within our stack buffers.
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+ if (plen > (BR_MAX_RSA_FACTOR >> 3)
+ || qlen > (BR_MAX_RSA_FACTOR >> 3))
+ {
+ return 0;
+ }
+
+ /*
+ * Decode p and q.
+ */
+ br_i32_decode(mp, p, plen);
+ br_i32_decode(mq, q, qlen);
+
+ /*
+ * Recompute modulus, to compare with the source value.
+ */
+ br_i32_zero(t2, mp[0]);
+ br_i32_mulacc(t2, mp, mq);
+ xlen = (sk->n_bitlen + 7) >> 3;
+ br_i32_encode(t2 + 2 * U, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)(t2 + 2 * U))[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Compute s1 = x^dp mod p.
+ */
+ p0i = br_i32_ninv32(mp[1]);
+ br_i32_decode_reduce(s1, x, xlen, mp);
+ br_i32_modpow(s1, sk->dp, sk->dplen, mp, p0i, t1, t2);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i32_ninv32(mq[1]);
+ br_i32_decode_reduce(s2, x, xlen, mq);
+ br_i32_modpow(s2, sk->dq, sk->dqlen, mq, q0i, t1, t2);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i32_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ br_i32_reduce(t2, s2, mp);
+ br_i32_add(s1, mp, br_i32_sub(s1, t2, 1));
+ br_i32_to_monty(s1, mp);
+ br_i32_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i32_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed. Moreover,
+ * the first step is to copy s2 into the destination buffer t3.
+ * We thus arranged for t3 to actually share space with s2, and
+ * to be followed by the space formerly used by s1 and t1.
+ */
+ br_i32_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i32_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_priv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_sign.c (revision 346145)
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i32_private(x, sk);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_vrfy.c (revision 346145)
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i32_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_pss_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i32_pub.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i32_pub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i32_pub.c (revision 346145)
@@ -0,0 +1,77 @@
+/*
+ * 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 bearssl_rsa.h */
+uint32_t
+br_rsa_i32_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint32_t m[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t a[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t t1[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t t2[1 + (BR_MAX_RSA_SIZE >> 5)];
+ uint32_t m0i, r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ br_i32_decode(m, n, nlen);
+ m0i = br_i32_ninv32(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i32_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i32_modpow(a, pk->e, pk->elen, m, m0i, t1, t2);
+
+ /*
+ * Encode the result.
+ */
+ br_i32_encode(x, xlen, a);
+ return r;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i32_pub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_keygen.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_keygen.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_keygen.c (revision 346145)
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_keygen(const br_prng_class **rng,
+ br_rsa_private_key *sk, void *kbuf_priv,
+ br_rsa_public_key *pk, void *kbuf_pub,
+ unsigned size, uint32_t pubexp)
+{
+ return br_rsa_i31_keygen_inner(rng,
+ sk, kbuf_priv, pk, kbuf_pub, size, pubexp,
+ &br_i62_modpow_opt_as_i31);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_keygen
+br_rsa_i62_keygen_get()
+{
+ return &br_rsa_i62_keygen;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_keygen
+br_rsa_i62_keygen_get()
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_keygen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_decrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_decrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_decrypt.c (revision 346145)
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_oaep_decrypt(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_private_key *sk, void *data, size_t *len)
+{
+ uint32_t r;
+
+ if (*len != ((sk->n_bitlen + 7) >> 3)) {
+ return 0;
+ }
+ r = br_rsa_i62_private(data, sk);
+ r &= br_rsa_oaep_unpad(dig, label, label_len, data, len);
+ return r;
+}
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_decrypt
+br_rsa_i62_oaep_decrypt_get(void)
+{
+ return &br_rsa_i62_oaep_decrypt;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_decrypt
+br_rsa_i62_oaep_decrypt_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_decrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_encrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_encrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_encrypt.c (revision 346145)
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+size_t
+br_rsa_i62_oaep_encrypt(
+ const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len)
+{
+ size_t dlen;
+
+ dlen = br_rsa_oaep_pad(rnd, dig, label, label_len,
+ pk, dst, dst_max_len, src, src_len);
+ if (dlen == 0) {
+ return 0;
+ }
+ return dlen & -(size_t)br_rsa_i62_public(dst, dlen, pk);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_encrypt
+br_rsa_i62_oaep_encrypt_get(void)
+{
+ return &br_rsa_i62_oaep_encrypt;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_oaep_encrypt
+br_rsa_i62_oaep_encrypt_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_oaep_encrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_sign.c (revision 346145)
@@ -0,0 +1,57 @@
+/*
+ * 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"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) {
+ return 0;
+ }
+ return br_rsa_i62_private(x, sk);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_sign
+br_rsa_i62_pkcs1_sign_get(void)
+{
+ return &br_rsa_i62_pkcs1_sign;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_sign
+br_rsa_i62_pkcs1_sign_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_vrfy.c (revision 346145)
@@ -0,0 +1,63 @@
+/*
+ * 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"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen,
+ const unsigned char *hash_oid, size_t hash_len,
+ const br_rsa_public_key *pk, unsigned char *hash_out)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i62_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_vrfy
+br_rsa_i62_pkcs1_vrfy_get(void)
+{
+ return &br_rsa_i62_pkcs1_vrfy;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pkcs1_vrfy
+br_rsa_i62_pkcs1_vrfy_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_pkcs1_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_priv.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_priv.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_priv.c (revision 346145)
@@ -0,0 +1,223 @@
+/*
+ * 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"
+
+#if BR_INT128 || BR_UMUL128
+
+#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31))
+#define TLEN (4 * U) /* TLEN is counted in 64-bit words */
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk)
+{
+ const unsigned char *p, *q;
+ size_t plen, qlen;
+ size_t fwlen;
+ uint32_t p0i, q0i;
+ size_t xlen, u;
+ uint64_t tmp[TLEN];
+ long z;
+ uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
+ uint32_t r;
+
+ /*
+ * Compute the actual lengths of p and q, in bytes.
+ * These lengths are not considered secret (we cannot really hide
+ * them anyway in constant-time code).
+ */
+ p = sk->p;
+ plen = sk->plen;
+ while (plen > 0 && *p == 0) {
+ p ++;
+ plen --;
+ }
+ q = sk->q;
+ qlen = sk->qlen;
+ while (qlen > 0 && *q == 0) {
+ q ++;
+ qlen --;
+ }
+
+ /*
+ * Compute the maximum factor length, in words.
+ */
+ z = (long)(plen > qlen ? plen : qlen) << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+
+ /*
+ * Convert size to 62-bit words.
+ */
+ fwlen = (fwlen + 1) >> 1;
+
+ /*
+ * We need to fit at least 6 values in the stack buffer.
+ */
+ if (6 * fwlen > TLEN) {
+ return 0;
+ }
+
+ /*
+ * Compute signature length (in bytes).
+ */
+ xlen = (sk->n_bitlen + 7) >> 3;
+
+ /*
+ * Decode q.
+ */
+ mq = (uint32_t *)tmp;
+ br_i31_decode(mq, q, qlen);
+
+ /*
+ * Decode p.
+ */
+ t1 = (uint32_t *)(tmp + fwlen);
+ br_i31_decode(t1, p, plen);
+
+ /*
+ * Compute the modulus (product of the two factors), to compare
+ * it with the source value. We use br_i31_mulacc(), since it's
+ * already used later on.
+ */
+ t2 = (uint32_t *)(tmp + 2 * fwlen);
+ br_i31_zero(t2, mq[0]);
+ br_i31_mulacc(t2, mq, t1);
+
+ /*
+ * We encode the modulus into bytes, to perform the comparison
+ * with bytes. We know that the product length, in bytes, is
+ * exactly xlen.
+ * The comparison actually computes the carry when subtracting
+ * the modulus from the source value; that carry must be 1 for
+ * a value in the correct range. We keep it in r, which is our
+ * accumulator for the error code.
+ */
+ t3 = (uint32_t *)(tmp + 4 * fwlen);
+ br_i31_encode(t3, xlen, t2);
+ u = xlen;
+ r = 0;
+ while (u > 0) {
+ uint32_t wn, wx;
+
+ u --;
+ wn = ((unsigned char *)t3)[u];
+ wx = x[u];
+ r = ((wx - (wn + r)) >> 8) & 1;
+ }
+
+ /*
+ * Move the decoded p to another temporary buffer.
+ */
+ mp = (uint32_t *)(tmp + 2 * fwlen);
+ memmove(mp, t1, 2 * fwlen * sizeof *t1);
+
+ /*
+ * Compute s2 = x^dq mod q.
+ */
+ q0i = br_i31_ninv31(mq[1]);
+ s2 = (uint32_t *)(tmp + fwlen);
+ br_i31_decode_reduce(s2, x, xlen, mq);
+ r &= br_i62_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
+ tmp + 3 * fwlen, TLEN - 3 * fwlen);
+
+ /*
+ * Compute s1 = x^dp mod p.
+ */
+ p0i = br_i31_ninv31(mp[1]);
+ s1 = (uint32_t *)(tmp + 3 * fwlen);
+ br_i31_decode_reduce(s1, x, xlen, mp);
+ r &= br_i62_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
+ tmp + 4 * fwlen, TLEN - 4 * fwlen);
+
+ /*
+ * Compute:
+ * h = (s1 - s2)*(1/q) mod p
+ * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is
+ * unclear about whether p may be lower than q (some existing,
+ * widely deployed implementations of RSA don't tolerate p < q),
+ * but we want to support that occurrence, so we need to use the
+ * reduction function.
+ *
+ * Since we use br_i31_decode_reduce() for iq (purportedly, the
+ * inverse of q modulo p), we also tolerate improperly large
+ * values for this parameter.
+ */
+ t1 = (uint32_t *)(tmp + 4 * fwlen);
+ t2 = (uint32_t *)(tmp + 5 * fwlen);
+ br_i31_reduce(t2, s2, mp);
+ br_i31_add(s1, mp, br_i31_sub(s1, t2, 1));
+ br_i31_to_monty(s1, mp);
+ br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp);
+ br_i31_montymul(t2, s1, t1, mp, p0i);
+
+ /*
+ * h is now in t2. We compute the final result:
+ * s = s2 + q*h
+ * All these operations are non-modular.
+ *
+ * We need mq, s2 and t2. We use the t3 buffer as destination.
+ * The buffers mp, s1 and t1 are no longer needed, so we can
+ * reuse them for t3. Moreover, the first step of the computation
+ * is to copy s2 into t3, after which s2 is not needed. Right
+ * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5.
+ * Therefore, we have ample room for t3 by simply using s2.
+ */
+ t3 = s2;
+ br_i31_mulacc(t3, mq, t2);
+
+ /*
+ * Encode the result. Since we already checked the value of xlen,
+ * we can just use it right away.
+ */
+ br_i31_encode(x, xlen, t3);
+
+ /*
+ * The only error conditions remaining at that point are invalid
+ * values for p and q (even integers).
+ */
+ return p0i & q0i & r;
+}
+
+/* see bearssl_rsa.h */
+br_rsa_private
+br_rsa_i62_private_get(void)
+{
+ return &br_rsa_i62_private;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_private
+br_rsa_i62_private_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_priv.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_sign.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_sign.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_sign.c (revision 346145)
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pss_sign(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_private_key *sk, unsigned char *x)
+{
+ if (!br_rsa_pss_sig_pad(rng, hf_data, hf_mgf1, hash,
+ salt_len, sk->n_bitlen, x))
+ {
+ return 0;
+ }
+ return br_rsa_i62_private(x, sk);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pss_sign
+br_rsa_i62_pss_sign_get(void)
+{
+ return &br_rsa_i62_pss_sign;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pss_sign
+br_rsa_i62_pss_sign_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_sign.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_vrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_vrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_vrfy.c (revision 346145)
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+#if BR_INT128 || BR_UMUL128
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const void *hash, size_t salt_len, const br_rsa_public_key *pk)
+{
+ unsigned char sig[BR_MAX_RSA_SIZE >> 3];
+
+ if (xlen > (sizeof sig)) {
+ return 0;
+ }
+ memcpy(sig, x, xlen);
+ if (!br_rsa_i62_public(sig, xlen, pk)) {
+ return 0;
+ }
+ return br_rsa_pss_sig_unpad(hf_data, hf_mgf1,
+ hash, salt_len, pk, sig);
+}
+
+/* see bearssl_rsa.h */
+br_rsa_pss_vrfy
+br_rsa_i62_pss_vrfy_get(void)
+{
+ return &br_rsa_i62_pss_vrfy;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_pss_vrfy
+br_rsa_i62_pss_vrfy_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_pss_vrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_i62_pub.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_i62_pub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_i62_pub.c (revision 346145)
@@ -0,0 +1,125 @@
+/*
+ * 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"
+
+#if BR_INT128 || BR_UMUL128
+
+/*
+ * As a strict minimum, we need four buffers that can hold a
+ * modular integer. But TLEN is expressed in 64-bit words.
+ */
+#define TLEN (2 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31)))
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_i62_public(unsigned char *x, size_t xlen,
+ const br_rsa_public_key *pk)
+{
+ const unsigned char *n;
+ size_t nlen;
+ uint64_t tmp[TLEN];
+ uint32_t *m, *a;
+ size_t fwlen;
+ long z;
+ uint32_t m0i, r;
+
+ /*
+ * Get the actual length of the modulus, and see if it fits within
+ * our stack buffer. We also check that the length of x[] is valid.
+ */
+ n = pk->n;
+ nlen = pk->nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+ if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) {
+ return 0;
+ }
+ z = (long)nlen << 3;
+ fwlen = 1;
+ while (z > 0) {
+ z -= 31;
+ fwlen ++;
+ }
+ /*
+ * Convert fwlen to a count in 62-bit words.
+ */
+ fwlen = (fwlen + 1) >> 1;
+
+ /*
+ * The modulus gets decoded into m[].
+ * The value to exponentiate goes into a[].
+ */
+ m = (uint32_t *)tmp;
+ a = (uint32_t *)(tmp + fwlen);
+
+ /*
+ * Decode the modulus.
+ */
+ br_i31_decode(m, n, nlen);
+ m0i = br_i31_ninv31(m[1]);
+
+ /*
+ * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be
+ * an odd integer.
+ */
+ r = m0i & 1;
+
+ /*
+ * Decode x[] into a[]; we also check that its value is proper.
+ */
+ r &= br_i31_decode_mod(a, x, xlen, m);
+
+ /*
+ * Compute the modular exponentiation.
+ */
+ br_i62_modpow_opt(a, pk->e, pk->elen, m, m0i,
+ tmp + 2 * fwlen, TLEN - 2 * fwlen);
+
+ /*
+ * Encode the result.
+ */
+ br_i31_encode(x, xlen, a);
+ return r;
+}
+
+/* see bearssl_rsa.h */
+br_rsa_public
+br_rsa_i62_public_get(void)
+{
+ return &br_rsa_i62_public;
+}
+
+#else
+
+/* see bearssl_rsa.h */
+br_rsa_public
+br_rsa_i62_public_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_i62_pub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_oaep_pad.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_oaep_pad.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_oaep_pad.c (revision 346145)
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Hash some data. This is put as a separate function so that stack
+ * allocation of the hash function context is done only for the duration
+ * of the hash.
+ */
+static void
+hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len)
+{
+ br_hash_compat_context hc;
+
+ hc.vtable = dig;
+ dig->init(&hc.vtable);
+ dig->update(&hc.vtable, src, len);
+ dig->out(&hc.vtable, dst);
+}
+
+/* see inner.h */
+size_t
+br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig,
+ const void *label, size_t label_len,
+ const br_rsa_public_key *pk,
+ void *dst, size_t dst_max_len,
+ const void *src, size_t src_len)
+{
+ size_t k, hlen;
+ unsigned char *buf;
+
+ hlen = br_digest_size(dig);
+
+ /*
+ * Compute actual modulus length (in bytes).
+ */
+ k = pk->nlen;
+ while (k > 0 && pk->n[k - 1] == 0) {
+ k --;
+ }
+
+ /*
+ * An error is reported if:
+ * - the modulus is too short;
+ * - the source message length is too long;
+ * - the destination buffer is too short.
+ */
+ if (k < ((hlen << 1) + 2)
+ || src_len > (k - (hlen << 1) - 2)
+ || dst_max_len < k)
+ {
+ return 0;
+ }
+
+ /*
+ * Apply padding. At this point, things cannot fail.
+ */
+ buf = dst;
+
+ /*
+ * Assemble: DB = lHash || PS || 0x01 || M
+ * We first place the source message M with memmove(), so that
+ * overlaps between source and destination buffers are supported.
+ */
+ memmove(buf + k - src_len, src, src_len);
+ hash_data(dig, buf + 1 + hlen, label, label_len);
+ memset(buf + 1 + (hlen << 1), 0, k - src_len - (hlen << 1) - 2);
+ buf[k - src_len - 1] = 0x01;
+
+ /*
+ * Make the random seed.
+ */
+ (*rnd)->generate(rnd, buf + 1, hlen);
+
+ /*
+ * Mask DB with the mask generated from the seed.
+ */
+ br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen);
+
+ /*
+ * Mask the seed with the mask generated from the masked DB.
+ */
+ br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1);
+
+ /*
+ * Padding result: EM = 0x00 || maskedSeed || maskedDB.
+ */
+ buf[0] = 0x00;
+ return k;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_oaep_pad.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_oaep_unpad.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_oaep_unpad.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_oaep_unpad.c (revision 346145)
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * Hash some data and XOR the result into the provided buffer. This is put
+ * as a separate function so that stack allocation of the hash function
+ * context is done only for the duration of the hash.
+ */
+static void
+xor_hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len)
+{
+ br_hash_compat_context hc;
+ unsigned char tmp[64];
+ unsigned char *buf;
+ size_t u, hlen;
+
+ hc.vtable = dig;
+ dig->init(&hc.vtable);
+ dig->update(&hc.vtable, src, len);
+ dig->out(&hc.vtable, tmp);
+ buf = dst;
+ hlen = br_digest_size(dig);
+ for (u = 0; u < hlen; u ++) {
+ buf[u] ^= tmp[u];
+ }
+}
+
+/* see inner.h */
+uint32_t
+br_rsa_oaep_unpad(const br_hash_class *dig,
+ const void *label, size_t label_len,
+ void *data, size_t *len)
+{
+ size_t u, k, hlen;
+ unsigned char *buf;
+ uint32_t r, s, zlen;
+
+ hlen = br_digest_size(dig);
+ k = *len;
+ buf = data;
+
+ /*
+ * There must be room for the padding.
+ */
+ if (k < ((hlen << 1) + 2)) {
+ return 0;
+ }
+
+ /*
+ * Unmask the seed, then the DB value.
+ */
+ br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1);
+ br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen);
+
+ /*
+ * Hash the label and XOR it with the value in the array; if
+ * they are equal then these should yield only zeros.
+ */
+ xor_hash_data(dig, buf + 1 + hlen, label, label_len);
+
+ /*
+ * At that point, if the padding was correct, when we should
+ * have: 0x00 || seed || 0x00 ... 0x00 0x01 || M
+ * Padding is valid as long as:
+ * - There is at least hlen+1 leading bytes of value 0x00.
+ * - There is at least one non-zero byte.
+ * - The first (leftmost) non-zero byte has value 0x01.
+ *
+ * Ultimately, we may leak the resulting message length, i.e.
+ * the position of the byte of value 0x01, but we must take care
+ * to do so only if the number of zero bytes has been verified
+ * to be at least hlen+1.
+ *
+ * The loop below counts the number of bytes of value 0x00, and
+ * checks that the next byte has value 0x01, in constant-time.
+ *
+ * - If the initial byte (before the seed) is not 0x00, then
+ * r and s are set to 0, and stay there.
+ * - Value r is 1 until the first non-zero byte is reached
+ * (after the seed); it switches to 0 at that point.
+ * - Value s is set to 1 if and only if the data encountered
+ * at the time of the transition of r from 1 to 0 has value
+ * exactly 0x01.
+ * - Value zlen counts the number of leading bytes of value zero
+ * (after the seed).
+ */
+ r = 1 - ((buf[0] + 0xFF) >> 8);
+ s = 0;
+ zlen = 0;
+ for (u = hlen + 1; u < k; u ++) {
+ uint32_t w, nz;
+
+ w = buf[u];
+
+ /*
+ * nz == 1 only for the first non-zero byte.
+ */
+ nz = r & ((w + 0xFF) >> 8);
+ s |= nz & EQ(w, 0x01);
+ r &= NOT(nz);
+ zlen += r;
+ }
+
+ /*
+ * Padding is correct only if s == 1, _and_ zlen >= hlen.
+ */
+ s &= GE(zlen, (uint32_t)hlen);
+
+ /*
+ * At that point, padding was verified, and we are now allowed
+ * to make conditional jumps.
+ */
+ if (s) {
+ size_t plen;
+
+ plen = 2 + hlen + zlen;
+ k -= plen;
+ memmove(buf, buf + plen, k);
+ *len = k;
+ }
+ return s;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_oaep_unpad.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_pad.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_pad.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_pad.c (revision 346145)
@@ -0,0 +1,100 @@
+/*
+ * 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"
+
+/* see inner.h */
+uint32_t
+br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid,
+ const unsigned char *hash, size_t hash_len,
+ uint32_t n_bitlen, unsigned char *x)
+{
+ size_t u, x3, xlen;
+
+ /*
+ * Padded hash value has format:
+ * 00 01 FF .. FF 00 30 x1 30 x2 06 x3 OID 05 00 04 x4 HASH
+ *
+ * with the following rules:
+ *
+ * -- Total length is equal to the modulus length (unsigned
+ * encoding).
+ *
+ * -- There must be at least eight bytes of value 0xFF.
+ *
+ * -- x4 is equal to the hash length (hash_len).
+ *
+ * -- x3 is equal to the encoded OID value length (hash_oid[0]).
+ *
+ * -- x2 = x3 + 4.
+ *
+ * -- x1 = x2 + x4 + 4 = x3 + x4 + 8.
+ *
+ * Note: the "05 00" is optional (signatures with and without
+ * that sequence exist in practice), but notes in PKCS#1 seem to
+ * indicate that the presence of that sequence (specifically,
+ * an ASN.1 NULL value for the hash parameters) may be slightly
+ * more "standard" than the opposite.
+ */
+ xlen = (n_bitlen + 7) >> 3;
+
+ if (hash_oid == NULL) {
+ if (xlen < hash_len + 11) {
+ return 0;
+ }
+ x[0] = 0x00;
+ x[1] = 0x01;
+ u = xlen - hash_len;
+ memset(x + 2, 0xFF, u - 3);
+ x[u - 1] = 0x00;
+ } else {
+ x3 = hash_oid[0];
+
+ /*
+ * Check that there is enough room for all the elements,
+ * including at least eight bytes of value 0xFF.
+ */
+ if (xlen < (x3 + hash_len + 21)) {
+ return 0;
+ }
+ x[0] = 0x00;
+ x[1] = 0x01;
+ u = xlen - x3 - hash_len - 11;
+ memset(x + 2, 0xFF, u - 2);
+ x[u] = 0x00;
+ x[u + 1] = 0x30;
+ x[u + 2] = x3 + hash_len + 8;
+ x[u + 3] = 0x30;
+ x[u + 4] = x3 + 4;
+ x[u + 5] = 0x06;
+ memcpy(x + u + 6, hash_oid, x3 + 1);
+ u += x3 + 7;
+ x[u ++] = 0x05;
+ x[u ++] = 0x00;
+ x[u ++] = 0x04;
+ x[u ++] = hash_len;
+ }
+ memcpy(x + u, hash, hash_len);
+ return 1;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_pad.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_unpad.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_unpad.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_unpad.c (revision 346145)
@@ -0,0 +1,121 @@
+/*
+ * 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"
+
+/* see bearssl_rsa.h */
+uint32_t
+br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len,
+ const unsigned char *hash_oid, size_t hash_len,
+ unsigned char *hash_out)
+{
+ static const unsigned char pad1[] = {
+ 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+
+ unsigned char pad2[43];
+ size_t u, x2, x3, pad_len, zlen;
+
+ if (sig_len < 11) {
+ return 0;
+ }
+
+ /*
+ * Expected format:
+ * 00 01 FF ... FF 00 30 x1 30 x2 06 x3 OID [ 05 00 ] 04 x4 HASH
+ *
+ * with the following rules:
+ *
+ * -- Total length is that of the modulus and the signature
+ * (this was already verified by br_rsa_i31_public()).
+ *
+ * -- There are at least eight bytes of value 0xFF.
+ *
+ * -- x4 is equal to the hash length (hash_len).
+ *
+ * -- x3 is equal to the encoded OID value length (so x3 is the
+ * first byte of hash_oid[]).
+ *
+ * -- If the "05 00" is present, then x2 == x3 + 4; otherwise,
+ * x2 == x3 + 2.
+ *
+ * -- x1 == x2 + x4 + 4.
+ *
+ * So the total length after the last "FF" is either x3 + x4 + 11
+ * (with the "05 00") or x3 + x4 + 9 (without the "05 00").
+ */
+
+ /*
+ * Check the "00 01 FF .. FF 00" with at least eight 0xFF bytes.
+ * The comparison is valid because we made sure that the signature
+ * is at least 11 bytes long.
+ */
+ if (memcmp(sig, pad1, sizeof pad1) != 0) {
+ return 0;
+ }
+ for (u = sizeof pad1; u < sig_len; u ++) {
+ if (sig[u] != 0xFF) {
+ break;
+ }
+ }
+
+ /*
+ * Remaining length is sig_len - u bytes (including the 00 just
+ * after the last FF). This must be equal to one of the two
+ * possible values (depending on whether the "05 00" sequence is
+ * present or not).
+ */
+ if (hash_oid == NULL) {
+ if (sig_len - u != hash_len + 1 || sig[u] != 0x00) {
+ return 0;
+ }
+ } else {
+ x3 = hash_oid[0];
+ pad_len = x3 + 9;
+ memset(pad2, 0, pad_len);
+ zlen = sig_len - u - hash_len;
+ if (zlen == pad_len) {
+ x2 = x3 + 2;
+ } else if (zlen == pad_len + 2) {
+ x2 = x3 + 4;
+ pad_len = zlen;
+ pad2[pad_len - 4] = 0x05;
+ } else {
+ return 0;
+ }
+ pad2[1] = 0x30;
+ pad2[2] = x2 + hash_len + 4;
+ pad2[3] = 0x30;
+ pad2[4] = x2;
+ pad2[5] = 0x06;
+ memcpy(pad2 + 6, hash_oid, x3 + 1);
+ pad2[pad_len - 2] = 0x04;
+ pad2[pad_len - 1] = hash_len;
+ if (memcmp(pad2, sig + u, pad_len) != 0) {
+ return 0;
+ }
+ }
+ memcpy(hash_out, sig + sig_len - hash_len, hash_len);
+ return 1;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_pkcs1_sig_unpad.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_pad.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_pad.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_pad.c (revision 346145)
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+uint32_t
+br_rsa_pss_sig_pad(const br_prng_class **rng,
+ const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ uint32_t n_bitlen, unsigned char *x)
+{
+ size_t xlen, hash_len;
+ br_hash_compat_context hc;
+ unsigned char *salt, *seed;
+
+ hash_len = br_digest_size(hf_data);
+
+ /*
+ * The padded string is one bit smaller than the modulus;
+ * notably, if the modulus length is equal to 1 modulo 8, then
+ * the padded string will be one _byte_ smaller, and the first
+ * byte will be set to 0. We apply these transformations here.
+ */
+ n_bitlen --;
+ if ((n_bitlen & 7) == 0) {
+ *x ++ = 0;
+ }
+ xlen = (n_bitlen + 7) >> 3;
+
+ /*
+ * Check that the modulus is large enough for the hash value
+ * length combined with the intended salt length.
+ */
+ if (hash_len > xlen || salt_len > xlen
+ || (hash_len + salt_len + 2) > xlen)
+ {
+ return 0;
+ }
+
+ /*
+ * Produce a random salt.
+ */
+ salt = x + xlen - hash_len - salt_len - 1;
+ if (salt_len != 0) {
+ (*rng)->generate(rng, salt, salt_len);
+ }
+
+ /*
+ * Compute the seed for MGF1.
+ */
+ seed = x + xlen - hash_len - 1;
+ hf_data->init(&hc.vtable);
+ memset(seed, 0, 8);
+ hf_data->update(&hc.vtable, seed, 8);
+ hf_data->update(&hc.vtable, hash, hash_len);
+ hf_data->update(&hc.vtable, salt, salt_len);
+ hf_data->out(&hc.vtable, seed);
+
+ /*
+ * Prepare string PS (padded salt). The salt is already at the
+ * right place.
+ */
+ memset(x, 0, xlen - salt_len - hash_len - 2);
+ x[xlen - salt_len - hash_len - 2] = 0x01;
+
+ /*
+ * Generate the mask and XOR it into PS.
+ */
+ br_mgf1_xor(x, xlen - hash_len - 1, hf_mgf1, seed, hash_len);
+
+ /*
+ * Clear the top bits to ensure the value is lower than the
+ * modulus.
+ */
+ x[0] &= 0xFF >> (((uint32_t)xlen << 3) - n_bitlen);
+
+ /*
+ * The seed (H) is already in the right place. We just set the
+ * last byte.
+ */
+ x[xlen - 1] = 0xBC;
+
+ return 1;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_pad.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_unpad.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_unpad.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_unpad.c (revision 346145)
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+uint32_t
+br_rsa_pss_sig_unpad(const br_hash_class *hf_data,
+ const br_hash_class *hf_mgf1,
+ const unsigned char *hash, size_t salt_len,
+ const br_rsa_public_key *pk, unsigned char *x)
+{
+ size_t u, xlen, hash_len;
+ br_hash_compat_context hc;
+ unsigned char *seed, *salt;
+ unsigned char tmp[64];
+ uint32_t r, n_bitlen;
+
+ hash_len = br_digest_size(hf_data);
+
+ /*
+ * Value r will be set to a non-zero value is any test fails.
+ */
+ r = 0;
+
+ /*
+ * The value bit length (as an integer) must be strictly less than
+ * that of the modulus.
+ */
+ for (u = 0; u < pk->nlen; u ++) {
+ if (pk->n[u] != 0) {
+ break;
+ }
+ }
+ if (u == pk->nlen) {
+ return 0;
+ }
+ n_bitlen = BIT_LENGTH(pk->n[u]) + ((uint32_t)(pk->nlen - u - 1) << 3);
+ n_bitlen --;
+ if ((n_bitlen & 7) == 0) {
+ r |= *x ++;
+ } else {
+ r |= x[0] & (0xFF << (n_bitlen & 7));
+ }
+ xlen = (n_bitlen + 7) >> 3;
+
+ /*
+ * Check that the modulus is large enough for the hash value
+ * length combined with the intended salt length.
+ */
+ if (hash_len > xlen || salt_len > xlen
+ || (hash_len + salt_len + 2) > xlen)
+ {
+ return 0;
+ }
+
+ /*
+ * Check value of rightmost byte.
+ */
+ r |= x[xlen - 1] ^ 0xBC;
+
+ /*
+ * Generate the mask and XOR it into the first bytes to reveal PS;
+ * we must also mask out the leading bits.
+ */
+ seed = x + xlen - hash_len - 1;
+ br_mgf1_xor(x, xlen - hash_len - 1, hf_mgf1, seed, hash_len);
+ if ((n_bitlen & 7) != 0) {
+ x[0] &= 0xFF >> (8 - (n_bitlen & 7));
+ }
+
+ /*
+ * Check that all padding bytes have the expected value.
+ */
+ for (u = 0; u < (xlen - hash_len - salt_len - 2); u ++) {
+ r |= x[u];
+ }
+ r |= x[xlen - hash_len - salt_len - 2] ^ 0x01;
+
+ /*
+ * Recompute H.
+ */
+ salt = x + xlen - hash_len - salt_len - 1;
+ hf_data->init(&hc.vtable);
+ memset(tmp, 0, 8);
+ hf_data->update(&hc.vtable, tmp, 8);
+ hf_data->update(&hc.vtable, hash, hash_len);
+ hf_data->update(&hc.vtable, salt, salt_len);
+ hf_data->out(&hc.vtable, tmp);
+
+ /*
+ * Check that the recomputed H value matches the one appearing
+ * in the string.
+ */
+ for (u = 0; u < hash_len; u ++) {
+ r |= tmp[u] ^ x[(xlen - salt_len - 1) + u];
+ }
+
+ return EQ0(r);
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_pss_sig_unpad.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/rsa/rsa_ssl_decrypt.c
===================================================================
--- stable/12/contrib/bearssl/src/rsa/rsa_ssl_decrypt.c (nonexistent)
+++ stable/12/contrib/bearssl/src/rsa/rsa_ssl_decrypt.c (revision 346145)
@@ -0,0 +1,52 @@
+/*
+ * 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 bearssl_rsa.h */
+uint32_t
+br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk,
+ unsigned char *data, size_t len)
+{
+ uint32_t x;
+ size_t u;
+
+ /*
+ * A first check on length. Since this test works only on the
+ * buffer length, it needs not (and cannot) be constant-time.
+ */
+ if (len < 59 || len != (sk->n_bitlen + 7) >> 3) {
+ return 0;
+ }
+ x = core(data, sk);
+
+ x &= EQ(data[0], 0x00);
+ x &= EQ(data[1], 0x02);
+ for (u = 2; u < (len - 49); u ++) {
+ x &= NEQ(data[u], 0);
+ }
+ x &= EQ(data[len - 49], 0x00);
+ memmove(data, data + len - 48, 48);
+ return x;
+}
Property changes on: stable/12/contrib/bearssl/src/rsa/rsa_ssl_decrypt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/settings.c
===================================================================
--- stable/12/contrib/bearssl/src/settings.c (nonexistent)
+++ stable/12/contrib/bearssl/src/settings.c (revision 346145)
@@ -0,0 +1,306 @@
+/*
+ * 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"
+
+static const br_config_option config[] = {
+ { "BR_64",
+#if BR_64
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_AES_X86NI",
+#if BR_AES_X86NI
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_amd64",
+#if BR_amd64
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_ARMEL_CORTEXM_GCC",
+#if BR_ARMEL_CORTEXM_GCC
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_BE_UNALIGNED",
+#if BR_BE_UNALIGNED
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_CLANG",
+#if BR_CLANG
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_CLANG_3_7",
+#if BR_CLANG_3_7
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_CLANG_3_8",
+#if BR_CLANG_3_8
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_CT_MUL15",
+#if BR_CT_MUL15
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_CT_MUL31",
+#if BR_CT_MUL31
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC",
+#if BR_GCC
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC_4_4",
+#if BR_GCC_4_4
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC_4_5",
+#if BR_GCC_4_5
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC_4_6",
+#if BR_GCC_4_6
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC_4_7",
+#if BR_GCC_4_7
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC_4_8",
+#if BR_GCC_4_8
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC_4_9",
+#if BR_GCC_4_9
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_GCC_5_0",
+#if BR_GCC_5_0
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_i386",
+#if BR_i386
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_INT128",
+#if BR_INT128
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_LE_UNALIGNED",
+#if BR_LE_UNALIGNED
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_LOMUL",
+#if BR_LOMUL
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_MAX_EC_SIZE", BR_MAX_EC_SIZE },
+ { "BR_MAX_RSA_SIZE", BR_MAX_RSA_SIZE },
+ { "BR_MAX_RSA_FACTOR", BR_MAX_RSA_FACTOR },
+ { "BR_MSC",
+#if BR_MSC
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_MSC_2005",
+#if BR_MSC_2005
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_MSC_2008",
+#if BR_MSC_2008
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_MSC_2010",
+#if BR_MSC_2010
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_MSC_2012",
+#if BR_MSC_2012
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_MSC_2013",
+#if BR_MSC_2013
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_MSC_2015",
+#if BR_MSC_2015
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_POWER8",
+#if BR_POWER8
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_RDRAND",
+#if BR_RDRAND
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_SLOW_MUL",
+#if BR_SLOW_MUL
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_SLOW_MUL15",
+#if BR_SLOW_MUL15
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_SSE2",
+#if BR_SSE2
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_UMUL128",
+#if BR_UMUL128
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_USE_UNIX_TIME",
+#if BR_USE_UNIX_TIME
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_USE_WIN32_RAND",
+#if BR_USE_WIN32_RAND
+ 1
+#else
+ 0
+#endif
+ },
+ { "BR_USE_WIN32_TIME",
+#if BR_USE_WIN32_TIME
+ 1
+#else
+ 0
+#endif
+ },
+
+ { NULL, 0 }
+};
+
+/* see bearssl.h */
+const br_config_option *
+br_get_config(void)
+{
+ return config;
+}
Property changes on: stable/12/contrib/bearssl/src/settings.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/prf.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/prf.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/prf.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_tls_phash(void *dst, size_t len,
+ const br_hash_class *dig,
+ const void *secret, size_t secret_len, const char *label,
+ size_t seed_num, const br_tls_prf_seed_chunk *seed)
+{
+ unsigned char *buf;
+ unsigned char tmp[64], a[64];
+ br_hmac_key_context kc;
+ br_hmac_context hc;
+ size_t label_len, hlen, u;
+
+ if (len == 0) {
+ return;
+ }
+ buf = dst;
+ for (label_len = 0; label[label_len]; label_len ++);
+ hlen = br_digest_size(dig);
+ br_hmac_key_init(&kc, dig, secret, secret_len);
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, label, label_len);
+ for (u = 0; u < seed_num; u ++) {
+ br_hmac_update(&hc, seed[u].data, seed[u].len);
+ }
+ br_hmac_out(&hc, a);
+ for (;;) {
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, a, hlen);
+ br_hmac_update(&hc, label, label_len);
+ for (u = 0; u < seed_num; u ++) {
+ br_hmac_update(&hc, seed[u].data, seed[u].len);
+ }
+ br_hmac_out(&hc, tmp);
+ for (u = 0; u < hlen && u < len; u ++) {
+ buf[u] ^= tmp[u];
+ }
+ buf += u;
+ len -= u;
+ if (len == 0) {
+ return;
+ }
+ br_hmac_init(&hc, &kc, 0);
+ br_hmac_update(&hc, a, hlen);
+ br_hmac_out(&hc, a);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/prf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/prf_md5sha1.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/prf_md5sha1.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/prf_md5sha1.c (revision 346145)
@@ -0,0 +1,43 @@
+/*
+ * 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 bearssl.h */
+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)
+{
+ const unsigned char *s1;
+ size_t slen;
+
+ s1 = secret;
+ slen = (secret_len + 1) >> 1;
+ memset(dst, 0, len);
+ br_tls_phash(dst, len, &br_md5_vtable,
+ s1, slen, label, seed_num, seed);
+ br_tls_phash(dst, len, &br_sha1_vtable,
+ s1 + secret_len - slen, slen, label, seed_num, seed);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/prf_md5sha1.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/prf_sha256.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/prf_sha256.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/prf_sha256.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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 bearssl.h */
+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)
+{
+ memset(dst, 0, len);
+ br_tls_phash(dst, len, &br_sha256_vtable,
+ secret, secret_len, label, seed_num, seed);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/prf_sha256.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/prf_sha384.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/prf_sha384.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/prf_sha384.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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 bearssl.h */
+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)
+{
+ memset(dst, 0, len);
+ br_tls_phash(dst, len, &br_sha384_vtable,
+ secret, secret_len, label, seed_num, seed);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/prf_sha384.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_ec.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_ec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_ec.c (revision 346145)
@@ -0,0 +1,156 @@
+/*
+ * 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"
+
+static void
+cc_none0(const br_ssl_client_certificate_class **pctx)
+{
+ (void)pctx;
+}
+
+static void
+cc_none1(const br_ssl_client_certificate_class **pctx, size_t len)
+{
+ (void)pctx;
+ (void)len;
+}
+
+static void
+cc_none2(const br_ssl_client_certificate_class **pctx,
+ const unsigned char *data, size_t len)
+{
+ (void)pctx;
+ (void)data;
+ (void)len;
+}
+
+static void
+cc_choose(const br_ssl_client_certificate_class **pctx,
+ const br_ssl_client_context *cc, uint32_t auth_types,
+ br_ssl_client_certificate *choices)
+{
+ br_ssl_client_certificate_ec_context *zc;
+ int x;
+ int scurve;
+
+ zc = (br_ssl_client_certificate_ec_context *)pctx;
+ scurve = br_ssl_client_get_server_curve(cc);
+
+ if ((zc->allowed_usages & BR_KEYTYPE_KEYX) != 0
+ && scurve == zc->sk->curve)
+ {
+ int x;
+
+ x = (zc->issuer_key_type == BR_KEYTYPE_RSA) ? 16 : 17;
+ if (((auth_types >> x) & 1) != 0) {
+ choices->auth_type = BR_AUTH_ECDH;
+ choices->hash_id = -1;
+ choices->chain = zc->chain;
+ choices->chain_len = zc->chain_len;
+ }
+ }
+
+ /*
+ * For ECDSA authentication, we must choose an appropriate
+ * hash function.
+ */
+ x = br_ssl_choose_hash((unsigned)(auth_types >> 8));
+ if (x == 0 || (zc->allowed_usages & BR_KEYTYPE_SIGN) == 0) {
+ memset(choices, 0, sizeof *choices);
+ return;
+ }
+ choices->auth_type = BR_AUTH_ECDSA;
+ choices->hash_id = x;
+ choices->chain = zc->chain;
+ choices->chain_len = zc->chain_len;
+}
+
+static uint32_t
+cc_do_keyx(const br_ssl_client_certificate_class **pctx,
+ unsigned char *data, size_t *len)
+{
+ br_ssl_client_certificate_ec_context *zc;
+ uint32_t r;
+ size_t xoff, xlen;
+
+ zc = (br_ssl_client_certificate_ec_context *)pctx;
+ r = zc->iec->mul(data, *len, zc->sk->x, zc->sk->xlen, zc->sk->curve);
+ xoff = zc->iec->xoff(zc->sk->curve, &xlen);
+ memmove(data, data + xoff, xlen);
+ *len = xlen;
+ return r;
+}
+
+static size_t
+cc_do_sign(const br_ssl_client_certificate_class **pctx,
+ int hash_id, size_t hv_len, unsigned char *data, size_t len)
+{
+ br_ssl_client_certificate_ec_context *zc;
+ unsigned char hv[64];
+ const br_hash_class *hc;
+
+ zc = (br_ssl_client_certificate_ec_context *)pctx;
+ memcpy(hv, data, hv_len);
+ hc = br_multihash_getimpl(zc->mhash, hash_id);
+ if (hc == NULL) {
+ return 0;
+ }
+ if (len < 139) {
+ return 0;
+ }
+ return zc->iecdsa(zc->iec, hc, hv, zc->sk, data);
+}
+
+static const br_ssl_client_certificate_class ccert_vtable = {
+ sizeof(br_ssl_client_certificate_ec_context),
+ cc_none0, /* start_name_list */
+ cc_none1, /* start_name */
+ cc_none2, /* append_name */
+ cc_none0, /* end_name */
+ cc_none0, /* end_name_list */
+ cc_choose,
+ cc_do_keyx,
+ cc_do_sign
+};
+
+/* see bearssl_ssl.h */
+void
+br_ssl_client_set_single_ec(br_ssl_client_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk, unsigned allowed_usages,
+ unsigned cert_issuer_key_type,
+ const br_ec_impl *iec, br_ecdsa_sign iecdsa)
+{
+ cc->client_auth.single_ec.vtable = &ccert_vtable;
+ cc->client_auth.single_ec.chain = chain;
+ cc->client_auth.single_ec.chain_len = chain_len;
+ cc->client_auth.single_ec.sk = sk;
+ cc->client_auth.single_ec.allowed_usages = allowed_usages;
+ cc->client_auth.single_ec.issuer_key_type = cert_issuer_key_type;
+ cc->client_auth.single_ec.mhash = &cc->eng.mhash;
+ cc->client_auth.single_ec.iec = iec;
+ cc->client_auth.single_ec.iecdsa = iecdsa;
+ cc->client_auth_vtable = &cc->client_auth.single_ec.vtable;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_rsa.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_rsa.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_rsa.c (revision 346145)
@@ -0,0 +1,149 @@
+/*
+ * 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"
+
+static void
+cc_none0(const br_ssl_client_certificate_class **pctx)
+{
+ (void)pctx;
+}
+
+static void
+cc_none1(const br_ssl_client_certificate_class **pctx, size_t len)
+{
+ (void)pctx;
+ (void)len;
+}
+
+static void
+cc_none2(const br_ssl_client_certificate_class **pctx,
+ const unsigned char *data, size_t len)
+{
+ (void)pctx;
+ (void)data;
+ (void)len;
+}
+
+static void
+cc_choose(const br_ssl_client_certificate_class **pctx,
+ const br_ssl_client_context *cc, uint32_t auth_types,
+ br_ssl_client_certificate *choices)
+{
+ br_ssl_client_certificate_rsa_context *zc;
+ int x;
+
+ (void)cc;
+ zc = (br_ssl_client_certificate_rsa_context *)pctx;
+ x = br_ssl_choose_hash((unsigned)auth_types);
+ if (x == 0 && (auth_types & 1) == 0) {
+ memset(choices, 0, sizeof *choices);
+ }
+ choices->auth_type = BR_AUTH_RSA;
+ choices->hash_id = x;
+ choices->chain = zc->chain;
+ choices->chain_len = zc->chain_len;
+}
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+ 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+ HASH_OID_SHA1,
+ HASH_OID_SHA224,
+ HASH_OID_SHA256,
+ HASH_OID_SHA384,
+ HASH_OID_SHA512
+};
+
+static size_t
+cc_do_sign(const br_ssl_client_certificate_class **pctx,
+ int hash_id, size_t hv_len, unsigned char *data, size_t len)
+{
+ br_ssl_client_certificate_rsa_context *zc;
+ unsigned char hv[64];
+ const unsigned char *hash_oid;
+ size_t sig_len;
+
+ zc = (br_ssl_client_certificate_rsa_context *)pctx;
+ memcpy(hv, data, hv_len);
+ if (hash_id == 0) {
+ hash_oid = NULL;
+ } else if (hash_id >= 2 && hash_id <= 6) {
+ hash_oid = HASH_OID[hash_id - 2];
+ } else {
+ return 0;
+ }
+ sig_len = (zc->sk->n_bitlen + 7) >> 3;
+ if (len < sig_len) {
+ return 0;
+ }
+ return zc->irsasign(hash_oid, hv, hv_len, zc->sk, data) ? sig_len : 0;
+}
+
+static const br_ssl_client_certificate_class ccert_vtable = {
+ sizeof(br_ssl_client_certificate_rsa_context),
+ cc_none0, /* start_name_list */
+ cc_none1, /* start_name */
+ cc_none2, /* append_name */
+ cc_none0, /* end_name */
+ cc_none0, /* end_name_list */
+ cc_choose,
+ 0,
+ cc_do_sign
+};
+
+/* see bearssl_ssl.h */
+void
+br_ssl_client_set_single_rsa(br_ssl_client_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign)
+{
+ cc->client_auth.single_rsa.vtable = &ccert_vtable;
+ cc->client_auth.single_rsa.chain = chain;
+ cc->client_auth.single_rsa.chain_len = chain_len;
+ cc->client_auth.single_rsa.sk = sk;
+ cc->client_auth.single_rsa.irsasign = irsasign;
+ cc->client_auth_vtable = &cc->client_auth.single_rsa.vtable;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_ccert_single_rsa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_client.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_client.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_client.c (revision 346145)
@@ -0,0 +1,78 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_client_zero(br_ssl_client_context *cc)
+{
+ /*
+ * For really standard C, we should explicitly set to NULL all
+ * pointers, and 0 all other fields. However, on all our target
+ * architectures, a direct memset() will work, be faster, and
+ * use a lot less code.
+ */
+ memset(cc, 0, sizeof *cc);
+}
+
+/* see bearssl_ssl.h */
+int
+br_ssl_client_reset(br_ssl_client_context *cc,
+ const char *server_name, int resume_session)
+{
+ size_t n;
+
+ br_ssl_engine_set_buffer(&cc->eng, NULL, 0, 0);
+ cc->eng.version_out = cc->eng.version_min;
+ if (!resume_session) {
+ br_ssl_client_forget_session(cc);
+ }
+ if (!br_ssl_engine_init_rand(&cc->eng)) {
+ return 0;
+ }
+
+ /*
+ * We always set back the "reneg" flag to 0 because we use it
+ * to distinguish between first handshake and renegotiation.
+ * Note that "renegotiation" and "session resumption" are two
+ * different things.
+ */
+ cc->eng.reneg = 0;
+
+ if (server_name == NULL) {
+ cc->eng.server_name[0] = 0;
+ } else {
+ n = strlen(server_name) + 1;
+ if (n > sizeof cc->eng.server_name) {
+ br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM);
+ return 0;
+ }
+ memcpy(cc->eng.server_name, server_name, n);
+ }
+
+ br_ssl_engine_hs_reset(&cc->eng,
+ br_ssl_hs_client_init_main, br_ssl_hs_client_run);
+ return br_ssl_engine_last_error(&cc->eng) == BR_ERR_OK;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_client.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_client_default_rsapub.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_client_default_rsapub.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_client_default_rsapub.c (revision 346145)
@@ -0,0 +1,32 @@
+/*
+ * 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"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_client_set_default_rsapub(br_ssl_client_context *cc)
+{
+ br_ssl_client_set_rsapub(cc, br_rsa_public_get_default());
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_client_default_rsapub.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_client_full.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_client_full.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_client_full.c (revision 346145)
@@ -0,0 +1,179 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_client_init_full(br_ssl_client_context *cc,
+ br_x509_minimal_context *xc,
+ const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num)
+{
+ /*
+ * The "full" profile supports all implemented cipher suites.
+ *
+ * Rationale for suite order, from most important to least
+ * important rule:
+ *
+ * -- Don't use 3DES if AES or ChaCha20 is available.
+ * -- Try to have Forward Secrecy (ECDHE suite) if possible.
+ * -- When not using Forward Secrecy, ECDH key exchange is
+ * better than RSA key exchange (slightly more expensive on the
+ * client, but much cheaper on the server, and it implies smaller
+ * messages).
+ * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller code).
+ * -- GCM is better than CCM and CBC. CCM is better than CBC.
+ * -- CCM is preferable over CCM_8 (with CCM_8, forgeries may succeed
+ * with probability 2^(-64)).
+ * -- AES-128 is preferred over AES-256 (AES-128 is already
+ * strong enough, and AES-256 is 40% more expensive).
+ */
+ 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_CCM,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
+ 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_CCM,
+ BR_TLS_RSA_WITH_AES_256_CCM,
+ BR_TLS_RSA_WITH_AES_128_CCM_8,
+ BR_TLS_RSA_WITH_AES_256_CCM_8,
+ 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
+ };
+
+ /*
+ * All hash functions are activated.
+ * Note: the X.509 validation engine will nonetheless refuse to
+ * validate signatures that use MD5 as hash function.
+ */
+ static const br_hash_class *hashes[] = {
+ &br_md5_vtable,
+ &br_sha1_vtable,
+ &br_sha224_vtable,
+ &br_sha256_vtable,
+ &br_sha384_vtable,
+ &br_sha512_vtable
+ };
+
+ int id;
+
+ /*
+ * Reset client context and set supported versions from TLS-1.0
+ * to TLS-1.2 (inclusive).
+ */
+ br_ssl_client_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
+
+ /*
+ * X.509 engine uses SHA-256 to hash certificate DN (for
+ * comparisons).
+ */
+ 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).
+ * TODO: change that when better implementations are made available.
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+ br_ssl_client_set_default_rsapub(cc);
+ br_ssl_engine_set_default_rsavrfy(&cc->eng);
+ br_ssl_engine_set_default_ecdsa(&cc->eng);
+ br_x509_minimal_set_rsa(xc, br_ssl_engine_get_rsavrfy(&cc->eng));
+ br_x509_minimal_set_ecdsa(xc,
+ br_ssl_engine_get_ec(&cc->eng),
+ br_ssl_engine_get_ecdsa(&cc->eng));
+
+ /*
+ * Set supported hash functions, for the SSL engine and for the
+ * X.509 engine.
+ */
+ for (id = br_md5_ID; id <= br_sha512_ID; id ++) {
+ const br_hash_class *hc;
+
+ hc = hashes[id - 1];
+ br_ssl_engine_set_hash(&cc->eng, id, hc);
+ br_x509_minimal_set_hash(xc, id, hc);
+ }
+
+ /*
+ * Link the X.509 engine in the SSL engine.
+ */
+ br_ssl_engine_set_x509(&cc->eng, &xc->vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ 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);
+
+ /*
+ * Symmetric encryption. We use the "default" implementations
+ * (fastest among constant-time implementations).
+ */
+ br_ssl_engine_set_default_aes_cbc(&cc->eng);
+ br_ssl_engine_set_default_aes_ccm(&cc->eng);
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+ br_ssl_engine_set_default_des_cbc(&cc->eng);
+ br_ssl_engine_set_default_chapol(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_client_full.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine.c (revision 346145)
@@ -0,0 +1,1569 @@
+/*
+ * 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"
+
+#if 0
+/* obsolete */
+
+/*
+ * If BR_USE_URANDOM is not defined, then try to autodetect its presence
+ * through compiler macros.
+ */
+#ifndef BR_USE_URANDOM
+
+/*
+ * Macro values documented on:
+ * https://sourceforge.net/p/predef/wiki/OperatingSystems/
+ *
+ * Only the most common systems have been included here for now. This
+ * should be enriched later on.
+ */
+#if defined _AIX \
+ || defined __ANDROID__ \
+ || defined __FreeBSD__ \
+ || defined __NetBSD__ \
+ || defined __OpenBSD__ \
+ || defined __DragonFly__ \
+ || defined __linux__ \
+ || (defined __sun && (defined __SVR4 || defined __svr4__)) \
+ || (defined __APPLE__ && defined __MACH__)
+#define BR_USE_URANDOM 1
+#endif
+
+#endif
+
+/*
+ * If BR_USE_WIN32_RAND is not defined, perform autodetection here.
+ */
+#ifndef BR_USE_WIN32_RAND
+
+#if defined _WIN32 || defined _WIN64
+#define BR_USE_WIN32_RAND 1
+#endif
+
+#endif
+
+#if BR_USE_URANDOM
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif
+
+#if BR_USE_WIN32_RAND
+#include <windows.h>
+#include <wincrypt.h>
+#pragma comment(lib, "advapi32")
+#endif
+
+#endif
+
+/* ==================================================================== */
+/*
+ * This part of the file does the low-level record management.
+ */
+
+/*
+ * IMPLEMENTATION NOTES
+ * ====================
+ *
+ * In this file, we designate by "input" (and the "i" letter) the "recv"
+ * operations: incoming records from the peer, from which payload data
+ * is obtained, and must be extracted by the application (or the SSL
+ * handshake engine). Similarly, "output" (and the "o" letter) is for
+ * "send": payload data injected by the application (and SSL handshake
+ * engine), to be wrapped into records, that are then conveyed to the
+ * peer over the transport medium.
+ *
+ * The input and output buffers may be distinct or shared. When
+ * shared, input and output cannot occur concurrently; the caller
+ * must make sure that it never needs to output data while input
+ * data has been received. In practice, a shared buffer prevents
+ * pipelining of HTTP requests, or similar protocols; however, a
+ * shared buffer saves RAM.
+ *
+ * The input buffer is pointed to by 'ibuf' and has size 'ibuf_len';
+ * the output buffer is pointed to by 'obuf' and has size 'obuf_len'.
+ * From the size of these buffers is derived the maximum fragment
+ * length, which will be honoured upon sending records; regardless of
+ * that length, incoming records will be processed as long as they
+ * fit in the input buffer, and their length still complies with the
+ * protocol specification (maximum plaintext payload length is 16384
+ * bytes).
+ *
+ * Three registers are used to manage buffering in ibuf, called ixa,
+ * ixb and ixc. Similarly, three registers are used to manage buffering
+ * in obuf, called oxa, oxb and oxc.
+ *
+ *
+ * At any time, the engine is in one of the following modes:
+ * -- Failed mode: an error occurs, no I/O can happen.
+ * -- Input mode: the engine can either receive record bytes from the
+ * transport layer, or it has some buffered payload bytes to yield.
+ * -- Output mode: the engine can either receive payload bytes, or it
+ * has some record bytes to send to the transport layer.
+ * -- Input/Output mode: both input and output modes are active. When
+ * the buffer is shared, this can happen only when the buffer is empty
+ * (no buffered payload bytes or record bytes in either direction).
+ *
+ *
+ * Failed mode:
+ * ------------
+ *
+ * I/O failed for some reason (invalid received data, not enough room
+ * for the next record...). No I/O may ever occur again for this context,
+ * until an explicit reset is performed. This mode, and the error code,
+ * are also used for protocol errors, especially handshake errors.
+ *
+ *
+ * Input mode:
+ * -----------
+ *
+ * ixa index within ibuf[] for the currently read data
+ * ixb maximum index within ibuf[] for the currently read data
+ * ixc number of bytes not yet received for the current record
+ *
+ * -- When ixa == ixb, there is no available data for readers. When
+ * ixa != ixb, there is available data and it starts at offset ixa.
+ *
+ * -- When waiting for the next record header, ixa and ixb are equal
+ * and contain a value ranging from 0 to 4; ixc is equal to 5-ixa.
+ *
+ * -- When the header has been received, record data is obtained. The
+ * ixc field records how many bytes are still needed to reach the
+ * end of the current record.
+ *
+ * ** If encryption is active, then ixa and ixb are kept equal, and
+ * point to the end of the currently received record bytes. When
+ * ixc reaches 0, decryption/MAC is applied, and ixa and ixb are
+ * adjusted.
+ *
+ * ** If encryption is not active, then ixa and ixb are distinct
+ * and data can be read right away. Additional record data is
+ * obtained only when ixa == ixb.
+ *
+ * Note: in input mode and no encryption, records larger than the buffer
+ * size are allowed. When encryption is active, the complete record must
+ * fit within the buffer, since it cannot be decrypted/MACed until it
+ * has been completely received.
+ *
+ * -- When receiving the next record header, 'version_in' contains the
+ * expected input version (0 if not expecting a specific version); on
+ * mismatch, the mode switches to 'failed'.
+ *
+ * -- When the header has been received, 'version_in' contains the received
+ * version. It is up to the caller to check and adjust the 'version_in' field
+ * to implement the required semantics.
+ *
+ * -- The 'record_type_in' field is updated with the incoming record type
+ * when the next record header has been received.
+ *
+ *
+ * Output mode:
+ * ------------
+ *
+ * oxa index within obuf[] for the currently accumulated data
+ * oxb maximum index within obuf[] for record data
+ * oxc pointer for start of record data, and for record sending
+ *
+ * -- When oxa != oxb, more data can be accumulated into the current
+ * record; when oxa == oxb, a closed record is being sent.
+ *
+ * -- When accumulating data, oxc points to the start of the data.
+ *
+ * -- During record sending, oxa (and oxb) point to the next record byte
+ * to send, and oxc indicates the end of the current record.
+ *
+ * Note: sent records must fit within the buffer, since the header is
+ * adjusted only when the complete record has been assembled.
+ *
+ * -- The 'version_out' and 'record_type_out' fields are used to build the
+ * record header when the mode is switched to 'sending'.
+ *
+ *
+ * Modes:
+ * ------
+ *
+ * The state register iomode contains one of the following values:
+ *
+ * BR_IO_FAILED I/O failed
+ * BR_IO_IN input mode
+ * BR_IO_OUT output mode
+ * BR_IO_INOUT input/output mode
+ *
+ * Whether encryption is active on incoming records is indicated by the
+ * incrypt flag. For outgoing records, there is no such flag; "encryption"
+ * is always considered active, but initially uses functions that do not
+ * encrypt anything. The 'incrypt' flag is needed because when there is
+ * no active encryption, records larger than the I/O buffer are accepted.
+ *
+ * Note: we do not support no-encryption modes (MAC only).
+ *
+ * TODO: implement GCM support
+ *
+ *
+ * Misc:
+ * -----
+ *
+ * 'max_frag_len' is the maximum plaintext size for an outgoing record.
+ * By default, it is set to the maximum value that fits in the provided
+ * buffers, in the following list: 512, 1024, 2048, 4096, 16384. The
+ * caller may change it if needed, but the new value MUST still fit in
+ * the buffers, and it MUST be one of the list above for compatibility
+ * with the Maximum Fragment Length extension.
+ *
+ * For incoming records, only the total buffer length and current
+ * encryption mode impact the maximum length for incoming records. The
+ * 'max_frag_len' value is still adjusted so that records up to that
+ * length can be both received and sent.
+ *
+ *
+ * Offsets and lengths:
+ * --------------------
+ *
+ * When sending fragments with TLS-1.1+, the maximum overhead is:
+ * 5 bytes for the record header
+ * 16 bytes for the explicit IV
+ * 48 bytes for the MAC (HMAC/SHA-384)
+ * 16 bytes for the padding (AES)
+ * so a total of 85 extra bytes. Note that we support block cipher sizes
+ * up to 16 bytes (AES) and HMAC output sizes up to 48 bytes (SHA-384).
+ *
+ * With TLS-1.0 and CBC mode, we apply a 1/n-1 split, for a maximum
+ * overhead of:
+ * 5 bytes for the first record header
+ * 32 bytes for the first record payload (AES-CBC + HMAC/SHA-1)
+ * 5 bytes for the second record header
+ * 20 bytes for the MAC (HMAC/SHA-1)
+ * 16 bytes for the padding (AES)
+ * -1 byte to account for the payload byte in the first record
+ * so a total of 77 extra bytes at most, less than the 85 bytes above.
+ * Note that with TLS-1.0, the MAC is HMAC with either MD5 or SHA-1, but
+ * no other hash function.
+ *
+ * The implementation does not try to send larger records when the current
+ * encryption mode has less overhead.
+ *
+ * Maximum input record overhead is:
+ * 5 bytes for the record header
+ * 16 bytes for the explicit IV (TLS-1.1+)
+ * 48 bytes for the MAC (HMAC/SHA-384)
+ * 256 bytes for the padding
+ * so a total of 325 extra bytes.
+ *
+ * When receiving the next record header, it is written into the buffer
+ * bytes 0 to 4 (inclusive). Record data is always written into buf[]
+ * starting at offset 5. When encryption is active, the plaintext data
+ * may start at a larger offset (e.g. because of an explicit IV).
+ */
+
+#define MAX_OUT_OVERHEAD 85
+#define MAX_IN_OVERHEAD 325
+
+/* see inner.h */
+void
+br_ssl_engine_fail(br_ssl_engine_context *rc, int err)
+{
+ if (rc->iomode != BR_IO_FAILED) {
+ rc->iomode = BR_IO_FAILED;
+ rc->err = err;
+ }
+}
+
+/*
+ * Adjust registers for a new incoming record.
+ */
+static void
+make_ready_in(br_ssl_engine_context *rc)
+{
+ rc->ixa = rc->ixb = 0;
+ rc->ixc = 5;
+ if (rc->iomode == BR_IO_IN) {
+ rc->iomode = BR_IO_INOUT;
+ }
+}
+
+/*
+ * Adjust registers for a new outgoing record.
+ */
+static void
+make_ready_out(br_ssl_engine_context *rc)
+{
+ size_t a, b;
+
+ a = 5;
+ b = rc->obuf_len - a;
+ rc->out.vtable->max_plaintext(&rc->out.vtable, &a, &b);
+ if ((b - a) > rc->max_frag_len) {
+ b = a + rc->max_frag_len;
+ }
+ rc->oxa = a;
+ rc->oxb = b;
+ rc->oxc = a;
+ if (rc->iomode == BR_IO_OUT) {
+ rc->iomode = BR_IO_INOUT;
+ }
+}
+
+/* see inner.h */
+void
+br_ssl_engine_new_max_frag_len(br_ssl_engine_context *rc, unsigned max_frag_len)
+{
+ size_t nxb;
+
+ rc->max_frag_len = max_frag_len;
+ nxb = rc->oxc + max_frag_len;
+ if (rc->oxa < rc->oxb && rc->oxb > nxb && rc->oxa < nxb) {
+ rc->oxb = nxb;
+ }
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_buffer(br_ssl_engine_context *rc,
+ void *buf, size_t buf_len, int bidi)
+{
+ if (buf == NULL) {
+ br_ssl_engine_set_buffers_bidi(rc, NULL, 0, NULL, 0);
+ } else {
+ /*
+ * In bidirectional mode, we want to maximise input
+ * buffer size, since we support arbitrary fragmentation
+ * when sending, but the peer will not necessarily
+ * comply to any low fragment length (in particular if
+ * we are the server, because the maximum fragment
+ * length extension is under client control).
+ *
+ * We keep a minimum size of 512 bytes for the plaintext
+ * of our outgoing records.
+ *
+ * br_ssl_engine_set_buffers_bidi() will compute the maximum
+ * fragment length for outgoing records by using the minimum
+ * of allocated spaces for both input and output records,
+ * rounded down to a standard length.
+ */
+ if (bidi) {
+ size_t w;
+
+ if (buf_len < (512 + MAX_IN_OVERHEAD
+ + 512 + MAX_OUT_OVERHEAD))
+ {
+ rc->iomode = BR_IO_FAILED;
+ rc->err = BR_ERR_BAD_PARAM;
+ return;
+ } else if (buf_len < (16384 + MAX_IN_OVERHEAD
+ + 512 + MAX_OUT_OVERHEAD))
+ {
+ w = 512 + MAX_OUT_OVERHEAD;
+ } else {
+ w = buf_len - (16384 + MAX_IN_OVERHEAD);
+ }
+ br_ssl_engine_set_buffers_bidi(rc,
+ buf, buf_len - w,
+ (unsigned char *)buf + w, w);
+ } else {
+ br_ssl_engine_set_buffers_bidi(rc,
+ buf, buf_len, NULL, 0);
+ }
+ }
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *rc,
+ void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len)
+{
+ rc->iomode = BR_IO_INOUT;
+ rc->incrypt = 0;
+ rc->err = BR_ERR_OK;
+ rc->version_in = 0;
+ rc->record_type_in = 0;
+ rc->version_out = 0;
+ rc->record_type_out = 0;
+ if (ibuf == NULL) {
+ if (rc->ibuf == NULL) {
+ br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM);
+ }
+ } else {
+ unsigned u;
+
+ rc->ibuf = ibuf;
+ rc->ibuf_len = ibuf_len;
+ if (obuf == NULL) {
+ obuf = ibuf;
+ obuf_len = ibuf_len;
+ }
+ rc->obuf = obuf;
+ rc->obuf_len = obuf_len;
+
+ /*
+ * Compute the maximum fragment length, that fits for
+ * both incoming and outgoing records. This length will
+ * be used in fragment length negotiation, so we must
+ * honour it both ways. Regardless, larger incoming
+ * records will be accepted, as long as they fit in the
+ * actual buffer size.
+ */
+ for (u = 14; u >= 9; u --) {
+ size_t flen;
+
+ flen = (size_t)1 << u;
+ if (obuf_len >= flen + MAX_OUT_OVERHEAD
+ && ibuf_len >= flen + MAX_IN_OVERHEAD)
+ {
+ break;
+ }
+ }
+ if (u == 8) {
+ br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM);
+ return;
+ } else if (u == 13) {
+ u = 12;
+ }
+ rc->max_frag_len = (size_t)1 << u;
+ rc->log_max_frag_len = u;
+ rc->peer_log_max_frag_len = 0;
+ }
+ rc->out.vtable = &br_sslrec_out_clear_vtable;
+ make_ready_in(rc);
+ make_ready_out(rc);
+}
+
+/*
+ * Clear buffers in both directions.
+ */
+static void
+engine_clearbuf(br_ssl_engine_context *rc)
+{
+ make_ready_in(rc);
+ make_ready_out(rc);
+}
+
+/*
+ * Make sure the internal PRNG is initialised (but not necessarily
+ * seeded properly yet).
+ */
+static int
+rng_init(br_ssl_engine_context *cc)
+{
+ const br_hash_class *h;
+
+ if (cc->rng_init_done != 0) {
+ return 1;
+ }
+
+ /*
+ * If using TLS-1.2, then SHA-256 or SHA-384 must be present (or
+ * both); we prefer SHA-256 which is faster for 32-bit systems.
+ *
+ * If using TLS-1.0 or 1.1 then SHA-1 must be present.
+ *
+ * Though HMAC_DRBG/SHA-1 is, as far as we know, as safe as
+ * these things can be, we still prefer the SHA-2 functions over
+ * SHA-1, if only for public relations (known theoretical
+ * weaknesses of SHA-1 with regards to collisions are mostly
+ * irrelevant here, but they still make people nervous).
+ */
+ h = br_multihash_getimpl(&cc->mhash, br_sha256_ID);
+ if (!h) {
+ h = br_multihash_getimpl(&cc->mhash, br_sha384_ID);
+ if (!h) {
+ h = br_multihash_getimpl(&cc->mhash,
+ br_sha1_ID);
+ if (!h) {
+ br_ssl_engine_fail(cc, BR_ERR_BAD_STATE);
+ return 0;
+ }
+ }
+ }
+ br_hmac_drbg_init(&cc->rng, h, NULL, 0);
+ cc->rng_init_done = 1;
+ return 1;
+}
+
+/* see inner.h */
+int
+br_ssl_engine_init_rand(br_ssl_engine_context *cc)
+{
+ if (!rng_init(cc)) {
+ return 0;
+ }
+
+ /*
+ * We always try OS/hardware seeding once. If it works, then
+ * we assume proper seeding. If not, then external entropy must
+ * have been injected; otherwise, we report an error.
+ */
+ if (!cc->rng_os_rand_done) {
+ br_prng_seeder sd;
+
+ sd = br_prng_seeder_system(NULL);
+ if (sd != 0 && sd(&cc->rng.vtable)) {
+ cc->rng_init_done = 2;
+ }
+ cc->rng_os_rand_done = 1;
+ }
+ if (cc->rng_init_done < 2) {
+ br_ssl_engine_fail(cc, BR_ERR_NO_RANDOM);
+ return 0;
+ }
+ return 1;
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_inject_entropy(br_ssl_engine_context *cc,
+ const void *data, size_t len)
+{
+ /*
+ * Externally provided entropy is assumed to be "good enough"
+ * (we cannot really test its quality) so if the RNG structure
+ * could be initialised at all, then we marked the RNG as
+ * "properly seeded".
+ */
+ if (!rng_init(cc)) {
+ return;
+ }
+ br_hmac_drbg_update(&cc->rng, data, len);
+ cc->rng_init_done = 2;
+}
+
+/*
+ * We define a few internal functions that implement the low-level engine
+ * API for I/O; the external API (br_ssl_engine_sendapp_buf() and similar
+ * functions) is built upon these function, with special processing for
+ * records which are not of type "application data".
+ *
+ * recvrec_buf, recvrec_ack receives bytes from transport medium
+ * sendrec_buf, sendrec_ack send bytes to transport medium
+ * recvpld_buf, recvpld_ack receives payload data from engine
+ * sendpld_buf, sendpld_ack send payload data to engine
+ */
+
+static unsigned char *
+recvrec_buf(const br_ssl_engine_context *rc, size_t *len)
+{
+ if (rc->shutdown_recv) {
+ *len = 0;
+ return NULL;
+ }
+
+ /*
+ * Bytes from the transport can be injected only if the mode is
+ * compatible (in or in/out), and ixa == ixb; ixc then contains
+ * the number of bytes that are still expected (but it may
+ * exceed our buffer size).
+ *
+ * We cannot get "stuck" here (buffer is full, but still more
+ * data is expected) because oversized records are detected when
+ * their header is processed.
+ */
+ switch (rc->iomode) {
+ case BR_IO_IN:
+ case BR_IO_INOUT:
+ if (rc->ixa == rc->ixb) {
+ size_t z;
+
+ z = rc->ixc;
+ if (z > rc->ibuf_len - rc->ixa) {
+ z = rc->ibuf_len - rc->ixa;
+ }
+ *len = z;
+ return rc->ibuf + rc->ixa;
+ }
+ break;
+ }
+ *len = 0;
+ return NULL;
+}
+
+static void
+recvrec_ack(br_ssl_engine_context *rc, size_t len)
+{
+ unsigned char *pbuf;
+ size_t pbuf_len;
+
+ /*
+ * Adjust state if necessary (for a shared input/output buffer):
+ * we got some incoming bytes, so we cannot (temporarily) handle
+ * outgoing data.
+ */
+ if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) {
+ rc->iomode = BR_IO_IN;
+ }
+
+ /*
+ * Adjust data pointers.
+ */
+ rc->ixb = (rc->ixa += len);
+ rc->ixc -= len;
+
+ /*
+ * If we are receiving a header and did not fully obtained it
+ * yet, then just wait for the next bytes.
+ */
+ if (rc->ixa < 5) {
+ return;
+ }
+
+ /*
+ * If we just obtained a full header, process it.
+ */
+ if (rc->ixa == 5) {
+ unsigned version;
+ unsigned rlen;
+
+ /*
+ * Get record type and version. We support only versions
+ * 3.x (if the version major number does not match, then
+ * we suppose that the record format is too alien for us
+ * to process it).
+ *
+ * Note: right now, we reject clients that try to send
+ * a ClientHello in a format compatible with SSL-2.0. It
+ * is unclear whether this will ever be supported; and
+ * if we want to support it, then this might be done in
+ * in the server-specific code, not here.
+ */
+ rc->record_type_in = rc->ibuf[0];
+ version = br_dec16be(rc->ibuf + 1);
+ if ((version >> 8) != 3) {
+ br_ssl_engine_fail(rc, BR_ERR_UNSUPPORTED_VERSION);
+ return;
+ }
+
+ /*
+ * We ensure that successive records have the same
+ * version. The handshake code must check and adjust the
+ * variables when necessary to accommodate the protocol
+ * negotiation details.
+ */
+ if (rc->version_in != 0 && rc->version_in != version) {
+ br_ssl_engine_fail(rc, BR_ERR_BAD_VERSION);
+ return;
+ }
+ rc->version_in = version;
+
+ /*
+ * Decode record length. We must check that the length
+ * is valid (relatively to the current encryption mode)
+ * and also (if encryption is active) that the record
+ * will fit in our buffer.
+ *
+ * When no encryption is active, we can process records
+ * by chunks, and thus accept any record up to the
+ * maximum allowed plaintext length (16384 bytes).
+ */
+ rlen = br_dec16be(rc->ibuf + 3);
+ if (rc->incrypt) {
+ if (!rc->in.vtable->check_length(
+ &rc->in.vtable, rlen))
+ {
+ br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH);
+ return;
+ }
+ if (rlen > (rc->ibuf_len - 5)) {
+ br_ssl_engine_fail(rc, BR_ERR_TOO_LARGE);
+ return;
+ }
+ } else {
+ if (rlen > 16384) {
+ br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH);
+ return;
+ }
+ }
+
+ /*
+ * If the record is completely empty then we must switch
+ * to a new record. Note that, in that case, we
+ * completely ignore the record type, which is fitting
+ * since we received no actual data of that type.
+ *
+ * A completely empty record is technically allowed as
+ * long as encryption/MAC is not active, i.e. before
+ * completion of the first handshake. It it still weird;
+ * it might conceptually be useful as a heartbeat or
+ * keep-alive mechanism while some lengthy operation is
+ * going on, e.g. interaction with a human user.
+ */
+ if (rlen == 0) {
+ make_ready_in(rc);
+ } else {
+ rc->ixa = rc->ixb = 5;
+ rc->ixc = rlen;
+ }
+ return;
+ }
+
+ /*
+ * If there is no active encryption, then the data can be read
+ * right away. Note that we do not receive bytes from the
+ * transport medium when we still have payload bytes to be
+ * acknowledged.
+ */
+ if (!rc->incrypt) {
+ rc->ixa = 5;
+ return;
+ }
+
+ /*
+ * Since encryption is active, we must wait for a full record
+ * before processing it.
+ */
+ if (rc->ixc != 0) {
+ return;
+ }
+
+ /*
+ * We got the full record. Decrypt it.
+ */
+ pbuf_len = rc->ixa - 5;
+ pbuf = rc->in.vtable->decrypt(&rc->in.vtable,
+ rc->record_type_in, rc->version_in, rc->ibuf + 5, &pbuf_len);
+ if (pbuf == 0) {
+ br_ssl_engine_fail(rc, BR_ERR_BAD_MAC);
+ return;
+ }
+ rc->ixa = (size_t)(pbuf - rc->ibuf);
+ rc->ixb = rc->ixa + pbuf_len;
+
+ /*
+ * Decryption may have yielded an empty record, in which case
+ * we get back to "ready" state immediately.
+ */
+ if (rc->ixa == rc->ixb) {
+ make_ready_in(rc);
+ }
+}
+
+/* see inner.h */
+int
+br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc)
+{
+ switch (rc->iomode) {
+ case BR_IO_IN:
+ case BR_IO_INOUT:
+ return rc->ixc == 0 || rc->ixa < 5;
+ default:
+ return 1;
+ }
+}
+
+static unsigned char *
+recvpld_buf(const br_ssl_engine_context *rc, size_t *len)
+{
+ /*
+ * There is payload data to be read only if the mode is
+ * compatible, and ixa != ixb.
+ */
+ switch (rc->iomode) {
+ case BR_IO_IN:
+ case BR_IO_INOUT:
+ *len = rc->ixb - rc->ixa;
+ return (*len == 0) ? NULL : (rc->ibuf + rc->ixa);
+ default:
+ *len = 0;
+ return NULL;
+ }
+}
+
+static void
+recvpld_ack(br_ssl_engine_context *rc, size_t len)
+{
+ rc->ixa += len;
+
+ /*
+ * If we read all the available data, then we either expect
+ * the remainder of the current record (if the current record
+ * was not finished; this may happen when encryption is not
+ * active), or go to "ready" state.
+ */
+ if (rc->ixa == rc->ixb) {
+ if (rc->ixc == 0) {
+ make_ready_in(rc);
+ } else {
+ rc->ixa = rc->ixb = 5;
+ }
+ }
+}
+
+static unsigned char *
+sendpld_buf(const br_ssl_engine_context *rc, size_t *len)
+{
+ /*
+ * Payload data can be injected only if the current mode is
+ * compatible, and oxa != oxb.
+ */
+ switch (rc->iomode) {
+ case BR_IO_OUT:
+ case BR_IO_INOUT:
+ *len = rc->oxb - rc->oxa;
+ return (*len == 0) ? NULL : (rc->obuf + rc->oxa);
+ default:
+ *len = 0;
+ return NULL;
+ }
+}
+
+/*
+ * If some payload bytes have been accumulated, then wrap them into
+ * an outgoing record. Otherwise, this function does nothing, unless
+ * 'force' is non-zero, in which case an empty record is assembled.
+ *
+ * The caller must take care not to invoke this function if the engine
+ * is not currently ready to receive payload bytes to send.
+ */
+static void
+sendpld_flush(br_ssl_engine_context *rc, int force)
+{
+ size_t xlen;
+ unsigned char *buf;
+
+ if (rc->oxa == rc->oxb) {
+ return;
+ }
+ xlen = rc->oxa - rc->oxc;
+ if (xlen == 0 && !force) {
+ return;
+ }
+ buf = rc->out.vtable->encrypt(&rc->out.vtable,
+ rc->record_type_out, rc->version_out,
+ rc->obuf + rc->oxc, &xlen);
+ rc->oxb = rc->oxa = (size_t)(buf - rc->obuf);
+ rc->oxc = rc->oxa + xlen;
+}
+
+static void
+sendpld_ack(br_ssl_engine_context *rc, size_t len)
+{
+ /*
+ * If using a shared buffer, then we may have to modify the
+ * current mode.
+ */
+ if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) {
+ rc->iomode = BR_IO_OUT;
+ }
+ rc->oxa += len;
+ if (rc->oxa >= rc->oxb) {
+ /*
+ * Set oxb to one more than oxa so that sendpld_flush()
+ * does not mistakingly believe that a record is
+ * already prepared and being sent.
+ */
+ rc->oxb = rc->oxa + 1;
+ sendpld_flush(rc, 0);
+ }
+}
+
+static unsigned char *
+sendrec_buf(const br_ssl_engine_context *rc, size_t *len)
+{
+ /*
+ * When still gathering payload bytes, oxc points to the start
+ * of the record data, so oxc <= oxa. However, when a full
+ * record has been completed, oxc points to the end of the record,
+ * so oxc > oxa.
+ */
+ switch (rc->iomode) {
+ case BR_IO_OUT:
+ case BR_IO_INOUT:
+ if (rc->oxc > rc->oxa) {
+ *len = rc->oxc - rc->oxa;
+ return rc->obuf + rc->oxa;
+ }
+ break;
+ }
+ *len = 0;
+ return NULL;
+}
+
+static void
+sendrec_ack(br_ssl_engine_context *rc, size_t len)
+{
+ rc->oxb = (rc->oxa += len);
+ if (rc->oxa == rc->oxc) {
+ make_ready_out(rc);
+ }
+}
+
+/*
+ * Test whether there is some buffered outgoing record that still must
+ * sent.
+ */
+static inline int
+has_rec_tosend(const br_ssl_engine_context *rc)
+{
+ return rc->oxa == rc->oxb && rc->oxa != rc->oxc;
+}
+
+/*
+ * The "no encryption" mode has no overhead. It limits the payload size
+ * to the maximum size allowed by the standard (16384 bytes); the caller
+ * is responsible for possibly enforcing a smaller fragment length.
+ */
+static void
+clear_max_plaintext(const br_sslrec_out_clear_context *cc,
+ size_t *start, size_t *end)
+{
+ size_t len;
+
+ (void)cc;
+ len = *end - *start;
+ if (len > 16384) {
+ *end = *start + 16384;
+ }
+}
+
+/*
+ * In "no encryption" mode, encryption is trivial (a no-operation) so
+ * we just have to encode the header.
+ */
+static unsigned char *
+clear_encrypt(br_sslrec_out_clear_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ unsigned char *buf;
+
+ (void)cc;
+ buf = (unsigned char *)data - 5;
+ buf[0] = record_type;
+ br_enc16be(buf + 1, version);
+ br_enc16be(buf + 3, *data_len);
+ *data_len += 5;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_out_class br_sslrec_out_clear_vtable = {
+ sizeof(br_sslrec_out_clear_context),
+ (void (*)(const br_sslrec_out_class *const *, size_t *, size_t *))
+ &clear_max_plaintext,
+ (unsigned char *(*)(const br_sslrec_out_class **,
+ int, unsigned, void *, size_t *))
+ &clear_encrypt
+};
+
+/* ==================================================================== */
+/*
+ * In this part of the file, we handle the various record types, and
+ * communications with the handshake processor.
+ */
+
+/*
+ * IMPLEMENTATION NOTES
+ * ====================
+ *
+ * The handshake processor is written in T0 and runs as a coroutine.
+ * It receives the contents of all records except application data, and
+ * is responsible for producing the contents of all records except
+ * application data.
+ *
+ * A state flag is maintained, which specifies whether application data
+ * is acceptable or not. When it is set:
+ *
+ * -- Application data can be injected as payload data (provided that
+ * the output buffer is ready for that).
+ *
+ * -- Incoming application data records are accepted, and yield data
+ * that the caller may retrieve.
+ *
+ * When the flag is cleared, application data is not accepted from the
+ * application, and incoming application data records trigger an error.
+ *
+ *
+ * Records of type handshake, alert or change-cipher-spec are handled
+ * by the handshake processor. The handshake processor is written in T0
+ * and runs as a coroutine; it gets invoked whenever one of the following
+ * situations is reached:
+ *
+ * -- An incoming record has type handshake, alert or change-cipher-spec,
+ * and yields data that can be read (zero-length records are thus
+ * ignored).
+ *
+ * -- An outgoing record has just finished being sent, and the "application
+ * data" flag is cleared.
+ *
+ * -- The caller wishes to perform a close (call to br_ssl_engine_close()).
+ *
+ * -- The caller wishes to perform a renegotiation (call to
+ * br_ssl_engine_renegotiate()).
+ *
+ * Whenever the handshake processor is entered, access to the payload
+ * buffers is provided, along with some information about explicit
+ * closures or renegotiations.
+ */
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_suites(br_ssl_engine_context *cc,
+ const uint16_t *suites, size_t suites_num)
+{
+ if ((suites_num * sizeof *suites) > sizeof cc->suites_buf) {
+ br_ssl_engine_fail(cc, BR_ERR_BAD_PARAM);
+ return;
+ }
+ memcpy(cc->suites_buf, suites, suites_num * sizeof *suites);
+ cc->suites_num = suites_num;
+}
+
+/*
+ * Give control to handshake processor. 'action' is 1 for a close,
+ * 2 for a renegotiation, or 0 for a jump due to I/O completion.
+ */
+static void
+jump_handshake(br_ssl_engine_context *cc, int action)
+{
+ /*
+ * We use a loop because the handshake processor actions may
+ * allow for more actions; namely, if the processor reads all
+ * input data, then it may allow for output data to be produced,
+ * in case of a shared in/out buffer.
+ */
+ for (;;) {
+ size_t hlen_in, hlen_out;
+
+ /*
+ * Get input buffer. We do not want to provide
+ * application data to the handshake processor (we could
+ * get called with an explicit close or renegotiation
+ * while there is application data ready to be read).
+ */
+ cc->hbuf_in = recvpld_buf(cc, &hlen_in);
+ if (cc->hbuf_in != NULL
+ && cc->record_type_in == BR_SSL_APPLICATION_DATA)
+ {
+ hlen_in = 0;
+ }
+
+ /*
+ * Get output buffer. The handshake processor never
+ * leaves an unfinished outgoing record, so if there is
+ * buffered output, then it MUST be some application
+ * data, so the processor cannot write to it.
+ */
+ cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &hlen_out);
+ if (cc->hbuf_out != NULL && br_ssl_engine_has_pld_to_send(cc)) {
+ hlen_out = 0;
+ }
+
+ /*
+ * Note: hlen_in and hlen_out can be both non-zero only if
+ * the input and output buffers are disjoint. Thus, we can
+ * offer both buffers to the handshake code.
+ */
+
+ cc->hlen_in = hlen_in;
+ cc->hlen_out = hlen_out;
+ cc->action = action;
+ cc->hsrun(&cc->cpu);
+ if (br_ssl_engine_closed(cc)) {
+ return;
+ }
+ if (cc->hbuf_out != cc->saved_hbuf_out) {
+ sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out);
+ }
+ if (hlen_in != cc->hlen_in) {
+ recvpld_ack(cc, hlen_in - cc->hlen_in);
+ if (cc->hlen_in == 0) {
+ /*
+ * We read all data bytes, which may have
+ * released the output buffer in case it
+ * is shared with the input buffer, and
+ * the handshake code might be waiting for
+ * that.
+ */
+ action = 0;
+ continue;
+ }
+ }
+ break;
+ }
+}
+
+/* see inner.h */
+void
+br_ssl_engine_flush_record(br_ssl_engine_context *cc)
+{
+ if (cc->hbuf_out != cc->saved_hbuf_out) {
+ sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out);
+ }
+ if (br_ssl_engine_has_pld_to_send(cc)) {
+ sendpld_flush(cc, 0);
+ }
+ cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &cc->hlen_out);
+}
+
+/* see bearssl_ssl.h */
+unsigned char *
+br_ssl_engine_sendapp_buf(const br_ssl_engine_context *cc, size_t *len)
+{
+ if (!(cc->application_data & 1)) {
+ *len = 0;
+ return NULL;
+ }
+ return sendpld_buf(cc, len);
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len)
+{
+ sendpld_ack(cc, len);
+}
+
+/* see bearssl_ssl.h */
+unsigned char *
+br_ssl_engine_recvapp_buf(const br_ssl_engine_context *cc, size_t *len)
+{
+ if (!(cc->application_data & 1)
+ || cc->record_type_in != BR_SSL_APPLICATION_DATA)
+ {
+ *len = 0;
+ return NULL;
+ }
+ return recvpld_buf(cc, len);
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len)
+{
+ recvpld_ack(cc, len);
+}
+
+/* see bearssl_ssl.h */
+unsigned char *
+br_ssl_engine_sendrec_buf(const br_ssl_engine_context *cc, size_t *len)
+{
+ return sendrec_buf(cc, len);
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len)
+{
+ sendrec_ack(cc, len);
+ if (len != 0 && !has_rec_tosend(cc)
+ && (cc->record_type_out != BR_SSL_APPLICATION_DATA
+ || (cc->application_data & 1) == 0))
+ {
+ jump_handshake(cc, 0);
+ }
+}
+
+/* see bearssl_ssl.h */
+unsigned char *
+br_ssl_engine_recvrec_buf(const br_ssl_engine_context *cc, size_t *len)
+{
+ return recvrec_buf(cc, len);
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len)
+{
+ unsigned char *buf;
+
+ recvrec_ack(cc, len);
+ if (br_ssl_engine_closed(cc)) {
+ return;
+ }
+
+ /*
+ * We just received some bytes from the peer. This may have
+ * yielded some payload bytes, in which case we must process
+ * them according to the record type.
+ */
+ buf = recvpld_buf(cc, &len);
+ if (buf != NULL) {
+ switch (cc->record_type_in) {
+ case BR_SSL_CHANGE_CIPHER_SPEC:
+ case BR_SSL_ALERT:
+ case BR_SSL_HANDSHAKE:
+ jump_handshake(cc, 0);
+ break;
+ case BR_SSL_APPLICATION_DATA:
+ if (cc->application_data == 1) {
+ break;
+ }
+
+ /*
+ * If we are currently closing, and waiting for
+ * a close_notify from the peer, then incoming
+ * application data should be discarded.
+ */
+ if (cc->application_data == 2) {
+ recvpld_ack(cc, len);
+ break;
+ }
+
+ /* Fall through */
+ default:
+ br_ssl_engine_fail(cc, BR_ERR_UNEXPECTED);
+ break;
+ }
+ }
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_close(br_ssl_engine_context *cc)
+{
+ if (!br_ssl_engine_closed(cc)) {
+ jump_handshake(cc, 1);
+ }
+}
+
+/* see bearssl_ssl.h */
+int
+br_ssl_engine_renegotiate(br_ssl_engine_context *cc)
+{
+ size_t len;
+
+ if (br_ssl_engine_closed(cc) || cc->reneg == 1
+ || (cc->flags & BR_OPT_NO_RENEGOTIATION) != 0
+ || br_ssl_engine_recvapp_buf(cc, &len) != NULL)
+ {
+ return 0;
+ }
+ jump_handshake(cc, 2);
+ return 1;
+}
+
+/* see bearssl.h */
+unsigned
+br_ssl_engine_current_state(const br_ssl_engine_context *cc)
+{
+ unsigned s;
+ size_t len;
+
+ if (br_ssl_engine_closed(cc)) {
+ return BR_SSL_CLOSED;
+ }
+
+ s = 0;
+ if (br_ssl_engine_sendrec_buf(cc, &len) != NULL) {
+ s |= BR_SSL_SENDREC;
+ }
+ if (br_ssl_engine_recvrec_buf(cc, &len) != NULL) {
+ s |= BR_SSL_RECVREC;
+ }
+ if (br_ssl_engine_sendapp_buf(cc, &len) != NULL) {
+ s |= BR_SSL_SENDAPP;
+ }
+ if (br_ssl_engine_recvapp_buf(cc, &len) != NULL) {
+ s |= BR_SSL_RECVAPP;
+ }
+ return s;
+}
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_flush(br_ssl_engine_context *cc, int force)
+{
+ if (!br_ssl_engine_closed(cc) && (cc->application_data & 1) != 0) {
+ sendpld_flush(cc, force);
+ }
+}
+
+/* see inner.h */
+void
+br_ssl_engine_hs_reset(br_ssl_engine_context *cc,
+ void (*hsinit)(void *), void (*hsrun)(void *))
+{
+ engine_clearbuf(cc);
+ cc->cpu.dp = cc->dp_stack;
+ cc->cpu.rp = cc->rp_stack;
+ hsinit(&cc->cpu);
+ cc->hsrun = hsrun;
+ cc->shutdown_recv = 0;
+ cc->application_data = 0;
+ cc->alert = 0;
+ jump_handshake(cc, 0);
+}
+
+/* see inner.h */
+br_tls_prf_impl
+br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id)
+{
+ if (cc->session.version >= BR_TLS12) {
+ if (prf_id == br_sha384_ID) {
+ return cc->prf_sha384;
+ } else {
+ return cc->prf_sha256;
+ }
+ } else {
+ return cc->prf10;
+ }
+}
+
+/* see inner.h */
+void
+br_ssl_engine_compute_master(br_ssl_engine_context *cc,
+ int prf_id, const void *pms, size_t pms_len)
+{
+ br_tls_prf_impl iprf;
+ br_tls_prf_seed_chunk seed[2] = {
+ { cc->client_random, sizeof cc->client_random },
+ { cc->server_random, sizeof cc->server_random }
+ };
+
+ iprf = br_ssl_engine_get_PRF(cc, prf_id);
+ iprf(cc->session.master_secret, sizeof cc->session.master_secret,
+ pms, pms_len, "master secret", 2, seed);
+}
+
+/*
+ * Compute key block.
+ */
+static void
+compute_key_block(br_ssl_engine_context *cc, int prf_id,
+ size_t half_len, unsigned char *kb)
+{
+ br_tls_prf_impl iprf;
+ br_tls_prf_seed_chunk seed[2] = {
+ { cc->server_random, sizeof cc->server_random },
+ { cc->client_random, sizeof cc->client_random }
+ };
+
+ iprf = br_ssl_engine_get_PRF(cc, prf_id);
+ iprf(kb, half_len << 1,
+ cc->session.master_secret, sizeof cc->session.master_secret,
+ "key expansion", 2, seed);
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id, int mac_id,
+ const br_block_cbcdec_class *bc_impl, size_t cipher_key_len)
+{
+ unsigned char kb[192];
+ unsigned char *cipher_key, *mac_key, *iv;
+ const br_hash_class *imh;
+ size_t mac_key_len, mac_out_len, iv_len;
+
+ imh = br_ssl_engine_get_hash(cc, mac_id);
+ mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+ mac_key_len = mac_out_len;
+
+ /*
+ * TLS 1.1+ uses per-record explicit IV, so no IV to generate here.
+ */
+ if (cc->session.version >= BR_TLS11) {
+ iv_len = 0;
+ } else {
+ iv_len = bc_impl->block_size;
+ }
+ compute_key_block(cc, prf_id,
+ mac_key_len + cipher_key_len + iv_len, kb);
+ if (is_client) {
+ mac_key = &kb[mac_key_len];
+ cipher_key = &kb[(mac_key_len << 1) + cipher_key_len];
+ iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len];
+ } else {
+ mac_key = &kb[0];
+ cipher_key = &kb[mac_key_len << 1];
+ iv = &kb[(mac_key_len + cipher_key_len) << 1];
+ }
+ if (iv_len == 0) {
+ iv = NULL;
+ }
+ cc->icbc_in->init(&cc->in.cbc.vtable,
+ bc_impl, cipher_key, cipher_key_len,
+ imh, mac_key, mac_key_len, mac_out_len, iv);
+ cc->incrypt = 1;
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id, int mac_id,
+ const br_block_cbcenc_class *bc_impl, size_t cipher_key_len)
+{
+ unsigned char kb[192];
+ unsigned char *cipher_key, *mac_key, *iv;
+ const br_hash_class *imh;
+ size_t mac_key_len, mac_out_len, iv_len;
+
+ imh = br_ssl_engine_get_hash(cc, mac_id);
+ mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+ mac_key_len = mac_out_len;
+
+ /*
+ * TLS 1.1+ uses per-record explicit IV, so no IV to generate here.
+ */
+ if (cc->session.version >= BR_TLS11) {
+ iv_len = 0;
+ } else {
+ iv_len = bc_impl->block_size;
+ }
+ compute_key_block(cc, prf_id,
+ mac_key_len + cipher_key_len + iv_len, kb);
+ if (is_client) {
+ mac_key = &kb[0];
+ cipher_key = &kb[mac_key_len << 1];
+ iv = &kb[(mac_key_len + cipher_key_len) << 1];
+ } else {
+ mac_key = &kb[mac_key_len];
+ cipher_key = &kb[(mac_key_len << 1) + cipher_key_len];
+ iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len];
+ }
+ if (iv_len == 0) {
+ iv = NULL;
+ }
+ cc->icbc_out->init(&cc->out.cbc.vtable,
+ bc_impl, cipher_key, cipher_key_len,
+ imh, mac_key, mac_key_len, mac_out_len, iv);
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctr_class *bc_impl, size_t cipher_key_len)
+{
+ unsigned char kb[72];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
+ if (is_client) {
+ cipher_key = &kb[cipher_key_len];
+ iv = &kb[(cipher_key_len << 1) + 4];
+ } else {
+ cipher_key = &kb[0];
+ iv = &kb[cipher_key_len << 1];
+ }
+ cc->igcm_in->init(&cc->in.gcm.vtable.in,
+ bc_impl, cipher_key, cipher_key_len, cc->ighash, iv);
+ cc->incrypt = 1;
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctr_class *bc_impl, size_t cipher_key_len)
+{
+ unsigned char kb[72];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
+ if (is_client) {
+ cipher_key = &kb[0];
+ iv = &kb[cipher_key_len << 1];
+ } else {
+ cipher_key = &kb[cipher_key_len];
+ iv = &kb[(cipher_key_len << 1) + 4];
+ }
+ cc->igcm_out->init(&cc->out.gcm.vtable.out,
+ bc_impl, cipher_key, cipher_key_len, cc->ighash, iv);
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id)
+{
+ unsigned char kb[88];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, 44, kb);
+ if (is_client) {
+ cipher_key = &kb[32];
+ iv = &kb[76];
+ } else {
+ cipher_key = &kb[0];
+ iv = &kb[64];
+ }
+ cc->ichapol_in->init(&cc->in.chapol.vtable.in,
+ cc->ichacha, cc->ipoly, cipher_key, iv);
+ cc->incrypt = 1;
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id)
+{
+ unsigned char kb[88];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, 44, kb);
+ if (is_client) {
+ cipher_key = &kb[0];
+ iv = &kb[64];
+ } else {
+ cipher_key = &kb[32];
+ iv = &kb[76];
+ }
+ cc->ichapol_out->init(&cc->out.chapol.vtable.out,
+ cc->ichacha, cc->ipoly, cipher_key, iv);
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctrcbc_class *bc_impl,
+ size_t cipher_key_len, size_t tag_len)
+{
+ unsigned char kb[72];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
+ if (is_client) {
+ cipher_key = &kb[cipher_key_len];
+ iv = &kb[(cipher_key_len << 1) + 4];
+ } else {
+ cipher_key = &kb[0];
+ iv = &kb[cipher_key_len << 1];
+ }
+ cc->iccm_in->init(&cc->in.ccm.vtable.in,
+ bc_impl, cipher_key, cipher_key_len, iv, tag_len);
+ cc->incrypt = 1;
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id,
+ const br_block_ctrcbc_class *bc_impl,
+ size_t cipher_key_len, size_t tag_len)
+{
+ unsigned char kb[72];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
+ if (is_client) {
+ cipher_key = &kb[0];
+ iv = &kb[cipher_key_len << 1];
+ } else {
+ cipher_key = &kb[cipher_key_len];
+ iv = &kb[(cipher_key_len << 1) + 4];
+ }
+ cc->iccm_out->init(&cc->out.ccm.vtable.out,
+ bc_impl, cipher_key, cipher_key_len, iv, tag_len);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aescbc.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aescbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aescbc.c (revision 346145)
@@ -0,0 +1,64 @@
+/*
+ * 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"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc)
+{
+#if BR_AES_X86NI || BR_POWER8
+ const br_block_cbcenc_class *ienc;
+ const br_block_cbcdec_class *idec;
+#endif
+
+ br_ssl_engine_set_cbc(cc,
+ &br_sslrec_in_cbc_vtable,
+ &br_sslrec_out_cbc_vtable);
+#if BR_AES_X86NI
+ ienc = br_aes_x86ni_cbcenc_get_vtable();
+ idec = br_aes_x86ni_cbcdec_get_vtable();
+ if (ienc != NULL && idec != NULL) {
+ br_ssl_engine_set_aes_cbc(cc, ienc, idec);
+ return;
+ }
+#endif
+#if BR_POWER8
+ ienc = br_aes_pwr8_cbcenc_get_vtable();
+ idec = br_aes_pwr8_cbcdec_get_vtable();
+ if (ienc != NULL && idec != NULL) {
+ br_ssl_engine_set_aes_cbc(cc, ienc, idec);
+ return;
+ }
+#endif
+#if BR_64
+ br_ssl_engine_set_aes_cbc(cc,
+ &br_aes_ct64_cbcenc_vtable,
+ &br_aes_ct64_cbcdec_vtable);
+#else
+ br_ssl_engine_set_aes_cbc(cc,
+ &br_aes_ct_cbcenc_vtable,
+ &br_aes_ct_cbcdec_vtable);
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aescbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesccm.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesccm.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesccm.c (revision 346145)
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc)
+{
+#if BR_AES_X86NI || BR_POWER8
+ const br_block_ctrcbc_class *ictrcbc;
+#endif
+
+ br_ssl_engine_set_ccm(cc,
+ &br_sslrec_in_ccm_vtable,
+ &br_sslrec_out_ccm_vtable);
+#if BR_AES_X86NI
+ ictrcbc = br_aes_x86ni_ctrcbc_get_vtable();
+ if (ictrcbc != NULL) {
+ br_ssl_engine_set_aes_ctrcbc(cc, ictrcbc);
+ } else {
+#if BR_64
+ br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable);
+#else
+ br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable);
+#endif
+ }
+#elif BR_POWER8
+ ictrcbc = br_aes_pwr8_ctrcbc_get_vtable();
+ if (ictrcbc != NULL) {
+ br_ssl_engine_set_aes_ctrcbc(cc, ictrcbc);
+ } else {
+#if BR_64
+ br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable);
+#else
+ br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable);
+#endif
+ }
+#else
+#if BR_64
+ br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable);
+#else
+ br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable);
+#endif
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesccm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesgcm.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesgcm.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesgcm.c (revision 346145)
@@ -0,0 +1,89 @@
+/*
+ * 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"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc)
+{
+#if BR_AES_X86NI || BR_POWER8
+ const br_block_ctr_class *ictr;
+ br_ghash ighash;
+#endif
+
+ br_ssl_engine_set_gcm(cc,
+ &br_sslrec_in_gcm_vtable,
+ &br_sslrec_out_gcm_vtable);
+#if BR_AES_X86NI
+ ictr = br_aes_x86ni_ctr_get_vtable();
+ if (ictr != NULL) {
+ br_ssl_engine_set_aes_ctr(cc, ictr);
+ } else {
+#if BR_64
+ br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable);
+#else
+ br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable);
+#endif
+ }
+#elif BR_POWER8
+ ictr = br_aes_pwr8_ctr_get_vtable();
+ if (ictr != NULL) {
+ br_ssl_engine_set_aes_ctr(cc, ictr);
+ } else {
+#if BR_64
+ br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable);
+#else
+ br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable);
+#endif
+ }
+#else
+#if BR_64
+ br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable);
+#else
+ br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable);
+#endif
+#endif
+#if BR_AES_X86NI
+ ighash = br_ghash_pclmul_get();
+ if (ighash != 0) {
+ br_ssl_engine_set_ghash(cc, ighash);
+ return;
+ }
+#endif
+#if BR_POWER8
+ ighash = br_ghash_pwr8_get();
+ if (ighash != 0) {
+ br_ssl_engine_set_ghash(cc, ighash);
+ return;
+ }
+#endif
+#if BR_LOMUL
+ br_ssl_engine_set_ghash(cc, &br_ghash_ctmul32);
+#elif BR_64
+ br_ssl_engine_set_ghash(cc, &br_ghash_ctmul64);
+#else
+ br_ssl_engine_set_ghash(cc, &br_ghash_ctmul);
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_aesgcm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_chapol.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_chapol.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_chapol.c (revision 346145)
@@ -0,0 +1,65 @@
+/*
+ * 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"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc)
+{
+#if BR_INT128 || BR_UMUL128
+ br_poly1305_run bp;
+#endif
+#if BR_SSE2
+ br_chacha20_run bc;
+#endif
+
+ br_ssl_engine_set_chapol(cc,
+ &br_sslrec_in_chapol_vtable,
+ &br_sslrec_out_chapol_vtable);
+#if BR_SSE2
+ bc = br_chacha20_sse2_get();
+ if (bc) {
+ br_ssl_engine_set_chacha20(cc, bc);
+ } else {
+#endif
+ br_ssl_engine_set_chacha20(cc, &br_chacha20_ct_run);
+#if BR_SSE2
+ }
+#endif
+#if BR_INT128 || BR_UMUL128
+ bp = br_poly1305_ctmulq_get();
+ if (bp) {
+ br_ssl_engine_set_poly1305(cc, bp);
+ } else {
+#endif
+#if BR_LOMUL
+ br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul32_run);
+#else
+ br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul_run);
+#endif
+#if BR_INT128 || BR_UMUL128
+ }
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_chapol.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_descbc.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_descbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_descbc.c (revision 346145)
@@ -0,0 +1,37 @@
+/*
+ * 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"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc)
+{
+ br_ssl_engine_set_cbc(cc,
+ &br_sslrec_in_cbc_vtable,
+ &br_sslrec_out_cbc_vtable);
+ br_ssl_engine_set_des_cbc(cc,
+ &br_des_ct_cbcenc_vtable,
+ &br_des_ct_cbcdec_vtable);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_descbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ec.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ec.c (revision 346145)
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_ec(br_ssl_engine_context *cc)
+{
+#if BR_LOMUL
+ br_ssl_engine_set_ec(cc, &br_ec_all_m15);
+#else
+ br_ssl_engine_set_ec(cc, &br_ec_all_m31);
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ecdsa.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ecdsa.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ecdsa.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc)
+{
+#if BR_LOMUL
+ br_ssl_engine_set_ec(cc, &br_ec_all_m15);
+ br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i15_vrfy_asn1);
+#else
+ br_ssl_engine_set_ec(cc, &br_ec_all_m31);
+ br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1);
+#endif
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_ecdsa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_rsavrfy.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_engine_default_rsavrfy.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_engine_default_rsavrfy.c (revision 346145)
@@ -0,0 +1,32 @@
+/*
+ * 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"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc)
+{
+ br_ssl_engine_set_rsavrfy(cc, br_rsa_pkcs1_vrfy_get_default());
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_engine_default_rsavrfy.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_hashes.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_hashes.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_hashes.c (revision 346145)
@@ -0,0 +1,46 @@
+/*
+ * 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 */
+int
+br_ssl_choose_hash(unsigned bf)
+{
+ static const unsigned char pref[] = {
+ br_sha256_ID, br_sha384_ID, br_sha512_ID,
+ br_sha224_ID, br_sha1_ID
+ };
+ size_t u;
+
+ for (u = 0; u < sizeof pref; u ++) {
+ int x;
+
+ x = pref[u];
+ if ((bf >> x) & 1) {
+ return x;
+ }
+ }
+ return 0;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_hashes.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_hs_client.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_hs_client.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_hs_client.c (revision 346145)
@@ -0,0 +1,1915 @@
+/* Automatically generated code; do not modify directly. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+} t0_context;
+
+static uint32_t
+t0_parse7E_unsigned(const unsigned char **p)
+{
+ uint32_t x;
+
+ x = 0;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ return x;
+ }
+ }
+}
+
+static int32_t
+t0_parse7E_signed(const unsigned char **p)
+{
+ int neg;
+ uint32_t x;
+
+ neg = ((**p) >> 6) & 1;
+ x = (uint32_t)-neg;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ if (neg) {
+ return -(int32_t)~x - 1;
+ } else {
+ return (int32_t)x;
+ }
+ }
+ }
+}
+
+#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
+#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
+#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
+#define T0_INT1(x) T0_FBYTE(x, 0)
+#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+
+/* static const unsigned char t0_datablock[]; */
+
+
+void br_ssl_hs_client_init_main(void *t0ctx);
+
+void br_ssl_hs_client_run(void *t0ctx);
+
+
+
+#include <stddef.h>
+#include <string.h>
+
+#include "inner.h"
+
+/*
+ * This macro evaluates to a pointer to the current engine context.
+ */
+#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu)))
+
+
+
+
+
+/*
+ * This macro evaluates to a pointer to the client context, under that
+ * specific name. It must be noted that since the engine context is the
+ * first field of the br_ssl_client_context structure ('eng'), then
+ * pointers values of both types are interchangeable, modulo an
+ * appropriate cast. This also means that "addresses" computed as offsets
+ * within the structure work for both kinds of context.
+ */
+#define CTX ((br_ssl_client_context *)ENG)
+
+/*
+ * Generate the pre-master secret for RSA key exchange, and encrypt it
+ * with the server's public key. Returned value is either the encrypted
+ * data length (in bytes), or -x on error, with 'x' being an error code.
+ *
+ * This code assumes that the public key has been already verified (it
+ * was properly obtained by the X.509 engine, and it has the right type,
+ * i.e. it is of type RSA and suitable for encryption).
+ */
+static int
+make_pms_rsa(br_ssl_client_context *ctx, int prf_id)
+{
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+ const unsigned char *n;
+ unsigned char *pms;
+ size_t nlen, u;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+
+ /*
+ * Compute actual RSA key length, in case there are leading zeros.
+ */
+ n = pk->key.rsa.n;
+ nlen = pk->key.rsa.nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+
+ /*
+ * We need at least 59 bytes (48 bytes for pre-master secret, and
+ * 11 bytes for the PKCS#1 type 2 padding). Note that the X.509
+ * minimal engine normally blocks RSA keys shorter than 128 bytes,
+ * so this is mostly for public keys provided explicitly by the
+ * caller.
+ */
+ if (nlen < 59) {
+ return -BR_ERR_X509_WEAK_PUBLIC_KEY;
+ }
+ if (nlen > sizeof ctx->eng.pad) {
+ return -BR_ERR_LIMIT_EXCEEDED;
+ }
+
+ /*
+ * Make PMS.
+ */
+ pms = ctx->eng.pad + nlen - 48;
+ br_enc16be(pms, ctx->eng.version_max);
+ br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46);
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48);
+
+ /*
+ * Apply PKCS#1 type 2 padding.
+ */
+ ctx->eng.pad[0] = 0x00;
+ ctx->eng.pad[1] = 0x02;
+ ctx->eng.pad[nlen - 49] = 0x00;
+ br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51);
+ for (u = 2; u < nlen - 49; u ++) {
+ while (ctx->eng.pad[u] == 0) {
+ br_hmac_drbg_generate(&ctx->eng.rng,
+ &ctx->eng.pad[u], 1);
+ }
+ }
+
+ /*
+ * Compute RSA encryption.
+ */
+ if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) {
+ return -BR_ERR_LIMIT_EXCEEDED;
+ }
+ return (int)nlen;
+}
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char *HASH_OID[] = {
+ BR_HASH_OID_SHA1,
+ BR_HASH_OID_SHA224,
+ BR_HASH_OID_SHA256,
+ BR_HASH_OID_SHA384,
+ BR_HASH_OID_SHA512
+};
+
+/*
+ * Check the RSA signature on the ServerKeyExchange message.
+ *
+ * hash hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)
+ * use_rsa non-zero for RSA signature, zero for ECDSA
+ * sig_len signature length (in bytes); signature value is in the pad
+ *
+ * Returned value is 0 on success, or an error code.
+ */
+static int
+verify_SKE_sig(br_ssl_client_context *ctx,
+ int hash, int use_rsa, size_t sig_len)
+{
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+ br_multihash_context mhc;
+ unsigned char hv[64], head[4];
+ size_t hv_len;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ br_multihash_zero(&mhc);
+ br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
+ br_multihash_init(&mhc);
+ br_multihash_update(&mhc,
+ ctx->eng.client_random, sizeof ctx->eng.client_random);
+ br_multihash_update(&mhc,
+ ctx->eng.server_random, sizeof ctx->eng.server_random);
+ head[0] = 3;
+ head[1] = 0;
+ head[2] = ctx->eng.ecdhe_curve;
+ head[3] = ctx->eng.ecdhe_point_len;
+ br_multihash_update(&mhc, head, sizeof head);
+ br_multihash_update(&mhc,
+ ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len);
+ if (hash) {
+ hv_len = br_multihash_out(&mhc, hash, hv);
+ if (hv_len == 0) {
+ return BR_ERR_INVALID_ALGORITHM;
+ }
+ } else {
+ if (!br_multihash_out(&mhc, br_md5_ID, hv)
+ || !br_multihash_out(&mhc, br_sha1_ID, hv + 16))
+ {
+ return BR_ERR_INVALID_ALGORITHM;
+ }
+ hv_len = 36;
+ }
+ if (use_rsa) {
+ unsigned char tmp[64];
+ const unsigned char *hash_oid;
+
+ if (hash) {
+ hash_oid = HASH_OID[hash - 2];
+ } else {
+ hash_oid = NULL;
+ }
+ if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
+ hash_oid, hv_len, &pk->key.rsa, tmp)
+ || memcmp(tmp, hv, hv_len) != 0)
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ } else {
+ if (!ctx->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec,
+ ctx->eng.pad, sig_len))
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Perform client-side ECDH (or ECDHE). The point that should be sent to
+ * the server is written in the pad; returned value is either the point
+ * length (in bytes), or -x on error, with 'x' being an error code.
+ *
+ * The point _from_ the server is taken from ecdhe_point[] if 'ecdhe'
+ * is non-zero, or from the X.509 engine context if 'ecdhe' is zero
+ * (for static ECDH).
+ */
+static int
+make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
+{
+ int curve;
+ unsigned char key[66], point[133];
+ const unsigned char *order, *point_src;
+ size_t glen, olen, point_len, xoff, xlen;
+ unsigned char mask;
+
+ if (ecdhe) {
+ curve = ctx->eng.ecdhe_curve;
+ point_src = ctx->eng.ecdhe_point;
+ point_len = ctx->eng.ecdhe_point_len;
+ } else {
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ curve = pk->key.ec.curve;
+ point_src = pk->key.ec.q;
+ point_len = pk->key.ec.qlen;
+ }
+ if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+
+ /*
+ * We need to generate our key, as a non-zero random value which
+ * is lower than the curve order, in a "large enough" range. We
+ * force top bit to 0 and bottom bit to 1, which guarantees that
+ * the value is in the proper range.
+ */
+ order = ctx->eng.iec->order(curve, &olen);
+ mask = 0xFF;
+ while (mask >= order[0]) {
+ mask >>= 1;
+ }
+ br_hmac_drbg_generate(&ctx->eng.rng, key, olen);
+ key[0] &= mask;
+ key[olen - 1] |= 0x01;
+
+ /*
+ * Compute the common ECDH point, whose X coordinate is the
+ * pre-master secret.
+ */
+ ctx->eng.iec->generator(curve, &glen);
+ if (glen != point_len) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+
+ memcpy(point, point_src, glen);
+ if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+
+ /*
+ * The pre-master secret is the X coordinate.
+ */
+ xoff = ctx->eng.iec->xoff(curve, &xlen);
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen);
+
+ ctx->eng.iec->mulgen(point, key, olen, curve);
+ memcpy(ctx->eng.pad, point, glen);
+ return (int)glen;
+}
+
+/*
+ * Perform full static ECDH. This occurs only in the context of client
+ * authentication with certificates: the server uses an EC public key,
+ * the cipher suite is of type ECDH (not ECDHE), the server requested a
+ * client certificate and accepts static ECDH, the client has a
+ * certificate with an EC public key in the same curve, and accepts
+ * static ECDH as well.
+ *
+ * Returned value is 0 on success, -1 on error.
+ */
+static int
+make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)
+{
+ unsigned char point[133];
+ size_t point_len;
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ point_len = pk->key.ec.qlen;
+ if (point_len > sizeof point) {
+ return -1;
+ }
+ memcpy(point, pk->key.ec.q, point_len);
+ if (!(*ctx->client_auth_vtable)->do_keyx(
+ ctx->client_auth_vtable, point, &point_len))
+ {
+ return -1;
+ }
+ br_ssl_engine_compute_master(&ctx->eng,
+ prf_id, point, point_len);
+ return 0;
+}
+
+/*
+ * Compute the client-side signature. This is invoked only when a
+ * signature-based client authentication was selected. The computed
+ * signature is in the pad; its length (in bytes) is returned. On
+ * error, 0 is returned.
+ */
+static size_t
+make_client_sign(br_ssl_client_context *ctx)
+{
+ size_t hv_len;
+
+ /*
+ * Compute hash of handshake messages so far. This "cannot" fail
+ * because the list of supported hash functions provided to the
+ * client certificate handler was trimmed to include only the
+ * hash functions that the multi-hasher supports.
+ */
+ if (ctx->hash_id) {
+ hv_len = br_multihash_out(&ctx->eng.mhash,
+ ctx->hash_id, ctx->eng.pad);
+ } else {
+ br_multihash_out(&ctx->eng.mhash,
+ br_md5_ID, ctx->eng.pad);
+ br_multihash_out(&ctx->eng.mhash,
+ br_sha1_ID, ctx->eng.pad + 16);
+ hv_len = 36;
+ }
+ return (*ctx->client_auth_vtable)->do_sign(
+ ctx->client_auth_vtable, ctx->hash_id, hv_len,
+ ctx->eng.pad, sizeof ctx->eng.pad);
+}
+
+
+
+static const unsigned char t0_datablock[] = {
+ 0x00, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x2F, 0x01, 0x24, 0x00, 0x35, 0x02,
+ 0x24, 0x00, 0x3C, 0x01, 0x44, 0x00, 0x3D, 0x02, 0x44, 0x00, 0x9C, 0x03,
+ 0x04, 0x00, 0x9D, 0x04, 0x05, 0xC0, 0x03, 0x40, 0x24, 0xC0, 0x04, 0x41,
+ 0x24, 0xC0, 0x05, 0x42, 0x24, 0xC0, 0x08, 0x20, 0x24, 0xC0, 0x09, 0x21,
+ 0x24, 0xC0, 0x0A, 0x22, 0x24, 0xC0, 0x0D, 0x30, 0x24, 0xC0, 0x0E, 0x31,
+ 0x24, 0xC0, 0x0F, 0x32, 0x24, 0xC0, 0x12, 0x10, 0x24, 0xC0, 0x13, 0x11,
+ 0x24, 0xC0, 0x14, 0x12, 0x24, 0xC0, 0x23, 0x21, 0x44, 0xC0, 0x24, 0x22,
+ 0x55, 0xC0, 0x25, 0x41, 0x44, 0xC0, 0x26, 0x42, 0x55, 0xC0, 0x27, 0x11,
+ 0x44, 0xC0, 0x28, 0x12, 0x55, 0xC0, 0x29, 0x31, 0x44, 0xC0, 0x2A, 0x32,
+ 0x55, 0xC0, 0x2B, 0x23, 0x04, 0xC0, 0x2C, 0x24, 0x05, 0xC0, 0x2D, 0x43,
+ 0x04, 0xC0, 0x2E, 0x44, 0x05, 0xC0, 0x2F, 0x13, 0x04, 0xC0, 0x30, 0x14,
+ 0x05, 0xC0, 0x31, 0x33, 0x04, 0xC0, 0x32, 0x34, 0x05, 0xC0, 0x9C, 0x06,
+ 0x04, 0xC0, 0x9D, 0x07, 0x04, 0xC0, 0xA0, 0x08, 0x04, 0xC0, 0xA1, 0x09,
+ 0x04, 0xC0, 0xAC, 0x26, 0x04, 0xC0, 0xAD, 0x27, 0x04, 0xC0, 0xAE, 0x28,
+ 0x04, 0xC0, 0xAF, 0x29, 0x04, 0xCC, 0xA8, 0x15, 0x04, 0xCC, 0xA9, 0x25,
+ 0x04, 0x00, 0x00
+};
+
+static const unsigned char t0_codeblock[] = {
+ 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01,
+ 0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08,
+ 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,
+ 0x01, 0x02, 0x09, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_CIPHER_SUITE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_COMPRESSION), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_HELLO_DONE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_SNI), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_VERSION),
+ 0x00, 0x00, 0x01, T0_INT1(BR_ERR_EXTRA_EXTENSION), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK),
+ 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_RESUME_MISMATCH), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_UNSUPPORTED_VERSION), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_client_context, auth_type)), 0x00, 0x00,
+ 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, client_random)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, close_received)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_curve)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hash_id)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hashes)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_client_context, min_clienthello_len)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, protocol_names_num)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, record_type_in)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, record_type_out)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, reneg)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, saved_finished)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, selected_protocol)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, server_name)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, server_random)), 0x00, 0x00,
+ 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id_len)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, shutdown_recv)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_buf)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_num)), 0x00, 0x00,
+ 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, version)),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_in)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),
+ 0x00, 0x00, 0x09, 0x26, 0x58, 0x06, 0x02, 0x68, 0x28, 0x00, 0x00, 0x06,
+ 0x08, 0x2C, 0x0E, 0x05, 0x02, 0x71, 0x28, 0x04, 0x01, 0x3C, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x99, 0x26, 0x5E, 0x44, 0x9D, 0x26,
+ 0x05, 0x04, 0x60, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06, 0x02, 0x9D,
+ 0x00, 0x5E, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x68, 0x28, 0x00, 0x00, 0x26,
+ 0x89, 0x44, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x44, 0x79, 0x2C, 0xAB, 0x1C,
+ 0x84, 0x01, 0x0C, 0x31, 0x00, 0x00, 0x26, 0x1F, 0x01, 0x08, 0x0B, 0x44,
+ 0x5C, 0x1F, 0x08, 0x00, 0x01, 0x03, 0x00, 0x77, 0x2E, 0x02, 0x00, 0x36,
+ 0x17, 0x01, 0x01, 0x0B, 0x77, 0x3E, 0x29, 0x1A, 0x36, 0x06, 0x07, 0x02,
+ 0x00, 0xCF, 0x03, 0x00, 0x04, 0x75, 0x01, 0x00, 0xC5, 0x02, 0x00, 0x26,
+ 0x1A, 0x17, 0x06, 0x02, 0x6F, 0x28, 0xCF, 0x04, 0x76, 0x01, 0x01, 0x00,
+ 0x77, 0x3E, 0x01, 0x16, 0x87, 0x3E, 0x01, 0x00, 0x8A, 0x3C, 0x34, 0xD5,
+ 0x29, 0xB4, 0x06, 0x09, 0x01, 0x7F, 0xAF, 0x01, 0x7F, 0xD2, 0x04, 0x80,
+ 0x53, 0xB1, 0x79, 0x2C, 0xA1, 0x01, T0_INT1(BR_KEYTYPE_SIGN), 0x17,
+ 0x06, 0x01, 0xB5, 0xB8, 0x26, 0x01, 0x0D, 0x0E, 0x06, 0x07, 0x25, 0xB7,
+ 0xB8, 0x01, 0x7F, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, 0x01, 0x0E, 0x0E,
+ 0x05, 0x02, 0x72, 0x28, 0x06, 0x02, 0x67, 0x28, 0x33, 0x06, 0x02, 0x72,
+ 0x28, 0x02, 0x00, 0x06, 0x1C, 0xD3, 0x80, 0x2E, 0x01, 0x81, 0x7F, 0x0E,
+ 0x06, 0x0D, 0x25, 0x01, 0x10, 0xDE, 0x01, 0x00, 0xDD, 0x79, 0x2C, 0xAB,
+ 0x24, 0x04, 0x04, 0xD6, 0x06, 0x01, 0xD4, 0x04, 0x01, 0xD6, 0x01, 0x7F,
+ 0xD2, 0x01, 0x7F, 0xAF, 0x01, 0x01, 0x77, 0x3E, 0x01, 0x17, 0x87, 0x3E,
+ 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x01, 0x00,
+ 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01,
+ T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30, 0x01, 0x01,
+ 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01,
+ T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN), 0x04, 0x25, 0x01, 0x02,
+ 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01,
+ T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_SIGN), 0x04, 0x1A, 0x01, 0x03,
+ 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01,
+ T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x0F, 0x01, 0x04,
+ 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01,
+ T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x04, 0x01, 0x00,
+ 0x44, 0x25, 0x00, 0x00, 0x82, 0x2E, 0x01, 0x0E, 0x0E, 0x06, 0x04, 0x01,
+ 0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x40, 0x06, 0x04, 0x01, 0x06,
+ 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x88, 0x2E, 0x26, 0x06, 0x08, 0x01,
+ 0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x25, 0x01, 0x05, 0x00, 0x01,
+ 0x41, 0x03, 0x00, 0x25, 0x01, 0x00, 0x43, 0x06, 0x03, 0x02, 0x00, 0x08,
+ 0x42, 0x06, 0x03, 0x02, 0x00, 0x08, 0x26, 0x06, 0x06, 0x01, 0x01, 0x0B,
+ 0x01, 0x06, 0x08, 0x00, 0x00, 0x8B, 0x3F, 0x26, 0x06, 0x03, 0x01, 0x09,
+ 0x08, 0x00, 0x01, 0x40, 0x26, 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00, 0x26,
+ 0x06, 0x0E, 0x26, 0x01, 0x01, 0x17, 0x02, 0x00, 0x08, 0x03, 0x00, 0x01,
+ 0x01, 0x11, 0x04, 0x6F, 0x25, 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01, 0x06,
+ 0x08, 0x00, 0x00, 0x7F, 0x2D, 0x44, 0x11, 0x01, 0x01, 0x17, 0x35, 0x00,
+ 0x00, 0x9F, 0xCE, 0x26, 0x01, 0x07, 0x17, 0x01, 0x00, 0x38, 0x0E, 0x06,
+ 0x09, 0x25, 0x01, 0x10, 0x17, 0x06, 0x01, 0x9F, 0x04, 0x35, 0x01, 0x01,
+ 0x38, 0x0E, 0x06, 0x2C, 0x25, 0x25, 0x01, 0x00, 0x77, 0x3E, 0xB3, 0x88,
+ 0x2E, 0x01, 0x01, 0x0E, 0x01, 0x01, 0xA8, 0x37, 0x06, 0x17, 0x29, 0x1A,
+ 0x36, 0x06, 0x04, 0xCE, 0x25, 0x04, 0x78, 0x01, 0x80, 0x64, 0xC5, 0x01,
+ 0x01, 0x77, 0x3E, 0x01, 0x17, 0x87, 0x3E, 0x04, 0x01, 0x9F, 0x04, 0x03,
+ 0x72, 0x28, 0x25, 0x04, 0xFF, 0x34, 0x01, 0x26, 0x03, 0x00, 0x09, 0x26,
+ 0x58, 0x06, 0x02, 0x68, 0x28, 0x02, 0x00, 0x00, 0x00, 0x9A, 0x01, 0x0F,
+ 0x17, 0x00, 0x00, 0x76, 0x2E, 0x01, 0x00, 0x38, 0x0E, 0x06, 0x10, 0x25,
+ 0x26, 0x01, 0x01, 0x0D, 0x06, 0x03, 0x25, 0x01, 0x02, 0x76, 0x3E, 0x01,
+ 0x00, 0x04, 0x21, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x14, 0x25, 0x01, 0x00,
+ 0x76, 0x3E, 0x26, 0x01, 0x80, 0x64, 0x0E, 0x06, 0x05, 0x01, 0x82, 0x00,
+ 0x08, 0x28, 0x5A, 0x04, 0x07, 0x25, 0x01, 0x82, 0x00, 0x08, 0x28, 0x25,
+ 0x00, 0x00, 0x01, 0x00, 0x2F, 0x06, 0x05, 0x3A, 0xAC, 0x37, 0x04, 0x78,
+ 0x26, 0x06, 0x04, 0x01, 0x01, 0x8F, 0x3E, 0x00, 0x01, 0xBF, 0xAA, 0xBF,
+ 0xAA, 0xC1, 0x84, 0x44, 0x26, 0x03, 0x00, 0xB6, 0x9B, 0x9B, 0x02, 0x00,
+ 0x4D, 0x26, 0x58, 0x06, 0x0A, 0x01, 0x03, 0xA8, 0x06, 0x02, 0x72, 0x28,
+ 0x25, 0x04, 0x03, 0x5C, 0x8A, 0x3C, 0x00, 0x00, 0x2F, 0x06, 0x0B, 0x86,
+ 0x2E, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x72, 0x28, 0x04, 0x11, 0xCE, 0x01,
+ 0x07, 0x17, 0x26, 0x01, 0x02, 0x0D, 0x06, 0x06, 0x06, 0x02, 0x72, 0x28,
+ 0x04, 0x70, 0x25, 0xC2, 0x01, 0x01, 0x0D, 0x33, 0x37, 0x06, 0x02, 0x61,
+ 0x28, 0x26, 0x01, 0x01, 0xC8, 0x36, 0xB2, 0x00, 0x01, 0xB8, 0x01, 0x0B,
+ 0x0E, 0x05, 0x02, 0x72, 0x28, 0x26, 0x01, 0x03, 0x0E, 0x06, 0x08, 0xC0,
+ 0x06, 0x02, 0x68, 0x28, 0x44, 0x25, 0x00, 0x44, 0x57, 0xC0, 0xAA, 0x26,
+ 0x06, 0x23, 0xC0, 0xAA, 0x26, 0x56, 0x26, 0x06, 0x18, 0x26, 0x01, 0x82,
+ 0x00, 0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x26, 0x03, 0x00,
+ 0x84, 0x02, 0x00, 0xB6, 0x02, 0x00, 0x53, 0x04, 0x65, 0x9B, 0x54, 0x04,
+ 0x5A, 0x9B, 0x9B, 0x55, 0x26, 0x06, 0x02, 0x35, 0x00, 0x25, 0x2B, 0x00,
+ 0x00, 0x79, 0x2C, 0xA1, 0x01, 0x7F, 0xB0, 0x26, 0x58, 0x06, 0x02, 0x35,
+ 0x28, 0x26, 0x05, 0x02, 0x72, 0x28, 0x38, 0x17, 0x0D, 0x06, 0x02, 0x74,
+ 0x28, 0x3B, 0x00, 0x00, 0x9C, 0xB8, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x72,
+ 0x28, 0x84, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0xB6, 0x9B, 0x84, 0x26, 0x01,
+ 0x0C, 0x08, 0x01, 0x0C, 0x30, 0x05, 0x02, 0x64, 0x28, 0x00, 0x00, 0xB9,
+ 0x06, 0x02, 0x72, 0x28, 0x06, 0x02, 0x66, 0x28, 0x00, 0x0A, 0xB8, 0x01,
+ 0x02, 0x0E, 0x05, 0x02, 0x72, 0x28, 0xBF, 0x03, 0x00, 0x02, 0x00, 0x95,
+ 0x2C, 0x0A, 0x02, 0x00, 0x94, 0x2C, 0x0F, 0x37, 0x06, 0x02, 0x73, 0x28,
+ 0x02, 0x00, 0x93, 0x2C, 0x0D, 0x06, 0x02, 0x6B, 0x28, 0x02, 0x00, 0x96,
+ 0x3C, 0x8C, 0x01, 0x20, 0xB6, 0x01, 0x00, 0x03, 0x01, 0xC1, 0x03, 0x02,
+ 0x02, 0x02, 0x01, 0x20, 0x0F, 0x06, 0x02, 0x70, 0x28, 0x84, 0x02, 0x02,
+ 0xB6, 0x02, 0x02, 0x8E, 0x2E, 0x0E, 0x02, 0x02, 0x01, 0x00, 0x0F, 0x17,
+ 0x06, 0x0B, 0x8D, 0x84, 0x02, 0x02, 0x30, 0x06, 0x04, 0x01, 0x7F, 0x03,
+ 0x01, 0x8D, 0x84, 0x02, 0x02, 0x31, 0x02, 0x02, 0x8E, 0x3E, 0x02, 0x00,
+ 0x92, 0x02, 0x01, 0x98, 0xBF, 0x26, 0xC3, 0x58, 0x06, 0x02, 0x62, 0x28,
+ 0x26, 0xCD, 0x02, 0x00, 0x01, 0x86, 0x03, 0x0A, 0x17, 0x06, 0x02, 0x62,
+ 0x28, 0x79, 0x02, 0x01, 0x98, 0xC1, 0x06, 0x02, 0x63, 0x28, 0x26, 0x06,
+ 0x81, 0x47, 0xBF, 0xAA, 0xA6, 0x03, 0x03, 0xA4, 0x03, 0x04, 0xA2, 0x03,
+ 0x05, 0xA5, 0x03, 0x06, 0xA7, 0x03, 0x07, 0xA3, 0x03, 0x08, 0x27, 0x03,
+ 0x09, 0x26, 0x06, 0x81, 0x18, 0xBF, 0x01, 0x00, 0x38, 0x0E, 0x06, 0x0F,
+ 0x25, 0x02, 0x03, 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x03, 0xBE,
+ 0x04, 0x80, 0x7F, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x0F, 0x25, 0x02, 0x05,
+ 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x05, 0xBC, 0x04, 0x80, 0x6A,
+ 0x01, 0x83, 0xFE, 0x01, 0x38, 0x0E, 0x06, 0x0F, 0x25, 0x02, 0x04, 0x05,
+ 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x04, 0xBD, 0x04, 0x80, 0x53, 0x01,
+ 0x0D, 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x02, 0x06, 0x05, 0x02, 0x6C, 0x28,
+ 0x01, 0x00, 0x03, 0x06, 0xBA, 0x04, 0x3F, 0x01, 0x0A, 0x38, 0x0E, 0x06,
+ 0x0E, 0x25, 0x02, 0x07, 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x07,
+ 0xBA, 0x04, 0x2B, 0x01, 0x0B, 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x02, 0x08,
+ 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x08, 0xBA, 0x04, 0x17, 0x01,
+ 0x10, 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x02, 0x09, 0x05, 0x02, 0x6C, 0x28,
+ 0x01, 0x00, 0x03, 0x09, 0xAE, 0x04, 0x03, 0x6C, 0x28, 0x25, 0x04, 0xFE,
+ 0x64, 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0F, 0x06, 0x02,
+ 0x69, 0x28, 0x01, 0x01, 0x88, 0x3E, 0x9B, 0x04, 0x0C, 0xA4, 0x01, 0x05,
+ 0x0F, 0x06, 0x02, 0x69, 0x28, 0x01, 0x01, 0x88, 0x3E, 0x9B, 0x02, 0x01,
+ 0x00, 0x04, 0xB8, 0x01, 0x0C, 0x0E, 0x05, 0x02, 0x72, 0x28, 0xC1, 0x01,
+ 0x03, 0x0E, 0x05, 0x02, 0x6D, 0x28, 0xBF, 0x26, 0x7C, 0x3E, 0x26, 0x01,
+ 0x20, 0x10, 0x06, 0x02, 0x6D, 0x28, 0x40, 0x44, 0x11, 0x01, 0x01, 0x17,
+ 0x05, 0x02, 0x6D, 0x28, 0xC1, 0x26, 0x01, 0x81, 0x05, 0x0F, 0x06, 0x02,
+ 0x6D, 0x28, 0x26, 0x7E, 0x3E, 0x7D, 0x44, 0xB6, 0x92, 0x2C, 0x01, 0x86,
+ 0x03, 0x10, 0x03, 0x00, 0x79, 0x2C, 0xCB, 0x03, 0x01, 0x01, 0x02, 0x03,
+ 0x02, 0x02, 0x00, 0x06, 0x21, 0xC1, 0x26, 0x26, 0x01, 0x02, 0x0A, 0x44,
+ 0x01, 0x06, 0x0F, 0x37, 0x06, 0x02, 0x6D, 0x28, 0x03, 0x02, 0xC1, 0x02,
+ 0x01, 0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x0E, 0x05, 0x02, 0x6D, 0x28,
+ 0x04, 0x08, 0x02, 0x01, 0x06, 0x04, 0x01, 0x00, 0x03, 0x02, 0xBF, 0x26,
+ 0x03, 0x03, 0x26, 0x01, 0x84, 0x00, 0x0F, 0x06, 0x02, 0x6E, 0x28, 0x84,
+ 0x44, 0xB6, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x50, 0x26, 0x06, 0x01,
+ 0x28, 0x25, 0x9B, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x97,
+ 0x02, 0x01, 0x02, 0x00, 0x39, 0x26, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x60,
+ 0x00, 0xD0, 0x04, 0x74, 0x02, 0x01, 0x00, 0x03, 0x00, 0xC1, 0xAA, 0x26,
+ 0x06, 0x80, 0x43, 0xC1, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x06, 0x25, 0x01,
+ 0x81, 0x7F, 0x04, 0x2E, 0x01, 0x80, 0x40, 0x38, 0x0E, 0x06, 0x07, 0x25,
+ 0x01, 0x83, 0xFE, 0x00, 0x04, 0x20, 0x01, 0x80, 0x41, 0x38, 0x0E, 0x06,
+ 0x07, 0x25, 0x01, 0x84, 0x80, 0x00, 0x04, 0x12, 0x01, 0x80, 0x42, 0x38,
+ 0x0E, 0x06, 0x07, 0x25, 0x01, 0x88, 0x80, 0x00, 0x04, 0x04, 0x01, 0x00,
+ 0x44, 0x25, 0x02, 0x00, 0x37, 0x03, 0x00, 0x04, 0xFF, 0x39, 0x9B, 0x79,
+ 0x2C, 0xC9, 0x05, 0x09, 0x02, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x17, 0x03,
+ 0x00, 0x92, 0x2C, 0x01, 0x86, 0x03, 0x10, 0x06, 0x3A, 0xBB, 0x26, 0x81,
+ 0x3D, 0x41, 0x25, 0x26, 0x01, 0x08, 0x0B, 0x37, 0x01, 0x8C, 0x80, 0x00,
+ 0x37, 0x17, 0x02, 0x00, 0x17, 0x02, 0x00, 0x01, 0x8C, 0x80, 0x00, 0x17,
+ 0x06, 0x19, 0x26, 0x01, 0x81, 0x7F, 0x17, 0x06, 0x05, 0x01, 0x84, 0x80,
+ 0x00, 0x37, 0x26, 0x01, 0x83, 0xFE, 0x00, 0x17, 0x06, 0x05, 0x01, 0x88,
+ 0x80, 0x00, 0x37, 0x03, 0x00, 0x04, 0x09, 0x02, 0x00, 0x01, 0x8C, 0x88,
+ 0x01, 0x17, 0x03, 0x00, 0x16, 0xBF, 0xAA, 0x26, 0x06, 0x23, 0xBF, 0xAA,
+ 0x26, 0x15, 0x26, 0x06, 0x18, 0x26, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05,
+ 0x01, 0x82, 0x00, 0x04, 0x01, 0x26, 0x03, 0x01, 0x84, 0x02, 0x01, 0xB6,
+ 0x02, 0x01, 0x12, 0x04, 0x65, 0x9B, 0x13, 0x04, 0x5A, 0x9B, 0x14, 0x9B,
+ 0x02, 0x00, 0x2A, 0x00, 0x00, 0xB9, 0x26, 0x5A, 0x06, 0x07, 0x25, 0x06,
+ 0x02, 0x66, 0x28, 0x04, 0x74, 0x00, 0x00, 0xC2, 0x01, 0x03, 0xC0, 0x44,
+ 0x25, 0x44, 0x00, 0x00, 0xBF, 0xC6, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00,
+ 0xBF, 0xAA, 0x26, 0x06, 0x80, 0x50, 0xC1, 0x03, 0x01, 0xC1, 0x03, 0x02,
+ 0x02, 0x01, 0x01, 0x08, 0x0E, 0x06, 0x16, 0x02, 0x02, 0x01, 0x0F, 0x0C,
+ 0x06, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x01, 0x10, 0x08, 0x0B, 0x02, 0x00,
+ 0x37, 0x03, 0x00, 0x04, 0x2A, 0x02, 0x01, 0x01, 0x02, 0x10, 0x02, 0x01,
+ 0x01, 0x06, 0x0C, 0x17, 0x02, 0x02, 0x01, 0x01, 0x0E, 0x02, 0x02, 0x01,
+ 0x03, 0x0E, 0x37, 0x17, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x5D, 0x01, 0x02, 0x0B, 0x02, 0x01, 0x08, 0x0B, 0x37, 0x03, 0x00, 0x04,
+ 0xFF, 0x2C, 0x9B, 0x02, 0x00, 0x00, 0x00, 0xBF, 0x01, 0x01, 0x0E, 0x05,
+ 0x02, 0x65, 0x28, 0xC1, 0x01, 0x08, 0x08, 0x82, 0x2E, 0x0E, 0x05, 0x02,
+ 0x65, 0x28, 0x00, 0x00, 0xBF, 0x88, 0x2E, 0x05, 0x15, 0x01, 0x01, 0x0E,
+ 0x05, 0x02, 0x69, 0x28, 0xC1, 0x01, 0x00, 0x0E, 0x05, 0x02, 0x69, 0x28,
+ 0x01, 0x02, 0x88, 0x3E, 0x04, 0x1C, 0x01, 0x19, 0x0E, 0x05, 0x02, 0x69,
+ 0x28, 0xC1, 0x01, 0x18, 0x0E, 0x05, 0x02, 0x69, 0x28, 0x84, 0x01, 0x18,
+ 0xB6, 0x89, 0x84, 0x01, 0x18, 0x30, 0x05, 0x02, 0x69, 0x28, 0x00, 0x00,
+ 0xBF, 0x06, 0x02, 0x6A, 0x28, 0x00, 0x00, 0x01, 0x02, 0x97, 0xC2, 0x01,
+ 0x08, 0x0B, 0xC2, 0x08, 0x00, 0x00, 0x01, 0x03, 0x97, 0xC2, 0x01, 0x08,
+ 0x0B, 0xC2, 0x08, 0x01, 0x08, 0x0B, 0xC2, 0x08, 0x00, 0x00, 0x01, 0x01,
+ 0x97, 0xC2, 0x00, 0x00, 0x3A, 0x26, 0x58, 0x05, 0x01, 0x00, 0x25, 0xD0,
+ 0x04, 0x76, 0x02, 0x03, 0x00, 0x91, 0x2E, 0x03, 0x01, 0x01, 0x00, 0x26,
+ 0x02, 0x01, 0x0A, 0x06, 0x10, 0x26, 0x01, 0x01, 0x0B, 0x90, 0x08, 0x2C,
+ 0x02, 0x00, 0x0E, 0x06, 0x01, 0x00, 0x5C, 0x04, 0x6A, 0x25, 0x01, 0x7F,
+ 0x00, 0x00, 0x01, 0x15, 0x87, 0x3E, 0x44, 0x52, 0x25, 0x52, 0x25, 0x29,
+ 0x00, 0x00, 0x01, 0x01, 0x44, 0xC4, 0x00, 0x00, 0x44, 0x38, 0x97, 0x44,
+ 0x26, 0x06, 0x05, 0xC2, 0x25, 0x5D, 0x04, 0x78, 0x25, 0x00, 0x00, 0x26,
+ 0x01, 0x81, 0xAC, 0x00, 0x0E, 0x06, 0x04, 0x25, 0x01, 0x7F, 0x00, 0x9A,
+ 0x59, 0x00, 0x02, 0x03, 0x00, 0x79, 0x2C, 0x9A, 0x03, 0x01, 0x02, 0x01,
+ 0x01, 0x0F, 0x17, 0x02, 0x01, 0x01, 0x04, 0x11, 0x01, 0x0F, 0x17, 0x02,
+ 0x01, 0x01, 0x08, 0x11, 0x01, 0x0F, 0x17, 0x01, 0x00, 0x38, 0x0E, 0x06,
+ 0x10, 0x25, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04,
+ 0x01, 0x4A, 0x04, 0x81, 0x0D, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x10, 0x25,
+ 0x01, 0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A,
+ 0x04, 0x80, 0x77, 0x01, 0x02, 0x38, 0x0E, 0x06, 0x10, 0x25, 0x01, 0x01,
+ 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04, 0x80,
+ 0x61, 0x01, 0x03, 0x38, 0x0E, 0x06, 0x0F, 0x25, 0x25, 0x01, 0x10, 0x02,
+ 0x00, 0x06, 0x03, 0x47, 0x04, 0x01, 0x48, 0x04, 0x80, 0x4C, 0x01, 0x04,
+ 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x25, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03,
+ 0x47, 0x04, 0x01, 0x48, 0x04, 0x38, 0x01, 0x05, 0x38, 0x0E, 0x06, 0x0C,
+ 0x25, 0x25, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, 0x4C, 0x04, 0x26,
+ 0x26, 0x01, 0x09, 0x0F, 0x06, 0x02, 0x68, 0x28, 0x44, 0x25, 0x26, 0x01,
+ 0x01, 0x17, 0x01, 0x04, 0x0B, 0x01, 0x10, 0x08, 0x44, 0x01, 0x08, 0x17,
+ 0x01, 0x10, 0x44, 0x09, 0x02, 0x00, 0x06, 0x03, 0x45, 0x04, 0x01, 0x46,
+ 0x00, 0x25, 0x00, 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x01, 0x02, 0x0F, 0x00,
+ 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x26, 0x5B, 0x44, 0x01, 0x03, 0x0A, 0x17,
+ 0x00, 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x9A,
+ 0x01, 0x0C, 0x11, 0x5A, 0x00, 0x00, 0x9A, 0x01, 0x81, 0x70, 0x17, 0x01,
+ 0x20, 0x0D, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x75, 0x2E, 0x26, 0x06, 0x22,
+ 0x01, 0x01, 0x38, 0x0E, 0x06, 0x06, 0x25, 0x01, 0x00, 0x9E, 0x04, 0x14,
+ 0x01, 0x02, 0x38, 0x0E, 0x06, 0x0D, 0x25, 0x77, 0x2E, 0x01, 0x01, 0x0E,
+ 0x06, 0x03, 0x01, 0x10, 0x37, 0x04, 0x01, 0x25, 0x04, 0x01, 0x25, 0x7B,
+ 0x2E, 0x05, 0x33, 0x2F, 0x06, 0x30, 0x86, 0x2E, 0x01, 0x14, 0x38, 0x0E,
+ 0x06, 0x06, 0x25, 0x01, 0x02, 0x37, 0x04, 0x22, 0x01, 0x15, 0x38, 0x0E,
+ 0x06, 0x09, 0x25, 0xAD, 0x06, 0x03, 0x01, 0x7F, 0x9E, 0x04, 0x13, 0x01,
+ 0x16, 0x38, 0x0E, 0x06, 0x06, 0x25, 0x01, 0x01, 0x37, 0x04, 0x07, 0x25,
+ 0x01, 0x04, 0x37, 0x01, 0x00, 0x25, 0x1A, 0x06, 0x03, 0x01, 0x08, 0x37,
+ 0x00, 0x00, 0x1B, 0x26, 0x05, 0x13, 0x2F, 0x06, 0x10, 0x86, 0x2E, 0x01,
+ 0x15, 0x0E, 0x06, 0x08, 0x25, 0xAD, 0x01, 0x00, 0x77, 0x3E, 0x04, 0x01,
+ 0x20, 0x00, 0x00, 0xCE, 0x01, 0x07, 0x17, 0x01, 0x01, 0x0F, 0x06, 0x02,
+ 0x72, 0x28, 0x00, 0x01, 0x03, 0x00, 0x29, 0x1A, 0x06, 0x05, 0x02, 0x00,
+ 0x87, 0x3E, 0x00, 0xCE, 0x25, 0x04, 0x74, 0x00, 0x01, 0x14, 0xD1, 0x01,
+ 0x01, 0xDE, 0x29, 0x26, 0x01, 0x00, 0xC8, 0x01, 0x16, 0xD1, 0xD7, 0x29,
+ 0x00, 0x00, 0x01, 0x0B, 0xDE, 0x4E, 0x26, 0x26, 0x01, 0x03, 0x08, 0xDD,
+ 0xDD, 0x18, 0x26, 0x58, 0x06, 0x02, 0x25, 0x00, 0xDD, 0x1D, 0x26, 0x06,
+ 0x05, 0x84, 0x44, 0xD8, 0x04, 0x77, 0x25, 0x04, 0x6C, 0x00, 0x21, 0x01,
+ 0x0F, 0xDE, 0x26, 0x92, 0x2C, 0x01, 0x86, 0x03, 0x10, 0x06, 0x0C, 0x01,
+ 0x04, 0x08, 0xDD, 0x80, 0x2E, 0xDE, 0x78, 0x2E, 0xDE, 0x04, 0x02, 0x5E,
+ 0xDD, 0x26, 0xDC, 0x84, 0x44, 0xD8, 0x00, 0x02, 0xA4, 0xA6, 0x08, 0xA2,
+ 0x08, 0xA5, 0x08, 0xA7, 0x08, 0xA3, 0x08, 0x27, 0x08, 0x03, 0x00, 0x01,
+ 0x01, 0xDE, 0x01, 0x27, 0x8E, 0x2E, 0x08, 0x91, 0x2E, 0x01, 0x01, 0x0B,
+ 0x08, 0x02, 0x00, 0x06, 0x04, 0x5E, 0x02, 0x00, 0x08, 0x83, 0x2C, 0x38,
+ 0x09, 0x26, 0x5B, 0x06, 0x24, 0x02, 0x00, 0x05, 0x04, 0x44, 0x5E, 0x44,
+ 0x5F, 0x01, 0x04, 0x09, 0x26, 0x58, 0x06, 0x03, 0x25, 0x01, 0x00, 0x26,
+ 0x01, 0x04, 0x08, 0x02, 0x00, 0x08, 0x03, 0x00, 0x44, 0x01, 0x04, 0x08,
+ 0x38, 0x08, 0x44, 0x04, 0x03, 0x25, 0x01, 0x7F, 0x03, 0x01, 0xDD, 0x94,
+ 0x2C, 0xDC, 0x7A, 0x01, 0x04, 0x19, 0x7A, 0x01, 0x04, 0x08, 0x01, 0x1C,
+ 0x32, 0x7A, 0x01, 0x20, 0xD8, 0x8D, 0x8E, 0x2E, 0xDA, 0x91, 0x2E, 0x26,
+ 0x01, 0x01, 0x0B, 0xDC, 0x90, 0x44, 0x26, 0x06, 0x0F, 0x5D, 0x38, 0x2C,
+ 0x26, 0xC7, 0x05, 0x02, 0x62, 0x28, 0xDC, 0x44, 0x5E, 0x44, 0x04, 0x6E,
+ 0x60, 0x01, 0x01, 0xDE, 0x01, 0x00, 0xDE, 0x02, 0x00, 0x06, 0x81, 0x5A,
+ 0x02, 0x00, 0xDC, 0xA4, 0x06, 0x0E, 0x01, 0x83, 0xFE, 0x01, 0xDC, 0x89,
+ 0xA4, 0x01, 0x04, 0x09, 0x26, 0xDC, 0x5D, 0xDA, 0xA6, 0x06, 0x16, 0x01,
+ 0x00, 0xDC, 0x8B, 0xA6, 0x01, 0x04, 0x09, 0x26, 0xDC, 0x01, 0x02, 0x09,
+ 0x26, 0xDC, 0x01, 0x00, 0xDE, 0x01, 0x03, 0x09, 0xD9, 0xA2, 0x06, 0x0C,
+ 0x01, 0x01, 0xDC, 0x01, 0x01, 0xDC, 0x82, 0x2E, 0x01, 0x08, 0x09, 0xDE,
+ 0xA5, 0x06, 0x19, 0x01, 0x0D, 0xDC, 0xA5, 0x01, 0x04, 0x09, 0x26, 0xDC,
+ 0x01, 0x02, 0x09, 0xDC, 0x42, 0x06, 0x03, 0x01, 0x03, 0xDB, 0x43, 0x06,
+ 0x03, 0x01, 0x01, 0xDB, 0xA7, 0x26, 0x06, 0x36, 0x01, 0x0A, 0xDC, 0x01,
+ 0x04, 0x09, 0x26, 0xDC, 0x5F, 0xDC, 0x40, 0x01, 0x00, 0x26, 0x01, 0x82,
+ 0x80, 0x80, 0x80, 0x00, 0x17, 0x06, 0x0A, 0x01, 0xFD, 0xFF, 0xFF, 0xFF,
+ 0x7F, 0x17, 0x01, 0x1D, 0xDC, 0x26, 0x01, 0x20, 0x0A, 0x06, 0x0C, 0xA0,
+ 0x11, 0x01, 0x01, 0x17, 0x06, 0x02, 0x26, 0xDC, 0x5C, 0x04, 0x6E, 0x60,
+ 0x04, 0x01, 0x25, 0xA3, 0x06, 0x0A, 0x01, 0x0B, 0xDC, 0x01, 0x02, 0xDC,
+ 0x01, 0x82, 0x00, 0xDC, 0x27, 0x26, 0x06, 0x1F, 0x01, 0x10, 0xDC, 0x01,
+ 0x04, 0x09, 0x26, 0xDC, 0x5F, 0xDC, 0x85, 0x2C, 0x01, 0x00, 0xA0, 0x0F,
+ 0x06, 0x0A, 0x26, 0x1E, 0x26, 0xDE, 0x84, 0x44, 0xD8, 0x5C, 0x04, 0x72,
+ 0x60, 0x04, 0x01, 0x25, 0x02, 0x01, 0x58, 0x05, 0x11, 0x01, 0x15, 0xDC,
+ 0x02, 0x01, 0x26, 0xDC, 0x26, 0x06, 0x06, 0x5D, 0x01, 0x00, 0xDE, 0x04,
+ 0x77, 0x25, 0x00, 0x00, 0x01, 0x10, 0xDE, 0x79, 0x2C, 0x26, 0xCC, 0x06,
+ 0x0C, 0xAB, 0x23, 0x26, 0x5E, 0xDD, 0x26, 0xDC, 0x84, 0x44, 0xD8, 0x04,
+ 0x0D, 0x26, 0xCA, 0x44, 0xAB, 0x22, 0x26, 0x5C, 0xDD, 0x26, 0xDE, 0x84,
+ 0x44, 0xD8, 0x00, 0x00, 0x9C, 0x01, 0x14, 0xDE, 0x01, 0x0C, 0xDD, 0x84,
+ 0x01, 0x0C, 0xD8, 0x00, 0x00, 0x51, 0x26, 0x01, 0x00, 0x0E, 0x06, 0x02,
+ 0x60, 0x00, 0xCE, 0x25, 0x04, 0x73, 0x00, 0x26, 0xDC, 0xD8, 0x00, 0x00,
+ 0x26, 0xDE, 0xD8, 0x00, 0x01, 0x03, 0x00, 0x41, 0x25, 0x26, 0x01, 0x10,
+ 0x17, 0x06, 0x06, 0x01, 0x04, 0xDE, 0x02, 0x00, 0xDE, 0x26, 0x01, 0x08,
+ 0x17, 0x06, 0x06, 0x01, 0x03, 0xDE, 0x02, 0x00, 0xDE, 0x26, 0x01, 0x20,
+ 0x17, 0x06, 0x06, 0x01, 0x05, 0xDE, 0x02, 0x00, 0xDE, 0x26, 0x01, 0x80,
+ 0x40, 0x17, 0x06, 0x06, 0x01, 0x06, 0xDE, 0x02, 0x00, 0xDE, 0x01, 0x04,
+ 0x17, 0x06, 0x06, 0x01, 0x02, 0xDE, 0x02, 0x00, 0xDE, 0x00, 0x00, 0x26,
+ 0x01, 0x08, 0x4F, 0xDE, 0xDE, 0x00, 0x00, 0x26, 0x01, 0x10, 0x4F, 0xDE,
+ 0xDC, 0x00, 0x00, 0x26, 0x52, 0x06, 0x02, 0x25, 0x00, 0xCE, 0x25, 0x04,
+ 0x76
+};
+
+static const uint16_t t0_caddr[] = {
+ 0,
+ 5,
+ 10,
+ 15,
+ 20,
+ 25,
+ 30,
+ 35,
+ 40,
+ 44,
+ 48,
+ 52,
+ 56,
+ 60,
+ 64,
+ 68,
+ 72,
+ 76,
+ 80,
+ 84,
+ 88,
+ 92,
+ 96,
+ 100,
+ 104,
+ 108,
+ 112,
+ 116,
+ 120,
+ 124,
+ 129,
+ 134,
+ 139,
+ 144,
+ 149,
+ 154,
+ 159,
+ 164,
+ 169,
+ 174,
+ 179,
+ 184,
+ 189,
+ 194,
+ 199,
+ 204,
+ 209,
+ 214,
+ 219,
+ 224,
+ 229,
+ 234,
+ 239,
+ 244,
+ 249,
+ 254,
+ 259,
+ 264,
+ 269,
+ 274,
+ 279,
+ 284,
+ 289,
+ 294,
+ 303,
+ 316,
+ 320,
+ 345,
+ 351,
+ 370,
+ 381,
+ 422,
+ 542,
+ 546,
+ 611,
+ 626,
+ 637,
+ 655,
+ 684,
+ 694,
+ 730,
+ 740,
+ 818,
+ 832,
+ 838,
+ 897,
+ 916,
+ 951,
+ 1000,
+ 1076,
+ 1103,
+ 1134,
+ 1145,
+ 1497,
+ 1644,
+ 1668,
+ 1884,
+ 1898,
+ 1907,
+ 1911,
+ 2006,
+ 2027,
+ 2083,
+ 2090,
+ 2101,
+ 2117,
+ 2123,
+ 2134,
+ 2169,
+ 2181,
+ 2187,
+ 2202,
+ 2218,
+ 2411,
+ 2420,
+ 2433,
+ 2442,
+ 2449,
+ 2459,
+ 2565,
+ 2590,
+ 2603,
+ 2619,
+ 2637,
+ 2669,
+ 2703,
+ 3071,
+ 3107,
+ 3120,
+ 3134,
+ 3139,
+ 3144,
+ 3210,
+ 3218,
+ 3226
+};
+
+#define T0_INTERPRETED 88
+
+#define T0_ENTER(ip, rp, slot) do { \
+ const unsigned char *t0_newip; \
+ uint32_t t0_lnum; \
+ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
+ t0_lnum = t0_parse7E_unsigned(&t0_newip); \
+ (rp) += t0_lnum; \
+ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
+ (ip) = t0_newip; \
+ } while (0)
+
+#define T0_DEFENTRY(name, slot) \
+void \
+name(void *ctx) \
+{ \
+ t0_context *t0ctx = ctx; \
+ t0ctx->ip = &t0_codeblock[0]; \
+ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
+}
+
+T0_DEFENTRY(br_ssl_hs_client_init_main, 169)
+
+#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
+
+void
+br_ssl_hs_client_run(void *t0ctx)
+{
+ uint32_t *dp, *rp;
+ const unsigned char *ip;
+
+#define T0_LOCAL(x) (*(rp - 2 - (x)))
+#define T0_POP() (*-- dp)
+#define T0_POPi() (*(int32_t *)(-- dp))
+#define T0_PEEK(x) (*(dp - 1 - (x)))
+#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
+#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
+#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
+#define T0_RPOP() (*-- rp)
+#define T0_RPOPi() (*(int32_t *)(-- rp))
+#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
+#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
+#define T0_ROLL(x) do { \
+ size_t t0len = (size_t)(x); \
+ uint32_t t0tmp = *(dp - 1 - t0len); \
+ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_SWAP() do { \
+ uint32_t t0tmp = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_ROT() do { \
+ uint32_t t0tmp = *(dp - 3); \
+ *(dp - 3) = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_NROT() do { \
+ uint32_t t0tmp = *(dp - 1); \
+ *(dp - 1) = *(dp - 2); \
+ *(dp - 2) = *(dp - 3); \
+ *(dp - 3) = t0tmp; \
+} while (0)
+#define T0_PICK(x) do { \
+ uint32_t t0depth = (x); \
+ T0_PUSH(T0_PEEK(t0depth)); \
+} while (0)
+#define T0_CO() do { \
+ goto t0_exit; \
+} while (0)
+#define T0_RET() goto t0_next
+
+ dp = ((t0_context *)t0ctx)->dp;
+ rp = ((t0_context *)t0ctx)->rp;
+ ip = ((t0_context *)t0ctx)->ip;
+ goto t0_next;
+ for (;;) {
+ uint32_t t0x;
+
+ t0_next:
+ t0x = T0_NEXT(&ip);
+ if (t0x < T0_INTERPRETED) {
+ switch (t0x) {
+ int32_t t0off;
+
+ case 0: /* ret */
+ t0x = T0_RPOP();
+ rp -= (t0x >> 16);
+ t0x &= 0xFFFF;
+ if (t0x == 0) {
+ ip = NULL;
+ goto t0_exit;
+ }
+ ip = &t0_codeblock[t0x];
+ break;
+ case 1: /* literal constant */
+ T0_PUSHi(t0_parse7E_signed(&ip));
+ break;
+ case 2: /* read local */
+ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
+ break;
+ case 3: /* write local */
+ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
+ break;
+ case 4: /* jump */
+ t0off = t0_parse7E_signed(&ip);
+ ip += t0off;
+ break;
+ case 5: /* jump if */
+ t0off = t0_parse7E_signed(&ip);
+ if (T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 6: /* jump if not */
+ t0off = t0_parse7E_signed(&ip);
+ if (!T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 7: {
+ /* * */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a * b);
+
+ }
+ break;
+ case 8: {
+ /* + */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a + b);
+
+ }
+ break;
+ case 9: {
+ /* - */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a - b);
+
+ }
+ break;
+ case 10: {
+ /* < */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a < b));
+
+ }
+ break;
+ case 11: {
+ /* << */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x << c);
+
+ }
+ break;
+ case 12: {
+ /* <= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a <= b));
+
+ }
+ break;
+ case 13: {
+ /* <> */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a != b));
+
+ }
+ break;
+ case 14: {
+ /* = */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a == b));
+
+ }
+ break;
+ case 15: {
+ /* > */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a > b));
+
+ }
+ break;
+ case 16: {
+ /* >= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a >= b));
+
+ }
+ break;
+ case 17: {
+ /* >> */
+
+ int c = (int)T0_POPi();
+ int32_t x = T0_POPi();
+ T0_PUSHi(x >> c);
+
+ }
+ break;
+ case 18: {
+ /* anchor-dn-append-name */
+
+ size_t len;
+
+ len = T0_POP();
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->append_name(
+ CTX->client_auth_vtable, ENG->pad, len);
+ }
+
+ }
+ break;
+ case 19: {
+ /* anchor-dn-end-name */
+
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->end_name(
+ CTX->client_auth_vtable);
+ }
+
+ }
+ break;
+ case 20: {
+ /* anchor-dn-end-name-list */
+
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->end_name_list(
+ CTX->client_auth_vtable);
+ }
+
+ }
+ break;
+ case 21: {
+ /* anchor-dn-start-name */
+
+ size_t len;
+
+ len = T0_POP();
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->start_name(
+ CTX->client_auth_vtable, len);
+ }
+
+ }
+ break;
+ case 22: {
+ /* anchor-dn-start-name-list */
+
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->start_name_list(
+ CTX->client_auth_vtable);
+ }
+
+ }
+ break;
+ case 23: {
+ /* and */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a & b);
+
+ }
+ break;
+ case 24: {
+ /* begin-cert */
+
+ if (ENG->chain_len == 0) {
+ T0_PUSHi(-1);
+ } else {
+ ENG->cert_cur = ENG->chain->data;
+ ENG->cert_len = ENG->chain->data_len;
+ ENG->chain ++;
+ ENG->chain_len --;
+ T0_PUSH(ENG->cert_len);
+ }
+
+ }
+ break;
+ case 25: {
+ /* bzero */
+
+ size_t len = (size_t)T0_POP();
+ void *addr = (unsigned char *)ENG + (size_t)T0_POP();
+ memset(addr, 0, len);
+
+ }
+ break;
+ case 26: {
+ /* can-output? */
+
+ T0_PUSHi(-(ENG->hlen_out > 0));
+
+ }
+ break;
+ case 27: {
+ /* co */
+ T0_CO();
+ }
+ break;
+ case 28: {
+ /* compute-Finished-inner */
+
+ int prf_id = T0_POP();
+ int from_client = T0_POPi();
+ unsigned char tmp[48];
+ br_tls_prf_seed_chunk seed;
+
+ br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id);
+ seed.data = tmp;
+ if (ENG->session.version >= BR_TLS12) {
+ seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp);
+ } else {
+ br_multihash_out(&ENG->mhash, br_md5_ID, tmp);
+ br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16);
+ seed.len = 36;
+ }
+ prf(ENG->pad, 12, ENG->session.master_secret,
+ sizeof ENG->session.master_secret,
+ from_client ? "client finished" : "server finished",
+ 1, &seed);
+
+ }
+ break;
+ case 29: {
+ /* copy-cert-chunk */
+
+ size_t clen;
+
+ clen = ENG->cert_len;
+ if (clen > sizeof ENG->pad) {
+ clen = sizeof ENG->pad;
+ }
+ memcpy(ENG->pad, ENG->cert_cur, clen);
+ ENG->cert_cur += clen;
+ ENG->cert_len -= clen;
+ T0_PUSH(clen);
+
+ }
+ break;
+ case 30: {
+ /* copy-protocol-name */
+
+ size_t idx = T0_POP();
+ size_t len = strlen(ENG->protocol_names[idx]);
+ memcpy(ENG->pad, ENG->protocol_names[idx], len);
+ T0_PUSH(len);
+
+ }
+ break;
+ case 31: {
+ /* data-get8 */
+
+ size_t addr = T0_POP();
+ T0_PUSH(t0_datablock[addr]);
+
+ }
+ break;
+ case 32: {
+ /* discard-input */
+
+ ENG->hlen_in = 0;
+
+ }
+ break;
+ case 33: {
+ /* do-client-sign */
+
+ size_t sig_len;
+
+ sig_len = make_client_sign(CTX);
+ if (sig_len == 0) {
+ br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+ T0_CO();
+ }
+ T0_PUSH(sig_len);
+
+ }
+ break;
+ case 34: {
+ /* do-ecdh */
+
+ unsigned prf_id = T0_POP();
+ unsigned ecdhe = T0_POP();
+ int x;
+
+ x = make_pms_ecdh(CTX, ecdhe, prf_id);
+ if (x < 0) {
+ br_ssl_engine_fail(ENG, -x);
+ T0_CO();
+ } else {
+ T0_PUSH(x);
+ }
+
+ }
+ break;
+ case 35: {
+ /* do-rsa-encrypt */
+
+ int x;
+
+ x = make_pms_rsa(CTX, T0_POP());
+ if (x < 0) {
+ br_ssl_engine_fail(ENG, -x);
+ T0_CO();
+ } else {
+ T0_PUSH(x);
+ }
+
+ }
+ break;
+ case 36: {
+ /* do-static-ecdh */
+
+ unsigned prf_id = T0_POP();
+
+ if (make_pms_static_ecdh(CTX, prf_id) < 0) {
+ br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+ T0_CO();
+ }
+
+ }
+ break;
+ case 37: {
+ /* drop */
+ (void)T0_POP();
+ }
+ break;
+ case 38: {
+ /* dup */
+ T0_PUSH(T0_PEEK(0));
+ }
+ break;
+ case 39: {
+ /* ext-ALPN-length */
+
+ size_t u, len;
+
+ if (ENG->protocol_names_num == 0) {
+ T0_PUSH(0);
+ T0_RET();
+ }
+ len = 6;
+ for (u = 0; u < ENG->protocol_names_num; u ++) {
+ len += 1 + strlen(ENG->protocol_names[u]);
+ }
+ T0_PUSH(len);
+
+ }
+ break;
+ case 40: {
+ /* fail */
+
+ br_ssl_engine_fail(ENG, (int)T0_POPi());
+ T0_CO();
+
+ }
+ break;
+ case 41: {
+ /* flush-record */
+
+ br_ssl_engine_flush_record(ENG);
+
+ }
+ break;
+ case 42: {
+ /* get-client-chain */
+
+ uint32_t auth_types;
+
+ auth_types = T0_POP();
+ if (CTX->client_auth_vtable != NULL) {
+ br_ssl_client_certificate ux;
+
+ (*CTX->client_auth_vtable)->choose(CTX->client_auth_vtable,
+ CTX, auth_types, &ux);
+ CTX->auth_type = (unsigned char)ux.auth_type;
+ CTX->hash_id = (unsigned char)ux.hash_id;
+ ENG->chain = ux.chain;
+ ENG->chain_len = ux.chain_len;
+ } else {
+ CTX->hash_id = 0;
+ ENG->chain_len = 0;
+ }
+
+ }
+ break;
+ case 43: {
+ /* get-key-type-usages */
+
+ const br_x509_class *xc;
+ const br_x509_pkey *pk;
+ unsigned usages;
+
+ xc = *(ENG->x509ctx);
+ pk = xc->get_pkey(ENG->x509ctx, &usages);
+ if (pk == NULL) {
+ T0_PUSH(0);
+ } else {
+ T0_PUSH(pk->key_type | usages);
+ }
+
+ }
+ break;
+ case 44: {
+ /* get16 */
+
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr));
+
+ }
+ break;
+ case 45: {
+ /* get32 */
+
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr));
+
+ }
+ break;
+ case 46: {
+ /* get8 */
+
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*((unsigned char *)ENG + addr));
+
+ }
+ break;
+ case 47: {
+ /* has-input? */
+
+ T0_PUSHi(-(ENG->hlen_in != 0));
+
+ }
+ break;
+ case 48: {
+ /* memcmp */
+
+ size_t len = (size_t)T0_POP();
+ void *addr2 = (unsigned char *)ENG + (size_t)T0_POP();
+ void *addr1 = (unsigned char *)ENG + (size_t)T0_POP();
+ int x = memcmp(addr1, addr2, len);
+ T0_PUSH((uint32_t)-(x == 0));
+
+ }
+ break;
+ case 49: {
+ /* memcpy */
+
+ size_t len = (size_t)T0_POP();
+ void *src = (unsigned char *)ENG + (size_t)T0_POP();
+ void *dst = (unsigned char *)ENG + (size_t)T0_POP();
+ memcpy(dst, src, len);
+
+ }
+ break;
+ case 50: {
+ /* mkrand */
+
+ size_t len = (size_t)T0_POP();
+ void *addr = (unsigned char *)ENG + (size_t)T0_POP();
+ br_hmac_drbg_generate(&ENG->rng, addr, len);
+
+ }
+ break;
+ case 51: {
+ /* more-incoming-bytes? */
+
+ T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
+
+ }
+ break;
+ case 52: {
+ /* multihash-init */
+
+ br_multihash_init(&ENG->mhash);
+
+ }
+ break;
+ case 53: {
+ /* neg */
+
+ uint32_t a = T0_POP();
+ T0_PUSH(-a);
+
+ }
+ break;
+ case 54: {
+ /* not */
+
+ uint32_t a = T0_POP();
+ T0_PUSH(~a);
+
+ }
+ break;
+ case 55: {
+ /* or */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a | b);
+
+ }
+ break;
+ case 56: {
+ /* over */
+ T0_PUSH(T0_PEEK(1));
+ }
+ break;
+ case 57: {
+ /* read-chunk-native */
+
+ size_t clen = ENG->hlen_in;
+ if (clen > 0) {
+ uint32_t addr, len;
+
+ len = T0_POP();
+ addr = T0_POP();
+ if ((size_t)len < clen) {
+ clen = (size_t)len;
+ }
+ memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen);
+ if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen);
+ }
+ T0_PUSH(addr + (uint32_t)clen);
+ T0_PUSH(len - (uint32_t)clen);
+ ENG->hbuf_in += clen;
+ ENG->hlen_in -= clen;
+ }
+
+ }
+ break;
+ case 58: {
+ /* read8-native */
+
+ if (ENG->hlen_in > 0) {
+ unsigned char x;
+
+ x = *ENG->hbuf_in ++;
+ if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, &x, 1);
+ }
+ T0_PUSH(x);
+ ENG->hlen_in --;
+ } else {
+ T0_PUSHi(-1);
+ }
+
+ }
+ break;
+ case 59: {
+ /* set-server-curve */
+
+ const br_x509_class *xc;
+ const br_x509_pkey *pk;
+
+ xc = *(ENG->x509ctx);
+ pk = xc->get_pkey(ENG->x509ctx, NULL);
+ CTX->server_curve =
+ (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0;
+
+ }
+ break;
+ case 60: {
+ /* set16 */
+
+ size_t addr = (size_t)T0_POP();
+ *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP();
+
+ }
+ break;
+ case 61: {
+ /* set32 */
+
+ size_t addr = (size_t)T0_POP();
+ *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP();
+
+ }
+ break;
+ case 62: {
+ /* set8 */
+
+ size_t addr = (size_t)T0_POP();
+ *((unsigned char *)ENG + addr) = (unsigned char)T0_POP();
+
+ }
+ break;
+ case 63: {
+ /* strlen */
+
+ void *str = (unsigned char *)ENG + (size_t)T0_POP();
+ T0_PUSH((uint32_t)strlen(str));
+
+ }
+ break;
+ case 64: {
+ /* supported-curves */
+
+ uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
+ T0_PUSH(x);
+
+ }
+ break;
+ case 65: {
+ /* supported-hash-functions */
+
+ int i;
+ unsigned x, num;
+
+ x = 0;
+ num = 0;
+ for (i = br_sha1_ID; i <= br_sha512_ID; i ++) {
+ if (br_multihash_getimpl(&ENG->mhash, i)) {
+ x |= 1U << i;
+ num ++;
+ }
+ }
+ T0_PUSH(x);
+ T0_PUSH(num);
+
+ }
+ break;
+ case 66: {
+ /* supports-ecdsa? */
+
+ T0_PUSHi(-(ENG->iecdsa != 0));
+
+ }
+ break;
+ case 67: {
+ /* supports-rsa-sign? */
+
+ T0_PUSHi(-(ENG->irsavrfy != 0));
+
+ }
+ break;
+ case 68: {
+ /* swap */
+ T0_SWAP();
+ }
+ break;
+ case 69: {
+ /* switch-aesccm-in */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len, tag_len;
+
+ tag_len = T0_POP();
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id,
+ ENG->iaes_ctrcbc, cipher_key_len, tag_len);
+
+ }
+ break;
+ case 70: {
+ /* switch-aesccm-out */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len, tag_len;
+
+ tag_len = T0_POP();
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id,
+ ENG->iaes_ctrcbc, cipher_key_len, tag_len);
+
+ }
+ break;
+ case 71: {
+ /* switch-aesgcm-in */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id,
+ ENG->iaes_ctr, cipher_key_len);
+
+ }
+ break;
+ case 72: {
+ /* switch-aesgcm-out */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id,
+ ENG->iaes_ctr, cipher_key_len);
+
+ }
+ break;
+ case 73: {
+ /* switch-cbc-in */
+
+ int is_client, prf_id, mac_id, aes;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ aes = T0_POP();
+ mac_id = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id,
+ aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len);
+
+ }
+ break;
+ case 74: {
+ /* switch-cbc-out */
+
+ int is_client, prf_id, mac_id, aes;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ aes = T0_POP();
+ mac_id = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id,
+ aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len);
+
+ }
+ break;
+ case 75: {
+ /* switch-chapol-in */
+
+ int is_client, prf_id;
+
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id);
+
+ }
+ break;
+ case 76: {
+ /* switch-chapol-out */
+
+ int is_client, prf_id;
+
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id);
+
+ }
+ break;
+ case 77: {
+ /* test-protocol-name */
+
+ size_t len = T0_POP();
+ size_t u;
+
+ for (u = 0; u < ENG->protocol_names_num; u ++) {
+ const char *name;
+
+ name = ENG->protocol_names[u];
+ if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) {
+ T0_PUSH(u);
+ T0_RET();
+ }
+ }
+ T0_PUSHi(-1);
+
+ }
+ break;
+ case 78: {
+ /* total-chain-length */
+
+ size_t u;
+ uint32_t total;
+
+ total = 0;
+ for (u = 0; u < ENG->chain_len; u ++) {
+ total += 3 + (uint32_t)ENG->chain[u].data_len;
+ }
+ T0_PUSH(total);
+
+ }
+ break;
+ case 79: {
+ /* u>> */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x >> c);
+
+ }
+ break;
+ case 80: {
+ /* verify-SKE-sig */
+
+ size_t sig_len = T0_POP();
+ int use_rsa = T0_POPi();
+ int hash = T0_POPi();
+
+ T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len));
+
+ }
+ break;
+ case 81: {
+ /* write-blob-chunk */
+
+ size_t clen = ENG->hlen_out;
+ if (clen > 0) {
+ uint32_t addr, len;
+
+ len = T0_POP();
+ addr = T0_POP();
+ if ((size_t)len < clen) {
+ clen = (size_t)len;
+ }
+ memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen);
+ if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen);
+ }
+ T0_PUSH(addr + (uint32_t)clen);
+ T0_PUSH(len - (uint32_t)clen);
+ ENG->hbuf_out += clen;
+ ENG->hlen_out -= clen;
+ }
+
+ }
+ break;
+ case 82: {
+ /* write8-native */
+
+ unsigned char x;
+
+ x = (unsigned char)T0_POP();
+ if (ENG->hlen_out > 0) {
+ if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, &x, 1);
+ }
+ *ENG->hbuf_out ++ = x;
+ ENG->hlen_out --;
+ T0_PUSHi(-1);
+ } else {
+ T0_PUSHi(0);
+ }
+
+ }
+ break;
+ case 83: {
+ /* x509-append */
+
+ const br_x509_class *xc;
+ size_t len;
+
+ xc = *(ENG->x509ctx);
+ len = T0_POP();
+ xc->append(ENG->x509ctx, ENG->pad, len);
+
+ }
+ break;
+ case 84: {
+ /* x509-end-cert */
+
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ xc->end_cert(ENG->x509ctx);
+
+ }
+ break;
+ case 85: {
+ /* x509-end-chain */
+
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ T0_PUSH(xc->end_chain(ENG->x509ctx));
+
+ }
+ break;
+ case 86: {
+ /* x509-start-cert */
+
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ xc->start_cert(ENG->x509ctx, T0_POP());
+
+ }
+ break;
+ case 87: {
+ /* x509-start-chain */
+
+ const br_x509_class *xc;
+ uint32_t bc;
+
+ bc = T0_POP();
+ xc = *(ENG->x509ctx);
+ xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL);
+
+ }
+ break;
+ }
+
+ } else {
+ T0_ENTER(ip, rp, t0x);
+ }
+ }
+t0_exit:
+ ((t0_context *)t0ctx)->dp = dp;
+ ((t0_context *)t0ctx)->rp = rp;
+ ((t0_context *)t0ctx)->ip = ip;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_hs_client.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_hs_client.t0
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_hs_client.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_hs_client.t0 (revision 346145)
@@ -0,0 +1,1276 @@
+\ 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.
+
+\ ----------------------------------------------------------------------
+\ Handshake processing code, for the client.
+\ The common T0 code (ssl_hs_common.t0) shall be read first.
+
+preamble {
+
+/*
+ * This macro evaluates to a pointer to the client context, under that
+ * specific name. It must be noted that since the engine context is the
+ * first field of the br_ssl_client_context structure ('eng'), then
+ * pointers values of both types are interchangeable, modulo an
+ * appropriate cast. This also means that "addresses" computed as offsets
+ * within the structure work for both kinds of context.
+ */
+#define CTX ((br_ssl_client_context *)ENG)
+
+/*
+ * Generate the pre-master secret for RSA key exchange, and encrypt it
+ * with the server's public key. Returned value is either the encrypted
+ * data length (in bytes), or -x on error, with 'x' being an error code.
+ *
+ * This code assumes that the public key has been already verified (it
+ * was properly obtained by the X.509 engine, and it has the right type,
+ * i.e. it is of type RSA and suitable for encryption).
+ */
+static int
+make_pms_rsa(br_ssl_client_context *ctx, int prf_id)
+{
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+ const unsigned char *n;
+ unsigned char *pms;
+ size_t nlen, u;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+
+ /*
+ * Compute actual RSA key length, in case there are leading zeros.
+ */
+ n = pk->key.rsa.n;
+ nlen = pk->key.rsa.nlen;
+ while (nlen > 0 && *n == 0) {
+ n ++;
+ nlen --;
+ }
+
+ /*
+ * We need at least 59 bytes (48 bytes for pre-master secret, and
+ * 11 bytes for the PKCS#1 type 2 padding). Note that the X.509
+ * minimal engine normally blocks RSA keys shorter than 128 bytes,
+ * so this is mostly for public keys provided explicitly by the
+ * caller.
+ */
+ if (nlen < 59) {
+ return -BR_ERR_X509_WEAK_PUBLIC_KEY;
+ }
+ if (nlen > sizeof ctx->eng.pad) {
+ return -BR_ERR_LIMIT_EXCEEDED;
+ }
+
+ /*
+ * Make PMS.
+ */
+ pms = ctx->eng.pad + nlen - 48;
+ br_enc16be(pms, ctx->eng.version_max);
+ br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46);
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48);
+
+ /*
+ * Apply PKCS#1 type 2 padding.
+ */
+ ctx->eng.pad[0] = 0x00;
+ ctx->eng.pad[1] = 0x02;
+ ctx->eng.pad[nlen - 49] = 0x00;
+ br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51);
+ for (u = 2; u < nlen - 49; u ++) {
+ while (ctx->eng.pad[u] == 0) {
+ br_hmac_drbg_generate(&ctx->eng.rng,
+ &ctx->eng.pad[u], 1);
+ }
+ }
+
+ /*
+ * Compute RSA encryption.
+ */
+ if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) {
+ return -BR_ERR_LIMIT_EXCEEDED;
+ }
+ return (int)nlen;
+}
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char *HASH_OID[] = {
+ BR_HASH_OID_SHA1,
+ BR_HASH_OID_SHA224,
+ BR_HASH_OID_SHA256,
+ BR_HASH_OID_SHA384,
+ BR_HASH_OID_SHA512
+};
+
+/*
+ * Check the RSA signature on the ServerKeyExchange message.
+ *
+ * hash hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only)
+ * use_rsa non-zero for RSA signature, zero for ECDSA
+ * sig_len signature length (in bytes); signature value is in the pad
+ *
+ * Returned value is 0 on success, or an error code.
+ */
+static int
+verify_SKE_sig(br_ssl_client_context *ctx,
+ int hash, int use_rsa, size_t sig_len)
+{
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+ br_multihash_context mhc;
+ unsigned char hv[64], head[4];
+ size_t hv_len;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ br_multihash_zero(&mhc);
+ br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
+ br_multihash_init(&mhc);
+ br_multihash_update(&mhc,
+ ctx->eng.client_random, sizeof ctx->eng.client_random);
+ br_multihash_update(&mhc,
+ ctx->eng.server_random, sizeof ctx->eng.server_random);
+ head[0] = 3;
+ head[1] = 0;
+ head[2] = ctx->eng.ecdhe_curve;
+ head[3] = ctx->eng.ecdhe_point_len;
+ br_multihash_update(&mhc, head, sizeof head);
+ br_multihash_update(&mhc,
+ ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len);
+ if (hash) {
+ hv_len = br_multihash_out(&mhc, hash, hv);
+ if (hv_len == 0) {
+ return BR_ERR_INVALID_ALGORITHM;
+ }
+ } else {
+ if (!br_multihash_out(&mhc, br_md5_ID, hv)
+ || !br_multihash_out(&mhc, br_sha1_ID, hv + 16))
+ {
+ return BR_ERR_INVALID_ALGORITHM;
+ }
+ hv_len = 36;
+ }
+ if (use_rsa) {
+ unsigned char tmp[64];
+ const unsigned char *hash_oid;
+
+ if (hash) {
+ hash_oid = HASH_OID[hash - 2];
+ } else {
+ hash_oid = NULL;
+ }
+ if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
+ hash_oid, hv_len, &pk->key.rsa, tmp)
+ || memcmp(tmp, hv, hv_len) != 0)
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ } else {
+ if (!ctx->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec,
+ ctx->eng.pad, sig_len))
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Perform client-side ECDH (or ECDHE). The point that should be sent to
+ * the server is written in the pad; returned value is either the point
+ * length (in bytes), or -x on error, with 'x' being an error code.
+ *
+ * The point _from_ the server is taken from ecdhe_point[] if 'ecdhe'
+ * is non-zero, or from the X.509 engine context if 'ecdhe' is zero
+ * (for static ECDH).
+ */
+static int
+make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id)
+{
+ int curve;
+ unsigned char key[66], point[133];
+ const unsigned char *order, *point_src;
+ size_t glen, olen, point_len, xoff, xlen;
+ unsigned char mask;
+
+ if (ecdhe) {
+ curve = ctx->eng.ecdhe_curve;
+ point_src = ctx->eng.ecdhe_point;
+ point_len = ctx->eng.ecdhe_point_len;
+ } else {
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ curve = pk->key.ec.curve;
+ point_src = pk->key.ec.q;
+ point_len = pk->key.ec.qlen;
+ }
+ if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+
+ /*
+ * We need to generate our key, as a non-zero random value which
+ * is lower than the curve order, in a "large enough" range. We
+ * force top bit to 0 and bottom bit to 1, which guarantees that
+ * the value is in the proper range.
+ */
+ order = ctx->eng.iec->order(curve, &olen);
+ mask = 0xFF;
+ while (mask >= order[0]) {
+ mask >>= 1;
+ }
+ br_hmac_drbg_generate(&ctx->eng.rng, key, olen);
+ key[0] &= mask;
+ key[olen - 1] |= 0x01;
+
+ /*
+ * Compute the common ECDH point, whose X coordinate is the
+ * pre-master secret.
+ */
+ ctx->eng.iec->generator(curve, &glen);
+ if (glen != point_len) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+
+ memcpy(point, point_src, glen);
+ if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+
+ /*
+ * The pre-master secret is the X coordinate.
+ */
+ xoff = ctx->eng.iec->xoff(curve, &xlen);
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen);
+
+ ctx->eng.iec->mulgen(point, key, olen, curve);
+ memcpy(ctx->eng.pad, point, glen);
+ return (int)glen;
+}
+
+/*
+ * Perform full static ECDH. This occurs only in the context of client
+ * authentication with certificates: the server uses an EC public key,
+ * the cipher suite is of type ECDH (not ECDHE), the server requested a
+ * client certificate and accepts static ECDH, the client has a
+ * certificate with an EC public key in the same curve, and accepts
+ * static ECDH as well.
+ *
+ * Returned value is 0 on success, -1 on error.
+ */
+static int
+make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id)
+{
+ unsigned char point[133];
+ size_t point_len;
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ point_len = pk->key.ec.qlen;
+ if (point_len > sizeof point) {
+ return -1;
+ }
+ memcpy(point, pk->key.ec.q, point_len);
+ if (!(*ctx->client_auth_vtable)->do_keyx(
+ ctx->client_auth_vtable, point, &point_len))
+ {
+ return -1;
+ }
+ br_ssl_engine_compute_master(&ctx->eng,
+ prf_id, point, point_len);
+ return 0;
+}
+
+/*
+ * Compute the client-side signature. This is invoked only when a
+ * signature-based client authentication was selected. The computed
+ * signature is in the pad; its length (in bytes) is returned. On
+ * error, 0 is returned.
+ */
+static size_t
+make_client_sign(br_ssl_client_context *ctx)
+{
+ size_t hv_len;
+
+ /*
+ * Compute hash of handshake messages so far. This "cannot" fail
+ * because the list of supported hash functions provided to the
+ * client certificate handler was trimmed to include only the
+ * hash functions that the multi-hasher supports.
+ */
+ if (ctx->hash_id) {
+ hv_len = br_multihash_out(&ctx->eng.mhash,
+ ctx->hash_id, ctx->eng.pad);
+ } else {
+ br_multihash_out(&ctx->eng.mhash,
+ br_md5_ID, ctx->eng.pad);
+ br_multihash_out(&ctx->eng.mhash,
+ br_sha1_ID, ctx->eng.pad + 16);
+ hv_len = 36;
+ }
+ return (*ctx->client_auth_vtable)->do_sign(
+ ctx->client_auth_vtable, ctx->hash_id, hv_len,
+ ctx->eng.pad, sizeof ctx->eng.pad);
+}
+
+}
+
+\ =======================================================================
+
+: addr-ctx:
+ next-word { field }
+ "addr-" field + 0 1 define-word
+ 0 8191 "offsetof(br_ssl_client_context, " field + ")" + make-CX
+ postpone literal postpone ; ;
+
+addr-ctx: min_clienthello_len
+addr-ctx: hashes
+addr-ctx: auth_type
+addr-ctx: hash_id
+
+\ Length of the Secure Renegotiation extension. This is 5 for the
+\ first handshake, 17 for a renegotiation (if the server supports the
+\ extension), or 0 if we know that the server does not support the
+\ extension.
+: ext-reneg-length ( -- n )
+ addr-reneg get8 dup if 1 - 17 * else drop 5 then ;
+
+\ Length of SNI extension.
+: ext-sni-length ( -- len )
+ addr-server_name strlen dup if 9 + then ;
+
+\ Length of Maximum Fragment Length extension.
+: ext-frag-length ( -- len )
+ addr-log_max_frag_len get8 14 = if 0 else 5 then ;
+
+\ Length of Signatures extension.
+: ext-signatures-length ( -- len )
+ supported-hash-functions { num } drop 0
+ supports-rsa-sign? if num + then
+ supports-ecdsa? if num + then
+ dup if 1 << 6 + then ;
+
+\ Write supported hash functions ( sign -- )
+: write-hashes
+ { sign }
+ supported-hash-functions drop
+ \ We advertise hash functions in the following preference order:
+ \ SHA-256 SHA-224 SHA-384 SHA-512 SHA-1
+ \ Rationale:
+ \ -- SHA-256 and SHA-224 are more efficient on 32-bit architectures
+ \ -- SHA-1 is less than ideally collision-resistant
+ dup 0x10 and if 4 write8 sign write8 then
+ dup 0x08 and if 3 write8 sign write8 then
+ dup 0x20 and if 5 write8 sign write8 then
+ dup 0x40 and if 6 write8 sign write8 then
+ 0x04 and if 2 write8 sign write8 then ;
+
+\ Length of Supported Curves extension.
+: ext-supported-curves-length ( -- len )
+ supported-curves dup if
+ 0 { x }
+ begin dup while
+ dup 1 and x + >x
+ 1 >>
+ repeat
+ drop x 1 << 6 +
+ then ;
+
+\ Length of Supported Point Formats extension.
+: ext-point-format-length ( -- len )
+ supported-curves if 6 else 0 then ;
+
+\ Length of ALPN extension.
+cc: ext-ALPN-length ( -- len ) {
+ size_t u, len;
+
+ if (ENG->protocol_names_num == 0) {
+ T0_PUSH(0);
+ T0_RET();
+ }
+ len = 6;
+ for (u = 0; u < ENG->protocol_names_num; u ++) {
+ len += 1 + strlen(ENG->protocol_names[u]);
+ }
+ T0_PUSH(len);
+}
+
+\ Write handshake message: ClientHello
+: write-ClientHello ( -- )
+ { ; total-ext-length }
+
+ \ Compute length for extensions (without the general two-byte header).
+ \ This does not take padding extension into account.
+ ext-reneg-length ext-sni-length + ext-frag-length +
+ ext-signatures-length +
+ ext-supported-curves-length + ext-point-format-length +
+ ext-ALPN-length +
+ >total-ext-length
+
+ \ ClientHello type
+ 1 write8
+
+ \ Compute and write length
+ 39 addr-session_id_len get8 + addr-suites_num get8 1 << +
+ total-ext-length if 2+ total-ext-length + then
+ \ Compute padding (if requested).
+ addr-min_clienthello_len get16 over - dup 0> if
+ \ We well add a Pad ClientHello extension, which has its
+ \ own header (4 bytes) and might be the only extension
+ \ (2 extra bytes for the extension list header).
+ total-ext-length ifnot swap 2+ swap 2- then
+ \ Account for the extension header.
+ 4 - dup 0< if drop 0 then
+ \ Adjust total extension length.
+ dup 4 + total-ext-length + >total-ext-length
+ \ Adjust ClientHello length.
+ swap 4 + over + swap
+ else
+ drop
+ -1
+ then
+ { ext-padding-amount }
+ write24
+
+ \ Protocol version
+ addr-version_max get16 write16
+
+ \ Client random
+ addr-client_random 4 bzero
+ addr-client_random 4 + 28 mkrand
+ addr-client_random 32 write-blob
+
+ \ Session ID
+ addr-session_id addr-session_id_len get8 write-blob-head8
+
+ \ Supported cipher suites. We also check here that we indeed
+ \ support all these suites.
+ addr-suites_num get8 dup 1 << write16
+ addr-suites_buf swap
+ begin
+ dup while 1-
+ over get16
+ dup suite-supported? ifnot ERR_BAD_CIPHER_SUITE fail then
+ write16
+ swap 2+ swap
+ repeat
+ 2drop
+
+ \ Compression methods (only "null" compression)
+ 1 write8 0 write8
+
+ \ Extensions
+ total-ext-length if
+ total-ext-length write16
+ ext-reneg-length if
+ 0xFF01 write16 \ extension type (0xFF01)
+ addr-saved_finished
+ ext-reneg-length 4 - dup write16 \ extension length
+ 1- write-blob-head8 \ verify data
+ then
+ ext-sni-length if
+ 0x0000 write16 \ extension type (0)
+ addr-server_name
+ ext-sni-length 4 - dup write16 \ extension length
+ 2 - dup write16 \ ServerNameList length
+ 0 write8 \ name type: host_name
+ 3 - write-blob-head16 \ the name itself
+ then
+ ext-frag-length if
+ 0x0001 write16 \ extension type (1)
+ 0x0001 write16 \ extension length
+ addr-log_max_frag_len get8 8 - write8
+ then
+ ext-signatures-length if
+ 0x000D write16 \ extension type (13)
+ ext-signatures-length 4 - dup write16 \ extension length
+ 2 - write16 \ list length
+ supports-ecdsa? if 3 write-hashes then
+ supports-rsa-sign? if 1 write-hashes then
+ then
+ \ TODO: add an API to specify preference order for curves.
+ \ Right now we send Curve25519 first, then other curves in
+ \ increasing ID values (hence P-256 in second).
+ ext-supported-curves-length dup if
+ 0x000A write16 \ extension type (10)
+ 4 - dup write16 \ extension length
+ 2- write16 \ list length
+ supported-curves 0
+ dup 0x20000000 and if
+ 0xDFFFFFFF and 29 write16
+ then
+ begin dup 32 < while
+ dup2 >> 1 and if dup write16 then
+ 1+
+ repeat
+ 2drop
+ else
+ drop
+ then
+ ext-point-format-length if
+ 0x000B write16 \ extension type (11)
+ 0x0002 write16 \ extension length
+ 0x0100 write16 \ value: 1 format: uncompressed
+ then
+ ext-ALPN-length dup if
+ 0x0010 write16 \ extension type (16)
+ 4 - dup write16 \ extension length
+ 2- write16 \ list length
+ addr-protocol_names_num get16 0
+ begin
+ dup2 > while
+ dup copy-protocol-name
+ dup write8 addr-pad swap write-blob
+ 1+
+ repeat
+ 2drop
+ else
+ drop
+ then
+ ext-padding-amount 0< ifnot
+ 0x0015 write16 \ extension value (21)
+ ext-padding-amount
+ dup write16 \ extension length
+ begin dup while
+ 1- 0 write8 repeat \ value (only zeros)
+ drop
+ then
+ then
+ ;
+
+\ =======================================================================
+
+\ Parse server SNI extension. If present, then it should be empty.
+: read-server-sni ( lim -- lim )
+ read16 if ERR_BAD_SNI fail then ;
+
+\ Parse server Max Fragment Length extension. If present, then it should
+\ advertise the same length as the client. Note that whether the server
+\ sends it or not changes nothing for us: we won't send any record larger
+\ than the advertised value anyway, and we will accept incoming records
+\ up to our input buffer length.
+: read-server-frag ( lim -- lim )
+ read16 1 = ifnot ERR_BAD_FRAGLEN fail then
+ read8 8 + addr-log_max_frag_len get8 = ifnot ERR_BAD_FRAGLEN fail then ;
+
+\ Parse server Secure Renegotiation extension. This is called only if
+\ the client sent that extension, so we only have two cases to
+\ distinguish: first handshake, and renegotiation; in the latter case,
+\ we know that the server supports the extension, otherwise the client
+\ would not have sent it.
+: read-server-reneg ( lim -- lim )
+ read16
+ addr-reneg get8 ifnot
+ \ "reneg" is 0, so this is a first handshake. The server's
+ \ extension MUST be empty. We also learn that the server
+ \ supports the extension.
+ 1 = ifnot ERR_BAD_SECRENEG fail then
+ read8 0 = ifnot ERR_BAD_SECRENEG fail then
+ 2 addr-reneg set8
+ else
+ \ "reneg" is non-zero, and we sent an extension, so it must
+ \ be 2 and this is a renegotiation. We must verify that
+ \ the extension contents have length exactly 24 bytes and
+ \ match the saved client and server "Finished".
+ 25 = ifnot ERR_BAD_SECRENEG fail then
+ read8 24 = ifnot ERR_BAD_SECRENEG fail then
+ addr-pad 24 read-blob
+ addr-saved_finished addr-pad 24 memcmp ifnot
+ ERR_BAD_SECRENEG fail
+ then
+ then ;
+
+\ Read the ALPN extension from the server. It must contain a single name,
+\ and that name must match one of our names.
+: read-ALPN-from-server ( lim -- lim )
+ \ Extension contents length.
+ read16 open-elt
+ \ Length of list of names.
+ read16 open-elt
+ \ There should be a single name.
+ read8 addr-pad swap dup { len } read-blob
+ close-elt
+ close-elt
+ len test-protocol-name dup 0< if
+ 3 flag? if ERR_UNEXPECTED fail then
+ drop
+ else
+ 1+ addr-selected_protocol set16
+ then ;
+
+\ Save a value in a 16-bit field, or check it in case of session resumption.
+: check-resume ( val addr resume -- )
+ if get16 = ifnot ERR_RESUME_MISMATCH fail then else set16 then ;
+
+cc: DEBUG-BLOB ( addr len -- ) {
+ extern int printf(const char *fmt, ...);
+
+ size_t len = T0_POP();
+ unsigned char *buf = (unsigned char *)CTX + T0_POP();
+ size_t u;
+
+ printf("BLOB:");
+ for (u = 0; u < len; u ++) {
+ if (u % 16 == 0) {
+ printf("\n ");
+ }
+ printf(" %02x", buf[u]);
+ }
+ printf("\n");
+}
+
+\ Parse incoming ServerHello. Returned value is true (-1) on session
+\ resumption.
+: read-ServerHello ( -- bool )
+ \ Get header, and check message type.
+ read-handshake-header 2 = ifnot ERR_UNEXPECTED fail then
+
+ \ Get protocol version.
+ read16 { version }
+ version addr-version_min get16 < version addr-version_max get16 > or if
+ ERR_UNSUPPORTED_VERSION fail
+ then
+
+ \ Enforce chosen version for subsequent records in both directions.
+ version addr-version_in get16 <> if ERR_BAD_VERSION fail then
+ version addr-version_out set16
+
+ \ Server random.
+ addr-server_random 32 read-blob
+
+ \ The "session resumption" flag.
+ 0 { resume }
+
+ \ Session ID.
+ read8 { idlen }
+ idlen 32 > if ERR_OVERSIZED_ID fail then
+ addr-pad idlen read-blob
+ idlen addr-session_id_len get8 = idlen 0 > and if
+ addr-session_id addr-pad idlen memcmp if
+ \ Server session ID is non-empty and matches what
+ \ we sent, so this is a session resumption.
+ -1 >resume
+ then
+ then
+ addr-session_id addr-pad idlen memcpy
+ idlen addr-session_id_len set8
+
+ \ Record version.
+ version addr-version resume check-resume
+
+ \ Cipher suite. We check that it is part of the list of cipher
+ \ suites that we advertised.
+ read16
+ dup scan-suite 0< if ERR_BAD_CIPHER_SUITE fail then
+ \ Also check that the cipher suite is compatible with the
+ \ announced version: suites that don't use HMAC/SHA-1 are
+ \ for TLS-1.2 only, not older versions.
+ dup use-tls12? version 0x0303 < and if ERR_BAD_CIPHER_SUITE fail then
+ addr-cipher_suite resume check-resume
+
+ \ Compression method. Should be 0 (no compression).
+ read8 if ERR_BAD_COMPRESSION fail then
+
+ \ Parse extensions (if any). If there is no extension, then the
+ \ read limit (on the TOS) should be 0 at that point.
+ dup if
+ \ Length of extension list.
+ \ message size.
+ read16 open-elt
+
+ \ Enumerate extensions. For each of them, check that we
+ \ sent an extension of that type, and did not see it
+ \ yet; and then process it.
+ ext-sni-length { ok-sni }
+ ext-reneg-length { ok-reneg }
+ ext-frag-length { ok-frag }
+ ext-signatures-length { ok-signatures }
+ ext-supported-curves-length { ok-curves }
+ ext-point-format-length { ok-points }
+ ext-ALPN-length { ok-ALPN }
+ begin dup while
+ read16
+ case
+ \ Server Name Indication. The server may
+ \ send such an extension if it uses the SNI
+ \ from the client, but that "response
+ \ extension" is supposed to be empty.
+ 0x0000 of
+ ok-sni ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-sni
+ read-server-sni
+ endof
+
+ \ Max Frag Length. The contents shall be
+ \ a single byte whose value matches the one
+ \ sent by the client.
+ 0x0001 of
+ ok-frag ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-frag
+ read-server-frag
+ endof
+
+ \ Secure Renegotiation.
+ 0xFF01 of
+ ok-reneg ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-reneg
+ read-server-reneg
+ endof
+
+ \ Signature Algorithms.
+ \ Normally, the server should never send this
+ \ extension (so says RFC 5246 #7.4.1.4.1),
+ \ but some existing servers do.
+ 0x000D of
+ ok-signatures ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-signatures
+ read-ignore-16
+ endof
+
+ \ Supported Curves.
+ 0x000A of
+ ok-curves ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-curves
+ read-ignore-16
+ endof
+
+ \ Supported Point Formats.
+ 0x000B of
+ ok-points ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-points
+ read-ignore-16
+ endof
+
+ \ ALPN.
+ 0x0010 of
+ ok-ALPN ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-ALPN
+ read-ALPN-from-server
+ endof
+
+ ERR_EXTRA_EXTENSION fail
+ endcase
+ repeat
+
+ \ If we sent a secure renegotiation extension but did not
+ \ receive a response, then the server does not support
+ \ secure renegotiation. This is a hard failure if this
+ \ is a renegotiation.
+ ok-reneg if
+ ok-reneg 5 > if ERR_BAD_SECRENEG fail then
+ 1 addr-reneg set8
+ then
+ close-elt
+ else
+ \ No extension received at all, so the server does not
+ \ support secure renegotiation. This is a hard failure
+ \ if the server was previously known to support it (i.e.
+ \ this is a renegotiation).
+ ext-reneg-length 5 > if ERR_BAD_SECRENEG fail then
+ 1 addr-reneg set8
+ then
+ close-elt
+ resume
+ ;
+
+cc: set-server-curve ( -- ) {
+ const br_x509_class *xc;
+ const br_x509_pkey *pk;
+
+ xc = *(ENG->x509ctx);
+ pk = xc->get_pkey(ENG->x509ctx, NULL);
+ CTX->server_curve =
+ (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0;
+}
+
+\ Read Certificate message from server.
+: read-Certificate-from-server ( -- )
+ addr-cipher_suite get16 expected-key-type
+ -1 read-Certificate
+ dup 0< if neg fail then
+ dup ifnot ERR_UNEXPECTED fail then
+ over and <> if ERR_WRONG_KEY_USAGE fail then
+
+ \ Set server curve (used for static ECDH).
+ set-server-curve ;
+
+\ Verify signature on ECDHE point sent by the server.
+\ 'hash' is the hash function to use (1 to 6, or 0 for RSA with MD5+SHA-1)
+\ 'use-rsa' is 0 for ECDSA, -1 for for RSA
+\ 'sig-len' is the signature length (in bytes)
+\ The signature itself is in the pad.
+cc: verify-SKE-sig ( hash use-rsa sig-len -- err ) {
+ size_t sig_len = T0_POP();
+ int use_rsa = T0_POPi();
+ int hash = T0_POPi();
+
+ T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len));
+}
+
+\ Parse ServerKeyExchange
+: read-ServerKeyExchange ( -- )
+ \ Get header, and check message type.
+ read-handshake-header 12 = ifnot ERR_UNEXPECTED fail then
+
+ \ We expect a named curve, and we must support it.
+ read8 3 = ifnot ERR_INVALID_ALGORITHM fail then
+ read16 dup addr-ecdhe_curve set8
+ dup 32 >= if ERR_INVALID_ALGORITHM fail then
+ supported-curves swap >> 1 and ifnot ERR_INVALID_ALGORITHM fail then
+
+ \ Read the server point.
+ read8
+ dup 133 > if ERR_INVALID_ALGORITHM fail then
+ dup addr-ecdhe_point_len set8
+ addr-ecdhe_point swap read-blob
+
+ \ If using TLS-1.2+, then the hash function and signature algorithm
+ \ are explicitly provided; the signature algorithm must match what
+ \ the cipher suite specifies. With TLS-1.0 and 1.1, the signature
+ \ algorithm is inferred from the cipher suite, and the hash is
+ \ either MD5+SHA-1 (for RSA signatures) or SHA-1 (for ECDSA).
+ addr-version get16 0x0303 >= { tls1.2+ }
+ addr-cipher_suite get16 use-rsa-ecdhe? { use-rsa }
+ 2 { hash }
+ tls1.2+ if
+ \ Read hash function; accept only the SHA-* identifiers
+ \ (from SHA-1 to SHA-512, no MD5 here).
+ read8
+ dup dup 2 < swap 6 > or if ERR_INVALID_ALGORITHM fail then
+ >hash
+ read8
+ \ Get expected signature algorithm and compare with what
+ \ the server just sent. Expected value is 1 for RSA, 3
+ \ for ECDSA. Note that 'use-rsa' evaluates to -1 for RSA,
+ \ 0 for ECDSA.
+ use-rsa 1 << 3 + = ifnot ERR_INVALID_ALGORITHM fail then
+ else
+ \ For MD5+SHA-1, we set 'hash' to 0.
+ use-rsa if 0 >hash then
+ then
+
+ \ Read signature into the pad.
+ read16 dup { sig-len }
+
+ dup 512 > if ERR_LIMIT_EXCEEDED fail then
+ addr-pad swap read-blob
+
+ \ Verify signature.
+ hash use-rsa sig-len verify-SKE-sig
+ dup if fail then drop
+
+ close-elt ;
+
+\ Client certificate: start processing of anchor names.
+cc: anchor-dn-start-name-list ( -- ) {
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->start_name_list(
+ CTX->client_auth_vtable);
+ }
+}
+
+\ Client certificate: start a new anchor DN (length is 16-bit).
+cc: anchor-dn-start-name ( length -- ) {
+ size_t len;
+
+ len = T0_POP();
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->start_name(
+ CTX->client_auth_vtable, len);
+ }
+}
+
+\ Client certificate: push some data for current anchor DN.
+cc: anchor-dn-append-name ( length -- ) {
+ size_t len;
+
+ len = T0_POP();
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->append_name(
+ CTX->client_auth_vtable, ENG->pad, len);
+ }
+}
+
+\ Client certificate: end current anchor DN.
+cc: anchor-dn-end-name ( -- ) {
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->end_name(
+ CTX->client_auth_vtable);
+ }
+}
+
+\ Client certificate: end list of anchor DN.
+cc: anchor-dn-end-name-list ( -- ) {
+ if (CTX->client_auth_vtable != NULL) {
+ (*CTX->client_auth_vtable)->end_name_list(
+ CTX->client_auth_vtable);
+ }
+}
+
+\ Client certificate: obtain the client certificate chain.
+cc: get-client-chain ( auth_types -- ) {
+ uint32_t auth_types;
+
+ auth_types = T0_POP();
+ if (CTX->client_auth_vtable != NULL) {
+ br_ssl_client_certificate ux;
+
+ (*CTX->client_auth_vtable)->choose(CTX->client_auth_vtable,
+ CTX, auth_types, &ux);
+ CTX->auth_type = (unsigned char)ux.auth_type;
+ CTX->hash_id = (unsigned char)ux.hash_id;
+ ENG->chain = ux.chain;
+ ENG->chain_len = ux.chain_len;
+ } else {
+ CTX->hash_id = 0;
+ ENG->chain_len = 0;
+ }
+}
+
+\ Parse CertificateRequest. Header has already been read.
+: read-contents-CertificateRequest ( lim -- )
+ \ Read supported client authentication types. We keep only
+ \ RSA, ECDSA, and ECDH.
+ 0 { auth_types }
+ read8 open-elt
+ begin dup while
+ read8 case
+ 1 of 0x0000FF endof
+ 64 of 0x00FF00 endof
+ 65 of 0x010000 endof
+ 66 of 0x020000 endof
+ 0 swap
+ endcase
+ auth_types or >auth_types
+ repeat
+ close-elt
+
+ \ Full static ECDH is allowed only if the cipher suite is ECDH
+ \ (not ECDHE). It would be theoretically feasible to use static
+ \ ECDH on the client side with an ephemeral key pair from the
+ \ server, but RFC 4492 (section 3) forbids it because ECDHE suites
+ \ are supposed to provide forward secrecy, and static ECDH would
+ \ negate that property.
+ addr-cipher_suite get16 use-ecdh? ifnot
+ auth_types 0xFFFF and >auth_types
+ then
+
+ \ Note: if the cipher suite is ECDH, then the X.509 validation
+ \ engine was invoked with the BR_KEYTYPE_EC | BR_KEYTYPE_KEYX
+ \ combination, so the server's public key has already been
+ \ checked to be fit for a key exchange.
+
+ \ With TLS 1.2:
+ \ - rsa_fixed_ecdh and ecdsa_fixed_ecdh are synoymous.
+ \ - There is an explicit list of supported sign+hash.
+ \ With TLS 1.0,
+ addr-version get16 0x0303 >= if
+ \ With TLS 1.2:
+ \ - There is an explicit list of supported sign+hash.
+ \ - The ECDH flags must be adjusted for RSA/ECDSA
+ \ support.
+ read-list-sign-algos dup addr-hashes set32
+
+ \ Trim down the list depending on what hash functions
+ \ we support (since the hashing itself is done by the SSL
+ \ engine, not by the certificate handler).
+ supported-hash-functions drop dup 8 << or 0x030000 or and
+
+ auth_types and
+ auth_types 0x030000 and if
+ dup 0x0000FF and if 0x010000 or then
+ dup 0x00FF00 and if 0x020000 or then
+ then
+ >auth_types
+ else
+ \ TLS 1.0 or 1.1. The hash function is fixed for signatures
+ \ (MD5+SHA-1 for RSA, SHA-1 for ECDSA).
+ auth_types 0x030401 and >auth_types
+ then
+
+ \ Parse list of anchor DN.
+ anchor-dn-start-name-list
+ read16 open-elt
+ begin dup while
+ read16 open-elt
+ dup anchor-dn-start-name
+
+ \ We read the DN by chunks through the pad, so
+ \ as to use the existing reading function (read-blob)
+ \ that also ensures proper hashing.
+ begin
+ dup while
+ dup 256 > if 256 else dup then { len }
+ addr-pad len read-blob
+ len anchor-dn-append-name
+ repeat
+ close-elt
+ anchor-dn-end-name
+ repeat
+ close-elt
+ anchor-dn-end-name-list
+
+ \ We should have reached the message end.
+ close-elt
+
+ \ Obtain the client chain.
+ auth_types get-client-chain
+ ;
+
+\ (obsolete)
+\ Write an empty Certificate message.
+\ : write-empty-Certificate ( -- )
+\ 11 write8 3 write24 0 write24 ;
+
+cc: do-rsa-encrypt ( prf_id -- nlen ) {
+ int x;
+
+ x = make_pms_rsa(CTX, T0_POP());
+ if (x < 0) {
+ br_ssl_engine_fail(ENG, -x);
+ T0_CO();
+ } else {
+ T0_PUSH(x);
+ }
+}
+
+cc: do-ecdh ( echde prf_id -- ulen ) {
+ unsigned prf_id = T0_POP();
+ unsigned ecdhe = T0_POP();
+ int x;
+
+ x = make_pms_ecdh(CTX, ecdhe, prf_id);
+ if (x < 0) {
+ br_ssl_engine_fail(ENG, -x);
+ T0_CO();
+ } else {
+ T0_PUSH(x);
+ }
+}
+
+cc: do-static-ecdh ( prf-id -- ) {
+ unsigned prf_id = T0_POP();
+
+ if (make_pms_static_ecdh(CTX, prf_id) < 0) {
+ br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+ T0_CO();
+ }
+}
+
+cc: do-client-sign ( -- sig_len ) {
+ size_t sig_len;
+
+ sig_len = make_client_sign(CTX);
+ if (sig_len == 0) {
+ br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM);
+ T0_CO();
+ }
+ T0_PUSH(sig_len);
+}
+
+\ Write ClientKeyExchange.
+: write-ClientKeyExchange ( -- )
+ 16 write8
+ addr-cipher_suite get16
+ dup use-rsa-keyx? if
+ prf-id do-rsa-encrypt
+ dup 2+ write24
+ dup write16
+ addr-pad swap write-blob
+ else
+ dup use-ecdhe? swap prf-id do-ecdh
+ dup 1+ write24
+ dup write8
+ addr-pad swap write-blob
+ then ;
+
+\ Write CertificateVerify. This is invoked only if a client certificate
+\ was requested and sent, and the authentication is not full static ECDH.
+: write-CertificateVerify ( -- )
+ do-client-sign
+ 15 write8 dup
+ addr-version get16 0x0303 >= if
+ 4 + write24
+ addr-hash_id get8 write8
+ addr-auth_type get8 write8
+ else
+ 2+ write24
+ then
+ dup write16 addr-pad swap write-blob ;
+
+\ =======================================================================
+
+\ Perform a handshake.
+: do-handshake ( -- )
+ 0 addr-application_data set8
+ 22 addr-record_type_out set8
+ 0 addr-selected_protocol set16
+ multihash-init
+
+ write-ClientHello
+ flush-record
+ read-ServerHello
+
+ if
+ \ Session resumption.
+ -1 read-CCS-Finished
+ -1 write-CCS-Finished
+
+ else
+
+ \ Not a session resumption.
+
+ \ Read certificate; then check key type and usages against
+ \ cipher suite.
+ read-Certificate-from-server
+
+ \ Depending on cipher suite, we may now expect a
+ \ ServerKeyExchange.
+ addr-cipher_suite get16 expected-key-type
+ CX 0 63 { BR_KEYTYPE_SIGN } and if
+ read-ServerKeyExchange
+ then
+
+ \ Get next header.
+ read-handshake-header
+
+ \ If this is a CertificateRequest, parse it, then read
+ \ next header.
+ dup 13 = if
+ drop read-contents-CertificateRequest
+ read-handshake-header
+ -1
+ else
+ 0
+ then
+ { seen-CR }
+
+ \ At that point, we should have a ServerHelloDone,
+ \ whose length must be 0.
+ 14 = ifnot ERR_UNEXPECTED fail then
+ if ERR_BAD_HELLO_DONE fail then
+
+ \ There should not be more bytes in the record at that point.
+ more-incoming-bytes? if ERR_UNEXPECTED fail then
+
+ seen-CR if
+ \ If the server requested a client certificate, then
+ \ we must write a Certificate message (it may be
+ \ empty).
+ write-Certificate
+
+ \ If using static ECDH, then the ClientKeyExchange
+ \ is empty, and there is no CertificateVerify.
+ \ Otherwise, there is a ClientKeyExchange; there
+ \ will then be a CertificateVerify if a client chain
+ \ was indeed sent.
+ addr-hash_id get8 0xFF = if
+ drop
+ 16 write8 0 write24
+ addr-cipher_suite get16 prf-id do-static-ecdh
+ else
+ write-ClientKeyExchange
+ if write-CertificateVerify then
+ then
+ else
+ write-ClientKeyExchange
+ then
+
+ -1 write-CCS-Finished
+ -1 read-CCS-Finished
+ then
+
+ \ Now we should be invoked only in case of renegotiation.
+ 1 addr-application_data set8
+ 23 addr-record_type_out set8 ;
+
+\ Read a HelloRequest message.
+: read-HelloRequest ( -- )
+ \ A HelloRequest has length 0 and type 0.
+ read-handshake-header-core
+ if ERR_UNEXPECTED fail then
+ if ERR_BAD_HANDSHAKE fail then ;
+
+\ Entry point.
+: main ( -- ! )
+ \ Perform initial handshake.
+ do-handshake
+
+ begin
+ \ Wait for further invocation. At that point, we should
+ \ get either an explicit call for renegotiation, or
+ \ an incoming HelloRequest handshake message.
+ wait-co
+ dup 0x07 and case
+ 0x00 of
+ 0x10 and if
+ do-handshake
+ then
+ endof
+ 0x01 of
+ drop
+ 0 addr-application_data set8
+ read-HelloRequest
+ \ Reject renegotiations if the peer does not
+ \ support secure renegotiation, or if the
+ \ "no renegotiation" flag is set.
+ addr-reneg get8 1 = 1 flag? or if
+ flush-record
+ begin can-output? not while
+ wait-co drop
+ repeat
+ 100 send-warning
+ \ We rejected the renegotiation,
+ \ but the connection is not dead.
+ \ We must set back things into
+ \ working "application data" state.
+ 1 addr-application_data set8
+ 23 addr-record_type_out set8
+ else
+ do-handshake
+ then
+ endof
+ ERR_UNEXPECTED fail
+ endcase
+ again
+ ;
Index: stable/12/contrib/bearssl/src/ssl/ssl_hs_common.t0
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_hs_common.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_hs_common.t0 (revision 346145)
@@ -0,0 +1,1382 @@
+\ 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.
+
+\ ----------------------------------------------------------------------
+\ This is the common T0 code for processing handshake messages (code that
+\ is used by both client and server).
+
+preamble {
+
+#include <stddef.h>
+#include <string.h>
+
+#include "inner.h"
+
+/*
+ * This macro evaluates to a pointer to the current engine context.
+ */
+#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu)))
+
+}
+
+\ IMPLEMENTATION NOTES
+\ ====================
+\
+\ This code handles all records except application data records.
+\ Application data is accepted (incoming records, outgoing payload data)
+\ only when the application_data flag is set, which is done at the end
+\ of the handshake; and it is cleared whenever a renegotiation or a
+\ closure takes place.
+\
+\ Incoming alerts are processed on the fly; fatal alerts terminate the
+\ context, while warnings are ignored, except for close_notify, which
+\ triggers the closure procedure. That procedure never returns (it ends
+\ with an 'ERR_OK fail' call). We can thus make this processing right
+\ into the read functions.
+\
+\ Specific actions from the caller (closure or renegotiation) may happen
+\ only when jumping back into the T0 code, i.e. just after a 'co' call.
+\ Similarly, incoming record type may change only while the caller has
+\ control, so we need to check that type only when returning from a 'co'.
+\
+\ The handshake processor needs to defer back to the caller ('co') only
+\ in one of the following situations:
+\
+\ -- Some handshake data is expected.
+\
+\ -- The handshake is finished, and application data may flow. There may
+\ be some incoming handshake data (HelloRequest from the server). This
+\ is the only situation where a renegotiation call won't be ignored.
+\
+\ -- Some change-cipher-spec data is expected.
+\
+\ -- An alert record is expected. Other types of incoming records will be
+\ skipped.
+\
+\ -- Waiting for the currently accumulated record to be sent and the
+\ output buffer to become free again for another record.
+
+\ Placeholder for handling not yet implemented functionalities.
+: NYI ( -- ! )
+ "NOT YET IMPLEMENTED!" puts cr -1 fail ;
+
+\ Debug function that prints a string (and a newline) on stderr.
+cc: DBG ( addr -- ) {
+ extern void *stderr;
+ extern int fprintf(void *, const char *, ...);
+ fprintf(stderr, "%s\n", &t0_datablock[T0_POPi()]);
+}
+
+\ Debug function that prints a string and an integer value (followed
+\ by a newline) on stderr.
+cc: DBG2 ( addr x -- ) {
+ extern void *stderr;
+ extern int fprintf(void *, const char *, ...);
+ int32_t x = T0_POPi();
+ fprintf(stderr, "%s: %ld (0x%08lX)\n",
+ &t0_datablock[T0_POPi()], (long)x, (unsigned long)(uint32_t)x);
+}
+
+\ Mark the context as failed with a specific error code. This also
+\ returns control to the caller.
+cc: fail ( err -- ! ) {
+ br_ssl_engine_fail(ENG, (int)T0_POPi());
+ T0_CO();
+}
+
+\ Read a byte from the context (address is offset in context).
+cc: get8 ( addr -- val ) {
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*((unsigned char *)ENG + addr));
+}
+
+\ Read a 16-bit word from the context (address is offset in context).
+cc: get16 ( addr -- val ) {
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr));
+}
+
+\ Read a 32-bit word from the context (address is offset in context).
+cc: get32 ( addr -- val ) {
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr));
+}
+
+\ Set a byte in the context (address is offset in context).
+cc: set8 ( val addr -- ) {
+ size_t addr = (size_t)T0_POP();
+ *((unsigned char *)ENG + addr) = (unsigned char)T0_POP();
+}
+
+\ Set a 16-bit word in the context (address is offset in context).
+cc: set16 ( val addr -- ) {
+ size_t addr = (size_t)T0_POP();
+ *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP();
+}
+
+\ Set a 32-bit word in the context (address is offset in context).
+cc: set32 ( val addr -- ) {
+ size_t addr = (size_t)T0_POP();
+ *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP();
+}
+
+\ Define a word that evaluates as an address of a field within the
+\ engine context. The field name (C identifier) must follow in the
+\ source. For field 'foo', the defined word is 'addr-foo'.
+: addr-eng:
+ next-word { field }
+ "addr-" field + 0 1 define-word
+ 0 8191 "offsetof(br_ssl_engine_context, " field + ")" + make-CX
+ postpone literal postpone ; ;
+
+addr-eng: max_frag_len
+addr-eng: log_max_frag_len
+addr-eng: peer_log_max_frag_len
+addr-eng: shutdown_recv
+addr-eng: record_type_in
+addr-eng: record_type_out
+addr-eng: version_in
+addr-eng: version_out
+addr-eng: application_data
+addr-eng: version_min
+addr-eng: version_max
+addr-eng: suites_buf
+addr-eng: suites_num
+addr-eng: server_name
+addr-eng: client_random
+addr-eng: server_random
+addr-eng: ecdhe_curve
+addr-eng: ecdhe_point
+addr-eng: ecdhe_point_len
+addr-eng: reneg
+addr-eng: saved_finished
+addr-eng: flags
+addr-eng: pad
+addr-eng: action
+addr-eng: alert
+addr-eng: close_received
+addr-eng: protocol_names_num
+addr-eng: selected_protocol
+
+\ Similar to 'addr-eng:', for fields in the 'session' substructure.
+: addr-session-field:
+ next-word { field }
+ "addr-" field + 0 1 define-word
+ 0 8191 "offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, " field + ")" + make-CX
+ postpone literal postpone ; ;
+
+addr-session-field: session_id
+addr-session-field: session_id_len
+addr-session-field: version
+addr-session-field: cipher_suite
+addr-session-field: master_secret
+
+\ Check a server flag by index.
+: flag? ( index -- bool )
+ addr-flags get32 swap >> 1 and neg ;
+
+\ Define a word that evaluates to an error constant. This assumes that
+\ all relevant error codes are in the 0..63 range.
+: err:
+ next-word { name }
+ name 0 1 define-word
+ 0 63 "BR_" name + make-CX postpone literal postpone ; ;
+
+err: ERR_OK
+err: ERR_BAD_PARAM
+err: ERR_BAD_STATE
+err: ERR_UNSUPPORTED_VERSION
+err: ERR_BAD_VERSION
+err: ERR_BAD_LENGTH
+err: ERR_TOO_LARGE
+err: ERR_BAD_MAC
+err: ERR_NO_RANDOM
+err: ERR_UNKNOWN_TYPE
+err: ERR_UNEXPECTED
+err: ERR_BAD_CCS
+err: ERR_BAD_ALERT
+err: ERR_BAD_HANDSHAKE
+err: ERR_OVERSIZED_ID
+err: ERR_BAD_CIPHER_SUITE
+err: ERR_BAD_COMPRESSION
+err: ERR_BAD_FRAGLEN
+err: ERR_BAD_SECRENEG
+err: ERR_EXTRA_EXTENSION
+err: ERR_BAD_SNI
+err: ERR_BAD_HELLO_DONE
+err: ERR_LIMIT_EXCEEDED
+err: ERR_BAD_FINISHED
+err: ERR_RESUME_MISMATCH
+err: ERR_INVALID_ALGORITHM
+err: ERR_BAD_SIGNATURE
+err: ERR_WRONG_KEY_USAGE
+err: ERR_NO_CLIENT_AUTH
+
+\ Get supported curves (bit mask).
+cc: supported-curves ( -- x ) {
+ uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
+ T0_PUSH(x);
+}
+
+\ Get supported hash functions (bit mask and number).
+\ Note: this (on purpose) skips MD5.
+cc: supported-hash-functions ( -- x num ) {
+ int i;
+ unsigned x, num;
+
+ x = 0;
+ num = 0;
+ for (i = br_sha1_ID; i <= br_sha512_ID; i ++) {
+ if (br_multihash_getimpl(&ENG->mhash, i)) {
+ x |= 1U << i;
+ num ++;
+ }
+ }
+ T0_PUSH(x);
+ T0_PUSH(num);
+}
+
+\ Test support for RSA signatures.
+cc: supports-rsa-sign? ( -- bool ) {
+ T0_PUSHi(-(ENG->irsavrfy != 0));
+}
+
+\ Test support for ECDSA signatures.
+cc: supports-ecdsa? ( -- bool ) {
+ T0_PUSHi(-(ENG->iecdsa != 0));
+}
+
+\ (Re)initialise the multihasher.
+cc: multihash-init ( -- ) {
+ br_multihash_init(&ENG->mhash);
+}
+
+\ Flush the current record: if some payload data has been accumulated,
+\ close the record and schedule it for sending. If there is no such data,
+\ this function does nothing.
+cc: flush-record ( -- ) {
+ br_ssl_engine_flush_record(ENG);
+}
+
+\ Yield control to the caller.
+\ When the control is returned to us, react to the new context. Returned
+\ value is a bitwise combination of the following:
+\ 0x01 handshake data is available
+\ 0x02 change-cipher-spec data is available
+\ 0x04 some data other than handshake or change-cipher-spec is available
+\ 0x08 output buffer is ready for a new outgoing record
+\ 0x10 renegotiation is requested and not to be ignored
+\ Flags 0x01, 0x02 and 0x04 are mutually exclusive.
+: wait-co ( -- state )
+ co
+ 0
+ addr-action get8 dup if
+ case
+ 1 of 0 do-close endof
+ 2 of addr-application_data get8 1 = if
+ 0x10 or
+ then endof
+ endcase
+ else
+ drop
+ then
+ addr-close_received get8 ifnot
+ has-input? if
+ addr-record_type_in get8 case
+
+ \ ChangeCipherSpec
+ 20 of 0x02 or endof
+
+ \ Alert -- if close_notify received, trigger
+ \ the closure sequence.
+ 21 of process-alerts if -1 do-close then endof
+
+ \ Handshake
+ 22 of 0x01 or endof
+
+ \ Not CCS, Alert or Handshake.
+ drop 0x04 or 0
+ endcase
+ then
+ then
+ can-output? if 0x08 or then ;
+
+\ Send an alert message. This shall be called only when there is room for
+\ an outgoing record.
+: send-alert ( level alert -- )
+ 21 addr-record_type_out set8
+ swap write8-native drop write8-native drop
+ flush-record ;
+
+\ Send an alert message of level "warning". This shall be called only when
+\ there is room for an outgoing record.
+: send-warning ( alert -- )
+ 1 swap send-alert ;
+
+\ Fail by sending a fatal alert.
+: fail-alert ( alert -- ! )
+ { alert }
+ flush-record
+ begin can-output? not while wait-co drop repeat
+ 2 alert send-alert
+ begin can-output? not while wait-co drop repeat
+ alert 512 + fail ;
+
+\ Perform the close operation:
+\ -- Prevent new application data from the caller.
+\ -- Incoming data is discarded (except alerts).
+\ -- Outgoing data is flushed.
+\ -- A close_notify alert is sent.
+\ -- If 'cnr' is zero, then incoming data is discarded until a close_notify
+\ is received.
+\ -- At the end, the context is terminated.
+\
+\ cnr shall be either 0 or -1.
+: do-close ( cnr -- ! )
+ \ 'cnr' is set to non-zero when a close_notify is received from
+ \ the peer.
+ { cnr }
+
+ \ Get out of application data state. If we were accepting
+ \ application data (flag is 1), and we still expect a close_notify
+ \ from the peer (cnr is 0), then we should set the flag to 2.
+ \ In all other cases, flag should be set to 0.
+ addr-application_data get8 cnr not and 1 << addr-application_data set8
+
+ \ Flush existing payload if any.
+ flush-record
+
+ \ Wait for room to send the close_notify. Since individual records
+ \ can always hold at least 512 bytes, we know that when there is
+ \ room, then there is room for a complete close_notify (two bytes).
+ begin can-output? not while cnr wait-for-close >cnr repeat
+
+ \ Write the close_notify and flush it.
+ \ 21 addr-record_type_out set8
+ \ 1 write8-native 0 write8-native 2drop
+ \ flush-record
+ 0 send-warning
+
+ \ Loop until our record has been sent (we know it's gone when
+ \ writing is again possible) and a close_notify has been received.
+ cnr
+ begin
+ dup can-output? and if ERR_OK fail then
+ wait-for-close
+ again ;
+
+\ Yield control to the engine, with a possible flush. If 'cnr' is 0,
+\ then input is analysed: all input is discarded, until a close_notify
+\ is received.
+: wait-for-close ( cnr -- cnr )
+ co
+ dup ifnot
+ has-input? if
+ addr-record_type_in get8 21 = if
+ drop process-alerts
+ \ If we received a close_notify then we
+ \ no longer accept incoming application
+ \ data records.
+ 0 addr-application_data set8
+ else
+ discard-input
+ then
+ then
+ then ;
+
+\ Test whether there is some accumulated payload that still needs to be
+\ sent.
+cc: payload-to-send? ( -- bool ) {
+ T0_PUSHi(-br_ssl_engine_has_pld_to_send(ENG));
+}
+
+\ Test whether there is some available input data.
+cc: has-input? ( -- bool ) {
+ T0_PUSHi(-(ENG->hlen_in != 0));
+}
+
+\ Test whether some payload bytes may be written.
+cc: can-output? ( -- bool ) {
+ T0_PUSHi(-(ENG->hlen_out > 0));
+}
+
+\ Discard current input entirely.
+cc: discard-input ( -- ) {
+ ENG->hlen_in = 0;
+}
+
+\ Low-level read for one byte. If there is no available byte right
+\ away, then -1 is returned. Otherwise, the byte value is returned.
+\ If the current record type is "handshake" then the read byte is also
+\ injected in the multi-hasher.
+cc: read8-native ( -- x ) {
+ if (ENG->hlen_in > 0) {
+ unsigned char x;
+
+ x = *ENG->hbuf_in ++;
+ if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, &x, 1);
+ }
+ T0_PUSH(x);
+ ENG->hlen_in --;
+ } else {
+ T0_PUSHi(-1);
+ }
+}
+
+\ Low-level read for several bytes. On entry, this expects an address
+\ (offset in the engine context) and a length; these values designate
+\ where the chunk should go. Upon exit, the new address and length
+\ are pushed; that output length contains how many bytes could not be
+\ read. If there is no available byte for reading, the address and
+\ length are unchanged.
+\ If the current record type is "handshake" then the read bytes are
+\ injected in the multi-hasher.
+cc: read-chunk-native ( addr len -- addr len ) {
+ size_t clen = ENG->hlen_in;
+ if (clen > 0) {
+ uint32_t addr, len;
+
+ len = T0_POP();
+ addr = T0_POP();
+ if ((size_t)len < clen) {
+ clen = (size_t)len;
+ }
+ memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen);
+ if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen);
+ }
+ T0_PUSH(addr + (uint32_t)clen);
+ T0_PUSH(len - (uint32_t)clen);
+ ENG->hbuf_in += clen;
+ ENG->hlen_in -= clen;
+ }
+}
+
+\ Process available alert bytes. If a fatal alert is received, then the
+\ context is terminated; otherwise, this returns either true (-1) if a
+\ close_notify was received, false (0) otherwise.
+: process-alerts ( -- bool )
+ 0
+ begin has-input? while read8-native process-alert-byte or repeat
+ dup if 1 addr-shutdown_recv set8 then ;
+
+\ Process an alert byte. Returned value is non-zero if this is a close_notify,
+\ zero otherwise.
+: process-alert-byte ( x -- bool )
+ addr-alert get8 case
+ 0 of
+ \ 'alert' field is 0, so this byte shall be a level.
+ \ Levels shall be 1 (warning) or 2 (fatal); we convert
+ \ all other values to "fatal".
+ dup 1 <> if drop 2 then
+ addr-alert set8 0
+ endof
+ 1 of
+ 0 addr-alert set8
+ \ close_notify has value 0.
+ \ no_renegotiation has value 100, and we treat it
+ \ as a fatal alert.
+ dup 100 = if 256 + fail then
+ 0=
+ endof
+ \ Fatal alert implies context termination.
+ drop 256 + fail
+ endcase ;
+
+\ In general we only deal with handshake data here. Alerts are processed
+\ in specific code right when they are received, and ChangeCipherSpec has
+\ its own handling code. So we need to check that the data is "handshake"
+\ only when returning from a coroutine call.
+
+\ Yield control to the engine. Alerts are processed; if incoming data is
+\ neither handshake or alert, then an error is triggered.
+: wait-for-handshake ( -- )
+ wait-co 0x07 and 0x01 > if ERR_UNEXPECTED fail then ;
+
+\ Flush outgoing data (if any), then wait for the output buffer to be
+\ clear; when this is done, set the output record type to the specified
+\ value.
+: wait-rectype-out ( rectype -- )
+ { rectype }
+ flush-record
+ begin
+ can-output? if rectype addr-record_type_out set8 ret then
+ wait-co drop
+ again ;
+
+\ Read one byte of handshake data. Block until that byte is available.
+\ This does not check any length.
+: read8-nc ( -- x )
+ begin
+ read8-native dup 0< ifnot ret then
+ drop wait-for-handshake
+ again ;
+
+\ Test whether there are some more bytes in the current record. These
+\ bytes have not necessarily been received yet (processing of unencrypted
+\ records may begin before all bytes are received).
+cc: more-incoming-bytes? ( -- bool ) {
+ T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
+}
+
+\ For reading functions, the TOS is supposed to contain the number of bytes
+\ that can still be read (from encapsulating structure header), and it is
+\ updated.
+
+: check-len ( lim len -- lim )
+ - dup 0< if ERR_BAD_PARAM fail then ;
+
+\ Read one byte of handshake data. This pushes an integer in the 0..255 range.
+: read8 ( lim -- lim x )
+ 1 check-len read8-nc ;
+
+\ Read a 16-bit value (in the 0..65535 range)
+: read16 ( lim -- lim n )
+ 2 check-len read8-nc 8 << read8-nc + ;
+
+\ Read a 24-bit value (in the 0..16777215 range)
+: read24 ( lim -- lim n )
+ 3 check-len read8-nc 8 << read8-nc + 8 << read8-nc + ;
+
+\ Read some bytes. The "address" is an offset within the context
+\ structure.
+: read-blob ( lim addr len -- lim )
+ { addr len }
+ len check-len
+ addr len
+ begin
+ read-chunk-native
+ dup 0 = if 2drop ret then
+ wait-for-handshake
+ again ;
+
+\ Read some bytes and drop them.
+: skip-blob ( lim len -- lim )
+ swap over check-len swap
+ begin dup while read8-nc drop 1- repeat
+ drop ;
+
+\ Read a 16-bit length, then skip exactly that many bytes.
+: read-ignore-16 ( lim -- lim )
+ read16 skip-blob ;
+
+\ Open a substructure: the inner structure length is checked against,
+\ and subtracted, from the output structure current limit.
+: open-elt ( lim len -- lim-outer lim-inner )
+ dup { len }
+ - dup 0< if ERR_BAD_PARAM fail then
+ len ;
+
+\ Close the current structure. This checks that the limit is 0.
+: close-elt ( lim -- )
+ if ERR_BAD_PARAM fail then ;
+
+\ Write one byte of handshake data.
+: write8 ( n -- )
+ begin
+ dup write8-native if drop ret then
+ wait-co drop
+ again ;
+
+\ Low-level write for one byte. On exit, it pushes either -1 (byte was
+\ written) or 0 (no room in output buffer).
+cc: write8-native ( x -- bool ) {
+ unsigned char x;
+
+ x = (unsigned char)T0_POP();
+ if (ENG->hlen_out > 0) {
+ if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, &x, 1);
+ }
+ *ENG->hbuf_out ++ = x;
+ ENG->hlen_out --;
+ T0_PUSHi(-1);
+ } else {
+ T0_PUSHi(0);
+ }
+}
+
+\ Write a 16-bit value.
+: write16 ( n -- )
+ dup 8 u>> write8 write8 ;
+
+\ Write a 24-bit value.
+: write24 ( n -- )
+ dup 16 u>> write8 write16 ;
+
+\ Write some bytes. The "address" is an offset within the context
+\ structure.
+: write-blob ( addr len -- )
+ begin
+ write-blob-chunk
+ dup 0 = if 2drop ret then
+ wait-co drop
+ again ;
+
+cc: write-blob-chunk ( addr len -- addr len ) {
+ size_t clen = ENG->hlen_out;
+ if (clen > 0) {
+ uint32_t addr, len;
+
+ len = T0_POP();
+ addr = T0_POP();
+ if ((size_t)len < clen) {
+ clen = (size_t)len;
+ }
+ memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen);
+ if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen);
+ }
+ T0_PUSH(addr + (uint32_t)clen);
+ T0_PUSH(len - (uint32_t)clen);
+ ENG->hbuf_out += clen;
+ ENG->hlen_out -= clen;
+ }
+}
+
+\ Write a blob with the length as header (over one byte)
+: write-blob-head8 ( addr len -- )
+ dup write8 write-blob ;
+
+\ Write a blob with the length as header (over two bytes)
+: write-blob-head16 ( addr len -- )
+ dup write16 write-blob ;
+
+\ Perform a byte-to-byte comparison between two blobs. Each blob is
+\ provided as an "address" (offset in the context structure); the
+\ length is common. Returned value is true (-1) if the two blobs are
+\ equal, false (0) otherwise.
+cc: memcmp ( addr1 addr2 len -- bool ) {
+ size_t len = (size_t)T0_POP();
+ void *addr2 = (unsigned char *)ENG + (size_t)T0_POP();
+ void *addr1 = (unsigned char *)ENG + (size_t)T0_POP();
+ int x = memcmp(addr1, addr2, len);
+ T0_PUSH((uint32_t)-(x == 0));
+}
+
+\ Copy bytes between two areas, whose addresses are provided as
+\ offsets in the context structure.
+cc: memcpy ( dst src len -- ) {
+ size_t len = (size_t)T0_POP();
+ void *src = (unsigned char *)ENG + (size_t)T0_POP();
+ void *dst = (unsigned char *)ENG + (size_t)T0_POP();
+ memcpy(dst, src, len);
+}
+
+\ Get string length (zero-terminated). The string address is provided as
+\ an offset relative to the context start. Returned length does not include
+\ the terminated 0.
+cc: strlen ( str -- len ) {
+ void *str = (unsigned char *)ENG + (size_t)T0_POP();
+ T0_PUSH((uint32_t)strlen(str));
+}
+
+\ Fill a buffer with zeros. The buffer address is an offset in the context.
+cc: bzero ( addr len -- ) {
+ size_t len = (size_t)T0_POP();
+ void *addr = (unsigned char *)ENG + (size_t)T0_POP();
+ memset(addr, 0, len);
+}
+
+\ Scan the list of supported cipher suites for a given value. If found,
+\ then the list index at which it was found is returned; otherwise, -1
+\ is returned.
+: scan-suite ( suite -- index )
+ { suite }
+ addr-suites_num get8 { num }
+ 0
+ begin dup num < while
+ dup 1 << addr-suites_buf + get16 suite = if ret then
+ 1+
+ repeat
+ drop -1 ;
+
+\ =======================================================================
+
+\ Generate random bytes into buffer (address is offset in context).
+cc: mkrand ( addr len -- ) {
+ size_t len = (size_t)T0_POP();
+ void *addr = (unsigned char *)ENG + (size_t)T0_POP();
+ br_hmac_drbg_generate(&ENG->rng, addr, len);
+}
+
+\ Read a handshake message header: type and length. These are returned
+\ in reverse order (type is TOS, length is below it).
+: read-handshake-header-core ( -- lim type )
+ read8-nc 3 read24 swap drop swap ;
+
+\ Read a handshake message header: type and length. If the header is for
+\ a HelloRequest message, then it is discarded and a new header is read
+\ (repeatedly if necessary).
+: read-handshake-header ( -- lim type )
+ begin
+ read-handshake-header-core dup 0= while
+ drop if ERR_BAD_HANDSHAKE fail then
+ repeat ;
+
+\ =======================================================================
+
+\ Cipher suite processing.
+\
+\ Unfortunately, cipher suite identifiers are attributed mostly arbitrary,
+\ so we have to map the cipher suite numbers we support into aggregate
+\ words that encode the information we need. Table below is organized
+\ as a sequence of pairs of 16-bit words, the first being the cipher suite
+\ identifier, the second encoding the algorithm elements. The suites are
+\ ordered by increasing cipher suite ID, so that fast lookups may be
+\ performed with a binary search (not implemented for the moment, since it
+\ does not appear to matter much in practice).
+\
+\ Algorithm elements are encoded over 4 bits each, in the following order
+\ (most significant to least significant):
+\
+\ -- Server key type:
+\ 0 RSA (RSA key exchange)
+\ 1 ECDHE-RSA (ECDHE key exchange, RSA signature)
+\ 2 ECDHE-ECDSA (ECDHE key exchange, ECDSA signature)
+\ 3 ECDH-RSA (ECDH key exchange, certificate is RSA-signed)
+\ 4 ECDH-ECDSA (ECDH key exchange, certificate is ECDSA-signed)
+\ -- Encryption algorithm:
+\ 0 3DES/CBC
+\ 1 AES-128/CBC
+\ 2 AES-256/CBC
+\ 3 AES-128/GCM
+\ 4 AES-256/GCM
+\ 5 ChaCha20/Poly1305
+\ 6 AES-128/CCM
+\ 7 AES-256/CCM
+\ 8 AES-128/CCM8
+\ 9 AES-256/CCM8
+\ -- MAC algorithm:
+\ 0 none (for suites with AEAD encryption)
+\ 2 HMAC/SHA-1
+\ 4 HMAC/SHA-256
+\ 5 HMAC/SHA-384
+\ -- PRF for TLS-1.2:
+\ 4 with SHA-256
+\ 5 with SHA-384
+\
+\ WARNING: if adding a new cipher suite that does not use SHA-256 for the
+\ PRF (with TLS 1.2), be sure to check the suites_sha384[] array defined
+\ in ssl/ssl_keyexport.c
+
+data: cipher-suite-def
+
+hexb| 000A 0024 | \ TLS_RSA_WITH_3DES_EDE_CBC_SHA
+hexb| 002F 0124 | \ TLS_RSA_WITH_AES_128_CBC_SHA
+hexb| 0035 0224 | \ TLS_RSA_WITH_AES_256_CBC_SHA
+hexb| 003C 0144 | \ TLS_RSA_WITH_AES_128_CBC_SHA256
+hexb| 003D 0244 | \ TLS_RSA_WITH_AES_256_CBC_SHA256
+
+hexb| 009C 0304 | \ TLS_RSA_WITH_AES_128_GCM_SHA256
+hexb| 009D 0405 | \ TLS_RSA_WITH_AES_256_GCM_SHA384
+
+hexb| C003 4024 | \ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+hexb| C004 4124 | \ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+hexb| C005 4224 | \ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+hexb| C008 2024 | \ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+hexb| C009 2124 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+hexb| C00A 2224 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+hexb| C00D 3024 | \ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+hexb| C00E 3124 | \ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+hexb| C00F 3224 | \ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+hexb| C012 1024 | \ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+hexb| C013 1124 | \ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+hexb| C014 1224 | \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+
+hexb| C023 2144 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+hexb| C024 2255 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+hexb| C025 4144 | \ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+hexb| C026 4255 | \ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+hexb| C027 1144 | \ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+hexb| C028 1255 | \ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+hexb| C029 3144 | \ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+hexb| C02A 3255 | \ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+hexb| C02B 2304 | \ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+hexb| C02C 2405 | \ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+hexb| C02D 4304 | \ TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+hexb| C02E 4405 | \ TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+hexb| C02F 1304 | \ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+hexb| C030 1405 | \ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+hexb| C031 3304 | \ TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+hexb| C032 3405 | \ TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+
+hexb| C09C 0604 | \ TLS_RSA_WITH_AES_128_CCM
+hexb| C09D 0704 | \ TLS_RSA_WITH_AES_256_CCM
+hexb| C0A0 0804 | \ TLS_RSA_WITH_AES_128_CCM_8
+hexb| C0A1 0904 | \ TLS_RSA_WITH_AES_256_CCM_8
+hexb| C0AC 2604 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CCM
+hexb| C0AD 2704 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CCM
+hexb| C0AE 2804 | \ TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+hexb| C0AF 2904 | \ TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8
+
+hexb| CCA8 1504 | \ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+hexb| CCA9 2504 | \ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+
+hexb| 0000 | \ List terminator.
+
+\ Convert cipher suite identifier to element words. This returns 0 if
+\ the cipher suite is not known.
+: cipher-suite-to-elements ( suite -- elts )
+ { id }
+ cipher-suite-def
+ begin
+ dup 2+ swap data-get16
+ dup ifnot 2drop 0 ret then
+ id = if data-get16 ret then
+ 2+
+ again ;
+
+\ Check that a given cipher suite is supported. Note that this also
+\ returns true (-1) for the TLS_FALLBACK_SCSV pseudo-ciphersuite.
+: suite-supported? ( suite -- bool )
+ dup 0x5600 = if drop -1 ret then
+ cipher-suite-to-elements 0<> ;
+
+\ Get expected key type for cipher suite. The key type is one of
+\ BR_KEYTYPE_RSA or BR_KEYTYPE_EC, combined with either BR_KEYTYPE_KEYX
+\ (RSA encryption or static ECDH) or BR_KEYTYPE_SIGN (RSA or ECDSA
+\ signature, for ECDHE cipher suites).
+: expected-key-type ( suite -- key-type )
+ cipher-suite-to-elements 12 >>
+ case
+ 0 of CX 0 63 { BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX } endof
+ 1 of CX 0 63 { BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN } endof
+ 2 of CX 0 63 { BR_KEYTYPE_EC | BR_KEYTYPE_SIGN } endof
+ 3 of CX 0 63 { BR_KEYTYPE_EC | BR_KEYTYPE_KEYX } endof
+ 4 of CX 0 63 { BR_KEYTYPE_EC | BR_KEYTYPE_KEYX } endof
+ 0 swap
+ endcase ;
+
+\ Test whether the cipher suite uses RSA key exchange.
+: use-rsa-keyx? ( suite -- bool )
+ cipher-suite-to-elements 12 >> 0= ;
+
+\ Test whether the cipher suite uses ECDHE key exchange, signed with RSA.
+: use-rsa-ecdhe? ( suite -- bool )
+ cipher-suite-to-elements 12 >> 1 = ;
+
+\ Test whether the cipher suite uses ECDHE key exchange, signed with ECDSA.
+: use-ecdsa-ecdhe? ( suite -- bool )
+ cipher-suite-to-elements 12 >> 2 = ;
+
+\ Test whether the cipher suite uses ECDHE key exchange (with RSA or ECDSA).
+: use-ecdhe? ( suite -- bool )
+ cipher-suite-to-elements 12 >> dup 0> swap 3 < and ;
+
+\ Test whether the cipher suite uses ECDH (static) key exchange.
+: use-ecdh? ( suite -- bool )
+ cipher-suite-to-elements 12 >> 2 > ;
+
+\ Get identifier for the PRF (TLS 1.2).
+: prf-id ( suite -- id )
+ cipher-suite-to-elements 15 and ;
+
+\ Test whether a cipher suite is only for TLS-1.2. Cipher suites that
+\ can be used with TLS-1.0 or 1.1 use HMAC/SHA-1. RFC do not formally
+\ forbid using a CBC-based TLS-1.2 cipher suite, e.g. based on HMAC/SHA-256,
+\ with older protocol versions; however, servers should not do that, since
+\ it may confuse clients. Since the server code does not try such games,
+\ for consistency, the client should reject it as well (normal servers
+\ don't do that, so any attempt is a sign of foul play).
+: use-tls12? ( suite -- bool )
+ cipher-suite-to-elements 0xF0 and 0x20 <> ;
+
+\ Switch to negotiated security parameters for input or output.
+: switch-encryption ( is-client for-input -- )
+ { for-input }
+ addr-cipher_suite get16 cipher-suite-to-elements { elts }
+
+ \ prf_id
+ elts 15 and
+
+ \ mac_id
+ elts 4 >> 15 and
+
+ \ cipher type and key length
+ elts 8 >> 15 and case
+ \ 3DES/CBC
+ 0 of 0 24
+ for-input if
+ switch-cbc-in
+ else
+ switch-cbc-out
+ then
+ endof
+
+ \ AES-128/CBC
+ 1 of 1 16
+ for-input if
+ switch-cbc-in
+ else
+ switch-cbc-out
+ then
+ endof
+
+ \ AES-256/CBC
+ 2 of 1 32
+ for-input if
+ switch-cbc-in
+ else
+ switch-cbc-out
+ then
+ endof
+
+ \ AES-128/GCM
+ 3 of drop 16
+ for-input if
+ switch-aesgcm-in
+ else
+ switch-aesgcm-out
+ then
+ endof
+
+ \ AES-256/GCM
+ 4 of drop 32
+ for-input if
+ switch-aesgcm-in
+ else
+ switch-aesgcm-out
+ then
+ endof
+
+ \ ChaCha20+Poly1305
+ 5 of drop
+ for-input if
+ switch-chapol-in
+ else
+ switch-chapol-out
+ then
+ endof
+
+ \ Now we only have AES/CCM suites (6 to 9). Since the
+ \ input is between 0 and 15, and we checked values 0 to 5,
+ \ we only need to reject values larger than 9.
+ dup 9 > if
+ ERR_BAD_PARAM fail
+ then
+
+ \ Stack: is_client prf_id mac_id cipher_id
+ \ We want to remove the mac_id (it is zero for CCM suites)
+ \ and replace the cipher_id with the key and tag lengths.
+ \ The following table applies:
+ \ id key length tag length
+ \ 6 16 16
+ \ 7 32 16
+ \ 8 16 8
+ \ 9 32 8
+ swap drop
+ dup 1 and 4 << 16 + swap
+ 8 and 16 swap -
+ for-input if
+ switch-aesccm-in
+ else
+ switch-aesccm-out
+ then
+ ret
+ endcase
+ ;
+
+cc: switch-cbc-out ( is_client prf_id mac_id aes cipher_key_len -- ) {
+ int is_client, prf_id, mac_id, aes;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ aes = T0_POP();
+ mac_id = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id,
+ aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len);
+}
+
+cc: switch-cbc-in ( is_client prf_id mac_id aes cipher_key_len -- ) {
+ int is_client, prf_id, mac_id, aes;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ aes = T0_POP();
+ mac_id = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id,
+ aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len);
+}
+
+cc: switch-aesgcm-out ( is_client prf_id cipher_key_len -- ) {
+ int is_client, prf_id;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id,
+ ENG->iaes_ctr, cipher_key_len);
+}
+
+cc: switch-aesgcm-in ( is_client prf_id cipher_key_len -- ) {
+ int is_client, prf_id;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id,
+ ENG->iaes_ctr, cipher_key_len);
+}
+
+cc: switch-chapol-out ( is_client prf_id -- ) {
+ int is_client, prf_id;
+
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id);
+}
+
+cc: switch-chapol-in ( is_client prf_id -- ) {
+ int is_client, prf_id;
+
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id);
+}
+
+cc: switch-aesccm-out ( is_client prf_id cipher_key_len tag_len -- ) {
+ int is_client, prf_id;
+ unsigned cipher_key_len, tag_len;
+
+ tag_len = T0_POP();
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id,
+ ENG->iaes_ctrcbc, cipher_key_len, tag_len);
+}
+
+cc: switch-aesccm-in ( is_client prf_id cipher_key_len tag_len -- ) {
+ int is_client, prf_id;
+ unsigned cipher_key_len, tag_len;
+
+ tag_len = T0_POP();
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id,
+ ENG->iaes_ctrcbc, cipher_key_len, tag_len);
+}
+
+\ Write Finished message.
+: write-Finished ( from_client -- )
+ compute-Finished
+ 20 write8 12 write24 addr-pad 12 write-blob ;
+
+\ Read Finished message.
+: read-Finished ( from_client -- )
+ compute-Finished
+ read-handshake-header 20 <> if ERR_UNEXPECTED fail then
+ addr-pad 12 + 12 read-blob
+ close-elt
+ addr-pad dup 12 + 12 memcmp ifnot ERR_BAD_FINISHED fail then ;
+
+\ Compute the "Finished" contents (either the value to send, or the
+\ expected value). The 12-byte string is written in the pad. The
+\ "from_client" value is non-zero for the Finished sent by the client.
+\ The computed value is also saved in the relevant buffer for handling
+\ secure renegotiation.
+: compute-Finished ( from_client -- )
+ dup addr-saved_finished swap ifnot 12 + then swap
+ addr-cipher_suite get16 prf-id compute-Finished-inner
+ addr-pad 12 memcpy ;
+
+cc: compute-Finished-inner ( from_client prf_id -- ) {
+ int prf_id = T0_POP();
+ int from_client = T0_POPi();
+ unsigned char tmp[48];
+ br_tls_prf_seed_chunk seed;
+
+ br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id);
+ seed.data = tmp;
+ if (ENG->session.version >= BR_TLS12) {
+ seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp);
+ } else {
+ br_multihash_out(&ENG->mhash, br_md5_ID, tmp);
+ br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16);
+ seed.len = 36;
+ }
+ prf(ENG->pad, 12, ENG->session.master_secret,
+ sizeof ENG->session.master_secret,
+ from_client ? "client finished" : "server finished",
+ 1, &seed);
+}
+
+\ Receive ChangeCipherSpec and Finished from the peer.
+: read-CCS-Finished ( is-client -- )
+ has-input? if
+ addr-record_type_in get8 20 <> if ERR_UNEXPECTED fail then
+ else
+ begin
+ wait-co 0x07 and dup 0x02 <> while
+ if ERR_UNEXPECTED fail then
+ repeat
+ drop
+ then
+ read8-nc 1 <> more-incoming-bytes? or if ERR_BAD_CCS fail then
+ dup 1 switch-encryption
+
+ \ Read and verify Finished from peer.
+ not read-Finished ;
+
+\ Send ChangeCipherSpec and Finished to the peer.
+: write-CCS-Finished ( is-client -- )
+ \ Flush and wait for output buffer to be clear, so that we may
+ \ write our ChangeCipherSpec. We must switch immediately after
+ \ triggering the flush.
+ 20 wait-rectype-out
+ 1 write8
+ flush-record
+ dup 0 switch-encryption
+ 22 wait-rectype-out
+ write-Finished
+ flush-record ;
+
+\ Read and parse a list of supported signature algorithms (with hash
+\ functions). The resulting bit field is returned.
+: read-list-sign-algos ( lim -- lim value )
+ 0 { hashes }
+ read16 open-elt
+ begin dup while
+ read8 { hash } read8 { sign }
+
+ \ If hash is 0x08 then this is a "new algorithm" identifier,
+ \ and we set the corresponding bit if it is in the 0..15
+ \ range. Otherwise, we keep the value only if the signature
+ \ is either 1 (RSA) or 3 (ECDSA), and the hash is one of the
+ \ SHA-* functions (2 to 6). Note that we reject MD5.
+ hash 8 = if
+ sign 15 <= if
+ 1 sign 16 + << hashes or >hashes
+ then
+ else
+ hash 2 >= hash 6 <= and
+ sign 1 = sign 3 = or
+ and if
+ hashes 1 sign 1- 2 << hash + << or >hashes
+ then
+ then
+ repeat
+ close-elt
+ hashes ;
+
+\ =======================================================================
+
+\ Compute total chain length. This includes the individual certificate
+\ headers, but not the total chain header. This also sets the cert_cur,
+\ cert_len and chain_len context fields.
+cc: total-chain-length ( -- len ) {
+ size_t u;
+ uint32_t total;
+
+ total = 0;
+ for (u = 0; u < ENG->chain_len; u ++) {
+ total += 3 + (uint32_t)ENG->chain[u].data_len;
+ }
+ T0_PUSH(total);
+}
+
+\ Get length for current certificate in the chain; if the chain end was
+\ reached, then this returns -1.
+cc: begin-cert ( -- len ) {
+ if (ENG->chain_len == 0) {
+ T0_PUSHi(-1);
+ } else {
+ ENG->cert_cur = ENG->chain->data;
+ ENG->cert_len = ENG->chain->data_len;
+ ENG->chain ++;
+ ENG->chain_len --;
+ T0_PUSH(ENG->cert_len);
+ }
+}
+
+\ Copy a chunk of certificate data into the pad. Returned value is the
+\ chunk length, or 0 if the certificate end is reached.
+cc: copy-cert-chunk ( -- len ) {
+ size_t clen;
+
+ clen = ENG->cert_len;
+ if (clen > sizeof ENG->pad) {
+ clen = sizeof ENG->pad;
+ }
+ memcpy(ENG->pad, ENG->cert_cur, clen);
+ ENG->cert_cur += clen;
+ ENG->cert_len -= clen;
+ T0_PUSH(clen);
+}
+
+\ Write a Certificate message. Total chain length (excluding the 3-byte
+\ header) is returned; it is 0 if the chain is empty.
+: write-Certificate ( -- total_chain_len )
+ 11 write8
+ total-chain-length dup
+ dup 3 + write24 write24
+ begin
+ begin-cert
+ dup 0< if drop ret then write24
+ begin copy-cert-chunk dup while
+ addr-pad swap write-blob
+ repeat
+ drop
+ again ;
+
+cc: x509-start-chain ( by_client -- ) {
+ const br_x509_class *xc;
+ uint32_t bc;
+
+ bc = T0_POP();
+ xc = *(ENG->x509ctx);
+ xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL);
+}
+
+cc: x509-start-cert ( length -- ) {
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ xc->start_cert(ENG->x509ctx, T0_POP());
+}
+
+cc: x509-append ( length -- ) {
+ const br_x509_class *xc;
+ size_t len;
+
+ xc = *(ENG->x509ctx);
+ len = T0_POP();
+ xc->append(ENG->x509ctx, ENG->pad, len);
+}
+
+cc: x509-end-cert ( -- ) {
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ xc->end_cert(ENG->x509ctx);
+}
+
+cc: x509-end-chain ( -- err ) {
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ T0_PUSH(xc->end_chain(ENG->x509ctx));
+}
+
+cc: get-key-type-usages ( -- key-type-usages ) {
+ const br_x509_class *xc;
+ const br_x509_pkey *pk;
+ unsigned usages;
+
+ xc = *(ENG->x509ctx);
+ pk = xc->get_pkey(ENG->x509ctx, &usages);
+ if (pk == NULL) {
+ T0_PUSH(0);
+ } else {
+ T0_PUSH(pk->key_type | usages);
+ }
+}
+
+\ Read a Certificate message.
+\ Parameter: non-zero if this is a read by the client of a certificate
+\ sent by the server; zero otherwise.
+\ Returned value:
+\ - Empty: 0
+\ - Valid: combination of key type and allowed key usages.
+\ - Invalid: negative (-x for error code x)
+: read-Certificate ( by_client -- key-type-usages )
+ \ Get header, and check message type.
+ read-handshake-header 11 = ifnot ERR_UNEXPECTED fail then
+
+ \ If the chain is empty, do some special processing.
+ dup 3 = if
+ read24 if ERR_BAD_PARAM fail then
+ swap drop ret
+ then
+
+ \ Start processing the chain through the X.509 engine.
+ swap x509-start-chain
+
+ \ Total chain length is a 24-bit integer.
+ read24 open-elt
+ begin
+ dup while
+ read24 open-elt
+ dup x509-start-cert
+
+ \ We read the certificate by chunks through the pad, so
+ \ as to use the existing reading function (read-blob)
+ \ that also ensures proper hashing.
+ begin
+ dup while
+ dup 256 > if 256 else dup then { len }
+ addr-pad len read-blob
+ len x509-append
+ repeat
+ close-elt
+ x509-end-cert
+ repeat
+
+ \ We must close the chain AND the handshake message.
+ close-elt
+ close-elt
+
+ \ Chain processing is finished; get the error code.
+ x509-end-chain
+ dup if neg ret then drop
+
+ \ Return key type and usages.
+ get-key-type-usages ;
+
+\ =======================================================================
+
+\ Copy a specific protocol name from the list to the pad. The byte
+\ length is returned.
+cc: copy-protocol-name ( idx -- len ) {
+ size_t idx = T0_POP();
+ size_t len = strlen(ENG->protocol_names[idx]);
+ memcpy(ENG->pad, ENG->protocol_names[idx], len);
+ T0_PUSH(len);
+}
+
+\ Compare name in pad with the configured list of protocol names.
+\ If a match is found, then the index is returned; otherwise, -1
+\ is returned.
+cc: test-protocol-name ( len -- n ) {
+ size_t len = T0_POP();
+ size_t u;
+
+ for (u = 0; u < ENG->protocol_names_num; u ++) {
+ const char *name;
+
+ name = ENG->protocol_names[u];
+ if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) {
+ T0_PUSH(u);
+ T0_RET();
+ }
+ }
+ T0_PUSHi(-1);
+}
Index: stable/12/contrib/bearssl/src/ssl/ssl_hs_server.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_hs_server.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_hs_server.c (revision 346145)
@@ -0,0 +1,2009 @@
+/* Automatically generated code; do not modify directly. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+} t0_context;
+
+static uint32_t
+t0_parse7E_unsigned(const unsigned char **p)
+{
+ uint32_t x;
+
+ x = 0;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ return x;
+ }
+ }
+}
+
+static int32_t
+t0_parse7E_signed(const unsigned char **p)
+{
+ int neg;
+ uint32_t x;
+
+ neg = ((**p) >> 6) & 1;
+ x = (uint32_t)-neg;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ if (neg) {
+ return -(int32_t)~x - 1;
+ } else {
+ return (int32_t)x;
+ }
+ }
+ }
+}
+
+#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
+#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
+#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
+#define T0_INT1(x) T0_FBYTE(x, 0)
+#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+
+/* static const unsigned char t0_datablock[]; */
+
+
+void br_ssl_hs_server_init_main(void *t0ctx);
+
+void br_ssl_hs_server_run(void *t0ctx);
+
+
+
+#include <stddef.h>
+#include <string.h>
+
+#include "inner.h"
+
+/*
+ * This macro evaluates to a pointer to the current engine context.
+ */
+#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu)))
+
+
+
+
+
+/*
+ * This macro evaluates to a pointer to the server context, under that
+ * specific name. It must be noted that since the engine context is the
+ * first field of the br_ssl_server_context structure ('eng'), then
+ * pointers values of both types are interchangeable, modulo an
+ * appropriate cast. This also means that "addresses" computed as offsets
+ * within the structure work for both kinds of context.
+ */
+#define CTX ((br_ssl_server_context *)ENG)
+
+/*
+ * Decrypt the pre-master secret (RSA key exchange).
+ */
+static void
+do_rsa_decrypt(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *epms, size_t len)
+{
+ uint32_t x;
+ unsigned char rpms[48];
+
+ /*
+ * Decrypt the PMS.
+ */
+ x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, epms, &len);
+
+ /*
+ * Set the first two bytes to the maximum supported client
+ * protocol version. These bytes are used for version rollback
+ * detection; forceing the two bytes will make the master secret
+ * wrong if the bytes are not correct. This process is
+ * recommended by RFC 5246 (section 7.4.7.1).
+ */
+ br_enc16be(epms, ctx->client_max_version);
+
+ /*
+ * Make a random PMS and copy it above the decrypted value if the
+ * decryption failed. Note that we use a constant-time conditional
+ * copy.
+ */
+ br_hmac_drbg_generate(&ctx->eng.rng, rpms, sizeof rpms);
+ br_ccopy(x ^ 1, epms, rpms, sizeof rpms);
+
+ /*
+ * Compute master secret.
+ */
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, epms, 48);
+
+ /*
+ * Clear the pre-master secret from RAM: it is normally a buffer
+ * in the context, hence potentially long-lived.
+ */
+ memset(epms, 0, len);
+}
+
+/*
+ * Common part for ECDH and ECDHE.
+ */
+static void
+ecdh_common(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *xcoor, size_t xcoor_len, uint32_t ctl)
+{
+ unsigned char rpms[80];
+
+ if (xcoor_len > sizeof rpms) {
+ xcoor_len = sizeof rpms;
+ ctl = 0;
+ }
+
+ /*
+ * Make a random PMS and copy it above the decrypted value if the
+ * decryption failed. Note that we use a constant-time conditional
+ * copy.
+ */
+ br_hmac_drbg_generate(&ctx->eng.rng, rpms, xcoor_len);
+ br_ccopy(ctl ^ 1, xcoor, rpms, xcoor_len);
+
+ /*
+ * Compute master secret.
+ */
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, xcoor, xcoor_len);
+
+ /*
+ * Clear the pre-master secret from RAM: it is normally a buffer
+ * in the context, hence potentially long-lived.
+ */
+ memset(xcoor, 0, xcoor_len);
+}
+
+/*
+ * Do the ECDH key exchange (not ECDHE).
+ */
+static void
+do_ecdh(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *cpoint, size_t cpoint_len)
+{
+ uint32_t x;
+
+ /*
+ * Finalise the key exchange.
+ */
+ x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable,
+ cpoint, &cpoint_len);
+ ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
+}
+
+/*
+ * Do the full static ECDH key exchange. When this function is called,
+ * it has already been verified that the cipher suite uses ECDH (not ECDHE),
+ * and the client's public key (from its certificate) has type EC and is
+ * apt for key exchange.
+ */
+static void
+do_static_ecdh(br_ssl_server_context *ctx, int prf_id)
+{
+ unsigned char cpoint[133];
+ size_t cpoint_len;
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ cpoint_len = pk->key.ec.qlen;
+ if (cpoint_len > sizeof cpoint) {
+ /*
+ * If the point is larger than our buffer then we need to
+ * restrict it. Length 2 is not a valid point length, so
+ * the ECDH will fail.
+ */
+ cpoint_len = 2;
+ }
+ memcpy(cpoint, pk->key.ec.q, cpoint_len);
+ do_ecdh(ctx, prf_id, cpoint, cpoint_len);
+}
+
+static size_t
+hash_data(br_ssl_server_context *ctx,
+ void *dst, int hash_id, const void *src, size_t len)
+{
+ const br_hash_class *hf;
+ br_hash_compat_context hc;
+
+ if (hash_id == 0) {
+ unsigned char tmp[36];
+
+ hf = br_multihash_getimpl(&ctx->eng.mhash, br_md5_ID);
+ if (hf == NULL) {
+ return 0;
+ }
+ hf->init(&hc.vtable);
+ hf->update(&hc.vtable, src, len);
+ hf->out(&hc.vtable, tmp);
+ hf = br_multihash_getimpl(&ctx->eng.mhash, br_sha1_ID);
+ if (hf == NULL) {
+ return 0;
+ }
+ hf->init(&hc.vtable);
+ hf->update(&hc.vtable, src, len);
+ hf->out(&hc.vtable, tmp + 16);
+ memcpy(dst, tmp, 36);
+ return 36;
+ } else {
+ hf = br_multihash_getimpl(&ctx->eng.mhash, hash_id);
+ if (hf == NULL) {
+ return 0;
+ }
+ hf->init(&hc.vtable);
+ hf->update(&hc.vtable, src, len);
+ hf->out(&hc.vtable, dst);
+ return (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+ }
+}
+
+/*
+ * Do the ECDHE key exchange (part 1: generation of transient key, and
+ * computing of the point to send to the client). Returned value is the
+ * signature length (in bytes), or -x on error (with x being an error
+ * code). The encoded point is written in the ecdhe_point[] context buffer
+ * (length in ecdhe_point_len).
+ */
+static int
+do_ecdhe_part1(br_ssl_server_context *ctx, int curve)
+{
+ unsigned algo_id;
+ unsigned mask;
+ const unsigned char *order;
+ size_t olen, glen;
+ size_t hv_len, sig_len;
+
+ if (!((ctx->eng.iec->supported_curves >> curve) & 1)) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+ ctx->eng.ecdhe_curve = curve;
+
+ /*
+ * Generate our private key. We need a non-zero random value
+ * which is lower than the curve order, in a "large enough"
+ * range. We force the top bit to 0 and bottom bit to 1, which
+ * does the trick. Note that contrary to what happens in ECDSA,
+ * this is not a problem if we do not cover the full range of
+ * possible values.
+ */
+ order = ctx->eng.iec->order(curve, &olen);
+ mask = 0xFF;
+ while (mask >= order[0]) {
+ mask >>= 1;
+ }
+ br_hmac_drbg_generate(&ctx->eng.rng, ctx->ecdhe_key, olen);
+ ctx->ecdhe_key[0] &= mask;
+ ctx->ecdhe_key[olen - 1] |= 0x01;
+ ctx->ecdhe_key_len = olen;
+
+ /*
+ * Compute our ECDH point.
+ */
+ glen = ctx->eng.iec->mulgen(ctx->eng.ecdhe_point,
+ ctx->ecdhe_key, olen, curve);
+ ctx->eng.ecdhe_point_len = glen;
+
+ /*
+ * Assemble the message to be signed, and possibly hash it.
+ */
+ memcpy(ctx->eng.pad, ctx->eng.client_random, 32);
+ memcpy(ctx->eng.pad + 32, ctx->eng.server_random, 32);
+ ctx->eng.pad[64 + 0] = 0x03;
+ ctx->eng.pad[64 + 1] = 0x00;
+ ctx->eng.pad[64 + 2] = curve;
+ ctx->eng.pad[64 + 3] = ctx->eng.ecdhe_point_len;
+ memcpy(ctx->eng.pad + 64 + 4,
+ ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len);
+ hv_len = 64 + 4 + ctx->eng.ecdhe_point_len;
+ algo_id = ctx->sign_hash_id;
+ if (algo_id >= (unsigned)0xFF00) {
+ hv_len = hash_data(ctx, ctx->eng.pad, algo_id & 0xFF,
+ ctx->eng.pad, hv_len);
+ if (hv_len == 0) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+ }
+
+ sig_len = (*ctx->policy_vtable)->do_sign(ctx->policy_vtable,
+ algo_id, ctx->eng.pad, hv_len, sizeof ctx->eng.pad);
+ return sig_len ? (int)sig_len : -BR_ERR_INVALID_ALGORITHM;
+}
+
+/*
+ * Do the ECDHE key exchange (part 2: computation of the shared secret
+ * from the point sent by the client).
+ */
+static void
+do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *cpoint, size_t cpoint_len)
+{
+ int curve;
+ uint32_t ctl;
+ size_t xoff, xlen;
+
+ curve = ctx->eng.ecdhe_curve;
+
+ /*
+ * Finalise the key exchange.
+ */
+ ctl = ctx->eng.iec->mul(cpoint, cpoint_len,
+ ctx->ecdhe_key, ctx->ecdhe_key_len, curve);
+ xoff = ctx->eng.iec->xoff(curve, &xlen);
+ ecdh_common(ctx, prf_id, cpoint + xoff, xlen, ctl);
+
+ /*
+ * Clear the ECDHE private key. Forward Secrecy is achieved insofar
+ * as that key does not get stolen, so we'd better destroy it
+ * as soon as it ceases to be useful.
+ */
+ memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
+}
+
+/*
+ * Offset for hash value within the pad (when obtaining all hash values,
+ * in preparation for verification of the CertificateVerify message).
+ * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value
+ * is used to get the total length.
+ */
+static const unsigned char HASH_PAD_OFF[] = { 0, 16, 36, 64, 96, 144, 208 };
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+ 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+ HASH_OID_SHA1,
+ HASH_OID_SHA224,
+ HASH_OID_SHA256,
+ HASH_OID_SHA384,
+ HASH_OID_SHA512
+};
+
+/*
+ * Verify the signature in CertificateVerify. Returned value is 0 on
+ * success, or a non-zero error code. Lack of implementation of the
+ * designated signature algorithm is reported as a "bad signature"
+ * error (because it means that the peer did not honour our advertised
+ * set of supported signature algorithms).
+ */
+static int
+verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len)
+{
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+ int id;
+
+ id = ctx->hash_CV_id;
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ if (pk->key_type == BR_KEYTYPE_RSA) {
+ unsigned char tmp[64];
+ const unsigned char *hash_oid;
+
+ if (id == 0) {
+ hash_oid = NULL;
+ } else {
+ hash_oid = HASH_OID[id - 2];
+ }
+ if (ctx->eng.irsavrfy == 0) {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
+ hash_oid, ctx->hash_CV_len, &pk->key.rsa, tmp)
+ || memcmp(tmp, ctx->hash_CV, ctx->hash_CV_len) != 0)
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ } else {
+ if (ctx->eng.iecdsa == 0) {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ if (!ctx->eng.iecdsa(ctx->eng.iec,
+ ctx->hash_CV, ctx->hash_CV_len,
+ &pk->key.ec, ctx->eng.pad, sig_len))
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ }
+ return 0;
+}
+
+
+
+static const unsigned char t0_datablock[] = {
+ 0x00, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x2F, 0x01, 0x24, 0x00, 0x35, 0x02,
+ 0x24, 0x00, 0x3C, 0x01, 0x44, 0x00, 0x3D, 0x02, 0x44, 0x00, 0x9C, 0x03,
+ 0x04, 0x00, 0x9D, 0x04, 0x05, 0xC0, 0x03, 0x40, 0x24, 0xC0, 0x04, 0x41,
+ 0x24, 0xC0, 0x05, 0x42, 0x24, 0xC0, 0x08, 0x20, 0x24, 0xC0, 0x09, 0x21,
+ 0x24, 0xC0, 0x0A, 0x22, 0x24, 0xC0, 0x0D, 0x30, 0x24, 0xC0, 0x0E, 0x31,
+ 0x24, 0xC0, 0x0F, 0x32, 0x24, 0xC0, 0x12, 0x10, 0x24, 0xC0, 0x13, 0x11,
+ 0x24, 0xC0, 0x14, 0x12, 0x24, 0xC0, 0x23, 0x21, 0x44, 0xC0, 0x24, 0x22,
+ 0x55, 0xC0, 0x25, 0x41, 0x44, 0xC0, 0x26, 0x42, 0x55, 0xC0, 0x27, 0x11,
+ 0x44, 0xC0, 0x28, 0x12, 0x55, 0xC0, 0x29, 0x31, 0x44, 0xC0, 0x2A, 0x32,
+ 0x55, 0xC0, 0x2B, 0x23, 0x04, 0xC0, 0x2C, 0x24, 0x05, 0xC0, 0x2D, 0x43,
+ 0x04, 0xC0, 0x2E, 0x44, 0x05, 0xC0, 0x2F, 0x13, 0x04, 0xC0, 0x30, 0x14,
+ 0x05, 0xC0, 0x31, 0x33, 0x04, 0xC0, 0x32, 0x34, 0x05, 0xC0, 0x9C, 0x06,
+ 0x04, 0xC0, 0x9D, 0x07, 0x04, 0xC0, 0xA0, 0x08, 0x04, 0xC0, 0xA1, 0x09,
+ 0x04, 0xC0, 0xAC, 0x26, 0x04, 0xC0, 0xAD, 0x27, 0x04, 0xC0, 0xAE, 0x28,
+ 0x04, 0xC0, 0xAF, 0x29, 0x04, 0xCC, 0xA8, 0x15, 0x04, 0xCC, 0xA9, 0x25,
+ 0x04, 0x00, 0x00
+};
+
+static const unsigned char t0_codeblock[] = {
+ 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x01,
+ 0x00, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x08,
+ 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00,
+ 0x01, 0x02, 0x09, 0x00, 0x00, 0x29, 0x29, 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_SIGNATURE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_BAD_VERSION), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_NO_CLIENT_AUTH), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK),
+ 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00,
+ 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_server_context, client_max_version)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, client_random)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_server_context, client_suites)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_server_context, client_suites_num)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, close_received)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_server_context, curves)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_server_context, hashes)),
+ 0x00, 0x00, 0x7B, 0x01,
+ T0_INT2(BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00,
+ 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, peer_log_max_frag_len)), 0x00,
+ 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, protocol_names_num)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, record_type_in)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, record_type_out)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, reneg)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, saved_finished)), 0x00,
+ 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, selected_protocol)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, server_name)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, server_random)), 0x00, 0x00,
+ 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id_len)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, shutdown_recv)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_server_context, sign_hash_id)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_buf)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_num)), 0x00,
+ 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, version)),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_in)),
+ 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)),
+ 0x00, 0x00, 0x09, 0x2A, 0x5D, 0x06, 0x02, 0x6A, 0x2B, 0x00, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x03, 0x00, 0x9B, 0x2A, 0x63, 0x47, 0x9F, 0x2A, 0x05,
+ 0x04, 0x65, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0F, 0x06, 0x02, 0x9F, 0x00,
+ 0x63, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x6A, 0x2B, 0x00, 0x00, 0x2A, 0x8B,
+ 0x47, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x47, 0x78, 0x2E, 0xA8, 0x1C, 0x85,
+ 0x01, 0x0C, 0x33, 0x00, 0x00, 0x2A, 0x22, 0x01, 0x08, 0x0C, 0x47, 0x61,
+ 0x22, 0x08, 0x00, 0x01, 0x03, 0x00, 0x77, 0x30, 0x02, 0x00, 0x38, 0x13,
+ 0x01, 0x01, 0x0C, 0x77, 0x42, 0x2C, 0x19, 0x38, 0x06, 0x07, 0x02, 0x00,
+ 0xD0, 0x03, 0x00, 0x04, 0x75, 0x01, 0x00, 0xC7, 0x02, 0x00, 0x2A, 0x19,
+ 0x13, 0x06, 0x02, 0x71, 0x2B, 0xD0, 0x04, 0x76, 0x00, 0x01, 0x00, 0x77,
+ 0x42, 0x01, 0x16, 0x89, 0x42, 0x01, 0x00, 0x8C, 0x40, 0x36, 0xB1, 0x35,
+ 0x06, 0x02, 0x73, 0x2B, 0x06, 0x0A, 0xD7, 0x01, 0x00, 0xD3, 0x01, 0x00,
+ 0xAD, 0x04, 0x80, 0x46, 0xD7, 0xD4, 0x29, 0xD9, 0x50, 0x06, 0x01, 0xD5,
+ 0xD8, 0x2C, 0x50, 0x06, 0x31, 0x01, 0x00, 0xAE, 0x2A, 0x5D, 0x06, 0x0F,
+ 0x01, 0x02, 0xA4, 0x05, 0x02, 0x37, 0x2B, 0x29, 0xB2, 0xB0, 0x2A, 0xC9,
+ 0x29, 0x04, 0x19, 0x2A, 0x5F, 0x06, 0x0B, 0x29, 0x01, 0x02, 0xA4, 0x05,
+ 0x02, 0x70, 0x2B, 0xB2, 0x04, 0x0A, 0xB4, 0x2A, 0x05, 0x04, 0x29, 0xAB,
+ 0x04, 0x02, 0xB3, 0xAF, 0x04, 0x01, 0xB2, 0x01, 0x00, 0xAD, 0x01, 0x00,
+ 0xD3, 0x3E, 0x01, 0x01, 0x77, 0x42, 0x01, 0x17, 0x89, 0x42, 0x00, 0x00,
+ 0x3A, 0x3A, 0x00, 0x01, 0x03, 0x00, 0x2C, 0x19, 0x38, 0x06, 0x04, 0xCF,
+ 0x29, 0x04, 0x78, 0x01, 0x02, 0x02, 0x00, 0xC6, 0x19, 0x38, 0x06, 0x04,
+ 0xCF, 0x29, 0x04, 0x78, 0x02, 0x00, 0x01, 0x84, 0x00, 0x08, 0x2B, 0x00,
+ 0x00, 0x81, 0x2F, 0x47, 0x12, 0x01, 0x01, 0x13, 0x37, 0x00, 0x00, 0x2A,
+ 0x05, 0x04, 0x29, 0x01, 0x7F, 0x00, 0x01, 0x00, 0xA2, 0x12, 0x01, 0x01,
+ 0x13, 0x5F, 0x06, 0x03, 0x61, 0x04, 0x75, 0x47, 0x29, 0x00, 0x00, 0x01,
+ 0x7F, 0xA1, 0xCF, 0x2A, 0x01, 0x07, 0x13, 0x01, 0x00, 0x3A, 0x0F, 0x06,
+ 0x0D, 0x29, 0x01, 0x10, 0x13, 0x06, 0x05, 0x01, 0x00, 0x77, 0x42, 0xC5,
+ 0x04, 0x33, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x2A, 0x29, 0x29, 0x8A, 0x30,
+ 0x01, 0x01, 0x0F, 0x01, 0x01, 0xA4, 0x39, 0x06, 0x18, 0xC8, 0x2C, 0x19,
+ 0x38, 0x06, 0x04, 0xCF, 0x29, 0x04, 0x78, 0x01, 0x80, 0x64, 0xC7, 0x01,
+ 0x01, 0x77, 0x42, 0x01, 0x17, 0x89, 0x42, 0x04, 0x03, 0x01, 0x00, 0xA1,
+ 0x04, 0x03, 0x73, 0x2B, 0x29, 0x04, 0xFF, 0x32, 0x01, 0x2A, 0x03, 0x00,
+ 0x09, 0x2A, 0x5D, 0x06, 0x02, 0x6A, 0x2B, 0x02, 0x00, 0x00, 0x00, 0x9C,
+ 0x01, 0x0F, 0x13, 0x00, 0x00, 0x76, 0x30, 0x01, 0x00, 0x3A, 0x0F, 0x06,
+ 0x10, 0x29, 0x2A, 0x01, 0x01, 0x0E, 0x06, 0x03, 0x29, 0x01, 0x02, 0x76,
+ 0x42, 0x01, 0x00, 0x04, 0x21, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x14, 0x29,
+ 0x01, 0x00, 0x76, 0x42, 0x2A, 0x01, 0x80, 0x64, 0x0F, 0x06, 0x05, 0x01,
+ 0x82, 0x00, 0x08, 0x2B, 0x5F, 0x04, 0x07, 0x29, 0x01, 0x82, 0x00, 0x08,
+ 0x2B, 0x29, 0x00, 0x00, 0x01, 0x00, 0x31, 0x06, 0x05, 0x3D, 0xA9, 0x39,
+ 0x04, 0x78, 0x2A, 0x06, 0x04, 0x01, 0x01, 0x91, 0x42, 0x00, 0x00, 0x01,
+ 0x1F, 0x13, 0x01, 0x12, 0x0F, 0x05, 0x02, 0x74, 0x2B, 0x78, 0x2E, 0x2A,
+ 0xCB, 0x05, 0x02, 0x73, 0x2B, 0xA8, 0x28, 0x00, 0x02, 0x87, 0x2E, 0x05,
+ 0x02, 0xBC, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x01, 0x7E, 0x03, 0x00, 0x2A,
+ 0x06, 0x17, 0xC2, 0x2A, 0x03, 0x01, 0x85, 0x47, 0xB6, 0x02, 0x01, 0x51,
+ 0x2A, 0x02, 0x00, 0x53, 0x06, 0x04, 0x03, 0x00, 0x04, 0x01, 0x29, 0x04,
+ 0x66, 0x9D, 0x9D, 0x02, 0x00, 0x61, 0x8C, 0x40, 0x00, 0x00, 0x31, 0x06,
+ 0x0B, 0x88, 0x30, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x73, 0x2B, 0x04, 0x11,
+ 0xCF, 0x01, 0x07, 0x13, 0x2A, 0x01, 0x02, 0x0E, 0x06, 0x06, 0x06, 0x02,
+ 0x73, 0x2B, 0x04, 0x70, 0x29, 0xC3, 0x01, 0x01, 0x0E, 0x35, 0x39, 0x06,
+ 0x02, 0x66, 0x2B, 0x2A, 0x01, 0x01, 0xCA, 0x38, 0xB5, 0x00, 0x01, 0xBA,
+ 0x01, 0x0B, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x2A, 0x01, 0x03, 0x0F, 0x06,
+ 0x08, 0xC1, 0x06, 0x02, 0x6A, 0x2B, 0x47, 0x29, 0x00, 0x47, 0x5C, 0xC1,
+ 0xA7, 0x2A, 0x06, 0x23, 0xC1, 0xA7, 0x2A, 0x5B, 0x2A, 0x06, 0x18, 0x2A,
+ 0x01, 0x82, 0x00, 0x10, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x2A,
+ 0x03, 0x00, 0x85, 0x02, 0x00, 0xB6, 0x02, 0x00, 0x58, 0x04, 0x65, 0x9D,
+ 0x59, 0x04, 0x5A, 0x9D, 0x9D, 0x5A, 0x2A, 0x06, 0x02, 0x37, 0x00, 0x29,
+ 0x2D, 0x00, 0x02, 0x2A, 0x01, 0x20, 0x13, 0x05, 0x02, 0x74, 0x2B, 0x01,
+ 0x0F, 0x13, 0x03, 0x00, 0xB0, 0x95, 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06,
+ 0x23, 0xC0, 0x2A, 0x01, 0x81, 0x7F, 0x13, 0x61, 0x01, 0x01, 0x12, 0x02,
+ 0x00, 0x0F, 0x05, 0x02, 0x6C, 0x2B, 0x01, 0x08, 0x12, 0x2A, 0x01, 0x02,
+ 0x0B, 0x3A, 0x01, 0x06, 0x10, 0x39, 0x06, 0x02, 0x6E, 0x2B, 0x04, 0x0D,
+ 0x02, 0x00, 0x01, 0x01, 0x0F, 0x06, 0x04, 0x01, 0x00, 0x04, 0x02, 0x01,
+ 0x02, 0x20, 0x05, 0x02, 0x6E, 0x2B, 0xC0, 0x2A, 0x03, 0x01, 0x2A, 0x01,
+ 0x84, 0x00, 0x10, 0x06, 0x02, 0x6F, 0x2B, 0x85, 0x47, 0xB6, 0x02, 0x01,
+ 0x55, 0x2A, 0x06, 0x01, 0x2B, 0x29, 0x9D, 0x00, 0x00, 0x1D, 0xBA, 0x01,
+ 0x0F, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x00, 0x0A, 0xBA, 0x01, 0x01, 0x0F,
+ 0x05, 0x02, 0x73, 0x2B, 0xC0, 0x2A, 0x03, 0x00, 0x79, 0x40, 0x7A, 0x01,
+ 0x20, 0xB6, 0xC2, 0x2A, 0x01, 0x20, 0x10, 0x06, 0x02, 0x72, 0x2B, 0x2A,
+ 0x90, 0x42, 0x8F, 0x47, 0xB6, 0x1A, 0x03, 0x01, 0xC0, 0xA7, 0x01, 0x00,
+ 0x03, 0x02, 0x01, 0x00, 0x03, 0x03, 0x83, 0xA2, 0x17, 0x3A, 0x08, 0x03,
+ 0x04, 0x03, 0x05, 0x2A, 0x06, 0x80, 0x6D, 0xC0, 0x2A, 0x03, 0x06, 0x02,
+ 0x01, 0x06, 0x0A, 0x2A, 0x78, 0x2E, 0x0F, 0x06, 0x04, 0x01, 0x7F, 0x03,
+ 0x03, 0x2A, 0x01, 0x81, 0x7F, 0x0F, 0x06, 0x0A, 0x8A, 0x30, 0x06, 0x02,
+ 0x6B, 0x2B, 0x01, 0x7F, 0x03, 0x02, 0x2A, 0x01, 0x81, 0xAC, 0x00, 0x0F,
+ 0x06, 0x11, 0x02, 0x00, 0x98, 0x2E, 0x11, 0x02, 0x00, 0x97, 0x2E, 0x0B,
+ 0x13, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0xC4, 0x2A, 0x5D, 0x06, 0x03,
+ 0x29, 0x04, 0x26, 0x01, 0x00, 0xA4, 0x06, 0x0B, 0x01, 0x02, 0x0C, 0x7B,
+ 0x08, 0x02, 0x06, 0x47, 0x40, 0x04, 0x16, 0x29, 0x02, 0x05, 0x02, 0x04,
+ 0x11, 0x06, 0x02, 0x69, 0x2B, 0x02, 0x06, 0x02, 0x05, 0x40, 0x02, 0x05,
+ 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0xFF, 0x0F, 0x29, 0x01, 0x00, 0x03,
+ 0x07, 0xC2, 0xA7, 0x2A, 0x06, 0x09, 0xC2, 0x05, 0x04, 0x01, 0x7F, 0x03,
+ 0x07, 0x04, 0x74, 0x9D, 0x01, 0x00, 0x8D, 0x42, 0x01, 0x88, 0x04, 0x82,
+ 0x41, 0x01, 0x84, 0x80, 0x80, 0x00, 0x7E, 0x41, 0x2A, 0x06, 0x80, 0x4E,
+ 0xC0, 0xA7, 0x2A, 0x06, 0x80, 0x47, 0xC0, 0x01, 0x00, 0x3A, 0x0F, 0x06,
+ 0x04, 0x29, 0xB9, 0x04, 0x39, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x04, 0x29,
+ 0xB7, 0x04, 0x2F, 0x01, 0x83, 0xFE, 0x01, 0x3A, 0x0F, 0x06, 0x04, 0x29,
+ 0xB8, 0x04, 0x23, 0x01, 0x0D, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xBE, 0x04,
+ 0x19, 0x01, 0x0A, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xBF, 0x04, 0x0F, 0x01,
+ 0x10, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xAC, 0x04, 0x05, 0x29, 0xBC, 0x01,
+ 0x00, 0x29, 0x04, 0xFF, 0x35, 0x9D, 0x9D, 0x02, 0x01, 0x02, 0x03, 0x13,
+ 0x03, 0x01, 0x02, 0x00, 0x5D, 0x06, 0x08, 0x79, 0x2E, 0x99, 0x40, 0x01,
+ 0x80, 0x56, 0xA3, 0x97, 0x2E, 0x2A, 0x02, 0x00, 0x10, 0x06, 0x03, 0x29,
+ 0x02, 0x00, 0x2A, 0x01, 0x86, 0x00, 0x0B, 0x06, 0x02, 0x6D, 0x2B, 0x02,
+ 0x00, 0x98, 0x2E, 0x0B, 0x06, 0x04, 0x01, 0x80, 0x46, 0xA3, 0x02, 0x01,
+ 0x06, 0x10, 0x95, 0x2E, 0x02, 0x00, 0x0D, 0x06, 0x05, 0x29, 0x95, 0x2E,
+ 0x04, 0x04, 0x01, 0x00, 0x03, 0x01, 0x2A, 0x95, 0x40, 0x2A, 0x96, 0x40,
+ 0x2A, 0x99, 0x40, 0x01, 0x86, 0x03, 0x11, 0x03, 0x08, 0x02, 0x02, 0x06,
+ 0x04, 0x01, 0x02, 0x8A, 0x42, 0x8A, 0x30, 0x05, 0x04, 0x01, 0x01, 0x8A,
+ 0x42, 0x02, 0x07, 0x05, 0x03, 0x01, 0x28, 0xA3, 0x44, 0x29, 0x01, 0x82,
+ 0x01, 0x07, 0x01, 0xFC, 0x80, 0x00, 0x39, 0x82, 0x2F, 0x13, 0x2A, 0x82,
+ 0x41, 0x2A, 0x01, 0x81, 0x7F, 0x13, 0x5E, 0x37, 0x47, 0x01, 0x08, 0x12,
+ 0x5E, 0x01, 0x02, 0x13, 0x39, 0x01, 0x0C, 0x0C, 0x03, 0x09, 0x7E, 0x2F,
+ 0x43, 0x13, 0x2A, 0x7E, 0x41, 0x05, 0x04, 0x01, 0x00, 0x03, 0x09, 0x02,
+ 0x01, 0x06, 0x03, 0x01, 0x7F, 0x00, 0x8F, 0x01, 0x20, 0x34, 0x01, 0x20,
+ 0x90, 0x42, 0x7B, 0x2A, 0x03, 0x05, 0x2A, 0x02, 0x04, 0x0B, 0x06, 0x80,
+ 0x49, 0x2A, 0x2E, 0x2A, 0x9C, 0x2A, 0x01, 0x0C, 0x12, 0x2A, 0x01, 0x01,
+ 0x0F, 0x47, 0x01, 0x02, 0x0F, 0x39, 0x06, 0x0A, 0x2A, 0x02, 0x09, 0x13,
+ 0x05, 0x04, 0x65, 0x01, 0x00, 0x2A, 0x02, 0x08, 0x05, 0x0E, 0x2A, 0x01,
+ 0x81, 0x70, 0x13, 0x01, 0x20, 0x0E, 0x06, 0x04, 0x65, 0x01, 0x00, 0x2A,
+ 0x2A, 0x06, 0x10, 0x02, 0x05, 0x63, 0x40, 0x02, 0x05, 0x40, 0x02, 0x05,
+ 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0x01, 0x65, 0x01, 0x04, 0x08, 0x04,
+ 0xFF, 0x30, 0x29, 0x02, 0x05, 0x7B, 0x09, 0x01, 0x02, 0x12, 0x2A, 0x05,
+ 0x03, 0x01, 0x28, 0xA3, 0x7C, 0x42, 0x8C, 0x2E, 0x01, 0x83, 0xFF, 0x7F,
+ 0x0F, 0x06, 0x0D, 0x01, 0x03, 0xA4, 0x06, 0x04, 0x01, 0x80, 0x78, 0xA3,
+ 0x01, 0x00, 0x8C, 0x40, 0x18, 0x05, 0x03, 0x01, 0x28, 0xA3, 0x01, 0x00,
+ 0x00, 0x00, 0xB4, 0xB3, 0x00, 0x04, 0x78, 0x2E, 0xCE, 0x06, 0x16, 0xC0,
+ 0x2A, 0x01, 0x84, 0x00, 0x10, 0x06, 0x02, 0x6F, 0x2B, 0x2A, 0x03, 0x00,
+ 0x85, 0x47, 0xB6, 0x02, 0x00, 0x78, 0x2E, 0xA8, 0x27, 0x78, 0x2E, 0x2A,
+ 0xCC, 0x47, 0xCB, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x39,
+ 0x06, 0x14, 0xC2, 0x2A, 0x03, 0x03, 0x85, 0x47, 0xB6, 0x02, 0x03, 0x78,
+ 0x2E, 0xA8, 0x02, 0x02, 0x06, 0x03, 0x26, 0x04, 0x01, 0x24, 0x9D, 0x00,
+ 0x00, 0xBA, 0x01, 0x10, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x00, 0x00, 0x9E,
+ 0xBA, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x73, 0x2B, 0x85, 0x01, 0x0C, 0x08,
+ 0x01, 0x0C, 0xB6, 0x9D, 0x85, 0x2A, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x32,
+ 0x05, 0x02, 0x67, 0x2B, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00,
+ 0x9A, 0x02, 0x01, 0x02, 0x00, 0x3C, 0x2A, 0x01, 0x00, 0x0F, 0x06, 0x02,
+ 0x65, 0x00, 0xD1, 0x04, 0x74, 0x00, 0xC0, 0x01, 0x01, 0x0E, 0x06, 0x02,
+ 0x68, 0x2B, 0xC2, 0x2A, 0x2A, 0x5F, 0x47, 0x01, 0x05, 0x11, 0x39, 0x06,
+ 0x02, 0x68, 0x2B, 0x01, 0x08, 0x08, 0x2A, 0x84, 0x30, 0x0B, 0x06, 0x0D,
+ 0x2A, 0x01, 0x01, 0x47, 0x0C, 0x3F, 0x2A, 0x84, 0x42, 0x86, 0x42, 0x04,
+ 0x01, 0x29, 0x00, 0x00, 0xC0, 0x8A, 0x30, 0x01, 0x00, 0x3A, 0x0F, 0x06,
+ 0x13, 0x29, 0x01, 0x01, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0xC2, 0x06, 0x02,
+ 0x6B, 0x2B, 0x01, 0x02, 0x8A, 0x42, 0x04, 0x28, 0x01, 0x02, 0x3A, 0x0F,
+ 0x06, 0x1F, 0x29, 0x01, 0x0D, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0xC2, 0x01,
+ 0x0C, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0x85, 0x01, 0x0C, 0xB6, 0x8B, 0x85,
+ 0x01, 0x0C, 0x32, 0x05, 0x02, 0x6B, 0x2B, 0x04, 0x03, 0x6B, 0x2B, 0x29,
+ 0x00, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x2A, 0x06, 0x1D, 0xC2, 0x06, 0x03,
+ 0xBC, 0x04, 0x15, 0xC0, 0x2A, 0x01, 0x81, 0x7F, 0x0D, 0x06, 0x0C, 0x2A,
+ 0x8D, 0x08, 0x01, 0x00, 0x47, 0x42, 0x8D, 0x47, 0xB6, 0x04, 0x01, 0xC9,
+ 0x04, 0x60, 0x9D, 0x9D, 0x00, 0x00, 0xBB, 0x2A, 0x5F, 0x06, 0x07, 0x29,
+ 0x06, 0x02, 0x69, 0x2B, 0x04, 0x74, 0x00, 0x00, 0xC3, 0x01, 0x03, 0xC1,
+ 0x47, 0x29, 0x47, 0x00, 0x00, 0xC0, 0xC9, 0x00, 0x03, 0x01, 0x00, 0x03,
+ 0x00, 0xC0, 0xA7, 0x2A, 0x06, 0x80, 0x50, 0xC2, 0x03, 0x01, 0xC2, 0x03,
+ 0x02, 0x02, 0x01, 0x01, 0x08, 0x0F, 0x06, 0x16, 0x02, 0x02, 0x01, 0x0F,
+ 0x0D, 0x06, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x01, 0x10, 0x08, 0x0C, 0x02,
+ 0x00, 0x39, 0x03, 0x00, 0x04, 0x2A, 0x02, 0x01, 0x01, 0x02, 0x11, 0x02,
+ 0x01, 0x01, 0x06, 0x0D, 0x13, 0x02, 0x02, 0x01, 0x01, 0x0F, 0x02, 0x02,
+ 0x01, 0x03, 0x0F, 0x39, 0x13, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x62, 0x01, 0x02, 0x0C, 0x02, 0x01, 0x08, 0x0C, 0x39, 0x03, 0x00,
+ 0x04, 0xFF, 0x2C, 0x9D, 0x02, 0x00, 0x00, 0x00, 0xC0, 0xA7, 0xBD, 0x82,
+ 0x41, 0x9D, 0x00, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x01, 0x00, 0x7E, 0x41,
+ 0x2A, 0x06, 0x15, 0xC0, 0x2A, 0x01, 0x20, 0x0B, 0x06, 0x0B, 0x01, 0x01,
+ 0x47, 0x0C, 0x7E, 0x2F, 0x39, 0x7E, 0x41, 0x04, 0x01, 0x29, 0x04, 0x68,
+ 0x9D, 0x9D, 0x00, 0x00, 0x01, 0x02, 0x9A, 0xC3, 0x01, 0x08, 0x0C, 0xC3,
+ 0x08, 0x00, 0x00, 0x01, 0x03, 0x9A, 0xC3, 0x01, 0x08, 0x0C, 0xC3, 0x08,
+ 0x01, 0x08, 0x0C, 0xC3, 0x08, 0x00, 0x00, 0x01, 0x01, 0x9A, 0xC3, 0x00,
+ 0x00, 0x3D, 0x2A, 0x5D, 0x05, 0x01, 0x00, 0x29, 0xD1, 0x04, 0x76, 0x02,
+ 0x03, 0x00, 0x94, 0x30, 0x03, 0x01, 0x01, 0x00, 0x2A, 0x02, 0x01, 0x0B,
+ 0x06, 0x10, 0x2A, 0x01, 0x01, 0x0C, 0x93, 0x08, 0x2E, 0x02, 0x00, 0x0F,
+ 0x06, 0x01, 0x00, 0x61, 0x04, 0x6A, 0x29, 0x01, 0x7F, 0x00, 0x00, 0x2C,
+ 0x19, 0x38, 0x06, 0x04, 0xCF, 0x29, 0x04, 0x78, 0x01, 0x16, 0x89, 0x42,
+ 0x01, 0x00, 0xE2, 0x01, 0x00, 0xE1, 0x2C, 0x01, 0x17, 0x89, 0x42, 0x00,
+ 0x00, 0x01, 0x15, 0x89, 0x42, 0x47, 0x57, 0x29, 0x57, 0x29, 0x2C, 0x00,
+ 0x00, 0x01, 0x01, 0x47, 0xC6, 0x00, 0x00, 0xBB, 0x01, 0x01, 0x0F, 0x05,
+ 0x02, 0x73, 0x2B, 0x2A, 0xC9, 0x29, 0x00, 0x00, 0x47, 0x3A, 0x9A, 0x47,
+ 0x2A, 0x06, 0x05, 0xC3, 0x29, 0x62, 0x04, 0x78, 0x29, 0x00, 0x02, 0x03,
+ 0x00, 0x78, 0x2E, 0x9C, 0x03, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x13, 0x02,
+ 0x01, 0x01, 0x04, 0x12, 0x01, 0x0F, 0x13, 0x02, 0x01, 0x01, 0x08, 0x12,
+ 0x01, 0x0F, 0x13, 0x01, 0x00, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x00,
+ 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x81,
+ 0x0D, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x01, 0x01, 0x10,
+ 0x02, 0x00, 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x80, 0x77, 0x01,
+ 0x02, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x01, 0x01, 0x20, 0x02, 0x00,
+ 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x80, 0x61, 0x01, 0x03, 0x3A,
+ 0x0F, 0x06, 0x0F, 0x29, 0x29, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x4A,
+ 0x04, 0x01, 0x4B, 0x04, 0x80, 0x4C, 0x01, 0x04, 0x3A, 0x0F, 0x06, 0x0E,
+ 0x29, 0x29, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x4A, 0x04, 0x01, 0x4B,
+ 0x04, 0x38, 0x01, 0x05, 0x3A, 0x0F, 0x06, 0x0C, 0x29, 0x29, 0x02, 0x00,
+ 0x06, 0x03, 0x4E, 0x04, 0x01, 0x4F, 0x04, 0x26, 0x2A, 0x01, 0x09, 0x10,
+ 0x06, 0x02, 0x6A, 0x2B, 0x47, 0x29, 0x2A, 0x01, 0x01, 0x13, 0x01, 0x04,
+ 0x0C, 0x01, 0x10, 0x08, 0x47, 0x01, 0x08, 0x13, 0x01, 0x10, 0x47, 0x09,
+ 0x02, 0x00, 0x06, 0x03, 0x48, 0x04, 0x01, 0x49, 0x00, 0x29, 0x00, 0x00,
+ 0x9C, 0x01, 0x0C, 0x12, 0x01, 0x02, 0x10, 0x00, 0x00, 0x9C, 0x01, 0x0C,
+ 0x12, 0x2A, 0x60, 0x47, 0x01, 0x03, 0x0B, 0x13, 0x00, 0x00, 0x9C, 0x01,
+ 0x0C, 0x12, 0x01, 0x01, 0x0F, 0x00, 0x00, 0x9C, 0x01, 0x0C, 0x12, 0x5F,
+ 0x00, 0x00, 0x1B, 0x01, 0x00, 0x75, 0x30, 0x2A, 0x06, 0x22, 0x01, 0x01,
+ 0x3A, 0x0F, 0x06, 0x06, 0x29, 0x01, 0x00, 0xA0, 0x04, 0x14, 0x01, 0x02,
+ 0x3A, 0x0F, 0x06, 0x0D, 0x29, 0x77, 0x30, 0x01, 0x01, 0x0F, 0x06, 0x03,
+ 0x01, 0x10, 0x39, 0x04, 0x01, 0x29, 0x04, 0x01, 0x29, 0x7D, 0x30, 0x05,
+ 0x33, 0x31, 0x06, 0x30, 0x88, 0x30, 0x01, 0x14, 0x3A, 0x0F, 0x06, 0x06,
+ 0x29, 0x01, 0x02, 0x39, 0x04, 0x22, 0x01, 0x15, 0x3A, 0x0F, 0x06, 0x09,
+ 0x29, 0xAA, 0x06, 0x03, 0x01, 0x7F, 0xA0, 0x04, 0x13, 0x01, 0x16, 0x3A,
+ 0x0F, 0x06, 0x06, 0x29, 0x01, 0x01, 0x39, 0x04, 0x07, 0x29, 0x01, 0x04,
+ 0x39, 0x01, 0x00, 0x29, 0x19, 0x06, 0x03, 0x01, 0x08, 0x39, 0x00, 0x00,
+ 0x1B, 0x2A, 0x05, 0x13, 0x31, 0x06, 0x10, 0x88, 0x30, 0x01, 0x15, 0x0F,
+ 0x06, 0x08, 0x29, 0xAA, 0x01, 0x00, 0x77, 0x42, 0x04, 0x01, 0x23, 0x00,
+ 0x00, 0xCF, 0x01, 0x07, 0x13, 0x01, 0x01, 0x10, 0x06, 0x02, 0x73, 0x2B,
+ 0x00, 0x01, 0x03, 0x00, 0x2C, 0x19, 0x06, 0x05, 0x02, 0x00, 0x89, 0x42,
+ 0x00, 0xCF, 0x29, 0x04, 0x74, 0x00, 0x01, 0x14, 0xD2, 0x01, 0x01, 0xE2,
+ 0x2C, 0x2A, 0x01, 0x00, 0xCA, 0x01, 0x16, 0xD2, 0xD6, 0x2C, 0x00, 0x00,
+ 0x01, 0x0B, 0xE2, 0x52, 0x2A, 0x2A, 0x01, 0x03, 0x08, 0xE1, 0xE1, 0x14,
+ 0x2A, 0x5D, 0x06, 0x02, 0x29, 0x00, 0xE1, 0x1E, 0x2A, 0x06, 0x05, 0x85,
+ 0x47, 0xDA, 0x04, 0x77, 0x29, 0x04, 0x6C, 0x00, 0x01, 0x00, 0xDC, 0x95,
+ 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06, 0x05, 0x63, 0x01, 0x00, 0xDD, 0x08,
+ 0x50, 0x08, 0x01, 0x03, 0x08, 0x01, 0x0D, 0xE2, 0xE1, 0x01, 0x00, 0xDC,
+ 0xE2, 0x01, 0x01, 0xDC, 0x29, 0x95, 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06,
+ 0x08, 0x01, 0x00, 0xDD, 0xE0, 0x01, 0x01, 0xDD, 0x29, 0x50, 0xE0, 0x16,
+ 0x15, 0x2A, 0x5D, 0x06, 0x02, 0x29, 0x00, 0xE0, 0x1F, 0x2A, 0x06, 0x05,
+ 0x85, 0x47, 0xDA, 0x04, 0x77, 0x29, 0x04, 0x6C, 0x00, 0x9E, 0x01, 0x14,
+ 0xE2, 0x01, 0x0C, 0xE1, 0x85, 0x01, 0x0C, 0xDA, 0x00, 0x04, 0x03, 0x00,
+ 0x01, 0x02, 0xE2, 0x01, 0x80, 0x46, 0x8A, 0x30, 0x01, 0x02, 0x0F, 0x06,
+ 0x0C, 0x02, 0x00, 0x06, 0x04, 0x01, 0x05, 0x04, 0x02, 0x01, 0x1D, 0x04,
+ 0x02, 0x01, 0x00, 0x03, 0x01, 0x86, 0x30, 0x06, 0x04, 0x01, 0x05, 0x04,
+ 0x02, 0x01, 0x00, 0x03, 0x02, 0x8C, 0x2E, 0x2A, 0x06, 0x05, 0x62, 0x21,
+ 0x01, 0x07, 0x08, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x02, 0x03,
+ 0x08, 0x2A, 0x06, 0x03, 0x01, 0x02, 0x08, 0x08, 0xE1, 0x95, 0x2E, 0xE0,
+ 0x8E, 0x01, 0x04, 0x17, 0x8E, 0x01, 0x04, 0x08, 0x01, 0x1C, 0x34, 0x8E,
+ 0x01, 0x20, 0xDA, 0x01, 0x20, 0xE2, 0x8F, 0x01, 0x20, 0xDA, 0x78, 0x2E,
+ 0xE0, 0x01, 0x00, 0xE2, 0x02, 0x01, 0x02, 0x02, 0x08, 0x02, 0x03, 0x08,
+ 0x2A, 0x06, 0x80, 0x40, 0xE0, 0x02, 0x01, 0x2A, 0x06, 0x10, 0x01, 0x83,
+ 0xFE, 0x01, 0xE0, 0x01, 0x04, 0x09, 0x2A, 0xE0, 0x62, 0x8B, 0x47, 0xDB,
+ 0x04, 0x01, 0x29, 0x02, 0x02, 0x06, 0x0C, 0x01, 0x01, 0xE0, 0x01, 0x01,
+ 0xE0, 0x86, 0x30, 0x01, 0x08, 0x09, 0xE2, 0x02, 0x03, 0x2A, 0x06, 0x11,
+ 0x01, 0x10, 0xE0, 0x01, 0x04, 0x09, 0x2A, 0xE0, 0x64, 0x2A, 0xE0, 0x62,
+ 0x85, 0x47, 0xDB, 0x04, 0x01, 0x29, 0x04, 0x01, 0x29, 0x00, 0x00, 0x01,
+ 0x0E, 0xE2, 0x01, 0x00, 0xE1, 0x00, 0x03, 0x78, 0x2E, 0xCC, 0x05, 0x01,
+ 0x00, 0x7E, 0x2F, 0x2A, 0x01, 0x82, 0x80, 0x80, 0x80, 0x00, 0x13, 0x06,
+ 0x05, 0x29, 0x01, 0x1D, 0x04, 0x0E, 0x2A, 0x01, 0x83, 0xC0, 0x80, 0x80,
+ 0x00, 0x13, 0x2A, 0x06, 0x01, 0x47, 0x29, 0xA5, 0x03, 0x00, 0x02, 0x00,
+ 0x25, 0x2A, 0x5D, 0x06, 0x02, 0x37, 0x2B, 0x03, 0x01, 0x95, 0x2E, 0x01,
+ 0x86, 0x03, 0x11, 0x03, 0x02, 0x01, 0x0C, 0xE2, 0x02, 0x01, 0x80, 0x30,
+ 0x08, 0x02, 0x02, 0x01, 0x02, 0x13, 0x08, 0x01, 0x06, 0x08, 0xE1, 0x01,
+ 0x03, 0xE2, 0x02, 0x00, 0xE0, 0x7F, 0x80, 0x30, 0xDB, 0x02, 0x02, 0x06,
+ 0x1C, 0x92, 0x2E, 0x2A, 0x01, 0x83, 0xFE, 0x00, 0x0B, 0x06, 0x03, 0xE0,
+ 0x04, 0x0F, 0x01, 0x81, 0x7F, 0x13, 0xE2, 0x78, 0x2E, 0xCD, 0x01, 0x01,
+ 0x0C, 0x01, 0x03, 0x08, 0xE2, 0x02, 0x01, 0xE0, 0x85, 0x02, 0x01, 0xDA,
+ 0x00, 0x00, 0x56, 0x2A, 0x01, 0x00, 0x0F, 0x06, 0x02, 0x65, 0x00, 0xCF,
+ 0x29, 0x04, 0x73, 0x00, 0x2A, 0xE2, 0xDA, 0x00, 0x00, 0x01, 0x00, 0x78,
+ 0x2E, 0xCB, 0x06, 0x0C, 0x63, 0x3A, 0x06, 0x08, 0x01, 0x80, 0x41, 0xE2,
+ 0x01, 0x80, 0x42, 0xE2, 0x46, 0x06, 0x07, 0x61, 0x3A, 0x06, 0x03, 0x01,
+ 0x01, 0xE2, 0x45, 0x06, 0x08, 0x61, 0x3A, 0x06, 0x04, 0x01, 0x80, 0x40,
+ 0xE2, 0x47, 0x29, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x46, 0x45, 0x39,
+ 0x05, 0x14, 0x01, 0x01, 0x01, 0x80, 0x7C, 0xDE, 0x03, 0x00, 0x01, 0x03,
+ 0x01, 0x80, 0x7C, 0xDE, 0x02, 0x00, 0x08, 0x47, 0x29, 0x00, 0x46, 0x06,
+ 0x07, 0x01, 0x01, 0x44, 0x29, 0xDE, 0x03, 0x00, 0x45, 0x06, 0x0A, 0x01,
+ 0x03, 0x44, 0x29, 0xDE, 0x02, 0x00, 0x08, 0x03, 0x00, 0x29, 0x02, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x01, 0x04, 0xDF, 0x01, 0x05, 0xDF, 0x01, 0x06,
+ 0xDF, 0x01, 0x03, 0xDF, 0x01, 0x02, 0xDF, 0x0A, 0x65, 0x00, 0x01, 0x03,
+ 0x00, 0x3A, 0x01, 0x01, 0x02, 0x00, 0x0C, 0x13, 0x05, 0x01, 0x00, 0x63,
+ 0x01, 0x03, 0x3B, 0x06, 0x07, 0x02, 0x00, 0xE2, 0x01, 0x02, 0x3B, 0xE2,
+ 0x00, 0x00, 0x2A, 0x01, 0x08, 0x54, 0xE2, 0xE2, 0x00, 0x00, 0x2A, 0x01,
+ 0x10, 0x54, 0xE2, 0xE0, 0x00, 0x00, 0x2A, 0x57, 0x06, 0x02, 0x29, 0x00,
+ 0xCF, 0x29, 0x04, 0x76
+};
+
+static const uint16_t t0_caddr[] = {
+ 0,
+ 5,
+ 10,
+ 15,
+ 20,
+ 25,
+ 30,
+ 35,
+ 40,
+ 44,
+ 48,
+ 52,
+ 56,
+ 60,
+ 64,
+ 68,
+ 72,
+ 76,
+ 80,
+ 84,
+ 88,
+ 92,
+ 96,
+ 100,
+ 104,
+ 109,
+ 114,
+ 119,
+ 124,
+ 129,
+ 134,
+ 139,
+ 144,
+ 149,
+ 154,
+ 159,
+ 164,
+ 169,
+ 174,
+ 180,
+ 185,
+ 190,
+ 195,
+ 200,
+ 205,
+ 210,
+ 215,
+ 220,
+ 225,
+ 230,
+ 235,
+ 240,
+ 245,
+ 250,
+ 255,
+ 260,
+ 265,
+ 270,
+ 275,
+ 280,
+ 285,
+ 290,
+ 299,
+ 303,
+ 328,
+ 334,
+ 353,
+ 364,
+ 405,
+ 516,
+ 520,
+ 553,
+ 563,
+ 587,
+ 669,
+ 683,
+ 689,
+ 748,
+ 767,
+ 789,
+ 838,
+ 887,
+ 963,
+ 1065,
+ 1076,
+ 1670,
+ 1674,
+ 1741,
+ 1751,
+ 1782,
+ 1806,
+ 1852,
+ 1922,
+ 1962,
+ 1976,
+ 1985,
+ 1989,
+ 2084,
+ 2092,
+ 2128,
+ 2139,
+ 2155,
+ 2161,
+ 2172,
+ 2207,
+ 2233,
+ 2245,
+ 2251,
+ 2264,
+ 2279,
+ 2472,
+ 2481,
+ 2494,
+ 2503,
+ 2510,
+ 2616,
+ 2641,
+ 2654,
+ 2670,
+ 2688,
+ 2720,
+ 2793,
+ 2806,
+ 2987,
+ 2995,
+ 3122,
+ 3136,
+ 3141,
+ 3185,
+ 3242,
+ 3263,
+ 3290,
+ 3298,
+ 3306
+};
+
+#define T0_INTERPRETED 93
+
+#define T0_ENTER(ip, rp, slot) do { \
+ const unsigned char *t0_newip; \
+ uint32_t t0_lnum; \
+ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
+ t0_lnum = t0_parse7E_unsigned(&t0_newip); \
+ (rp) += t0_lnum; \
+ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
+ (ip) = t0_newip; \
+ } while (0)
+
+#define T0_DEFENTRY(name, slot) \
+void \
+name(void *ctx) \
+{ \
+ t0_context *t0ctx = ctx; \
+ t0ctx->ip = &t0_codeblock[0]; \
+ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
+}
+
+T0_DEFENTRY(br_ssl_hs_server_init_main, 166)
+
+#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
+
+void
+br_ssl_hs_server_run(void *t0ctx)
+{
+ uint32_t *dp, *rp;
+ const unsigned char *ip;
+
+#define T0_LOCAL(x) (*(rp - 2 - (x)))
+#define T0_POP() (*-- dp)
+#define T0_POPi() (*(int32_t *)(-- dp))
+#define T0_PEEK(x) (*(dp - 1 - (x)))
+#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
+#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
+#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
+#define T0_RPOP() (*-- rp)
+#define T0_RPOPi() (*(int32_t *)(-- rp))
+#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
+#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
+#define T0_ROLL(x) do { \
+ size_t t0len = (size_t)(x); \
+ uint32_t t0tmp = *(dp - 1 - t0len); \
+ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_SWAP() do { \
+ uint32_t t0tmp = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_ROT() do { \
+ uint32_t t0tmp = *(dp - 3); \
+ *(dp - 3) = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_NROT() do { \
+ uint32_t t0tmp = *(dp - 1); \
+ *(dp - 1) = *(dp - 2); \
+ *(dp - 2) = *(dp - 3); \
+ *(dp - 3) = t0tmp; \
+} while (0)
+#define T0_PICK(x) do { \
+ uint32_t t0depth = (x); \
+ T0_PUSH(T0_PEEK(t0depth)); \
+} while (0)
+#define T0_CO() do { \
+ goto t0_exit; \
+} while (0)
+#define T0_RET() goto t0_next
+
+ dp = ((t0_context *)t0ctx)->dp;
+ rp = ((t0_context *)t0ctx)->rp;
+ ip = ((t0_context *)t0ctx)->ip;
+ goto t0_next;
+ for (;;) {
+ uint32_t t0x;
+
+ t0_next:
+ t0x = T0_NEXT(&ip);
+ if (t0x < T0_INTERPRETED) {
+ switch (t0x) {
+ int32_t t0off;
+
+ case 0: /* ret */
+ t0x = T0_RPOP();
+ rp -= (t0x >> 16);
+ t0x &= 0xFFFF;
+ if (t0x == 0) {
+ ip = NULL;
+ goto t0_exit;
+ }
+ ip = &t0_codeblock[t0x];
+ break;
+ case 1: /* literal constant */
+ T0_PUSHi(t0_parse7E_signed(&ip));
+ break;
+ case 2: /* read local */
+ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
+ break;
+ case 3: /* write local */
+ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
+ break;
+ case 4: /* jump */
+ t0off = t0_parse7E_signed(&ip);
+ ip += t0off;
+ break;
+ case 5: /* jump if */
+ t0off = t0_parse7E_signed(&ip);
+ if (T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 6: /* jump if not */
+ t0off = t0_parse7E_signed(&ip);
+ if (!T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 7: {
+ /* * */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a * b);
+
+ }
+ break;
+ case 8: {
+ /* + */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a + b);
+
+ }
+ break;
+ case 9: {
+ /* - */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a - b);
+
+ }
+ break;
+ case 10: {
+ /* -rot */
+ T0_NROT();
+ }
+ break;
+ case 11: {
+ /* < */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a < b));
+
+ }
+ break;
+ case 12: {
+ /* << */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x << c);
+
+ }
+ break;
+ case 13: {
+ /* <= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a <= b));
+
+ }
+ break;
+ case 14: {
+ /* <> */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a != b));
+
+ }
+ break;
+ case 15: {
+ /* = */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a == b));
+
+ }
+ break;
+ case 16: {
+ /* > */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a > b));
+
+ }
+ break;
+ case 17: {
+ /* >= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a >= b));
+
+ }
+ break;
+ case 18: {
+ /* >> */
+
+ int c = (int)T0_POPi();
+ int32_t x = T0_POPi();
+ T0_PUSHi(x >> c);
+
+ }
+ break;
+ case 19: {
+ /* and */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a & b);
+
+ }
+ break;
+ case 20: {
+ /* begin-cert */
+
+ if (ENG->chain_len == 0) {
+ T0_PUSHi(-1);
+ } else {
+ ENG->cert_cur = ENG->chain->data;
+ ENG->cert_len = ENG->chain->data_len;
+ ENG->chain ++;
+ ENG->chain_len --;
+ T0_PUSH(ENG->cert_len);
+ }
+
+ }
+ break;
+ case 21: {
+ /* begin-ta-name */
+
+ const br_x500_name *dn;
+ if (CTX->cur_dn_index >= CTX->num_tas) {
+ T0_PUSHi(-1);
+ } else {
+ if (CTX->ta_names == NULL) {
+ dn = &CTX->tas[CTX->cur_dn_index].dn;
+ } else {
+ dn = &CTX->ta_names[CTX->cur_dn_index];
+ }
+ CTX->cur_dn_index ++;
+ CTX->cur_dn = dn->data;
+ CTX->cur_dn_len = dn->len;
+ T0_PUSH(CTX->cur_dn_len);
+ }
+
+ }
+ break;
+ case 22: {
+ /* begin-ta-name-list */
+
+ CTX->cur_dn_index = 0;
+
+ }
+ break;
+ case 23: {
+ /* bzero */
+
+ size_t len = (size_t)T0_POP();
+ void *addr = (unsigned char *)ENG + (size_t)T0_POP();
+ memset(addr, 0, len);
+
+ }
+ break;
+ case 24: {
+ /* call-policy-handler */
+
+ int x;
+ br_ssl_server_choices choices;
+
+ x = (*CTX->policy_vtable)->choose(
+ CTX->policy_vtable, CTX, &choices);
+ ENG->session.cipher_suite = choices.cipher_suite;
+ CTX->sign_hash_id = choices.algo_id;
+ ENG->chain = choices.chain;
+ ENG->chain_len = choices.chain_len;
+ T0_PUSHi(-(x != 0));
+
+ }
+ break;
+ case 25: {
+ /* can-output? */
+
+ T0_PUSHi(-(ENG->hlen_out > 0));
+
+ }
+ break;
+ case 26: {
+ /* check-resume */
+
+ if (ENG->session.session_id_len == 32
+ && CTX->cache_vtable != NULL && (*CTX->cache_vtable)->load(
+ CTX->cache_vtable, CTX, &ENG->session))
+ {
+ T0_PUSHi(-1);
+ } else {
+ T0_PUSH(0);
+ }
+
+ }
+ break;
+ case 27: {
+ /* co */
+ T0_CO();
+ }
+ break;
+ case 28: {
+ /* compute-Finished-inner */
+
+ int prf_id = T0_POP();
+ int from_client = T0_POPi();
+ unsigned char tmp[48];
+ br_tls_prf_seed_chunk seed;
+
+ br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id);
+ seed.data = tmp;
+ if (ENG->session.version >= BR_TLS12) {
+ seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp);
+ } else {
+ br_multihash_out(&ENG->mhash, br_md5_ID, tmp);
+ br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16);
+ seed.len = 36;
+ }
+ prf(ENG->pad, 12, ENG->session.master_secret,
+ sizeof ENG->session.master_secret,
+ from_client ? "client finished" : "server finished",
+ 1, &seed);
+
+ }
+ break;
+ case 29: {
+ /* compute-hash-CV */
+
+ int i;
+
+ for (i = 1; i <= 6; i ++) {
+ br_multihash_out(&ENG->mhash, i,
+ ENG->pad + HASH_PAD_OFF[i - 1]);
+ }
+
+ }
+ break;
+ case 30: {
+ /* copy-cert-chunk */
+
+ size_t clen;
+
+ clen = ENG->cert_len;
+ if (clen > sizeof ENG->pad) {
+ clen = sizeof ENG->pad;
+ }
+ memcpy(ENG->pad, ENG->cert_cur, clen);
+ ENG->cert_cur += clen;
+ ENG->cert_len -= clen;
+ T0_PUSH(clen);
+
+ }
+ break;
+ case 31: {
+ /* copy-dn-chunk */
+
+ size_t clen;
+
+ clen = CTX->cur_dn_len;
+ if (clen > sizeof ENG->pad) {
+ clen = sizeof ENG->pad;
+ }
+ memcpy(ENG->pad, CTX->cur_dn, clen);
+ CTX->cur_dn += clen;
+ CTX->cur_dn_len -= clen;
+ T0_PUSH(clen);
+
+ }
+ break;
+ case 32: {
+ /* copy-hash-CV */
+
+ int id = T0_POP();
+ size_t off, len;
+
+ if (id == 0) {
+ off = 0;
+ len = 36;
+ } else {
+ if (br_multihash_getimpl(&ENG->mhash, id) == 0) {
+ T0_PUSH(0);
+ T0_RET();
+ }
+ off = HASH_PAD_OFF[id - 1];
+ len = HASH_PAD_OFF[id] - off;
+ }
+ memcpy(CTX->hash_CV, ENG->pad + off, len);
+ CTX->hash_CV_len = len;
+ CTX->hash_CV_id = id;
+ T0_PUSHi(-1);
+
+ }
+ break;
+ case 33: {
+ /* copy-protocol-name */
+
+ size_t idx = T0_POP();
+ size_t len = strlen(ENG->protocol_names[idx]);
+ memcpy(ENG->pad, ENG->protocol_names[idx], len);
+ T0_PUSH(len);
+
+ }
+ break;
+ case 34: {
+ /* data-get8 */
+
+ size_t addr = T0_POP();
+ T0_PUSH(t0_datablock[addr]);
+
+ }
+ break;
+ case 35: {
+ /* discard-input */
+
+ ENG->hlen_in = 0;
+
+ }
+ break;
+ case 36: {
+ /* do-ecdh */
+
+ int prf_id = T0_POPi();
+ size_t len = T0_POP();
+ do_ecdh(CTX, prf_id, ENG->pad, len);
+
+ }
+ break;
+ case 37: {
+ /* do-ecdhe-part1 */
+
+ int curve = T0_POPi();
+ T0_PUSHi(do_ecdhe_part1(CTX, curve));
+
+ }
+ break;
+ case 38: {
+ /* do-ecdhe-part2 */
+
+ int prf_id = T0_POPi();
+ size_t len = T0_POP();
+ do_ecdhe_part2(CTX, prf_id, ENG->pad, len);
+
+ }
+ break;
+ case 39: {
+ /* do-rsa-decrypt */
+
+ int prf_id = T0_POPi();
+ size_t len = T0_POP();
+ do_rsa_decrypt(CTX, prf_id, ENG->pad, len);
+
+ }
+ break;
+ case 40: {
+ /* do-static-ecdh */
+
+ do_static_ecdh(CTX, T0_POP());
+
+ }
+ break;
+ case 41: {
+ /* drop */
+ (void)T0_POP();
+ }
+ break;
+ case 42: {
+ /* dup */
+ T0_PUSH(T0_PEEK(0));
+ }
+ break;
+ case 43: {
+ /* fail */
+
+ br_ssl_engine_fail(ENG, (int)T0_POPi());
+ T0_CO();
+
+ }
+ break;
+ case 44: {
+ /* flush-record */
+
+ br_ssl_engine_flush_record(ENG);
+
+ }
+ break;
+ case 45: {
+ /* get-key-type-usages */
+
+ const br_x509_class *xc;
+ const br_x509_pkey *pk;
+ unsigned usages;
+
+ xc = *(ENG->x509ctx);
+ pk = xc->get_pkey(ENG->x509ctx, &usages);
+ if (pk == NULL) {
+ T0_PUSH(0);
+ } else {
+ T0_PUSH(pk->key_type | usages);
+ }
+
+ }
+ break;
+ case 46: {
+ /* get16 */
+
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr));
+
+ }
+ break;
+ case 47: {
+ /* get32 */
+
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr));
+
+ }
+ break;
+ case 48: {
+ /* get8 */
+
+ size_t addr = (size_t)T0_POP();
+ T0_PUSH(*((unsigned char *)ENG + addr));
+
+ }
+ break;
+ case 49: {
+ /* has-input? */
+
+ T0_PUSHi(-(ENG->hlen_in != 0));
+
+ }
+ break;
+ case 50: {
+ /* memcmp */
+
+ size_t len = (size_t)T0_POP();
+ void *addr2 = (unsigned char *)ENG + (size_t)T0_POP();
+ void *addr1 = (unsigned char *)ENG + (size_t)T0_POP();
+ int x = memcmp(addr1, addr2, len);
+ T0_PUSH((uint32_t)-(x == 0));
+
+ }
+ break;
+ case 51: {
+ /* memcpy */
+
+ size_t len = (size_t)T0_POP();
+ void *src = (unsigned char *)ENG + (size_t)T0_POP();
+ void *dst = (unsigned char *)ENG + (size_t)T0_POP();
+ memcpy(dst, src, len);
+
+ }
+ break;
+ case 52: {
+ /* mkrand */
+
+ size_t len = (size_t)T0_POP();
+ void *addr = (unsigned char *)ENG + (size_t)T0_POP();
+ br_hmac_drbg_generate(&ENG->rng, addr, len);
+
+ }
+ break;
+ case 53: {
+ /* more-incoming-bytes? */
+
+ T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
+
+ }
+ break;
+ case 54: {
+ /* multihash-init */
+
+ br_multihash_init(&ENG->mhash);
+
+ }
+ break;
+ case 55: {
+ /* neg */
+
+ uint32_t a = T0_POP();
+ T0_PUSH(-a);
+
+ }
+ break;
+ case 56: {
+ /* not */
+
+ uint32_t a = T0_POP();
+ T0_PUSH(~a);
+
+ }
+ break;
+ case 57: {
+ /* or */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a | b);
+
+ }
+ break;
+ case 58: {
+ /* over */
+ T0_PUSH(T0_PEEK(1));
+ }
+ break;
+ case 59: {
+ /* pick */
+ T0_PICK(T0_POP());
+ }
+ break;
+ case 60: {
+ /* read-chunk-native */
+
+ size_t clen = ENG->hlen_in;
+ if (clen > 0) {
+ uint32_t addr, len;
+
+ len = T0_POP();
+ addr = T0_POP();
+ if ((size_t)len < clen) {
+ clen = (size_t)len;
+ }
+ memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen);
+ if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen);
+ }
+ T0_PUSH(addr + (uint32_t)clen);
+ T0_PUSH(len - (uint32_t)clen);
+ ENG->hbuf_in += clen;
+ ENG->hlen_in -= clen;
+ }
+
+ }
+ break;
+ case 61: {
+ /* read8-native */
+
+ if (ENG->hlen_in > 0) {
+ unsigned char x;
+
+ x = *ENG->hbuf_in ++;
+ if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, &x, 1);
+ }
+ T0_PUSH(x);
+ ENG->hlen_in --;
+ } else {
+ T0_PUSHi(-1);
+ }
+
+ }
+ break;
+ case 62: {
+ /* save-session */
+
+ if (CTX->cache_vtable != NULL) {
+ (*CTX->cache_vtable)->save(
+ CTX->cache_vtable, CTX, &ENG->session);
+ }
+
+ }
+ break;
+ case 63: {
+ /* set-max-frag-len */
+
+ size_t max_frag_len = T0_POP();
+
+ br_ssl_engine_new_max_frag_len(ENG, max_frag_len);
+
+ /*
+ * We must adjust our own output limit. Since we call this only
+ * after receiving a ClientHello and before beginning to send
+ * the ServerHello, the next output record should be empty at
+ * that point, so we can use max_frag_len as a limit.
+ */
+ if (ENG->hlen_out > max_frag_len) {
+ ENG->hlen_out = max_frag_len;
+ }
+
+ }
+ break;
+ case 64: {
+ /* set16 */
+
+ size_t addr = (size_t)T0_POP();
+ *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP();
+
+ }
+ break;
+ case 65: {
+ /* set32 */
+
+ size_t addr = (size_t)T0_POP();
+ *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP();
+
+ }
+ break;
+ case 66: {
+ /* set8 */
+
+ size_t addr = (size_t)T0_POP();
+ *((unsigned char *)ENG + addr) = (unsigned char)T0_POP();
+
+ }
+ break;
+ case 67: {
+ /* supported-curves */
+
+ uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
+ T0_PUSH(x);
+
+ }
+ break;
+ case 68: {
+ /* supported-hash-functions */
+
+ int i;
+ unsigned x, num;
+
+ x = 0;
+ num = 0;
+ for (i = br_sha1_ID; i <= br_sha512_ID; i ++) {
+ if (br_multihash_getimpl(&ENG->mhash, i)) {
+ x |= 1U << i;
+ num ++;
+ }
+ }
+ T0_PUSH(x);
+ T0_PUSH(num);
+
+ }
+ break;
+ case 69: {
+ /* supports-ecdsa? */
+
+ T0_PUSHi(-(ENG->iecdsa != 0));
+
+ }
+ break;
+ case 70: {
+ /* supports-rsa-sign? */
+
+ T0_PUSHi(-(ENG->irsavrfy != 0));
+
+ }
+ break;
+ case 71: {
+ /* swap */
+ T0_SWAP();
+ }
+ break;
+ case 72: {
+ /* switch-aesccm-in */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len, tag_len;
+
+ tag_len = T0_POP();
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id,
+ ENG->iaes_ctrcbc, cipher_key_len, tag_len);
+
+ }
+ break;
+ case 73: {
+ /* switch-aesccm-out */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len, tag_len;
+
+ tag_len = T0_POP();
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id,
+ ENG->iaes_ctrcbc, cipher_key_len, tag_len);
+
+ }
+ break;
+ case 74: {
+ /* switch-aesgcm-in */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id,
+ ENG->iaes_ctr, cipher_key_len);
+
+ }
+ break;
+ case 75: {
+ /* switch-aesgcm-out */
+
+ int is_client, prf_id;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id,
+ ENG->iaes_ctr, cipher_key_len);
+
+ }
+ break;
+ case 76: {
+ /* switch-cbc-in */
+
+ int is_client, prf_id, mac_id, aes;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ aes = T0_POP();
+ mac_id = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id,
+ aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len);
+
+ }
+ break;
+ case 77: {
+ /* switch-cbc-out */
+
+ int is_client, prf_id, mac_id, aes;
+ unsigned cipher_key_len;
+
+ cipher_key_len = T0_POP();
+ aes = T0_POP();
+ mac_id = T0_POP();
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id,
+ aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len);
+
+ }
+ break;
+ case 78: {
+ /* switch-chapol-in */
+
+ int is_client, prf_id;
+
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id);
+
+ }
+ break;
+ case 79: {
+ /* switch-chapol-out */
+
+ int is_client, prf_id;
+
+ prf_id = T0_POP();
+ is_client = T0_POP();
+ br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id);
+
+ }
+ break;
+ case 80: {
+ /* ta-names-total-length */
+
+ size_t u, len;
+
+ len = 0;
+ if (CTX->ta_names != NULL) {
+ for (u = 0; u < CTX->num_tas; u ++) {
+ len += CTX->ta_names[u].len + 2;
+ }
+ } else if (CTX->tas != NULL) {
+ for (u = 0; u < CTX->num_tas; u ++) {
+ len += CTX->tas[u].dn.len + 2;
+ }
+ }
+ T0_PUSH(len);
+
+ }
+ break;
+ case 81: {
+ /* test-protocol-name */
+
+ size_t len = T0_POP();
+ size_t u;
+
+ for (u = 0; u < ENG->protocol_names_num; u ++) {
+ const char *name;
+
+ name = ENG->protocol_names[u];
+ if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) {
+ T0_PUSH(u);
+ T0_RET();
+ }
+ }
+ T0_PUSHi(-1);
+
+ }
+ break;
+ case 82: {
+ /* total-chain-length */
+
+ size_t u;
+ uint32_t total;
+
+ total = 0;
+ for (u = 0; u < ENG->chain_len; u ++) {
+ total += 3 + (uint32_t)ENG->chain[u].data_len;
+ }
+ T0_PUSH(total);
+
+ }
+ break;
+ case 83: {
+ /* u< */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a < b));
+
+ }
+ break;
+ case 84: {
+ /* u>> */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x >> c);
+
+ }
+ break;
+ case 85: {
+ /* verify-CV-sig */
+
+ int err;
+
+ err = verify_CV_sig(CTX, T0_POP());
+ T0_PUSHi(err);
+
+ }
+ break;
+ case 86: {
+ /* write-blob-chunk */
+
+ size_t clen = ENG->hlen_out;
+ if (clen > 0) {
+ uint32_t addr, len;
+
+ len = T0_POP();
+ addr = T0_POP();
+ if ((size_t)len < clen) {
+ clen = (size_t)len;
+ }
+ memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen);
+ if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen);
+ }
+ T0_PUSH(addr + (uint32_t)clen);
+ T0_PUSH(len - (uint32_t)clen);
+ ENG->hbuf_out += clen;
+ ENG->hlen_out -= clen;
+ }
+
+ }
+ break;
+ case 87: {
+ /* write8-native */
+
+ unsigned char x;
+
+ x = (unsigned char)T0_POP();
+ if (ENG->hlen_out > 0) {
+ if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
+ br_multihash_update(&ENG->mhash, &x, 1);
+ }
+ *ENG->hbuf_out ++ = x;
+ ENG->hlen_out --;
+ T0_PUSHi(-1);
+ } else {
+ T0_PUSHi(0);
+ }
+
+ }
+ break;
+ case 88: {
+ /* x509-append */
+
+ const br_x509_class *xc;
+ size_t len;
+
+ xc = *(ENG->x509ctx);
+ len = T0_POP();
+ xc->append(ENG->x509ctx, ENG->pad, len);
+
+ }
+ break;
+ case 89: {
+ /* x509-end-cert */
+
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ xc->end_cert(ENG->x509ctx);
+
+ }
+ break;
+ case 90: {
+ /* x509-end-chain */
+
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ T0_PUSH(xc->end_chain(ENG->x509ctx));
+
+ }
+ break;
+ case 91: {
+ /* x509-start-cert */
+
+ const br_x509_class *xc;
+
+ xc = *(ENG->x509ctx);
+ xc->start_cert(ENG->x509ctx, T0_POP());
+
+ }
+ break;
+ case 92: {
+ /* x509-start-chain */
+
+ const br_x509_class *xc;
+ uint32_t bc;
+
+ bc = T0_POP();
+ xc = *(ENG->x509ctx);
+ xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL);
+
+ }
+ break;
+ }
+
+ } else {
+ T0_ENTER(ip, rp, t0x);
+ }
+ }
+t0_exit:
+ ((t0_context *)t0ctx)->dp = dp;
+ ((t0_context *)t0ctx)->rp = rp;
+ ((t0_context *)t0ctx)->ip = ip;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_hs_server.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_hs_server.t0
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_hs_server.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_hs_server.t0 (revision 346145)
@@ -0,0 +1,1510 @@
+\ 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.
+
+\ ----------------------------------------------------------------------
+\ Handshake processing code, for the server.
+\ The common T0 code (ssl_hs_common.t0) shall be read first.
+
+preamble {
+
+/*
+ * This macro evaluates to a pointer to the server context, under that
+ * specific name. It must be noted that since the engine context is the
+ * first field of the br_ssl_server_context structure ('eng'), then
+ * pointers values of both types are interchangeable, modulo an
+ * appropriate cast. This also means that "addresses" computed as offsets
+ * within the structure work for both kinds of context.
+ */
+#define CTX ((br_ssl_server_context *)ENG)
+
+/*
+ * Decrypt the pre-master secret (RSA key exchange).
+ */
+static void
+do_rsa_decrypt(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *epms, size_t len)
+{
+ uint32_t x;
+ unsigned char rpms[48];
+
+ /*
+ * Decrypt the PMS.
+ */
+ x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, epms, &len);
+
+ /*
+ * Set the first two bytes to the maximum supported client
+ * protocol version. These bytes are used for version rollback
+ * detection; forceing the two bytes will make the master secret
+ * wrong if the bytes are not correct. This process is
+ * recommended by RFC 5246 (section 7.4.7.1).
+ */
+ br_enc16be(epms, ctx->client_max_version);
+
+ /*
+ * Make a random PMS and copy it above the decrypted value if the
+ * decryption failed. Note that we use a constant-time conditional
+ * copy.
+ */
+ br_hmac_drbg_generate(&ctx->eng.rng, rpms, sizeof rpms);
+ br_ccopy(x ^ 1, epms, rpms, sizeof rpms);
+
+ /*
+ * Compute master secret.
+ */
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, epms, 48);
+
+ /*
+ * Clear the pre-master secret from RAM: it is normally a buffer
+ * in the context, hence potentially long-lived.
+ */
+ memset(epms, 0, len);
+}
+
+/*
+ * Common part for ECDH and ECDHE.
+ */
+static void
+ecdh_common(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *xcoor, size_t xcoor_len, uint32_t ctl)
+{
+ unsigned char rpms[80];
+
+ if (xcoor_len > sizeof rpms) {
+ xcoor_len = sizeof rpms;
+ ctl = 0;
+ }
+
+ /*
+ * Make a random PMS and copy it above the decrypted value if the
+ * decryption failed. Note that we use a constant-time conditional
+ * copy.
+ */
+ br_hmac_drbg_generate(&ctx->eng.rng, rpms, xcoor_len);
+ br_ccopy(ctl ^ 1, xcoor, rpms, xcoor_len);
+
+ /*
+ * Compute master secret.
+ */
+ br_ssl_engine_compute_master(&ctx->eng, prf_id, xcoor, xcoor_len);
+
+ /*
+ * Clear the pre-master secret from RAM: it is normally a buffer
+ * in the context, hence potentially long-lived.
+ */
+ memset(xcoor, 0, xcoor_len);
+}
+
+/*
+ * Do the ECDH key exchange (not ECDHE).
+ */
+static void
+do_ecdh(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *cpoint, size_t cpoint_len)
+{
+ uint32_t x;
+
+ /*
+ * Finalise the key exchange.
+ */
+ x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable,
+ cpoint, &cpoint_len);
+ ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
+}
+
+/*
+ * Do the full static ECDH key exchange. When this function is called,
+ * it has already been verified that the cipher suite uses ECDH (not ECDHE),
+ * and the client's public key (from its certificate) has type EC and is
+ * apt for key exchange.
+ */
+static void
+do_static_ecdh(br_ssl_server_context *ctx, int prf_id)
+{
+ unsigned char cpoint[133];
+ size_t cpoint_len;
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ cpoint_len = pk->key.ec.qlen;
+ if (cpoint_len > sizeof cpoint) {
+ /*
+ * If the point is larger than our buffer then we need to
+ * restrict it. Length 2 is not a valid point length, so
+ * the ECDH will fail.
+ */
+ cpoint_len = 2;
+ }
+ memcpy(cpoint, pk->key.ec.q, cpoint_len);
+ do_ecdh(ctx, prf_id, cpoint, cpoint_len);
+}
+
+static size_t
+hash_data(br_ssl_server_context *ctx,
+ void *dst, int hash_id, const void *src, size_t len)
+{
+ const br_hash_class *hf;
+ br_hash_compat_context hc;
+
+ if (hash_id == 0) {
+ unsigned char tmp[36];
+
+ hf = br_multihash_getimpl(&ctx->eng.mhash, br_md5_ID);
+ if (hf == NULL) {
+ return 0;
+ }
+ hf->init(&hc.vtable);
+ hf->update(&hc.vtable, src, len);
+ hf->out(&hc.vtable, tmp);
+ hf = br_multihash_getimpl(&ctx->eng.mhash, br_sha1_ID);
+ if (hf == NULL) {
+ return 0;
+ }
+ hf->init(&hc.vtable);
+ hf->update(&hc.vtable, src, len);
+ hf->out(&hc.vtable, tmp + 16);
+ memcpy(dst, tmp, 36);
+ return 36;
+ } else {
+ hf = br_multihash_getimpl(&ctx->eng.mhash, hash_id);
+ if (hf == NULL) {
+ return 0;
+ }
+ hf->init(&hc.vtable);
+ hf->update(&hc.vtable, src, len);
+ hf->out(&hc.vtable, dst);
+ return (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+ }
+}
+
+/*
+ * Do the ECDHE key exchange (part 1: generation of transient key, and
+ * computing of the point to send to the client). Returned value is the
+ * signature length (in bytes), or -x on error (with x being an error
+ * code). The encoded point is written in the ecdhe_point[] context buffer
+ * (length in ecdhe_point_len).
+ */
+static int
+do_ecdhe_part1(br_ssl_server_context *ctx, int curve)
+{
+ unsigned algo_id;
+ unsigned mask;
+ const unsigned char *order;
+ size_t olen, glen;
+ size_t hv_len, sig_len;
+
+ if (!((ctx->eng.iec->supported_curves >> curve) & 1)) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+ ctx->eng.ecdhe_curve = curve;
+
+ /*
+ * Generate our private key. We need a non-zero random value
+ * which is lower than the curve order, in a "large enough"
+ * range. We force the top bit to 0 and bottom bit to 1, which
+ * does the trick. Note that contrary to what happens in ECDSA,
+ * this is not a problem if we do not cover the full range of
+ * possible values.
+ */
+ order = ctx->eng.iec->order(curve, &olen);
+ mask = 0xFF;
+ while (mask >= order[0]) {
+ mask >>= 1;
+ }
+ br_hmac_drbg_generate(&ctx->eng.rng, ctx->ecdhe_key, olen);
+ ctx->ecdhe_key[0] &= mask;
+ ctx->ecdhe_key[olen - 1] |= 0x01;
+ ctx->ecdhe_key_len = olen;
+
+ /*
+ * Compute our ECDH point.
+ */
+ glen = ctx->eng.iec->mulgen(ctx->eng.ecdhe_point,
+ ctx->ecdhe_key, olen, curve);
+ ctx->eng.ecdhe_point_len = glen;
+
+ /*
+ * Assemble the message to be signed, and possibly hash it.
+ */
+ memcpy(ctx->eng.pad, ctx->eng.client_random, 32);
+ memcpy(ctx->eng.pad + 32, ctx->eng.server_random, 32);
+ ctx->eng.pad[64 + 0] = 0x03;
+ ctx->eng.pad[64 + 1] = 0x00;
+ ctx->eng.pad[64 + 2] = curve;
+ ctx->eng.pad[64 + 3] = ctx->eng.ecdhe_point_len;
+ memcpy(ctx->eng.pad + 64 + 4,
+ ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len);
+ hv_len = 64 + 4 + ctx->eng.ecdhe_point_len;
+ algo_id = ctx->sign_hash_id;
+ if (algo_id >= (unsigned)0xFF00) {
+ hv_len = hash_data(ctx, ctx->eng.pad, algo_id & 0xFF,
+ ctx->eng.pad, hv_len);
+ if (hv_len == 0) {
+ return -BR_ERR_INVALID_ALGORITHM;
+ }
+ }
+
+ sig_len = (*ctx->policy_vtable)->do_sign(ctx->policy_vtable,
+ algo_id, ctx->eng.pad, hv_len, sizeof ctx->eng.pad);
+ return sig_len ? (int)sig_len : -BR_ERR_INVALID_ALGORITHM;
+}
+
+/*
+ * Do the ECDHE key exchange (part 2: computation of the shared secret
+ * from the point sent by the client).
+ */
+static void
+do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,
+ unsigned char *cpoint, size_t cpoint_len)
+{
+ int curve;
+ uint32_t ctl;
+ size_t xoff, xlen;
+
+ curve = ctx->eng.ecdhe_curve;
+
+ /*
+ * Finalise the key exchange.
+ */
+ ctl = ctx->eng.iec->mul(cpoint, cpoint_len,
+ ctx->ecdhe_key, ctx->ecdhe_key_len, curve);
+ xoff = ctx->eng.iec->xoff(curve, &xlen);
+ ecdh_common(ctx, prf_id, cpoint + xoff, xlen, ctl);
+
+ /*
+ * Clear the ECDHE private key. Forward Secrecy is achieved insofar
+ * as that key does not get stolen, so we'd better destroy it
+ * as soon as it ceases to be useful.
+ */
+ memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
+}
+
+/*
+ * Offset for hash value within the pad (when obtaining all hash values,
+ * in preparation for verification of the CertificateVerify message).
+ * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value
+ * is used to get the total length.
+ */
+static const unsigned char HASH_PAD_OFF[] = { 0, 16, 36, 64, 96, 144, 208 };
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+ 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+ HASH_OID_SHA1,
+ HASH_OID_SHA224,
+ HASH_OID_SHA256,
+ HASH_OID_SHA384,
+ HASH_OID_SHA512
+};
+
+/*
+ * Verify the signature in CertificateVerify. Returned value is 0 on
+ * success, or a non-zero error code. Lack of implementation of the
+ * designated signature algorithm is reported as a "bad signature"
+ * error (because it means that the peer did not honour our advertised
+ * set of supported signature algorithms).
+ */
+static int
+verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len)
+{
+ const br_x509_class **xc;
+ const br_x509_pkey *pk;
+ int id;
+
+ id = ctx->hash_CV_id;
+ xc = ctx->eng.x509ctx;
+ pk = (*xc)->get_pkey(xc, NULL);
+ if (pk->key_type == BR_KEYTYPE_RSA) {
+ unsigned char tmp[64];
+ const unsigned char *hash_oid;
+
+ if (id == 0) {
+ hash_oid = NULL;
+ } else {
+ hash_oid = HASH_OID[id - 2];
+ }
+ if (ctx->eng.irsavrfy == 0) {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
+ hash_oid, ctx->hash_CV_len, &pk->key.rsa, tmp)
+ || memcmp(tmp, ctx->hash_CV, ctx->hash_CV_len) != 0)
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ } else {
+ if (ctx->eng.iecdsa == 0) {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ if (!ctx->eng.iecdsa(ctx->eng.iec,
+ ctx->hash_CV, ctx->hash_CV_len,
+ &pk->key.ec, ctx->eng.pad, sig_len))
+ {
+ return BR_ERR_BAD_SIGNATURE;
+ }
+ }
+ return 0;
+}
+
+}
+
+\ =======================================================================
+
+: addr-ctx:
+ next-word { field }
+ "addr-" field + 0 1 define-word
+ 0 8191 "offsetof(br_ssl_server_context, " field + ")" + make-CX
+ postpone literal postpone ; ;
+
+addr-ctx: client_max_version
+addr-ctx: client_suites
+addr-ctx: client_suites_num
+addr-ctx: hashes
+addr-ctx: curves
+addr-ctx: sign_hash_id
+
+\ Get address and length of the client_suites[] buffer. Length is expressed
+\ in bytes.
+: addr-len-client_suites ( -- addr len )
+ addr-client_suites
+ CX 0 1023 { BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated) } ;
+
+\ Read the client SNI extension.
+: read-client-sni ( lim -- lim )
+ \ Open extension value.
+ read16 open-elt
+
+ \ Open ServerNameList.
+ read16 open-elt
+
+ \ Find if there is a name of type 0 (host_name) with a length
+ \ that fits in our dedicated buffer.
+ begin dup while
+ read8 if
+ read-ignore-16
+ else
+ read16
+ dup 255 <= if
+ dup addr-server_name + 0 swap set8
+ addr-server_name swap read-blob
+ else
+ skip-blob
+ then
+ then
+ repeat
+
+ \ Close ServerNameList.
+ close-elt
+
+ \ Close extension value.
+ close-elt ;
+
+\ Set the new maximum fragment length. BEWARE: this shall be called only
+\ after reading the ClientHello and before writing the ServerHello.
+cc: set-max-frag-len ( len -- ) {
+ size_t max_frag_len = T0_POP();
+
+ br_ssl_engine_new_max_frag_len(ENG, max_frag_len);
+
+ /*
+ * We must adjust our own output limit. Since we call this only
+ * after receiving a ClientHello and before beginning to send
+ * the ServerHello, the next output record should be empty at
+ * that point, so we can use max_frag_len as a limit.
+ */
+ if (ENG->hlen_out > max_frag_len) {
+ ENG->hlen_out = max_frag_len;
+ }
+}
+
+\ Read the client Max Frag Length extension.
+: read-client-frag ( lim -- lim )
+ \ Extension value must have length exactly 1 byte.
+ read16 1 <> if ERR_BAD_FRAGLEN fail then
+ read8
+
+ \ The byte value must be 1, 2, 3 or 4.
+ dup dup 0= swap 5 >= or if ERR_BAD_FRAGLEN fail then
+
+ \ If our own maximum fragment length is greater, then we reduce
+ \ our length.
+ 8 + dup addr-log_max_frag_len get8 < if
+ dup 1 swap << set-max-frag-len
+ dup addr-log_max_frag_len set8
+ addr-peer_log_max_frag_len set8
+ else
+ drop
+ then ;
+
+\ Read the Secure Renegotiation extension from the client.
+: read-client-reneg ( lim -- lim )
+ \ Get value length.
+ read16
+
+ \ The "reneg" value is one of:
+ \ 0 on first handshake, client support is unknown
+ \ 1 client does not support secure renegotiation
+ \ 2 client supports secure renegotiation
+ addr-reneg get8 case
+ 0 of
+ \ First handshake, value length shall be 1.
+ 1 = ifnot ERR_BAD_SECRENEG fail then
+ read8 if ERR_BAD_SECRENEG fail then
+ 2 addr-reneg set8
+ endof
+ 2 of
+ \ Renegotiation, value shall consist of 13 bytes
+ \ (header + copy of the saved client "Finished").
+ 13 = ifnot ERR_BAD_SECRENEG fail then
+ read8 12 = ifnot ERR_BAD_SECRENEG fail then
+ addr-pad 12 read-blob
+ addr-saved_finished addr-pad 12 memcmp ifnot
+ ERR_BAD_SECRENEG fail
+ then
+ endof
+
+ \ If "reneg" is 1 then the client is not supposed to support
+ \ the extension, and it sends it nonetheless, which means
+ \ foul play.
+ ERR_BAD_SECRENEG fail
+ endcase ;
+
+\ Read the Signature Algorithms extension.
+: read-signatures ( lim -- lim )
+ \ Open extension value.
+ read16 open-elt
+
+ read-list-sign-algos addr-hashes set32
+
+ \ Close extension value.
+ close-elt ;
+
+\ Read the Supported Curves extension.
+: read-supported-curves ( lim -- lim )
+ \ Open extension value.
+ read16 open-elt
+
+ \ Open list of curve identifiers.
+ read16 open-elt
+
+ \ Get all supported curves.
+ 0 addr-curves set32
+ begin dup while
+ read16 dup 32 < if
+ 1 swap << addr-curves get32 or addr-curves set32
+ else
+ drop
+ then
+ repeat
+ close-elt
+ close-elt ;
+
+\ Read the ALPN extension from client.
+: read-ALPN-from-client ( lim -- lim )
+ \ If we do not have configured names, then we just ignore the
+ \ extension.
+ addr-protocol_names_num get16 ifnot read-ignore-16 ret then
+
+ \ Open extension value.
+ read16 open-elt
+
+ \ Open list of protocol names.
+ read16 open-elt
+
+ \ Get all names and test for their support. We keep the one with
+ \ the lowest index (because we apply server's preferences, as
+ \ recommended by RFC 7301, section 3.2. We set the 'found' variable
+ \ to -2 and use an unsigned comparison, making -2 a huge value.
+ -2 { found }
+ begin dup while
+ read8 dup { len } addr-pad swap read-blob
+ len test-protocol-name dup found u< if
+ >found
+ else
+ drop
+ then
+ repeat
+
+ \ End of extension.
+ close-elt
+ close-elt
+
+ \ Write back found name index (or not). If no match was found,
+ \ then we write -1 (0xFFFF) in the index value, not 0, so that
+ \ the caller knows that we tried to match, and failed.
+ found 1+ addr-selected_protocol set16 ;
+
+\ Call policy handler to get cipher suite, hash function identifier and
+\ certificate chain. Returned value is 0 (false) on failure.
+cc: call-policy-handler ( -- bool ) {
+ int x;
+ br_ssl_server_choices choices;
+
+ x = (*CTX->policy_vtable)->choose(
+ CTX->policy_vtable, CTX, &choices);
+ ENG->session.cipher_suite = choices.cipher_suite;
+ CTX->sign_hash_id = choices.algo_id;
+ ENG->chain = choices.chain;
+ ENG->chain_len = choices.chain_len;
+ T0_PUSHi(-(x != 0));
+}
+
+\ Check for a remembered session.
+cc: check-resume ( -- bool ) {
+ if (ENG->session.session_id_len == 32
+ && CTX->cache_vtable != NULL && (*CTX->cache_vtable)->load(
+ CTX->cache_vtable, CTX, &ENG->session))
+ {
+ T0_PUSHi(-1);
+ } else {
+ T0_PUSH(0);
+ }
+}
+
+\ Save the current session.
+cc: save-session ( -- ) {
+ if (CTX->cache_vtable != NULL) {
+ (*CTX->cache_vtable)->save(
+ CTX->cache_vtable, CTX, &ENG->session);
+ }
+}
+
+\ Read and drop ClientHello. This is used when a client-triggered
+\ renegotiation attempt is rejected.
+: skip-ClientHello ( -- )
+ read-handshake-header-core
+ 1 = ifnot ERR_UNEXPECTED fail then
+ dup skip-blob drop ;
+
+\ Read ClientHello. If the session is resumed, then -1 is returned.
+: read-ClientHello ( -- resume )
+ \ Get header, and check message type.
+ read-handshake-header 1 = ifnot ERR_UNEXPECTED fail then
+
+ \ Get maximum protocol version from client.
+ read16 dup { client-version-max } addr-client_max_version set16
+
+ \ Client random.
+ addr-client_random 32 read-blob
+
+ \ Client session ID.
+ read8 dup 32 > if ERR_OVERSIZED_ID fail then
+ dup addr-session_id_len set8
+ addr-session_id swap read-blob
+
+ \ Lookup session for resumption. We should do that here because
+ \ we need to verify that the remembered cipher suite is still
+ \ matched by this ClientHello.
+ check-resume { resume }
+
+ \ Cipher suites. We read all cipher suites from client, each time
+ \ matching against our own list. We accumulate suites in the
+ \ client_suites[] context buffer: we keep suites that are
+ \ supported by both the client and the server (so the list size
+ \ cannot exceed that of the server list), and we keep them in
+ \ either client or server preference order (depending on the
+ \ relevant flag).
+ \
+ \ We also need to identify the pseudo cipher suite for secure
+ \ renegotiation here.
+ read16 open-elt
+ 0 { reneg-scsv }
+ 0 { resume-suite }
+ addr-len-client_suites dup2 bzero
+ over + { css-off css-max }
+ begin
+ dup while
+ read16 dup { suite }
+
+ \ Check that when resuming a session, the requested
+ \ suite is still valid.
+ resume if
+ dup addr-cipher_suite get16 = if
+ -1 >resume-suite
+ then
+ then
+
+ \ Special handling for TLS_EMPTY_RENEGOTIATION_INFO_SCSV.
+ \ This fake cipher suite may occur only in the first
+ \ handshake.
+ dup 0x00FF = if
+ addr-reneg get8 if ERR_BAD_SECRENEG fail then
+ -1 >reneg-scsv
+ then
+
+ \ Special handling for TLS_FALLBACK_SCSV. If the client
+ \ maximum version is less than our own maximum version,
+ \ then this is an undue downgrade. We mark it by setting
+ \ the client max version to 0x10000.
+ dup 0x5600 = if
+ client-version-max addr-version_min get16 >=
+ client-version-max addr-version_max get16 < and if
+ -1 >client-version-max
+ then
+ then
+
+ \ Test whether the suite is supported by the server.
+ scan-suite dup 0< if
+ \ We do not support this cipher suite. Note
+ \ that this also covers the case of pseudo
+ \ cipher suites.
+ drop
+ else
+ \ If we use server order, then we place the
+ \ suite at the computed offset; otherwise, we
+ \ append it to the list at the current place.
+ 0 flag? if
+ 2 << addr-client_suites + suite swap set16
+ else
+ drop
+ \ We need to test for list length because
+ \ the client list may have duplicates,
+ \ that we do not filter. Duplicates are
+ \ invalid so this is not a problem if we
+ \ reject such clients.
+ css-off css-max >= if
+ ERR_BAD_HANDSHAKE fail
+ then
+ suite css-off set16
+ css-off 4 + >css-off
+ then
+ then
+ repeat
+ drop
+
+ \ Compression methods. We need method 0 (no compression).
+ 0 { ok-compression }
+ read8 open-elt
+ begin dup while
+ read8 ifnot -1 >ok-compression then
+ repeat
+ close-elt
+
+ \ Set default values for parameters that may be affected by
+ \ extensions:
+ \ -- server name is empty
+ \ -- client is reputed to know RSA and ECDSA, both with SHA-1
+ \ -- the default elliptic curve is P-256 (secp256r1, id = 23)
+ 0 addr-server_name set8
+ 0x0404 addr-hashes set32
+ 0x800000 addr-curves set32
+
+ \ Process extensions, if any.
+ dup if
+ read16 open-elt
+ begin dup while
+ read16 case
+ \ Server Name Indication.
+ 0x0000 of
+ read-client-sni
+ endof
+ \ Max Frag Length.
+ 0x0001 of
+ read-client-frag
+ endof
+ \ Secure Renegotiation.
+ 0xFF01 of
+ read-client-reneg
+ endof
+ \ Signature Algorithms.
+ 0x000D of
+ read-signatures
+ endof
+ \ Supported Curves.
+ 0x000A of
+ read-supported-curves
+ endof
+ \ Supported Point Formats.
+ \ We only support "uncompressed", that all
+ \ implementations are supposed to support,
+ \ so we can simply ignore that extension.
+ \ 0x000B of
+ \ read-ignore-16
+ \ endof
+
+ \ ALPN
+ 0x0010 of
+ read-ALPN-from-client
+ endof
+
+ \ Other extensions are ignored.
+ drop read-ignore-16 0
+ endcase
+ repeat
+ close-elt
+ then
+
+ \ Close message.
+ close-elt
+
+ \ Cancel session resumption if the cipher suite was not found.
+ resume resume-suite and >resume
+
+ \ Now check the received data. Since the client is expecting an
+ \ answer, we can send an appropriate fatal alert on any error.
+
+ \ Compute protocol version as the minimum of our maximum version,
+ \ and the maximum version sent by the client. If that is less than
+ \ 0x0300 (SSL-3.0), then fail. Otherwise, we may at least send an
+ \ alert with that version. We still reject versions lower than our
+ \ configured minimum.
+ \ As a special case, in case of undue downgrade, we send a specific
+ \ alert (see RFC 7507). Note that this case may happen only if
+ \ we would otherwise accept the client's version.
+ client-version-max 0< if
+ addr-client_max_version get16 addr-version_out set16
+ 86 fail-alert
+ then
+ addr-version_max get16
+ dup client-version-max > if drop client-version-max then
+ dup 0x0300 < if ERR_BAD_VERSION fail then
+ client-version-max addr-version_min get16 < if
+ 70 fail-alert
+ then
+ \ If resuming the session, then enforce the previously negotiated
+ \ version (if still possible).
+ resume if
+ addr-version get16 client-version-max <= if
+ drop addr-version get16
+ else
+ 0 >resume
+ then
+ then
+ dup addr-version set16
+ dup addr-version_in set16
+ dup addr-version_out set16
+ 0x0303 >= { can-tls12 }
+
+ \ If the client sent TLS_EMPTY_RENEGOTIATION_INFO_SCSV, then
+ \ we should mark the client as "supporting secure renegotiation".
+ reneg-scsv if 2 addr-reneg set8 then
+
+ \ If, at that point, the 'reneg' value is still 0, then the client
+ \ did not send the extension or the SCSV, so we have to assume
+ \ that secure renegotiation is not supported by that client.
+ addr-reneg get8 ifnot 1 addr-reneg set8 then
+
+ \ Check compression.
+ ok-compression ifnot 40 fail-alert then
+
+ \ Filter hash function support by what the server also supports.
+ \ If no common hash function remains with RSA and/or ECDSA, then
+ \ the corresponding ECDHE suites are not possible.
+ supported-hash-functions drop 257 * 0xFFFF0000 or
+ addr-hashes get32 and dup addr-hashes set32
+ \ In 'can-ecdhe', bit 12 is set if ECDHE_RSA is possible, bit 13 is
+ \ set if ECDHE_ECDSA is possible.
+ dup 0xFF and 0<> neg
+ swap 8 >> 0<> 2 and or 12 << { can-ecdhe }
+
+ \ Filter supported curves. If there is no common curve between
+ \ client and us, then ECDHE suites cannot be used. Note that we
+ \ may still allow ECDH, depending on the EC key handler.
+ addr-curves get32 supported-curves and dup addr-curves set32
+ ifnot 0 >can-ecdhe then
+
+ \ If resuming a session, then the next steps are not necessary;
+ \ we won't invoke the policy handler.
+ resume if -1 ret then
+
+ \ We are not resuming, so a new session ID should be generated.
+ \ We don't check that the new ID is distinct from the one sent
+ \ by the client because probability of such an event is 2^(-256),
+ \ i.e. much (much) lower than that of an undetected transmission
+ \ error or hardware miscomputation, and with similar consequences
+ \ (handshake simply fails).
+ addr-session_id 32 mkrand
+ 32 addr-session_id_len set8
+
+ \ Translate common cipher suites, then squeeze out holes: there
+ \ may be holes because of the way we fill the list when the
+ \ server preference order is enforced, and also in case some
+ \ suites are filtered out. In particular:
+ \ -- ECDHE suites are removed if there is no common hash function
+ \ (for the relevant signature algorithm) or no common curve.
+ \ -- TLS-1.2-only suites are removed if the negotiated version is
+ \ TLS-1.1 or lower.
+ addr-client_suites dup >css-off
+ begin dup css-max < while
+ dup get16 dup cipher-suite-to-elements
+ dup 12 >> dup 1 = swap 2 = or if
+ dup can-ecdhe and ifnot
+ 2drop 0 dup
+ then
+ then
+ can-tls12 ifnot
+ \ Suites compatible with TLS-1.0 and TLS-1.1 are
+ \ exactly the ones that use HMAC/SHA-1.
+ dup 0xF0 and 0x20 <> if
+ 2drop 0 dup
+ then
+ then
+ dup if
+ css-off 2+ set16 css-off set16
+ css-off 4 + >css-off
+ else
+ 2drop
+ then
+ 4 +
+ repeat
+ drop
+ css-off addr-client_suites - 2 >>
+ dup ifnot
+ \ No common cipher suite: handshake failure.
+ 40 fail-alert
+ then
+ addr-client_suites_num set8
+
+ \ Check ALPN.
+ addr-selected_protocol get16 0xFFFF = if
+ 3 flag? if 120 fail-alert then
+ 0 addr-selected_protocol set16
+ then
+
+ \ Call policy handler to obtain the cipher suite and other
+ \ parameters.
+ call-policy-handler ifnot 40 fail-alert then
+
+ \ We are not resuming a session.
+ 0 ;
+
+\ Write ServerHello.
+: write-ServerHello ( initial -- )
+ { initial }
+ \ Compute ServerHello length.
+ 2 write8 70
+
+ \ Compute length of Secure Renegotiation extension.
+ addr-reneg get8 2 = if
+ initial if 5 else 29 then
+ else
+ 0
+ then
+ { ext-reneg-len }
+
+ \ Compute length of Max Fragment Length extension.
+ addr-peer_log_max_frag_len get8 if 5 else 0 then
+ { ext-max-frag-len }
+
+ \ Compute length of ALPN extension. This also copy the
+ \ selected protocol name into the pad.
+ addr-selected_protocol get16 dup if 1- copy-protocol-name 7 + then
+ { ext-ALPN-len }
+
+ \ Adjust ServerHello length to account for the extensions.
+ ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if 2 + then +
+ write24
+
+ \ Protocol version
+ addr-version get16 write16
+
+ \ Server random
+ addr-server_random 4 bzero
+ addr-server_random 4 + 28 mkrand
+ addr-server_random 32 write-blob
+
+ \ Session ID
+ \ TODO: if we have no session cache at all, we might send here
+ \ an empty session ID. This would save a bit of network
+ \ bandwidth.
+ 32 write8
+ addr-session_id 32 write-blob
+
+ \ Cipher suite
+ addr-cipher_suite get16 write16
+
+ \ Compression method
+ 0 write8
+
+ \ Extensions
+ ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if
+ write16
+ ext-reneg-len dup if
+ 0xFF01 write16
+ 4 - dup write16
+ 1- addr-saved_finished swap write-blob-head8
+ else
+ drop
+ then
+ ext-max-frag-len if
+ 0x0001 write16
+ 1 write16 addr-peer_log_max_frag_len get8 8 - write8
+ then
+ ext-ALPN-len dup if
+ \ Note: the selected protocol name was previously
+ \ copied into the pad.
+ 0x0010 write16
+ 4 - dup write16
+ 2- dup write16
+ 1- addr-pad swap write-blob-head8
+ else
+ drop
+ then
+ else
+ drop
+ then ;
+
+\ Do the first part of ECDHE. Returned value is the computed signature
+\ length, or a negative error code on error.
+cc: do-ecdhe-part1 ( curve -- len ) {
+ int curve = T0_POPi();
+ T0_PUSHi(do_ecdhe_part1(CTX, curve));
+}
+
+\ Get index of first bit set to 1 (in low to high order).
+: lowest-1 ( bits -- n )
+ dup ifnot drop -1 ret then
+ 0 begin dup2 >> 1 and 0= while 1+ repeat
+ swap drop ;
+
+\ Write the Server Key Exchange message (if applicable).
+: write-ServerKeyExchange ( -- )
+ addr-cipher_suite get16 use-ecdhe? ifnot ret then
+
+ \ We must select an appropriate curve among the curves that
+ \ are supported both by us and the peer. Right now, we apply
+ \ a fixed preference order: Curve25519, P-256, P-384, P-521,
+ \ then the common curve with the lowest ID.
+ \ (TODO: add some option to make that behaviour configurable.)
+ \
+ \ This loop always terminates because previous processing made
+ \ sure that ECDHE suites are not selectable if there is no common
+ \ curve.
+ addr-curves get32
+ dup 0x20000000 and if
+ drop 29
+ else
+ dup 0x38000000 and dup if swap then
+ drop lowest-1
+ then
+ { curve-id }
+
+ \ Compute the signed curve point to send.
+ curve-id do-ecdhe-part1 dup 0< if neg fail then { sig-len }
+
+ \ If using TLS-1.2+, then the hash function and signature
+ \ algorithm are explicitly encoded in the message.
+ addr-version get16 0x0303 >= { tls1.2+ }
+
+ 12 write8
+ sig-len addr-ecdhe_point_len get8 + tls1.2+ 2 and + 6 + write24
+
+ \ Curve parameters: named curve with 16-bit ID.
+ 3 write8 curve-id write16
+
+ \ Public point.
+ addr-ecdhe_point addr-ecdhe_point_len get8 write-blob-head8
+
+ \ If TLS-1.2+, write hash and signature identifiers.
+ tls1.2+ if
+ \ sign_hash_id contains either a hash identifier,
+ \ or the complete 16-bit value to write.
+ addr-sign_hash_id get16
+ dup 0xFF00 < if
+ write16
+ else
+ 0xFF and write8
+ \ 'use-rsa-ecdhe?' returns -1 for RSA, 0 for
+ \ ECDSA. The byte on the wire shall be 1 for RSA,
+ \ 3 for ECDSA.
+ addr-cipher_suite get16 use-rsa-ecdhe? 1 << 3 + write8
+ then
+ then
+
+ \ Signature.
+ sig-len write16
+ addr-pad sig-len write-blob ;
+
+\ Get length of the list of anchor names to send to the client. The length
+\ includes the per-name 2-byte header, but _not_ the 2-byte header for
+\ the list itself. If no client certificate is requested, then this
+\ returns 0.
+cc: ta-names-total-length ( -- len ) {
+ size_t u, len;
+
+ len = 0;
+ if (CTX->ta_names != NULL) {
+ for (u = 0; u < CTX->num_tas; u ++) {
+ len += CTX->ta_names[u].len + 2;
+ }
+ } else if (CTX->tas != NULL) {
+ for (u = 0; u < CTX->num_tas; u ++) {
+ len += CTX->tas[u].dn.len + 2;
+ }
+ }
+ T0_PUSH(len);
+}
+
+\ Compute length and optionally write the contents of the list of
+\ supported client authentication methods.
+: write-list-auth ( do_write -- len )
+ 0
+ addr-cipher_suite get16 use-ecdh? if
+ 2+ over if 65 write8 66 write8 then
+ then
+ supports-rsa-sign? if 1+ over if 1 write8 then then
+ supports-ecdsa? if 1+ over if 64 write8 then then
+ swap drop ;
+
+: write-signhash-inner2 ( dow algo hashes len id -- dow algo hashes len )
+ { id }
+ over 1 id << and ifnot ret then
+ 2+
+ 3 pick if id write8 2 pick write8 then ;
+
+: write-signhash-inner1 ( dow algo hashes -- dow len )
+ 0
+ 4 write-signhash-inner2
+ 5 write-signhash-inner2
+ 6 write-signhash-inner2
+ 3 write-signhash-inner2
+ 2 write-signhash-inner2
+ -rot 2drop ;
+
+\ Compute length and optionally write the contents of the list of
+\ supported sign+hash algorithms.
+: write-list-signhash ( do_write -- len )
+ 0 { len }
+ \ If supporting neither RSA nor ECDSA in the engine, then we
+ \ will do only static ECDH, and thus we claim support for
+ \ everything (for the X.509 validator).
+ supports-rsa-sign? supports-ecdsa? or ifnot
+ 1 0x7C write-signhash-inner1 >len
+ 3 0x7C write-signhash-inner1 len +
+ swap drop ret
+ then
+ supports-rsa-sign? if
+ 1 supported-hash-functions drop
+ write-signhash-inner1 >len
+ then
+ supports-ecdsa? if
+ 3 supported-hash-functions drop
+ write-signhash-inner1 len + >len
+ then
+ drop len ;
+
+\ Initialise index for sending the list of anchor DN.
+cc: begin-ta-name-list ( -- ) {
+ CTX->cur_dn_index = 0;
+}
+
+\ Switch to next DN in the list. Returned value is the DN length, or -1
+\ if the end of the list was reached.
+cc: begin-ta-name ( -- len ) {
+ const br_x500_name *dn;
+ if (CTX->cur_dn_index >= CTX->num_tas) {
+ T0_PUSHi(-1);
+ } else {
+ if (CTX->ta_names == NULL) {
+ dn = &CTX->tas[CTX->cur_dn_index].dn;
+ } else {
+ dn = &CTX->ta_names[CTX->cur_dn_index];
+ }
+ CTX->cur_dn_index ++;
+ CTX->cur_dn = dn->data;
+ CTX->cur_dn_len = dn->len;
+ T0_PUSH(CTX->cur_dn_len);
+ }
+}
+
+\ Copy a chunk of the current DN into the pad. Returned value is the
+\ chunk length; this is 0 when the end of the current DN is reached.
+cc: copy-dn-chunk ( -- len ) {
+ size_t clen;
+
+ clen = CTX->cur_dn_len;
+ if (clen > sizeof ENG->pad) {
+ clen = sizeof ENG->pad;
+ }
+ memcpy(ENG->pad, CTX->cur_dn, clen);
+ CTX->cur_dn += clen;
+ CTX->cur_dn_len -= clen;
+ T0_PUSH(clen);
+}
+
+\ Write a CertificateRequest message.
+: write-CertificateRequest ( -- )
+ \ The list of client authentication types includes:
+ \ rsa_sign (1)
+ \ ecdsa_sign (64)
+ \ rsa_fixed_ecdh (65)
+ \ ecdsa_fixed_ecdh (66)
+ \ rsa_sign and ecdsa_sign require, respectively, RSA and ECDSA
+ \ support. Static ECDH requires that the cipher suite is ECDH.
+ \ When we ask for static ECDH, we always send both rsa_fixed_ecdh
+ \ and ecdsa_fixed_ecdh because what matters there is what the
+ \ X.509 engine may support, and we do not control that.
+ \
+ \ With TLS 1.2, we must also send a list of supported signature
+ \ and hash algorithms. That list is supposed to qualify both
+ \ the engine itself, and the X.509 validator, which are separate
+ \ in BearSSL. There again, we use the engine capabilities in that
+ \ list, and resort to a generic all-support list if only
+ \ static ECDH is accepted.
+ \
+ \ (In practice, client implementations tend to have at most one
+ \ or two certificates, and send the chain regardless of what
+ \ algorithms are used in it.)
+
+ 0 write-list-auth
+ addr-version get16 0x0303 >= if
+ 2+ 0 write-list-signhash +
+ then
+ ta-names-total-length + 3 +
+
+ \ Message header
+ 13 write8 write24
+
+ \ List of authentication methods
+ 0 write-list-auth write8 1 write-list-auth drop
+
+ \ For TLS 1.2+, list of sign+hash
+ addr-version get16 0x0303 >= if
+ 0 write-list-signhash write16 1 write-list-signhash drop
+ then
+
+ \ Trust anchor names
+ ta-names-total-length write16
+ begin-ta-name-list
+ begin
+ begin-ta-name
+ dup 0< if drop ret then write16
+ begin copy-dn-chunk dup while
+ addr-pad swap write-blob
+ repeat
+ drop
+ again ;
+
+\ Write the Server Hello Done message.
+: write-ServerHelloDone ( -- )
+ 14 write8 0 write24 ;
+
+\ Perform RSA decryption of the client-sent pre-master secret. The value
+\ is in the pad, and its length is provided as parameter.
+cc: do-rsa-decrypt ( len prf_id -- ) {
+ int prf_id = T0_POPi();
+ size_t len = T0_POP();
+ do_rsa_decrypt(CTX, prf_id, ENG->pad, len);
+}
+
+\ Perform ECDH (not ECDHE). The point from the client is in the pad, and
+\ its length is provided as parameter.
+cc: do-ecdh ( len prf_id -- ) {
+ int prf_id = T0_POPi();
+ size_t len = T0_POP();
+ do_ecdh(CTX, prf_id, ENG->pad, len);
+}
+
+\ Do the second part of ECDHE.
+cc: do-ecdhe-part2 ( len prf_id -- ) {
+ int prf_id = T0_POPi();
+ size_t len = T0_POP();
+ do_ecdhe_part2(CTX, prf_id, ENG->pad, len);
+}
+
+\ Perform static ECDH. The point from the client is the public key
+\ extracted from its certificate.
+cc: do-static-ecdh ( prf_id -- ) {
+ do_static_ecdh(CTX, T0_POP());
+}
+
+\ Read a ClientKeyExchange header.
+: read-ClientKeyExchange-header ( -- len )
+ read-handshake-header 16 = ifnot ERR_UNEXPECTED fail then ;
+
+\ Read the Client Key Exchange contents (non-empty case).
+: read-ClientKeyExchange-contents ( lim -- )
+ \ What we should get depends on the cipher suite.
+ addr-cipher_suite get16 use-rsa-keyx? if
+ \ RSA key exchange: we expect a RSA-encrypted value.
+ read16
+ dup 512 > if ERR_LIMIT_EXCEEDED fail then
+ dup { enc-rsa-len }
+ addr-pad swap read-blob
+ enc-rsa-len addr-cipher_suite get16 prf-id do-rsa-decrypt
+ then
+ addr-cipher_suite get16 dup use-ecdhe? swap use-ecdh? { ecdhe ecdh }
+ ecdh ecdhe or if
+ \ ECDH or ECDHE key exchange: we expect an EC point.
+ read8 dup { ec-point-len }
+ addr-pad swap read-blob
+ ec-point-len addr-cipher_suite get16 prf-id
+ ecdhe if do-ecdhe-part2 else do-ecdh then
+ then
+ close-elt ;
+
+\ Read the Client Key Exchange (normal case).
+: read-ClientKeyExchange ( -- )
+ read-ClientKeyExchange-header
+ read-ClientKeyExchange-contents ;
+
+\ Obtain all possible hash values for handshake messages so far. This
+\ is done because we need the hash value for the CertificateVerify
+\ _before_ knowing which hash function will actually be used, as this
+\ information is obtained from decoding the message header itself.
+\ All hash values are stored in the pad (208 bytes in total).
+cc: compute-hash-CV ( -- ) {
+ int i;
+
+ for (i = 1; i <= 6; i ++) {
+ br_multihash_out(&ENG->mhash, i,
+ ENG->pad + HASH_PAD_OFF[i - 1]);
+ }
+}
+
+\ Copy the proper hash value from the pad into the dedicated buffer.
+\ Returned value is true (-1) on success, false (0) on error (error
+\ being an unimplemented hash function). The id has already been verified
+\ to be either 0 (for MD5+SHA-1) or one of the SHA-* functions.
+cc: copy-hash-CV ( hash_id -- bool ) {
+ int id = T0_POP();
+ size_t off, len;
+
+ if (id == 0) {
+ off = 0;
+ len = 36;
+ } else {
+ if (br_multihash_getimpl(&ENG->mhash, id) == 0) {
+ T0_PUSH(0);
+ T0_RET();
+ }
+ off = HASH_PAD_OFF[id - 1];
+ len = HASH_PAD_OFF[id] - off;
+ }
+ memcpy(CTX->hash_CV, ENG->pad + off, len);
+ CTX->hash_CV_len = len;
+ CTX->hash_CV_id = id;
+ T0_PUSHi(-1);
+}
+
+\ Verify signature in CertificateVerify. Output is 0 on success, or a
+\ non-zero error code.
+cc: verify-CV-sig ( sig-len -- err ) {
+ int err;
+
+ err = verify_CV_sig(CTX, T0_POP());
+ T0_PUSHi(err);
+}
+
+\ Process static ECDH.
+: process-static-ECDH ( ktu -- )
+ \ Static ECDH is allowed only if the cipher suite uses ECDH, and
+ \ the client's public key has type EC and allows key exchange.
+ \ BR_KEYTYPE_KEYX is 0x10, and BR_KEYTYPE_EC is 2.
+ 0x1F and 0x12 = ifnot ERR_WRONG_KEY_USAGE fail then
+ addr-cipher_suite get16
+ dup use-ecdh? ifnot ERR_UNEXPECTED fail then
+ prf-id
+ do-static-ecdh ;
+
+\ Read CertificateVerify header.
+: read-CertificateVerify-header ( -- lim )
+ compute-hash-CV
+ read-handshake-header 15 = ifnot ERR_UNEXPECTED fail then ;
+
+\ Read CertificateVerify. The client key type + usage is expected on the
+\ stack.
+: read-CertificateVerify ( ktu -- )
+ \ Check that the key allows for signatures.
+ dup 0x20 and ifnot ERR_WRONG_KEY_USAGE fail then
+ 0x0F and { key-type }
+
+ \ Get header.
+ read-CertificateVerify-header
+
+ \ With TLS 1.2+, there is an explicit hash + signature indication,
+ \ which must be compatible with the key type.
+ addr-version get16 0x0303 >= if
+ \ Get hash function, then signature algorithm. The
+ \ signature algorithm is 1 (RSA) or 3 (ECDSA) while our
+ \ symbolic constants for key types are 1 (RSA) or 2 (EC).
+ read16
+ dup 0xFF and 1+ 1 >> key-type = ifnot
+ ERR_BAD_SIGNATURE fail
+ then
+ 8 >>
+
+ \ We support only SHA-1, SHA-224, SHA-256, SHA-384
+ \ and SHA-512. We explicitly reject MD5.
+ dup 2 < over 6 > or if ERR_INVALID_ALGORITHM fail then
+ else
+ \ With TLS 1.0 and 1.1, hash is MD5+SHA-1 (0) for RSA,
+ \ SHA-1 (2) for ECDSA.
+ key-type 0x01 = if 0 else 2 then
+ then
+ copy-hash-CV ifnot ERR_INVALID_ALGORITHM fail then
+
+ \ Read signature.
+ read16 dup { sig-len }
+ dup 512 > if ERR_LIMIT_EXCEEDED fail then
+ addr-pad swap read-blob
+ sig-len verify-CV-sig
+ dup if fail then drop
+
+ close-elt ;
+
+\ Send a HelloRequest.
+: send-HelloRequest ( -- )
+ flush-record
+ begin can-output? not while wait-co drop repeat
+ 22 addr-record_type_out set8
+ 0 write8 0 write24 flush-record
+ 23 addr-record_type_out set8 ;
+
+\ Make a handshake.
+: do-handshake ( initial -- )
+ 0 addr-application_data set8
+ 22 addr-record_type_out set8
+ 0 addr-selected_protocol set16
+ multihash-init
+ read-ClientHello
+ more-incoming-bytes? if ERR_UNEXPECTED fail then
+ if
+ \ Session resumption
+ write-ServerHello
+ 0 write-CCS-Finished
+ 0 read-CCS-Finished
+ else
+ \ Not a session resumption
+ write-ServerHello
+ write-Certificate drop
+ write-ServerKeyExchange
+ ta-names-total-length if
+ write-CertificateRequest
+ then
+ write-ServerHelloDone
+ flush-record
+
+ \ If we sent a CertificateRequest then we expect a
+ \ Certificate message.
+ ta-names-total-length if
+ \ Read client certificate.
+ 0 read-Certificate
+
+ choice
+ dup 0< uf
+ \ Client certificate validation failed.
+ 2 flag? ifnot neg fail then
+ drop
+ read-ClientKeyExchange
+ read-CertificateVerify-header
+ dup skip-blob drop
+ enduf
+ dup 0= uf
+ \ Client sent no certificate at all.
+ drop
+ 2 flag? ifnot
+ ERR_NO_CLIENT_AUTH fail
+ then
+ read-ClientKeyExchange
+ enduf
+
+ \ Client certificate was validated.
+ read-ClientKeyExchange-header
+ dup ifnot
+ \ Empty ClientKeyExchange.
+ drop
+ process-static-ECDH
+ else
+ read-ClientKeyExchange-contents
+ read-CertificateVerify
+ then
+ endchoice
+ else
+ \ No client certificate request, we just expect
+ \ a non-empty ClientKeyExchange.
+ read-ClientKeyExchange
+ then
+ 0 read-CCS-Finished
+ 0 write-CCS-Finished
+ save-session
+ then
+ 1 addr-application_data set8
+ 23 addr-record_type_out set8 ;
+
+\ Entry point.
+: main ( -- ! )
+ \ Perform initial handshake.
+ -1 do-handshake
+
+ begin
+ \ Wait for further invocation. At that point, we should
+ \ get either an explicit call for renegotiation, or
+ \ an incoming ClientHello handshake message.
+ wait-co
+ dup 0x07 and case
+ 0x00 of
+ 0x10 and if
+ \ The best we can do is ask for a
+ \ renegotiation, then wait for it
+ \ to happen.
+ 0 addr-application_data set8
+ send-HelloRequest
+ then
+ endof
+ 0x01 of
+ \ Reject renegotiations if the peer does not
+ \ support secure renegotiation, or if the
+ \ "no renegotiation" flag is set.
+ drop
+ addr-reneg get8 1 = 1 flag? or if
+ skip-ClientHello
+ flush-record
+ begin can-output? not while
+ wait-co drop
+ repeat
+ 100 send-warning
+ \ Put back connection in "application
+ \ data" state: it's not dead yet.
+ 1 addr-application_data set8
+ 23 addr-record_type_out set8
+ else
+ 0 do-handshake
+ then
+ endof
+ ERR_UNEXPECTED fail
+ endcase
+ again
+ ;
Index: stable/12/contrib/bearssl/src/ssl/ssl_io.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_io.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_io.c (revision 346145)
@@ -0,0 +1,261 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_sslio_init(br_sslio_context *ctx,
+ br_ssl_engine_context *engine,
+ int (*low_read)(void *read_context,
+ unsigned char *data, size_t len),
+ void *read_context,
+ int (*low_write)(void *write_context,
+ const unsigned char *data, size_t len),
+ void *write_context)
+{
+ ctx->engine = engine;
+ ctx->low_read = low_read;
+ ctx->read_context = read_context;
+ ctx->low_write = low_write;
+ ctx->write_context = write_context;
+}
+
+/*
+ * Run the engine, until the specified target state is achieved, or
+ * an error occurs. The target state is SENDAPP, RECVAPP, or the
+ * combination of both (the combination matches either). When a match is
+ * achieved, this function returns 0. On error, it returns -1.
+ */
+static int
+run_until(br_sslio_context *ctx, unsigned target)
+{
+ for (;;) {
+ unsigned state;
+
+ state = br_ssl_engine_current_state(ctx->engine);
+ if (state & BR_SSL_CLOSED) {
+ return -1;
+ }
+
+ /*
+ * If there is some record data to send, do it. This takes
+ * precedence over everything else.
+ */
+ if (state & BR_SSL_SENDREC) {
+ unsigned char *buf;
+ size_t len;
+ int wlen;
+
+ buf = br_ssl_engine_sendrec_buf(ctx->engine, &len);
+ wlen = ctx->low_write(ctx->write_context, buf, len);
+ if (wlen < 0) {
+ /*
+ * If we received a close_notify and we
+ * still send something, then we have our
+ * own response close_notify to send, and
+ * the peer is allowed by RFC 5246 not to
+ * wait for it.
+ */
+ if (!ctx->engine->shutdown_recv) {
+ br_ssl_engine_fail(
+ ctx->engine, BR_ERR_IO);
+ }
+ return -1;
+ }
+ if (wlen > 0) {
+ br_ssl_engine_sendrec_ack(ctx->engine, wlen);
+ }
+ continue;
+ }
+
+ /*
+ * If we reached our target, then we are finished.
+ */
+ if (state & target) {
+ return 0;
+ }
+
+ /*
+ * If some application data must be read, and we did not
+ * exit, then this means that we are trying to write data,
+ * and that's not possible until the application data is
+ * read. This may happen if using a shared in/out buffer,
+ * and the underlying protocol is not strictly half-duplex.
+ * This is unrecoverable here, so we report an error.
+ */
+ if (state & BR_SSL_RECVAPP) {
+ return -1;
+ }
+
+ /*
+ * If we reached that point, then either we are trying
+ * to read data and there is some, or the engine is stuck
+ * until a new record is obtained.
+ */
+ if (state & BR_SSL_RECVREC) {
+ unsigned char *buf;
+ size_t len;
+ int rlen;
+
+ buf = br_ssl_engine_recvrec_buf(ctx->engine, &len);
+ rlen = ctx->low_read(ctx->read_context, buf, len);
+ if (rlen < 0) {
+ br_ssl_engine_fail(ctx->engine, BR_ERR_IO);
+ return -1;
+ }
+ if (rlen > 0) {
+ br_ssl_engine_recvrec_ack(ctx->engine, rlen);
+ }
+ continue;
+ }
+
+ /*
+ * We can reach that point if the target RECVAPP, and
+ * the state contains SENDAPP only. This may happen with
+ * a shared in/out buffer. In that case, we must flush
+ * the buffered data to "make room" for a new incoming
+ * record.
+ */
+ br_ssl_engine_flush(ctx->engine, 0);
+ }
+}
+
+/* see bearssl_ssl.h */
+int
+br_sslio_read(br_sslio_context *ctx, void *dst, size_t len)
+{
+ unsigned char *buf;
+ size_t alen;
+
+ if (len == 0) {
+ return 0;
+ }
+ if (run_until(ctx, BR_SSL_RECVAPP) < 0) {
+ return -1;
+ }
+ buf = br_ssl_engine_recvapp_buf(ctx->engine, &alen);
+ if (alen > len) {
+ alen = len;
+ }
+ memcpy(dst, buf, alen);
+ br_ssl_engine_recvapp_ack(ctx->engine, alen);
+ return (int)alen;
+}
+
+/* see bearssl_ssl.h */
+int
+br_sslio_read_all(br_sslio_context *ctx, void *dst, size_t len)
+{
+ unsigned char *buf;
+
+ buf = dst;
+ while (len > 0) {
+ int rlen;
+
+ rlen = br_sslio_read(ctx, buf, len);
+ if (rlen < 0) {
+ return -1;
+ }
+ buf += rlen;
+ len -= (size_t)rlen;
+ }
+ return 0;
+}
+
+/* see bearssl_ssl.h */
+int
+br_sslio_write(br_sslio_context *ctx, const void *src, size_t len)
+{
+ unsigned char *buf;
+ size_t alen;
+
+ if (len == 0) {
+ return 0;
+ }
+ if (run_until(ctx, BR_SSL_SENDAPP) < 0) {
+ return -1;
+ }
+ buf = br_ssl_engine_sendapp_buf(ctx->engine, &alen);
+ if (alen > len) {
+ alen = len;
+ }
+ memcpy(buf, src, alen);
+ br_ssl_engine_sendapp_ack(ctx->engine, alen);
+ return (int)alen;
+}
+
+/* see bearssl_ssl.h */
+int
+br_sslio_write_all(br_sslio_context *ctx, const void *src, size_t len)
+{
+ const unsigned char *buf;
+
+ buf = src;
+ while (len > 0) {
+ int wlen;
+
+ wlen = br_sslio_write(ctx, buf, len);
+ if (wlen < 0) {
+ return -1;
+ }
+ buf += wlen;
+ len -= (size_t)wlen;
+ }
+ return 0;
+}
+
+/* see bearssl_ssl.h */
+int
+br_sslio_flush(br_sslio_context *ctx)
+{
+ /*
+ * We trigger a flush. We know the data is gone when there is
+ * no longer any record data to send, and we can either read
+ * or write application data. The call to run_until() does the
+ * job because it ensures that any assembled record data is
+ * first sent down the wire before considering anything else.
+ */
+ br_ssl_engine_flush(ctx->engine, 0);
+ return run_until(ctx, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
+}
+
+/* see bearssl_ssl.h */
+int
+br_sslio_close(br_sslio_context *ctx)
+{
+ br_ssl_engine_close(ctx->engine);
+ while (br_ssl_engine_current_state(ctx->engine) != BR_SSL_CLOSED) {
+ /*
+ * Discard any incoming application data.
+ */
+ size_t len;
+
+ run_until(ctx, BR_SSL_RECVAPP);
+ if (br_ssl_engine_recvapp_buf(ctx->engine, &len) != NULL) {
+ br_ssl_engine_recvapp_ack(ctx->engine, len);
+ }
+ }
+ return br_ssl_engine_last_error(ctx->engine) == BR_ERR_OK;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_io.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_keyexport.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_keyexport.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_keyexport.c (revision 346145)
@@ -0,0 +1,83 @@
+/*
+ * 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"
+
+/*
+ * Supported cipher suites that use SHA-384 for the PRF when selected
+ * for TLS 1.2. All other cipher suites are deemed to use SHA-256.
+ */
+static const uint16_t suites_sha384[] = {
+ BR_TLS_RSA_WITH_AES_256_GCM_SHA384,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+};
+
+/* see bearssl_ssl.h */
+int
+br_ssl_key_export(br_ssl_engine_context *cc,
+ void *dst, size_t len, const char *label,
+ const void *context, size_t context_len)
+{
+ br_tls_prf_seed_chunk chunks[4];
+ br_tls_prf_impl iprf;
+ size_t num_chunks, u;
+ unsigned char tmp[2];
+ int prf_id;
+
+ if (cc->application_data != 1) {
+ return 0;
+ }
+ chunks[0].data = cc->client_random;
+ chunks[0].len = sizeof cc->client_random;
+ chunks[1].data = cc->server_random;
+ chunks[1].len = sizeof cc->server_random;
+ if (context != NULL) {
+ br_enc16be(tmp, (unsigned)context_len);
+ chunks[2].data = tmp;
+ chunks[2].len = 2;
+ chunks[3].data = context;
+ chunks[3].len = context_len;
+ num_chunks = 4;
+ } else {
+ num_chunks = 2;
+ }
+ prf_id = BR_SSLPRF_SHA256;
+ for (u = 0; u < (sizeof suites_sha384) / sizeof(uint16_t); u ++) {
+ if (suites_sha384[u] == cc->session.cipher_suite) {
+ prf_id = BR_SSLPRF_SHA384;
+ }
+ }
+ iprf = br_ssl_engine_get_PRF(cc, prf_id);
+ iprf(dst, len,
+ cc->session.master_secret, sizeof cc->session.master_secret,
+ label, num_chunks, chunks);
+ return 1;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_keyexport.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_lru.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_lru.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_lru.c (revision 346145)
@@ -0,0 +1,537 @@
+/*
+ * 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"
+
+/*
+ * Each entry consists in a fixed number of bytes. Entries are concatenated
+ * in the store block. "Addresses" are really offsets in the block,
+ * expressed over 32 bits (so the cache may have size at most 4 GB, which
+ * "ought to be enough for everyone"). The "null address" is 0xFFFFFFFF.
+ * Note that since the storage block alignment is in no way guaranteed, we
+ * perform only accesses that can handle unaligned data.
+ *
+ * Two concurrent data structures are maintained:
+ *
+ * -- Entries are organised in a doubly-linked list; saved entries are added
+ * at the head, and loaded entries are moved to the head. Eviction uses
+ * the list tail (this is the LRU algorithm).
+ *
+ * -- Entries are indexed with a binary tree: all left descendants of a
+ * node have a lower session ID (in lexicographic order), while all
+ * right descendants have a higher session ID. The tree is heuristically
+ * balanced.
+ *
+ * Entry format:
+ *
+ * session ID 32 bytes
+ * master secret 48 bytes
+ * protocol version 2 bytes (big endian)
+ * cipher suite 2 bytes (big endian)
+ * list prev 4 bytes (big endian)
+ * list next 4 bytes (big endian)
+ * tree left child 4 bytes (big endian)
+ * tree right child 4 bytes (big endian)
+ *
+ * If an entry has a protocol version set to 0, then it is "disabled":
+ * it was a session pushed to the cache at some point, but it has
+ * been explicitly removed.
+ *
+ * We need to keep the tree balanced because an attacker could make
+ * handshakes, selecting some specific sessions (by reusing them) to
+ * try to make us make an imbalanced tree that makes lookups expensive
+ * (a denial-of-service attack that would persist as long as the cache
+ * remains, i.e. even after the attacker made all his connections).
+ * To do that, we replace the session ID (or the start of the session ID)
+ * with a HMAC value computed over the replaced part; the hash function
+ * implementation and the key are obtained from the server context upon
+ * first save() call.
+ *
+ * Theoretically, an attacker could use the exact timing of the lookup
+ * to infer the current tree topology, and try to revive entries to make
+ * it as unbalanced as possible. However, since the session ID are
+ * chosen randomly by the server, and the attacker cannot see the
+ * indexing values and must thus rely on blind selection, it should be
+ * exponentially difficult for the attacker to maintain a large
+ * imbalance.
+ */
+#define SESSION_ID_LEN 32
+#define MASTER_SECRET_LEN 48
+
+#define SESSION_ID_OFF 0
+#define MASTER_SECRET_OFF 32
+#define VERSION_OFF 80
+#define CIPHER_SUITE_OFF 82
+#define LIST_PREV_OFF 84
+#define LIST_NEXT_OFF 88
+#define TREE_LEFT_OFF 92
+#define TREE_RIGHT_OFF 96
+
+#define LRU_ENTRY_LEN 100
+
+#define ADDR_NULL ((uint32_t)-1)
+
+#define GETSET(name, off) \
+static inline uint32_t get_ ## name(br_ssl_session_cache_lru *cc, uint32_t x) \
+{ \
+ return br_dec32be(cc->store + x + (off)); \
+} \
+static inline void set_ ## name(br_ssl_session_cache_lru *cc, \
+ uint32_t x, uint32_t val) \
+{ \
+ br_enc32be(cc->store + x + (off), val); \
+}
+
+GETSET(prev, LIST_PREV_OFF)
+GETSET(next, LIST_NEXT_OFF)
+GETSET(left, TREE_LEFT_OFF)
+GETSET(right, TREE_RIGHT_OFF)
+
+/*
+ * Transform the session ID by replacing the first N bytes with a HMAC
+ * value computed over these bytes, using the random key K (the HMAC
+ * value is truncated if needed). HMAC will use the same hash function
+ * as the DRBG in the SSL server context, so with SHA-256, SHA-384,
+ * or SHA-1, depending on what is available.
+ *
+ * The risk of collision is considered too small to be a concern; and
+ * the impact of a collision is low (the handshake won't succeed). This
+ * risk is much lower than any transmission error, which would lead to
+ * the same consequences.
+ *
+ * Source and destination arrays msut be disjoint.
+ */
+static void
+mask_id(br_ssl_session_cache_lru *cc,
+ const unsigned char *src, unsigned char *dst)
+{
+ br_hmac_key_context hkc;
+ br_hmac_context hc;
+
+ memcpy(dst, src, SESSION_ID_LEN);
+ br_hmac_key_init(&hkc, cc->hash, cc->index_key, sizeof cc->index_key);
+ br_hmac_init(&hc, &hkc, SESSION_ID_LEN);
+ br_hmac_update(&hc, src, SESSION_ID_LEN);
+ br_hmac_out(&hc, dst);
+}
+
+/*
+ * Find a node by ID. Returned value is the node address, or ADDR_NULL if
+ * the node is not found.
+ *
+ * If addr_link is not NULL, then '*addr_link' is set to the address of the
+ * last followed link. If the found node is the root, or if the tree is
+ * empty, then '*addr_link' is set to ADDR_NULL.
+ */
+static uint32_t
+find_node(br_ssl_session_cache_lru *cc, const unsigned char *id,
+ uint32_t *addr_link)
+{
+ uint32_t x, y;
+
+ x = cc->root;
+ y = ADDR_NULL;
+ while (x != ADDR_NULL) {
+ int r;
+
+ r = memcmp(id, cc->store + x + SESSION_ID_OFF, SESSION_ID_LEN);
+ if (r < 0) {
+ y = x + TREE_LEFT_OFF;
+ x = get_left(cc, x);
+ } else if (r == 0) {
+ if (addr_link != NULL) {
+ *addr_link = y;
+ }
+ return x;
+ } else {
+ y = x + TREE_RIGHT_OFF;
+ x = get_right(cc, x);
+ }
+ }
+ if (addr_link != NULL) {
+ *addr_link = y;
+ }
+ return ADDR_NULL;
+}
+
+/*
+ * For node x, find its replacement upon removal.
+ *
+ * -- If node x has no child, then this returns ADDR_NULL.
+ * -- Otherwise, if node x has a left child, then the replacement is the
+ * rightmost left-descendent.
+ * -- Otherwise, the replacement is the leftmost right-descendent.
+ *
+ * If a node is returned, then '*al' is set to the address of the field
+ * that points to that node. Otherwise (node x has no child), '*al' is
+ * set to ADDR_NULL.
+ *
+ * Note that the replacement node, when found, is always a descendent
+ * of node 'x', so it cannot be the tree root. Thus, '*al' can be set
+ * to ADDR_NULL only when no node is found and ADDR_NULL is returned.
+ */
+static uint32_t
+find_replacement_node(br_ssl_session_cache_lru *cc, uint32_t x, uint32_t *al)
+{
+ uint32_t y1, y2;
+
+ y1 = get_left(cc, x);
+ if (y1 != ADDR_NULL) {
+ y2 = x + TREE_LEFT_OFF;
+ for (;;) {
+ uint32_t z;
+
+ z = get_right(cc, y1);
+ if (z == ADDR_NULL) {
+ *al = y2;
+ return y1;
+ }
+ y2 = y1 + TREE_RIGHT_OFF;
+ y1 = z;
+ }
+ }
+ y1 = get_right(cc, x);
+ if (y1 != ADDR_NULL) {
+ y2 = x + TREE_RIGHT_OFF;
+ for (;;) {
+ uint32_t z;
+
+ z = get_left(cc, y1);
+ if (z == ADDR_NULL) {
+ *al = y2;
+ return y1;
+ }
+ y2 = y1 + TREE_LEFT_OFF;
+ y1 = z;
+ }
+ }
+ *al = ADDR_NULL;
+ return ADDR_NULL;
+}
+
+/*
+ * Set the link at address 'alx' to point to node 'x'. If 'alx' is
+ * ADDR_NULL, then this sets the tree root to 'x'.
+ */
+static inline void
+set_link(br_ssl_session_cache_lru *cc, uint32_t alx, uint32_t x)
+{
+ if (alx == ADDR_NULL) {
+ cc->root = x;
+ } else {
+ br_enc32be(cc->store + alx, x);
+ }
+}
+
+/*
+ * Remove node 'x' from the tree. This function shall not be called if
+ * node 'x' is not part of the tree.
+ */
+static void
+remove_node(br_ssl_session_cache_lru *cc, uint32_t x)
+{
+ uint32_t alx, y, aly;
+
+ /*
+ * Removal algorithm:
+ * ------------------
+ *
+ * - If we remove the root, then the tree becomes empty.
+ *
+ * - If the removed node has no child, then we can simply remove
+ * it, with nothing else to do.
+ *
+ * - Otherwise, the removed node must be replaced by either its
+ * rightmost left-descendent, or its leftmost right-descendent.
+ * The replacement node itself must be removed from its current
+ * place. By definition, that replacement node has either no
+ * child, or at most a single child that will replace it in the
+ * tree.
+ */
+
+ /*
+ * Find node back and its ancestor link. If the node was the
+ * root, then alx is set to ADDR_NULL.
+ */
+ find_node(cc, cc->store + x + SESSION_ID_OFF, &alx);
+
+ /*
+ * Find replacement node 'y', and 'aly' is set to the address of
+ * the link to that replacement node. If the removed node has no
+ * child, then both 'y' and 'aly' are set to ADDR_NULL.
+ */
+ y = find_replacement_node(cc, x, &aly);
+
+ if (y != ADDR_NULL) {
+ uint32_t z;
+
+ /*
+ * The unlinked replacement node may have one child (but
+ * not two) that takes its place.
+ */
+ z = get_left(cc, y);
+ if (z == ADDR_NULL) {
+ z = get_right(cc, y);
+ }
+ set_link(cc, aly, z);
+
+ /*
+ * Link the replacement node in its new place, overwriting
+ * the current link to the node 'x' (which removes 'x').
+ */
+ set_link(cc, alx, y);
+
+ /*
+ * The replacement node adopts the left and right children
+ * of the removed node. Note that this also works even if
+ * the replacement node was a direct descendent of the
+ * removed node, since we unlinked it previously.
+ */
+ set_left(cc, y, get_left(cc, x));
+ set_right(cc, y, get_right(cc, x));
+ } else {
+ /*
+ * No replacement, we simply unlink the node 'x'.
+ */
+ set_link(cc, alx, ADDR_NULL);
+ }
+}
+
+static void
+lru_save(const br_ssl_session_cache_class **ctx,
+ br_ssl_server_context *server_ctx,
+ const br_ssl_session_parameters *params)
+{
+ br_ssl_session_cache_lru *cc;
+ unsigned char id[SESSION_ID_LEN];
+ uint32_t x, alx;
+
+ cc = (br_ssl_session_cache_lru *)ctx;
+
+ /*
+ * If the buffer is too small, we don't record anything. This
+ * test avoids problems in subsequent code.
+ */
+ if (cc->store_len < LRU_ENTRY_LEN) {
+ return;
+ }
+
+ /*
+ * Upon the first save in a session cache instance, we obtain
+ * a random key for our indexing.
+ */
+ if (!cc->init_done) {
+ br_hmac_drbg_generate(&server_ctx->eng.rng,
+ cc->index_key, sizeof cc->index_key);
+ cc->hash = br_hmac_drbg_get_hash(&server_ctx->eng.rng);
+ cc->init_done = 1;
+ }
+ mask_id(cc, params->session_id, id);
+
+ /*
+ * Look for the node in the tree. If the same ID is already used,
+ * then reject it. This is a collision event, which should be
+ * exceedingly rare.
+ * Note: we do NOT record the emplacement here, because the
+ * removal of an entry may change the tree topology.
+ */
+ if (find_node(cc, id, NULL) != ADDR_NULL) {
+ return;
+ }
+
+ /*
+ * Find some room for the new parameters. If the cache is not
+ * full yet, add it to the end of the area and bump the pointer up.
+ * Otherwise, evict the list tail entry. Note that we already
+ * filtered out the case of a ridiculously small buffer that
+ * cannot hold any entry at all; thus, if there is no room for an
+ * extra entry, then the cache cannot be empty.
+ */
+ if (cc->store_ptr > (cc->store_len - LRU_ENTRY_LEN)) {
+ /*
+ * Evict tail. If the buffer has room for a single entry,
+ * then this may also be the head.
+ */
+ x = cc->tail;
+ cc->tail = get_prev(cc, x);
+ if (cc->tail == ADDR_NULL) {
+ cc->head = ADDR_NULL;
+ } else {
+ set_next(cc, cc->tail, ADDR_NULL);
+ }
+
+ /*
+ * Remove the node from the tree.
+ */
+ remove_node(cc, x);
+ } else {
+ /*
+ * Allocate room for new node.
+ */
+ x = cc->store_ptr;
+ cc->store_ptr += LRU_ENTRY_LEN;
+ }
+
+ /*
+ * Find the emplacement for the new node, and link it.
+ */
+ find_node(cc, id, &alx);
+ set_link(cc, alx, x);
+ set_left(cc, x, ADDR_NULL);
+ set_right(cc, x, ADDR_NULL);
+
+ /*
+ * New entry becomes new list head. It may also become the list
+ * tail if the cache was empty at that point.
+ */
+ if (cc->head == ADDR_NULL) {
+ cc->tail = x;
+ } else {
+ set_prev(cc, cc->head, x);
+ }
+ set_prev(cc, x, ADDR_NULL);
+ set_next(cc, x, cc->head);
+ cc->head = x;
+
+ /*
+ * Fill data in the entry.
+ */
+ memcpy(cc->store + x + SESSION_ID_OFF, id, SESSION_ID_LEN);
+ memcpy(cc->store + x + MASTER_SECRET_OFF,
+ params->master_secret, MASTER_SECRET_LEN);
+ br_enc16be(cc->store + x + VERSION_OFF, params->version);
+ br_enc16be(cc->store + x + CIPHER_SUITE_OFF, params->cipher_suite);
+}
+
+static int
+lru_load(const br_ssl_session_cache_class **ctx,
+ br_ssl_server_context *server_ctx,
+ br_ssl_session_parameters *params)
+{
+ br_ssl_session_cache_lru *cc;
+ unsigned char id[SESSION_ID_LEN];
+ uint32_t x;
+
+ (void)server_ctx;
+ cc = (br_ssl_session_cache_lru *)ctx;
+ if (!cc->init_done) {
+ return 0;
+ }
+ mask_id(cc, params->session_id, id);
+ x = find_node(cc, id, NULL);
+ if (x != ADDR_NULL) {
+ unsigned version;
+
+ version = br_dec16be(cc->store + x + VERSION_OFF);
+ if (version == 0) {
+ /*
+ * Entry is disabled, we pretend we did not find it.
+ * Notably, we don't move it to the front of the
+ * LRU list.
+ */
+ return 0;
+ }
+ params->version = version;
+ params->cipher_suite = br_dec16be(
+ cc->store + x + CIPHER_SUITE_OFF);
+ memcpy(params->master_secret,
+ cc->store + x + MASTER_SECRET_OFF,
+ MASTER_SECRET_LEN);
+ if (x != cc->head) {
+ /*
+ * Found node is not at list head, so move
+ * it to the head.
+ */
+ uint32_t p, n;
+
+ p = get_prev(cc, x);
+ n = get_next(cc, x);
+ set_next(cc, p, n);
+ if (n == ADDR_NULL) {
+ cc->tail = p;
+ } else {
+ set_prev(cc, n, p);
+ }
+ set_prev(cc, cc->head, x);
+ set_next(cc, x, cc->head);
+ set_prev(cc, x, ADDR_NULL);
+ cc->head = x;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static const br_ssl_session_cache_class lru_class = {
+ sizeof(br_ssl_session_cache_lru),
+ &lru_save,
+ &lru_load
+};
+
+/* see inner.h */
+void
+br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
+ unsigned char *store, size_t store_len)
+{
+ cc->vtable = &lru_class;
+ cc->store = store;
+ cc->store_len = store_len;
+ cc->store_ptr = 0;
+ cc->init_done = 0;
+ cc->head = ADDR_NULL;
+ cc->tail = ADDR_NULL;
+ cc->root = ADDR_NULL;
+}
+
+/* see bearssl_ssl.h */
+void br_ssl_session_cache_lru_forget(
+ br_ssl_session_cache_lru *cc, const unsigned char *id)
+{
+ unsigned char mid[SESSION_ID_LEN];
+ uint32_t addr;
+
+ /*
+ * If the cache is not initialised yet, then it is empty, and
+ * there is nothing to forget.
+ */
+ if (!cc->init_done) {
+ return;
+ }
+
+ /*
+ * Look for the node in the tree. If found, the entry is marked
+ * as "disabled"; it will be reused in due course, as it ages
+ * through the list.
+ *
+ * We do not go through the complex moves of actually releasing
+ * the entry right away because explicitly forgetting sessions
+ * should be a rare event, meant mostly for testing purposes,
+ * so this is not worth the extra code size.
+ */
+ mask_id(cc, id, mid);
+ addr = find_node(cc, mid, NULL);
+ if (addr != ADDR_NULL) {
+ br_enc16be(cc->store + addr + VERSION_OFF, 0);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_lru.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_rec_cbc.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_rec_cbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_rec_cbc.c (revision 346145)
@@ -0,0 +1,440 @@
+/*
+ * 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"
+
+static void
+in_cbc_init(br_sslrec_in_cbc_context *cc,
+ const br_block_cbcdec_class *bc_impl,
+ const void *bc_key, size_t bc_key_len,
+ const br_hash_class *dig_impl,
+ const void *mac_key, size_t mac_key_len, size_t mac_out_len,
+ const void *iv)
+{
+ cc->vtable = &br_sslrec_in_cbc_vtable;
+ cc->seq = 0;
+ bc_impl->init(&cc->bc.vtable, bc_key, bc_key_len);
+ br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len);
+ cc->mac_len = mac_out_len;
+ if (iv == NULL) {
+ memset(cc->iv, 0, sizeof cc->iv);
+ cc->explicit_IV = 1;
+ } else {
+ memcpy(cc->iv, iv, bc_impl->block_size);
+ cc->explicit_IV = 0;
+ }
+}
+
+static int
+cbc_check_length(const br_sslrec_in_cbc_context *cc, size_t rlen)
+{
+ /*
+ * Plaintext size: at most 16384 bytes
+ * Padding: at most 256 bytes
+ * MAC: mac_len extra bytes
+ * TLS 1.1+: each record has an explicit IV
+ *
+ * Minimum length includes at least one byte of padding, and the
+ * MAC.
+ *
+ * Total length must be a multiple of the block size.
+ */
+ size_t blen;
+ size_t min_len, max_len;
+
+ blen = cc->bc.vtable->block_size;
+ min_len = (blen + cc->mac_len) & ~(blen - 1);
+ max_len = (16384 + 256 + cc->mac_len) & ~(blen - 1);
+ if (cc->explicit_IV) {
+ min_len += blen;
+ max_len += blen;
+ }
+ return min_len <= rlen && rlen <= max_len;
+}
+
+/*
+ * Rotate array buf[] of length 'len' to the left (towards low indices)
+ * by 'num' bytes if ctl is 1; otherwise, leave it unchanged. This is
+ * constant-time. 'num' MUST be lower than 'len'. 'len' MUST be lower
+ * than or equal to 64.
+ */
+static void
+cond_rotate(uint32_t ctl, unsigned char *buf, size_t len, size_t num)
+{
+ unsigned char tmp[64];
+ size_t u, v;
+
+ for (u = 0, v = num; u < len; u ++) {
+ tmp[u] = MUX(ctl, buf[v], buf[u]);
+ if (++ v == len) {
+ v = 0;
+ }
+ }
+ memcpy(buf, tmp, len);
+}
+
+static unsigned char *
+cbc_decrypt(br_sslrec_in_cbc_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ /*
+ * We represent all lengths on 32-bit integers, because:
+ * -- SSL record lengths always fit in 32 bits;
+ * -- our constant-time primitives operate on 32-bit integers.
+ */
+ unsigned char *buf;
+ uint32_t u, v, len, blen, min_len, max_len;
+ uint32_t good, pad_len, rot_count, len_withmac, len_nomac;
+ unsigned char tmp1[64], tmp2[64];
+ int i;
+ br_hmac_context hc;
+
+ buf = data;
+ len = *data_len;
+ blen = cc->bc.vtable->block_size;
+
+ /*
+ * Decrypt data, and skip the explicit IV (if applicable). Note
+ * that the total length is supposed to have been verified by
+ * the caller. If there is an explicit IV, then we actually
+ * "decrypt" it using the implicit IV (from previous record),
+ * which is useless but harmless.
+ */
+ cc->bc.vtable->run(&cc->bc.vtable, cc->iv, data, len);
+ if (cc->explicit_IV) {
+ buf += blen;
+ len -= blen;
+ }
+
+ /*
+ * Compute minimum and maximum length of plaintext + MAC. These
+ * lengths can be inferred from the outside: they are not secret.
+ */
+ min_len = (cc->mac_len + 256 < len) ? len - 256 : cc->mac_len;
+ max_len = len - 1;
+
+ /*
+ * Use the last decrypted byte to compute the actual payload
+ * length. Take care not to underflow (we use unsigned types).
+ */
+ pad_len = buf[max_len];
+ good = LE(pad_len, (uint32_t)(max_len - min_len));
+ len = MUX(good, (uint32_t)(max_len - pad_len), min_len);
+
+ /*
+ * Check padding contents: all padding bytes must be equal to
+ * the value of pad_len.
+ */
+ for (u = min_len; u < max_len; u ++) {
+ good &= LT(u, len) | EQ(buf[u], pad_len);
+ }
+
+ /*
+ * Extract the MAC value. This is done in one pass, but results
+ * in a "rotated" MAC value depending on where it actually
+ * occurs. The 'rot_count' value is set to the offset of the
+ * first MAC byte within tmp1[].
+ *
+ * min_len and max_len are also adjusted to the minimum and
+ * maximum lengths of the plaintext alone (without the MAC).
+ */
+ len_withmac = (uint32_t)len;
+ len_nomac = len_withmac - cc->mac_len;
+ min_len -= cc->mac_len;
+ rot_count = 0;
+ memset(tmp1, 0, cc->mac_len);
+ v = 0;
+ for (u = min_len; u < max_len; u ++) {
+ tmp1[v] |= MUX(GE(u, len_nomac) & LT(u, len_withmac),
+ buf[u], 0x00);
+ rot_count = MUX(EQ(u, len_nomac), v, rot_count);
+ if (++ v == cc->mac_len) {
+ v = 0;
+ }
+ }
+ max_len -= cc->mac_len;
+
+ /*
+ * Rotate back the MAC value. The loop below does the constant-time
+ * rotation in time n*log n for a MAC output of length n. We assume
+ * that the MAC output length is no more than 64 bytes, so the
+ * rotation count fits on 6 bits.
+ */
+ for (i = 5; i >= 0; i --) {
+ uint32_t rc;
+
+ rc = (uint32_t)1 << i;
+ cond_rotate(rot_count >> i, tmp1, cc->mac_len, rc);
+ rot_count &= ~rc;
+ }
+
+ /*
+ * Recompute the HMAC value. The input is the concatenation of
+ * the sequence number (8 bytes), the record header (5 bytes),
+ * and the payload.
+ *
+ * At that point, min_len is the minimum plaintext length, but
+ * max_len still includes the MAC length.
+ */
+ br_enc64be(tmp2, cc->seq ++);
+ tmp2[8] = (unsigned char)record_type;
+ br_enc16be(tmp2 + 9, version);
+ br_enc16be(tmp2 + 11, len_nomac);
+ br_hmac_init(&hc, &cc->mac, cc->mac_len);
+ br_hmac_update(&hc, tmp2, 13);
+ br_hmac_outCT(&hc, buf, len_nomac, min_len, max_len, tmp2);
+
+ /*
+ * Compare the extracted and recomputed MAC values.
+ */
+ for (u = 0; u < cc->mac_len; u ++) {
+ good &= EQ0(tmp1[u] ^ tmp2[u]);
+ }
+
+ /*
+ * Check that the plaintext length is valid. The previous
+ * check was on the encrypted length, but the padding may have
+ * turned shorter than expected.
+ *
+ * Once this final test is done, the critical "constant-time"
+ * section ends and we can make conditional jumps again.
+ */
+ good &= LE(len_nomac, 16384);
+
+ if (!good) {
+ return 0;
+ }
+ *data_len = len_nomac;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable = {
+ {
+ sizeof(br_sslrec_in_cbc_context),
+ (int (*)(const br_sslrec_in_class *const *, size_t))
+ &cbc_check_length,
+ (unsigned char *(*)(const br_sslrec_in_class **,
+ int, unsigned, void *, size_t *))
+ &cbc_decrypt
+ },
+ (void (*)(const br_sslrec_in_cbc_class **,
+ const br_block_cbcdec_class *, const void *, size_t,
+ const br_hash_class *, const void *, size_t, size_t,
+ const void *))
+ &in_cbc_init
+};
+
+/*
+ * For CBC output:
+ *
+ * -- With TLS 1.1+, there is an explicit IV. Generation method uses
+ * HMAC, computed over the current sequence number, and the current MAC
+ * key. The resulting value is truncated to the size of a block, and
+ * added at the head of the plaintext; it will get encrypted along with
+ * the data. This custom generation mechanism is "safe" under the
+ * assumption that HMAC behaves like a random oracle; since the MAC for
+ * a record is computed over the concatenation of the sequence number,
+ * the record header and the plaintext, the HMAC-for-IV will not collide
+ * with the normal HMAC.
+ *
+ * -- With TLS 1.0, for application data, we want to enforce a 1/n-1
+ * split, as a countermeasure against chosen-plaintext attacks. We thus
+ * need to leave some room in the buffer for that extra record.
+ */
+
+static void
+out_cbc_init(br_sslrec_out_cbc_context *cc,
+ const br_block_cbcenc_class *bc_impl,
+ const void *bc_key, size_t bc_key_len,
+ const br_hash_class *dig_impl,
+ const void *mac_key, size_t mac_key_len, size_t mac_out_len,
+ const void *iv)
+{
+ cc->vtable = &br_sslrec_out_cbc_vtable;
+ cc->seq = 0;
+ bc_impl->init(&cc->bc.vtable, bc_key, bc_key_len);
+ br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len);
+ cc->mac_len = mac_out_len;
+ if (iv == NULL) {
+ memset(cc->iv, 0, sizeof cc->iv);
+ cc->explicit_IV = 1;
+ } else {
+ memcpy(cc->iv, iv, bc_impl->block_size);
+ cc->explicit_IV = 0;
+ }
+}
+
+static void
+cbc_max_plaintext(const br_sslrec_out_cbc_context *cc,
+ size_t *start, size_t *end)
+{
+ size_t blen, len;
+
+ blen = cc->bc.vtable->block_size;
+ if (cc->explicit_IV) {
+ *start += blen;
+ } else {
+ *start += 4 + ((cc->mac_len + blen + 1) & ~(blen - 1));
+ }
+ len = (*end - *start) & ~(blen - 1);
+ len -= 1 + cc->mac_len;
+ if (len > 16384) {
+ len = 16384;
+ }
+ *end = *start + len;
+}
+
+static unsigned char *
+cbc_encrypt(br_sslrec_out_cbc_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ unsigned char *buf, *rbuf;
+ size_t len, blen, plen;
+ unsigned char tmp[13];
+ br_hmac_context hc;
+
+ buf = data;
+ len = *data_len;
+ blen = cc->bc.vtable->block_size;
+
+ /*
+ * If using TLS 1.0, with more than one byte of plaintext, and
+ * the record is application data, then we need to compute
+ * a "split". We do not perform the split on other record types
+ * because it turned out that some existing, deployed
+ * implementations of SSL/TLS do not tolerate the splitting of
+ * some message types (in particular the Finished message).
+ *
+ * If using TLS 1.1+, then there is an explicit IV. We produce
+ * that IV by adding an extra initial plaintext block, whose
+ * value is computed with HMAC over the record sequence number.
+ */
+ if (cc->explicit_IV) {
+ /*
+ * We use here the fact that all the HMAC variants we
+ * support can produce at least 16 bytes, while all the
+ * block ciphers we support have blocks of no more than
+ * 16 bytes. Thus, we can always truncate the HMAC output
+ * down to the block size.
+ */
+ br_enc64be(tmp, cc->seq);
+ br_hmac_init(&hc, &cc->mac, blen);
+ br_hmac_update(&hc, tmp, 8);
+ br_hmac_out(&hc, buf - blen);
+ rbuf = buf - blen - 5;
+ } else {
+ if (len > 1 && record_type == BR_SSL_APPLICATION_DATA) {
+ /*
+ * To do the split, we use a recursive invocation;
+ * since we only give one byte to the inner call,
+ * the recursion stops there.
+ *
+ * We need to compute the exact size of the extra
+ * record, so that the two resulting records end up
+ * being sequential in RAM.
+ *
+ * We use here the fact that cbc_max_plaintext()
+ * adjusted the start offset to leave room for the
+ * initial fragment.
+ */
+ size_t xlen;
+
+ rbuf = buf - 4
+ - ((cc->mac_len + blen + 1) & ~(blen - 1));
+ rbuf[0] = buf[0];
+ xlen = 1;
+ rbuf = cbc_encrypt(cc, record_type,
+ version, rbuf, &xlen);
+ buf ++;
+ len --;
+ } else {
+ rbuf = buf - 5;
+ }
+ }
+
+ /*
+ * Compute MAC.
+ */
+ br_enc64be(tmp, cc->seq ++);
+ tmp[8] = record_type;
+ br_enc16be(tmp + 9, version);
+ br_enc16be(tmp + 11, len);
+ br_hmac_init(&hc, &cc->mac, cc->mac_len);
+ br_hmac_update(&hc, tmp, 13);
+ br_hmac_update(&hc, buf, len);
+ br_hmac_out(&hc, buf + len);
+ len += cc->mac_len;
+
+ /*
+ * Add padding.
+ */
+ plen = blen - (len & (blen - 1));
+ memset(buf + len, (unsigned)plen - 1, plen);
+ len += plen;
+
+ /*
+ * If an explicit IV is used, the corresponding extra block was
+ * already put in place earlier; we just have to account for it
+ * here.
+ */
+ if (cc->explicit_IV) {
+ buf -= blen;
+ len += blen;
+ }
+
+ /*
+ * Encrypt the whole thing. If there is an explicit IV, we also
+ * encrypt it, which is fine (encryption of a uniformly random
+ * block is still a uniformly random block).
+ */
+ cc->bc.vtable->run(&cc->bc.vtable, cc->iv, buf, len);
+
+ /*
+ * Add the header and return.
+ */
+ buf[-5] = record_type;
+ br_enc16be(buf - 4, version);
+ br_enc16be(buf - 2, len);
+ *data_len = (size_t)((buf + len) - rbuf);
+ return rbuf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable = {
+ {
+ sizeof(br_sslrec_out_cbc_context),
+ (void (*)(const br_sslrec_out_class *const *,
+ size_t *, size_t *))
+ &cbc_max_plaintext,
+ (unsigned char *(*)(const br_sslrec_out_class **,
+ int, unsigned, void *, size_t *))
+ &cbc_encrypt
+ },
+ (void (*)(const br_sslrec_out_cbc_class **,
+ const br_block_cbcenc_class *, const void *, size_t,
+ const br_hash_class *, const void *, size_t, size_t,
+ const void *))
+ &out_cbc_init
+};
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_rec_cbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_rec_ccm.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_rec_ccm.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_rec_ccm.c (revision 346145)
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/*
+ * CCM initialisation. This does everything except setting the vtable,
+ * which depends on whether this is a context for encrypting or for
+ * decrypting.
+ */
+static void
+gen_ccm_init(br_sslrec_ccm_context *cc,
+ const br_block_ctrcbc_class *bc_impl,
+ const void *key, size_t key_len,
+ const void *iv, size_t tag_len)
+{
+ cc->seq = 0;
+ bc_impl->init(&cc->bc.vtable, key, key_len);
+ memcpy(cc->iv, iv, sizeof cc->iv);
+ cc->tag_len = tag_len;
+}
+
+static void
+in_ccm_init(br_sslrec_ccm_context *cc,
+ const br_block_ctrcbc_class *bc_impl,
+ const void *key, size_t key_len,
+ const void *iv, size_t tag_len)
+{
+ cc->vtable.in = &br_sslrec_in_ccm_vtable;
+ gen_ccm_init(cc, bc_impl, key, key_len, iv, tag_len);
+}
+
+static int
+ccm_check_length(const br_sslrec_ccm_context *cc, size_t rlen)
+{
+ /*
+ * CCM overhead is 8 bytes for nonce_explicit, and the tag
+ * (normally 8 or 16 bytes, depending on cipher suite).
+ */
+ size_t over;
+
+ over = 8 + cc->tag_len;
+ return rlen >= over && rlen <= (16384 + over);
+}
+
+static unsigned char *
+ccm_decrypt(br_sslrec_ccm_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ br_ccm_context zc;
+ unsigned char *buf;
+ unsigned char nonce[12], header[13];
+ size_t len;
+
+ buf = (unsigned char *)data + 8;
+ len = *data_len - (8 + cc->tag_len);
+
+ /*
+ * Make nonce (implicit + explicit parts).
+ */
+ memcpy(nonce, cc->iv, sizeof cc->iv);
+ memcpy(nonce + 4, data, 8);
+
+ /*
+ * Assemble synthetic header for the AAD.
+ */
+ br_enc64be(header, cc->seq ++);
+ header[8] = (unsigned char)record_type;
+ br_enc16be(header + 9, version);
+ br_enc16be(header + 11, len);
+
+ /*
+ * Perform CCM decryption.
+ */
+ br_ccm_init(&zc, &cc->bc.vtable);
+ br_ccm_reset(&zc, nonce, sizeof nonce, sizeof header, len, cc->tag_len);
+ br_ccm_aad_inject(&zc, header, sizeof header);
+ br_ccm_flip(&zc);
+ br_ccm_run(&zc, 0, buf, len);
+ if (!br_ccm_check_tag(&zc, buf + len)) {
+ return NULL;
+ }
+ *data_len = len;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable = {
+ {
+ sizeof(br_sslrec_ccm_context),
+ (int (*)(const br_sslrec_in_class *const *, size_t))
+ &ccm_check_length,
+ (unsigned char *(*)(const br_sslrec_in_class **,
+ int, unsigned, void *, size_t *))
+ &ccm_decrypt
+ },
+ (void (*)(const br_sslrec_in_ccm_class **,
+ const br_block_ctrcbc_class *, const void *, size_t,
+ const void *, size_t))
+ &in_ccm_init
+};
+
+static void
+out_ccm_init(br_sslrec_ccm_context *cc,
+ const br_block_ctrcbc_class *bc_impl,
+ const void *key, size_t key_len,
+ const void *iv, size_t tag_len)
+{
+ cc->vtable.out = &br_sslrec_out_ccm_vtable;
+ gen_ccm_init(cc, bc_impl, key, key_len, iv, tag_len);
+}
+
+static void
+ccm_max_plaintext(const br_sslrec_ccm_context *cc,
+ size_t *start, size_t *end)
+{
+ size_t len;
+
+ *start += 8;
+ len = *end - *start - cc->tag_len;
+ if (len > 16384) {
+ len = 16384;
+ }
+ *end = *start + len;
+}
+
+static unsigned char *
+ccm_encrypt(br_sslrec_ccm_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ br_ccm_context zc;
+ unsigned char *buf;
+ unsigned char nonce[12], header[13];
+ size_t len;
+
+ buf = (unsigned char *)data;
+ len = *data_len;
+
+ /*
+ * Make nonce; the explicit part is an encoding of the sequence
+ * number.
+ */
+ memcpy(nonce, cc->iv, sizeof cc->iv);
+ br_enc64be(nonce + 4, cc->seq);
+
+ /*
+ * Assemble synthetic header for the AAD.
+ */
+ br_enc64be(header, cc->seq ++);
+ header[8] = (unsigned char)record_type;
+ br_enc16be(header + 9, version);
+ br_enc16be(header + 11, len);
+
+ /*
+ * Perform CCM encryption.
+ */
+ br_ccm_init(&zc, &cc->bc.vtable);
+ br_ccm_reset(&zc, nonce, sizeof nonce, sizeof header, len, cc->tag_len);
+ br_ccm_aad_inject(&zc, header, sizeof header);
+ br_ccm_flip(&zc);
+ br_ccm_run(&zc, 1, buf, len);
+ br_ccm_get_tag(&zc, buf + len);
+
+ /*
+ * Assemble header and adjust pointer/length.
+ */
+ len += 8 + cc->tag_len;
+ buf -= 13;
+ memcpy(buf + 5, nonce + 4, 8);
+ buf[0] = (unsigned char)record_type;
+ br_enc16be(buf + 1, version);
+ br_enc16be(buf + 3, len);
+ *data_len = len + 5;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable = {
+ {
+ sizeof(br_sslrec_ccm_context),
+ (void (*)(const br_sslrec_out_class *const *,
+ size_t *, size_t *))
+ &ccm_max_plaintext,
+ (unsigned char *(*)(const br_sslrec_out_class **,
+ int, unsigned, void *, size_t *))
+ &ccm_encrypt
+ },
+ (void (*)(const br_sslrec_out_ccm_class **,
+ const br_block_ctrcbc_class *, const void *, size_t,
+ const void *, size_t))
+ &out_ccm_init
+};
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_rec_ccm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_rec_chapol.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_rec_chapol.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_rec_chapol.c (revision 346145)
@@ -0,0 +1,177 @@
+/*
+ * 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"
+
+static void
+gen_chapol_init(br_sslrec_chapol_context *cc,
+ br_chacha20_run ichacha, br_poly1305_run ipoly,
+ const void *key, const void *iv)
+{
+ cc->seq = 0;
+ cc->ichacha = ichacha;
+ cc->ipoly = ipoly;
+ memcpy(cc->key, key, sizeof cc->key);
+ memcpy(cc->iv, iv, sizeof cc->iv);
+}
+
+static void
+gen_chapol_process(br_sslrec_chapol_context *cc,
+ int record_type, unsigned version, void *data, size_t len,
+ void *tag, int encrypt)
+{
+ unsigned char header[13];
+ unsigned char nonce[12];
+ uint64_t seq;
+ size_t u;
+
+ seq = cc->seq ++;
+ br_enc64be(header, seq);
+ header[8] = (unsigned char)record_type;
+ br_enc16be(header + 9, version);
+ br_enc16be(header + 11, len);
+ memcpy(nonce, cc->iv, 12);
+ for (u = 0; u < 8; u ++) {
+ nonce[11 - u] ^= (unsigned char)seq;
+ seq >>= 8;
+ }
+ cc->ipoly(cc->key, nonce, data, len, header, sizeof header,
+ tag, cc->ichacha, encrypt);
+}
+
+static void
+in_chapol_init(br_sslrec_chapol_context *cc,
+ br_chacha20_run ichacha, br_poly1305_run ipoly,
+ const void *key, const void *iv)
+{
+ cc->vtable.in = &br_sslrec_in_chapol_vtable;
+ gen_chapol_init(cc, ichacha, ipoly, key, iv);
+}
+
+static int
+chapol_check_length(const br_sslrec_chapol_context *cc, size_t rlen)
+{
+ /*
+ * Overhead is just the authentication tag (16 bytes).
+ */
+ (void)cc;
+ return rlen >= 16 && rlen <= (16384 + 16);
+}
+
+static unsigned char *
+chapol_decrypt(br_sslrec_chapol_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ unsigned char *buf;
+ size_t u, len;
+ unsigned char tag[16];
+ unsigned bad;
+
+ buf = data;
+ len = *data_len - 16;
+ gen_chapol_process(cc, record_type, version, buf, len, tag, 0);
+ bad = 0;
+ for (u = 0; u < 16; u ++) {
+ bad |= tag[u] ^ buf[len + u];
+ }
+ if (bad) {
+ return NULL;
+ }
+ *data_len = len;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable = {
+ {
+ sizeof(br_sslrec_chapol_context),
+ (int (*)(const br_sslrec_in_class *const *, size_t))
+ &chapol_check_length,
+ (unsigned char *(*)(const br_sslrec_in_class **,
+ int, unsigned, void *, size_t *))
+ &chapol_decrypt
+ },
+ (void (*)(const br_sslrec_in_chapol_class **,
+ br_chacha20_run, br_poly1305_run,
+ const void *, const void *))
+ &in_chapol_init
+};
+
+static void
+out_chapol_init(br_sslrec_chapol_context *cc,
+ br_chacha20_run ichacha, br_poly1305_run ipoly,
+ const void *key, const void *iv)
+{
+ cc->vtable.out = &br_sslrec_out_chapol_vtable;
+ gen_chapol_init(cc, ichacha, ipoly, key, iv);
+}
+
+static void
+chapol_max_plaintext(const br_sslrec_chapol_context *cc,
+ size_t *start, size_t *end)
+{
+ size_t len;
+
+ (void)cc;
+ len = *end - *start - 16;
+ if (len > 16384) {
+ len = 16384;
+ }
+ *end = *start + len;
+}
+
+static unsigned char *
+chapol_encrypt(br_sslrec_chapol_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ unsigned char *buf;
+ size_t len;
+
+ buf = data;
+ len = *data_len;
+ gen_chapol_process(cc, record_type, version, buf, len, buf + len, 1);
+ buf -= 5;
+ buf[0] = (unsigned char)record_type;
+ br_enc16be(buf + 1, version);
+ br_enc16be(buf + 3, len + 16);
+ *data_len = len + 21;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable = {
+ {
+ sizeof(br_sslrec_chapol_context),
+ (void (*)(const br_sslrec_out_class *const *,
+ size_t *, size_t *))
+ &chapol_max_plaintext,
+ (unsigned char *(*)(const br_sslrec_out_class **,
+ int, unsigned, void *, size_t *))
+ &chapol_encrypt
+ },
+ (void (*)(const br_sslrec_out_chapol_class **,
+ br_chacha20_run, br_poly1305_run,
+ const void *, const void *))
+ &out_chapol_init
+};
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_rec_chapol.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_rec_gcm.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_rec_gcm.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_rec_gcm.c (revision 346145)
@@ -0,0 +1,235 @@
+/*
+ * 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"
+
+/*
+ * GCM initialisation. This does everything except setting the vtable,
+ * which depends on whether this is a context for encrypting or for
+ * decrypting.
+ */
+static void
+gen_gcm_init(br_sslrec_gcm_context *cc,
+ const br_block_ctr_class *bc_impl,
+ const void *key, size_t key_len,
+ br_ghash gh_impl,
+ const void *iv)
+{
+ unsigned char tmp[12];
+
+ cc->seq = 0;
+ bc_impl->init(&cc->bc.vtable, key, key_len);
+ cc->gh = gh_impl;
+ memcpy(cc->iv, iv, sizeof cc->iv);
+ memset(cc->h, 0, sizeof cc->h);
+ memset(tmp, 0, sizeof tmp);
+ bc_impl->run(&cc->bc.vtable, tmp, 0, cc->h, sizeof cc->h);
+}
+
+static void
+in_gcm_init(br_sslrec_gcm_context *cc,
+ const br_block_ctr_class *bc_impl,
+ const void *key, size_t key_len,
+ br_ghash gh_impl,
+ const void *iv)
+{
+ cc->vtable.in = &br_sslrec_in_gcm_vtable;
+ gen_gcm_init(cc, bc_impl, key, key_len, gh_impl, iv);
+}
+
+static int
+gcm_check_length(const br_sslrec_gcm_context *cc, size_t rlen)
+{
+ /*
+ * GCM adds a fixed overhead:
+ * 8 bytes for the nonce_explicit (before the ciphertext)
+ * 16 bytes for the authentication tag (after the ciphertext)
+ */
+ (void)cc;
+ return rlen >= 24 && rlen <= (16384 + 24);
+}
+
+/*
+ * Compute the authentication tag. The value written in 'tag' must still
+ * be CTR-encrypted.
+ */
+static void
+do_tag(br_sslrec_gcm_context *cc,
+ int record_type, unsigned version,
+ void *data, size_t len, void *tag)
+{
+ unsigned char header[13];
+ unsigned char footer[16];
+
+ /*
+ * Compute authentication tag. Three elements must be injected in
+ * sequence, each possibly 0-padded to reach a length multiple
+ * of the block size: the 13-byte header (sequence number, record
+ * type, protocol version, record length), the cipher text, and
+ * the word containing the encodings of the bit lengths of the two
+ * other elements.
+ */
+ br_enc64be(header, cc->seq ++);
+ header[8] = (unsigned char)record_type;
+ br_enc16be(header + 9, version);
+ br_enc16be(header + 11, len);
+ br_enc64be(footer, (uint64_t)(sizeof header) << 3);
+ br_enc64be(footer + 8, (uint64_t)len << 3);
+ memset(tag, 0, 16);
+ cc->gh(tag, cc->h, header, sizeof header);
+ cc->gh(tag, cc->h, data, len);
+ cc->gh(tag, cc->h, footer, sizeof footer);
+}
+
+/*
+ * Do CTR encryption. This also does CTR encryption of a single block at
+ * address 'xortag' with the counter value appropriate for the final
+ * processing of the authentication tag.
+ */
+static void
+do_ctr(br_sslrec_gcm_context *cc, const void *nonce, void *data, size_t len,
+ void *xortag)
+{
+ unsigned char iv[12];
+
+ memcpy(iv, cc->iv, 4);
+ memcpy(iv + 4, nonce, 8);
+ cc->bc.vtable->run(&cc->bc.vtable, iv, 2, data, len);
+ cc->bc.vtable->run(&cc->bc.vtable, iv, 1, xortag, 16);
+}
+
+static unsigned char *
+gcm_decrypt(br_sslrec_gcm_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ unsigned char *buf;
+ size_t len, u;
+ uint32_t bad;
+ unsigned char tag[16];
+
+ buf = (unsigned char *)data + 8;
+ len = *data_len - 24;
+ do_tag(cc, record_type, version, buf, len, tag);
+ do_ctr(cc, data, buf, len, tag);
+
+ /*
+ * Compare the computed tag with the value from the record. It
+ * is possibly useless to do a constant-time comparison here,
+ * but it does not hurt.
+ */
+ bad = 0;
+ for (u = 0; u < 16; u ++) {
+ bad |= tag[u] ^ buf[len + u];
+ }
+ if (bad) {
+ return NULL;
+ }
+ *data_len = len;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable = {
+ {
+ sizeof(br_sslrec_gcm_context),
+ (int (*)(const br_sslrec_in_class *const *, size_t))
+ &gcm_check_length,
+ (unsigned char *(*)(const br_sslrec_in_class **,
+ int, unsigned, void *, size_t *))
+ &gcm_decrypt
+ },
+ (void (*)(const br_sslrec_in_gcm_class **,
+ const br_block_ctr_class *, const void *, size_t,
+ br_ghash, const void *))
+ &in_gcm_init
+};
+
+static void
+out_gcm_init(br_sslrec_gcm_context *cc,
+ const br_block_ctr_class *bc_impl,
+ const void *key, size_t key_len,
+ br_ghash gh_impl,
+ const void *iv)
+{
+ cc->vtable.out = &br_sslrec_out_gcm_vtable;
+ gen_gcm_init(cc, bc_impl, key, key_len, gh_impl, iv);
+}
+
+static void
+gcm_max_plaintext(const br_sslrec_gcm_context *cc,
+ size_t *start, size_t *end)
+{
+ size_t len;
+
+ (void)cc;
+ *start += 8;
+ len = *end - *start - 16;
+ if (len > 16384) {
+ len = 16384;
+ }
+ *end = *start + len;
+}
+
+static unsigned char *
+gcm_encrypt(br_sslrec_gcm_context *cc,
+ int record_type, unsigned version, void *data, size_t *data_len)
+{
+ unsigned char *buf;
+ size_t u, len;
+ unsigned char tmp[16];
+
+ buf = (unsigned char *)data;
+ len = *data_len;
+ memset(tmp, 0, sizeof tmp);
+ br_enc64be(buf - 8, cc->seq);
+ do_ctr(cc, buf - 8, buf, len, tmp);
+ do_tag(cc, record_type, version, buf, len, buf + len);
+ for (u = 0; u < 16; u ++) {
+ buf[len + u] ^= tmp[u];
+ }
+ len += 24;
+ buf -= 13;
+ buf[0] = (unsigned char)record_type;
+ br_enc16be(buf + 1, version);
+ br_enc16be(buf + 3, len);
+ *data_len = len + 5;
+ return buf;
+}
+
+/* see bearssl_ssl.h */
+const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable = {
+ {
+ sizeof(br_sslrec_gcm_context),
+ (void (*)(const br_sslrec_out_class *const *,
+ size_t *, size_t *))
+ &gcm_max_plaintext,
+ (unsigned char *(*)(const br_sslrec_out_class **,
+ int, unsigned, void *, size_t *))
+ &gcm_encrypt
+ },
+ (void (*)(const br_sslrec_out_gcm_class **,
+ const br_block_ctr_class *, const void *, size_t,
+ br_ghash, const void *))
+ &out_gcm_init
+};
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_rec_gcm.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_scert_single_ec.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_scert_single_ec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_scert_single_ec.c (revision 346145)
@@ -0,0 +1,142 @@
+/*
+ * 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"
+
+static int
+se_choose(const br_ssl_server_policy_class **pctx,
+ const br_ssl_server_context *cc,
+ br_ssl_server_choices *choices)
+{
+ br_ssl_server_policy_ec_context *pc;
+ const br_suite_translated *st;
+ size_t u, st_num;
+ unsigned hash_id;
+
+ pc = (br_ssl_server_policy_ec_context *)pctx;
+ st = br_ssl_server_get_client_suites(cc, &st_num);
+ hash_id = br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc) >> 8);
+ if (cc->eng.session.version < BR_TLS12) {
+ hash_id = br_sha1_ID;
+ }
+ choices->chain = pc->chain;
+ choices->chain_len = pc->chain_len;
+ for (u = 0; u < st_num; u ++) {
+ unsigned tt;
+
+ tt = st[u][1];
+ switch (tt >> 12) {
+ case BR_SSLKEYX_ECDH_RSA:
+ if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0
+ && pc->cert_issuer_key_type == BR_KEYTYPE_RSA)
+ {
+ choices->cipher_suite = st[u][0];
+ return 1;
+ }
+ break;
+ case BR_SSLKEYX_ECDH_ECDSA:
+ if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0
+ && pc->cert_issuer_key_type == BR_KEYTYPE_EC)
+ {
+ choices->cipher_suite = st[u][0];
+ return 1;
+ }
+ break;
+ case BR_SSLKEYX_ECDHE_ECDSA:
+ if ((pc->allowed_usages & BR_KEYTYPE_SIGN) != 0
+ && hash_id != 0)
+ {
+ choices->cipher_suite = st[u][0];
+ choices->algo_id = hash_id + 0xFF00;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static uint32_t
+se_do_keyx(const br_ssl_server_policy_class **pctx,
+ unsigned char *data, size_t *len)
+{
+ br_ssl_server_policy_ec_context *pc;
+ uint32_t r;
+ size_t xoff, xlen;
+
+ pc = (br_ssl_server_policy_ec_context *)pctx;
+ r = pc->iec->mul(data, *len, pc->sk->x, pc->sk->xlen, pc->sk->curve);
+ xoff = pc->iec->xoff(pc->sk->curve, &xlen);
+ memmove(data, data + xoff, xlen);
+ *len = xlen;
+ return r;
+}
+
+static size_t
+se_do_sign(const br_ssl_server_policy_class **pctx,
+ unsigned algo_id, unsigned char *data, size_t hv_len, size_t len)
+{
+ br_ssl_server_policy_ec_context *pc;
+ unsigned char hv[64];
+ const br_hash_class *hc;
+
+ algo_id &= 0xFF;
+ pc = (br_ssl_server_policy_ec_context *)pctx;
+ hc = br_multihash_getimpl(pc->mhash, algo_id);
+ if (hc == NULL) {
+ return 0;
+ }
+ memcpy(hv, data, hv_len);
+ if (len < 139) {
+ return 0;
+ }
+ return pc->iecdsa(pc->iec, hc, hv, pc->sk, data);
+}
+
+static const br_ssl_server_policy_class se_policy_vtable = {
+ sizeof(br_ssl_server_policy_ec_context),
+ se_choose,
+ se_do_keyx,
+ se_do_sign
+};
+
+/* see bearssl_ssl.h */
+void
+br_ssl_server_set_single_ec(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk, unsigned allowed_usages,
+ unsigned cert_issuer_key_type,
+ const br_ec_impl *iec, br_ecdsa_sign iecdsa)
+{
+ cc->chain_handler.single_ec.vtable = &se_policy_vtable;
+ cc->chain_handler.single_ec.chain = chain;
+ cc->chain_handler.single_ec.chain_len = chain_len;
+ cc->chain_handler.single_ec.sk = sk;
+ cc->chain_handler.single_ec.allowed_usages = allowed_usages;
+ cc->chain_handler.single_ec.cert_issuer_key_type = cert_issuer_key_type;
+ cc->chain_handler.single_ec.mhash = &cc->eng.mhash;
+ cc->chain_handler.single_ec.iec = iec;
+ cc->chain_handler.single_ec.iecdsa = iecdsa;
+ cc->policy_vtable = &cc->chain_handler.single_ec.vtable;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_scert_single_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_scert_single_rsa.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_scert_single_rsa.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_scert_single_rsa.c (revision 346145)
@@ -0,0 +1,162 @@
+/*
+ * 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"
+
+static int
+sr_choose(const br_ssl_server_policy_class **pctx,
+ const br_ssl_server_context *cc,
+ br_ssl_server_choices *choices)
+{
+ br_ssl_server_policy_rsa_context *pc;
+ const br_suite_translated *st;
+ size_t u, st_num;
+ unsigned hash_id;
+ int fh;
+
+ pc = (br_ssl_server_policy_rsa_context *)pctx;
+ st = br_ssl_server_get_client_suites(cc, &st_num);
+ if (cc->eng.session.version < BR_TLS12) {
+ hash_id = 0;
+ fh = 1;
+ } else {
+ hash_id = br_ssl_choose_hash(
+ br_ssl_server_get_client_hashes(cc));
+ fh = (hash_id != 0);
+ }
+ choices->chain = pc->chain;
+ choices->chain_len = pc->chain_len;
+ for (u = 0; u < st_num; u ++) {
+ unsigned tt;
+
+ tt = st[u][1];
+ switch (tt >> 12) {
+ case BR_SSLKEYX_RSA:
+ if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0) {
+ choices->cipher_suite = st[u][0];
+ return 1;
+ }
+ break;
+ case BR_SSLKEYX_ECDHE_RSA:
+ if ((pc->allowed_usages & BR_KEYTYPE_SIGN) != 0 && fh) {
+ choices->cipher_suite = st[u][0];
+ choices->algo_id = hash_id + 0xFF00;
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static uint32_t
+sr_do_keyx(const br_ssl_server_policy_class **pctx,
+ unsigned char *data, size_t *len)
+{
+ br_ssl_server_policy_rsa_context *pc;
+
+ pc = (br_ssl_server_policy_rsa_context *)pctx;
+ return br_rsa_ssl_decrypt(pc->irsacore, pc->sk, data, *len);
+}
+
+/*
+ * OID for hash functions in RSA signatures.
+ */
+static const unsigned char HASH_OID_SHA1[] = {
+ 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static const unsigned char HASH_OID_SHA224[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
+};
+
+static const unsigned char HASH_OID_SHA256[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
+};
+
+static const unsigned char HASH_OID_SHA384[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
+};
+
+static const unsigned char HASH_OID_SHA512[] = {
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
+};
+
+static const unsigned char *HASH_OID[] = {
+ HASH_OID_SHA1,
+ HASH_OID_SHA224,
+ HASH_OID_SHA256,
+ HASH_OID_SHA384,
+ HASH_OID_SHA512
+};
+
+static size_t
+sr_do_sign(const br_ssl_server_policy_class **pctx,
+ unsigned algo_id, unsigned char *data, size_t hv_len, size_t len)
+{
+ br_ssl_server_policy_rsa_context *pc;
+ unsigned char hv[64];
+ size_t sig_len;
+ const unsigned char *hash_oid;
+
+ pc = (br_ssl_server_policy_rsa_context *)pctx;
+ memcpy(hv, data, hv_len);
+ algo_id &= 0xFF;
+ if (algo_id == 0) {
+ hash_oid = NULL;
+ } else if (algo_id >= 2 && algo_id <= 6) {
+ hash_oid = HASH_OID[algo_id - 2];
+ } else {
+ return 0;
+ }
+ sig_len = (pc->sk->n_bitlen + 7) >> 3;
+ if (len < sig_len) {
+ return 0;
+ }
+ return pc->irsasign(hash_oid, hv, hv_len, pc->sk, data) ? sig_len : 0;
+}
+
+static const br_ssl_server_policy_class sr_policy_vtable = {
+ sizeof(br_ssl_server_policy_rsa_context),
+ sr_choose,
+ sr_do_keyx,
+ sr_do_sign
+};
+
+/* see bearssl_ssl.h */
+void
+br_ssl_server_set_single_rsa(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk, unsigned allowed_usages,
+ br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign)
+{
+ cc->chain_handler.single_rsa.vtable = &sr_policy_vtable;
+ cc->chain_handler.single_rsa.chain = chain;
+ cc->chain_handler.single_rsa.chain_len = chain_len;
+ cc->chain_handler.single_rsa.sk = sk;
+ cc->chain_handler.single_rsa.allowed_usages = allowed_usages;
+ cc->chain_handler.single_rsa.irsacore = irsacore;
+ cc->chain_handler.single_rsa.irsasign = irsasign;
+ cc->policy_vtable = &cc->chain_handler.single_rsa.vtable;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_scert_single_rsa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server.c (revision 346145)
@@ -0,0 +1,52 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_server_zero(br_ssl_server_context *cc)
+{
+ /*
+ * For really standard C, we should explicitly set to NULL all
+ * pointers, and 0 all other fields. However, on all our target
+ * architectures, a direct memset() will work, be faster, and
+ * use a lot less code.
+ */
+ memset(cc, 0, sizeof *cc);
+}
+
+/* see bearssl_ssl.h */
+int
+br_ssl_server_reset(br_ssl_server_context *cc)
+{
+ br_ssl_engine_set_buffer(&cc->eng, NULL, 0, 0);
+ if (!br_ssl_engine_init_rand(&cc->eng)) {
+ return 0;
+ }
+ cc->eng.reneg = 0;
+ br_ssl_engine_hs_reset(&cc->eng,
+ br_ssl_hs_server_init_main, br_ssl_hs_server_run);
+ return br_ssl_engine_last_error(&cc->eng) == BR_ERR_OK;
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_full_ec.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_full_ec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_full_ec.c (revision 346145)
@@ -0,0 +1,149 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_server_init_full_ec(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ unsigned cert_issuer_key_type, const br_ec_private_key *sk)
+{
+ /*
+ * The "full" profile supports all implemented cipher suites.
+ *
+ * Rationale for suite order, from most important to least
+ * important rule:
+ *
+ * -- Don't use 3DES if AES is available.
+ * -- Try to have Forward Secrecy (ECDHE suite) if possible.
+ * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller).
+ * -- GCM is better than CCM and CBC. CCM is better than CBC.
+ * -- CCM is better than CCM_8.
+ * -- AES-128 is preferred over AES-256 (AES-128 is already
+ * strong enough, and AES-256 is 40% more expensive).
+ *
+ * Note that for ECDH suites, the list will be automatically
+ * filtered based on the issuing CA key type.
+ */
+ static const uint16_t suites[] = {
+ BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ BR_TLS_ECDHE_ECDSA_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_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ };
+
+ /*
+ * All hash functions are activated.
+ * Note: the X.509 validation engine will nonetheless refuse to
+ * validate signatures that use MD5 as hash function.
+ */
+ static const br_hash_class *hashes[] = {
+ &br_md5_vtable,
+ &br_sha1_vtable,
+ &br_sha224_vtable,
+ &br_sha256_vtable,
+ &br_sha384_vtable,
+ &br_sha512_vtable
+ };
+
+ int id;
+
+ /*
+ * Reset server context and set supported versions from TLS-1.0
+ * to TLS-1.2 (inclusive).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
+
+ /*
+ * Set suites and elliptic curve implementation (for ECDHE).
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+ br_ssl_engine_set_default_ec(&cc->eng);
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
+ BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
+ cert_issuer_key_type,
+ br_ssl_engine_get_ec(&cc->eng),
+#if BR_LOMUL
+ br_ecdsa_i15_sign_asn1
+#else
+ br_ecdsa_i31_sign_asn1
+#endif
+ );
+
+ /*
+ * Set supported hash functions.
+ */
+ for (id = br_md5_ID; id <= br_sha512_ID; id ++) {
+ const br_hash_class *hc;
+
+ hc = hashes[id - 1];
+ br_ssl_engine_set_hash(&cc->eng, id, hc);
+ }
+
+ /*
+ * Set the PRF implementations.
+ */
+ 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);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_aes_cbc(&cc->eng);
+ br_ssl_engine_set_default_aes_ccm(&cc->eng);
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+ br_ssl_engine_set_default_des_cbc(&cc->eng);
+ br_ssl_engine_set_default_chapol(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_full_ec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_full_rsa.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_full_rsa.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_full_rsa.c (revision 346145)
@@ -0,0 +1,132 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_rsa_private_key *sk)
+{
+ /*
+ * The "full" profile supports all implemented cipher suites.
+ *
+ * Rationale for suite order, from most important to least
+ * important rule:
+ *
+ * -- Don't use 3DES if AES is available.
+ * -- Try to have Forward Secrecy (ECDHE suite) if possible.
+ * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller).
+ * -- GCM is better than CBC.
+ * -- AES-128 is preferred over AES-256 (AES-128 is already
+ * strong enough, and AES-256 is 40% more expensive).
+ */
+ static const uint16_t suites[] = {
+ BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ 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_CCM,
+ BR_TLS_RSA_WITH_AES_256_CCM,
+ BR_TLS_RSA_WITH_AES_128_CCM_8,
+ BR_TLS_RSA_WITH_AES_256_CCM_8,
+ 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
+ };
+
+ /*
+ * All hash functions are activated.
+ * Note: the X.509 validation engine will nonetheless refuse to
+ * validate signatures that use MD5 as hash function.
+ */
+ static const br_hash_class *hashes[] = {
+ &br_md5_vtable,
+ &br_sha1_vtable,
+ &br_sha224_vtable,
+ &br_sha256_vtable,
+ &br_sha384_vtable,
+ &br_sha512_vtable
+ };
+
+ int id;
+
+ /*
+ * Reset server context and set supported versions from TLS-1.0
+ * to TLS-1.2 (inclusive).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
+
+ /*
+ * Set suites and elliptic curve implementation (for ECDHE).
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+ br_ssl_engine_set_default_ec(&cc->eng);
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_rsa(cc, chain, chain_len, sk,
+ BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
+ br_rsa_private_get_default(),
+ br_rsa_pkcs1_sign_get_default());
+
+ /*
+ * Set supported hash functions.
+ */
+ for (id = br_md5_ID; id <= br_sha512_ID; id ++) {
+ const br_hash_class *hc;
+
+ hc = hashes[id - 1];
+ br_ssl_engine_set_hash(&cc->eng, id, hc);
+ }
+
+ /*
+ * Set the PRF implementations.
+ */
+ 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);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_aes_cbc(&cc->eng);
+ br_ssl_engine_set_default_aes_ccm(&cc->eng);
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+ br_ssl_engine_set_default_des_cbc(&cc->eng);
+ br_ssl_engine_set_default_chapol(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_full_rsa.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_mine2c.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_mine2c.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_mine2c.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_server_init_mine2c(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_CHACHA20_POLY1305_SHA256
+ };
+
+ /*
+ * Reset server context and set supported versions to TLS-1.2 (only).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
+
+ /*
+ * Set suites and elliptic curve implementation (for ECDHE).
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+ br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15);
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_rsa(cc, chain, chain_len, sk,
+ BR_KEYTYPE_SIGN, 0, br_rsa_i31_pkcs1_sign);
+
+ /*
+ * Set supported hash functions.
+ */
+ br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_chapol(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_mine2c.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_mine2g.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_mine2g.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_mine2g.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_server_init_mine2g(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
+ };
+
+ /*
+ * Reset server context and set supported versions to TLS-1.2 (only).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
+
+ /*
+ * Set suites and elliptic curve implementation (for ECDHE).
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+ br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15);
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_rsa(cc, chain, chain_len, sk,
+ BR_KEYTYPE_SIGN, 0, br_rsa_i31_pkcs1_sign);
+
+ /*
+ * Set supported hash functions.
+ */
+ br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_mine2g.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_minf2c.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_minf2c.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_minf2c.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_server_init_minf2c(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk)
+{
+ static const uint16_t suites[] = {
+ BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+ };
+
+ /*
+ * Reset server context and set supported versions to TLS-1.2 (only).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
+
+ /*
+ * Set suites and elliptic curve implementation (for ECDHE).
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+ br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15);
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
+ BR_KEYTYPE_SIGN, 0, &br_ec_all_m15, br_ecdsa_i31_sign_asn1);
+
+ /*
+ * Set supported hash functions.
+ */
+ br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_chapol(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_minf2c.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_minf2g.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_minf2g.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_minf2g.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_ssl.h */
+void
+br_ssl_server_init_minf2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk)
+{
+ static const uint16_t suites[] = {
+ BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ };
+
+ /*
+ * Reset server context and set supported versions to TLS-1.2 (only).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
+
+ /*
+ * Set suites and elliptic curve implementation (for ECDHE).
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+ br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15);
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
+ BR_KEYTYPE_SIGN, 0, &br_ec_all_m15, br_ecdsa_i31_sign_asn1);
+
+ /*
+ * Set supported hash functions.
+ */
+ br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_minf2g.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_minr2g.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_minr2g.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_minr2g.c (revision 346145)
@@ -0,0 +1,70 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_server_init_minr2g(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_RSA_WITH_AES_128_GCM_SHA256
+ };
+
+ /*
+ * Reset server context and set supported versions to TLS-1.2 (only).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
+
+ /*
+ * Set suites.
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_rsa(cc, chain, chain_len, sk,
+ BR_KEYTYPE_KEYX, br_rsa_i31_private, 0);
+
+ /*
+ * Set supported hash functions.
+ */
+ br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_minr2g.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_minu2g.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_minu2g.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_minu2g.c (revision 346145)
@@ -0,0 +1,70 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_server_init_minu2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk)
+{
+ static const uint16_t suites[] = {
+ BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ };
+
+ /*
+ * Reset server context and set supported versions to TLS-1.2 (only).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
+
+ /*
+ * Set suites.
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
+ BR_KEYTYPE_KEYX, BR_KEYTYPE_RSA, &br_ec_all_m15, 0);
+
+ /*
+ * Set supported hash functions.
+ */
+ br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_minu2g.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/ssl/ssl_server_minv2g.c
===================================================================
--- stable/12/contrib/bearssl/src/ssl/ssl_server_minv2g.c (nonexistent)
+++ stable/12/contrib/bearssl/src/ssl/ssl_server_minv2g.c (revision 346145)
@@ -0,0 +1,70 @@
+/*
+ * 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 bearssl_ssl.h */
+void
+br_ssl_server_init_minv2g(br_ssl_server_context *cc,
+ const br_x509_certificate *chain, size_t chain_len,
+ const br_ec_private_key *sk)
+{
+ static const uint16_t suites[] = {
+ BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ };
+
+ /*
+ * Reset server context and set supported versions to TLS-1.2 (only).
+ */
+ br_ssl_server_zero(cc);
+ br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
+
+ /*
+ * Set suites.
+ */
+ br_ssl_engine_set_suites(&cc->eng, suites,
+ (sizeof suites) / (sizeof suites[0]));
+
+ /*
+ * Set the "server policy": handler for the certificate chain
+ * and private key operations.
+ */
+ br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
+ BR_KEYTYPE_KEYX, BR_KEYTYPE_EC, &br_ec_all_m15, 0);
+
+ /*
+ * Set supported hash functions.
+ */
+ br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
+
+ /*
+ * Set the PRF implementations.
+ */
+ br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
+
+ /*
+ * Symmetric encryption.
+ */
+ br_ssl_engine_set_default_aes_gcm(&cc->eng);
+}
Property changes on: stable/12/contrib/bearssl/src/ssl/ssl_server_minv2g.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_big_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_big_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_big_cbcdec.c (revision 346145)
@@ -0,0 +1,69 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_big_cbcdec_vtable;
+ ctx->num_rounds = br_aes_big_keysched_inv(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[16];
+ int i;
+
+ memcpy(tmp, buf, 16);
+ br_aes_big_decrypt(ctx->num_rounds, ctx->skey, buf);
+ for (i = 0; i < 16; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ memcpy(ivbuf, tmp, 16);
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_aes_big_cbcdec_vtable = {
+ sizeof(br_aes_big_cbcdec_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_aes_big_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_aes_big_cbcdec_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_big_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_big_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_big_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_big_cbcenc.c (revision 346145)
@@ -0,0 +1,67 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_big_cbcenc_vtable;
+ ctx->num_rounds = br_aes_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ int i;
+
+ for (i = 0; i < 16; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ br_aes_big_encrypt(ctx->num_rounds, ctx->skey, buf);
+ memcpy(ivbuf, buf, 16);
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_aes_big_cbcenc_vtable = {
+ sizeof(br_aes_big_cbcenc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_aes_big_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_aes_big_cbcenc_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_big_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_big_ctr.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_big_ctr.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_big_ctr.c (revision 346145)
@@ -0,0 +1,84 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_big_ctr_vtable;
+ ctx->num_rounds = br_aes_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+uint32_t
+br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[16];
+
+ memcpy(tmp, iv, 12);
+ br_enc32be(tmp + 12, cc ++);
+ br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp);
+ if (len <= 16) {
+ xorbuf(buf, tmp, len);
+ break;
+ }
+ xorbuf(buf, tmp, 16);
+ buf += 16;
+ len -= 16;
+ }
+ return cc;
+}
+
+/* see bearssl_block.h */
+const br_block_ctr_class br_aes_big_ctr_vtable = {
+ sizeof(br_aes_big_ctr_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctr_class **, const void *, size_t))
+ &br_aes_big_ctr_init,
+ (uint32_t (*)(const br_block_ctr_class *const *,
+ const void *, uint32_t, void *, size_t))
+ &br_aes_big_ctr_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_big_ctr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_big_ctrcbc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_big_ctrcbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_big_ctrcbc.c (revision 346145)
@@ -0,0 +1,142 @@
+/*
+ * 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"
+
+/* see bearssl_block.h */
+void
+br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_big_ctrcbc_vtable;
+ ctx->num_rounds = br_aes_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len)
+{
+ unsigned char *buf, *bctr;
+ uint32_t cc0, cc1, cc2, cc3;
+
+ buf = data;
+ bctr = ctr;
+ cc3 = br_dec32be(bctr + 0);
+ cc2 = br_dec32be(bctr + 4);
+ cc1 = br_dec32be(bctr + 8);
+ cc0 = br_dec32be(bctr + 12);
+ while (len > 0) {
+ unsigned char tmp[16];
+ uint32_t carry;
+
+ br_enc32be(tmp + 0, cc3);
+ br_enc32be(tmp + 4, cc2);
+ br_enc32be(tmp + 8, cc1);
+ br_enc32be(tmp + 12, cc0);
+ br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp);
+ xorbuf(buf, tmp, 16);
+ buf += 16;
+ len -= 16;
+ cc0 ++;
+ carry = (~(cc0 | -cc0)) >> 31;
+ cc1 += carry;
+ carry &= (~(cc1 | -cc1)) >> 31;
+ cc2 += carry;
+ carry &= (~(cc2 | -cc2)) >> 31;
+ cc3 += carry;
+ }
+ br_enc32be(bctr + 0, cc3);
+ br_enc32be(bctr + 4, cc2);
+ br_enc32be(bctr + 8, cc1);
+ br_enc32be(bctr + 12, cc0);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len)
+{
+ const unsigned char *buf;
+
+ buf = data;
+ while (len > 0) {
+ xorbuf(cbcmac, buf, 16);
+ br_aes_big_encrypt(ctx->num_rounds, ctx->skey, cbcmac);
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ br_aes_big_ctrcbc_ctr(ctx, ctr, data, len);
+ br_aes_big_ctrcbc_mac(ctx, cbcmac, data, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ br_aes_big_ctrcbc_mac(ctx, cbcmac, data, len);
+ br_aes_big_ctrcbc_ctr(ctx, ctr, data, len);
+}
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable = {
+ sizeof(br_aes_big_ctrcbc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
+ &br_aes_big_ctrcbc_init,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_big_ctrcbc_encrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_big_ctrcbc_decrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, size_t))
+ &br_aes_big_ctrcbc_ctr,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, const void *, size_t))
+ &br_aes_big_ctrcbc_mac
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_big_ctrcbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_big_dec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_big_dec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_big_dec.c (revision 346145)
@@ -0,0 +1,254 @@
+/*
+ * 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"
+
+/*
+ * Inverse S-box (used in key schedule for decryption).
+ */
+static const unsigned char iS[] = {
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
+ 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
+ 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
+ 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
+ 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
+ 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
+ 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
+ 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
+ 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
+ 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
+ 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
+ 0x55, 0x21, 0x0C, 0x7D
+};
+
+static const uint32_t iSsm0[] = {
+ 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1,
+ 0xACFA58AB, 0x4BE30393, 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25,
+ 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F, 0xDEB15A49, 0x25BA1B67,
+ 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6,
+ 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3,
+ 0x49E06929, 0x8EC9C844, 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD,
+ 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, 0x63DF4A18, 0xE51A3182,
+ 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94,
+ 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2,
+ 0xE31F8F57, 0x6655AB2A, 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5,
+ 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, 0x8ACF1C2B, 0xA779B492,
+ 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A,
+ 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA,
+ 0x5E719F06, 0xBD6E1051, 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46,
+ 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF, 0x1998FB24, 0xD6BDE997,
+ 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB,
+ 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48,
+ 0x1E1170AC, 0x6C5A724E, 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927,
+ 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A, 0x0C0A67B1, 0x9357E70F,
+ 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16,
+ 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD,
+ 0x2DB6A8B9, 0x141EA9C8, 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD,
+ 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34, 0x8B432976, 0xCB23C6DC,
+ 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120,
+ 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3,
+ 0x0D8652EC, 0x77C1E3D0, 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422,
+ 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, 0x87494EC7, 0xD938D1C1,
+ 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4,
+ 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8,
+ 0x2E39F75E, 0x82C3AFF5, 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3,
+ 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, 0xCD267809, 0x6E5918F4,
+ 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6,
+ 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331,
+ 0xC6A59430, 0x35A266C0, 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815,
+ 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, 0x764DD68D, 0x43EFB04D,
+ 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F,
+ 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252,
+ 0xE9105633, 0x6DD64713, 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89,
+ 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C, 0x9CD2DF59, 0x55F2733F,
+ 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86,
+ 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C,
+ 0x283C498B, 0xFF0D9541, 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190,
+ 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742
+};
+
+static unsigned
+mul2(unsigned x)
+{
+ x <<= 1;
+ return x ^ ((unsigned)(-(int)(x >> 8)) & 0x11B);
+}
+
+static unsigned
+mul9(unsigned x)
+{
+ return x ^ mul2(mul2(mul2(x)));
+}
+
+static unsigned
+mulb(unsigned x)
+{
+ unsigned x2;
+
+ x2 = mul2(x);
+ return x ^ x2 ^ mul2(mul2(x2));
+}
+
+static unsigned
+muld(unsigned x)
+{
+ unsigned x4;
+
+ x4 = mul2(mul2(x));
+ return x ^ x4 ^ mul2(x4);
+}
+
+static unsigned
+mule(unsigned x)
+{
+ unsigned x2, x4;
+
+ x2 = mul2(x);
+ x4 = mul2(x2);
+ return x2 ^ x4 ^ mul2(x4);
+}
+
+/* see inner.h */
+unsigned
+br_aes_big_keysched_inv(uint32_t *skey, const void *key, size_t key_len)
+{
+ unsigned num_rounds;
+ int i, m;
+
+ /*
+ * Sub-keys for decryption are distinct from encryption sub-keys
+ * in that InvMixColumns() is already applied for the inner
+ * rounds.
+ */
+ num_rounds = br_aes_keysched(skey, key, key_len);
+ m = (int)(num_rounds << 2);
+ for (i = 4; i < m; i ++) {
+ uint32_t p;
+ unsigned p0, p1, p2, p3;
+ uint32_t q0, q1, q2, q3;
+
+ p = skey[i];
+ p0 = p >> 24;
+ p1 = (p >> 16) & 0xFF;
+ p2 = (p >> 8) & 0xFF;
+ p3 = p & 0xFF;
+ q0 = mule(p0) ^ mulb(p1) ^ muld(p2) ^ mul9(p3);
+ q1 = mul9(p0) ^ mule(p1) ^ mulb(p2) ^ muld(p3);
+ q2 = muld(p0) ^ mul9(p1) ^ mule(p2) ^ mulb(p3);
+ q3 = mulb(p0) ^ muld(p1) ^ mul9(p2) ^ mule(p3);
+ skey[i] = (q0 << 24) | (q1 << 16) | (q2 << 8) | q3;
+ }
+ return num_rounds;
+}
+
+static inline uint32_t
+rotr(uint32_t x, int n)
+{
+ return (x << (32 - n)) | (x >> n);
+}
+
+#define iSboxExt0(x) (iSsm0[x])
+#define iSboxExt1(x) (rotr(iSsm0[x], 8))
+#define iSboxExt2(x) (rotr(iSsm0[x], 16))
+#define iSboxExt3(x) (rotr(iSsm0[x], 24))
+
+/* see bearssl.h */
+void
+br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data)
+{
+ unsigned char *buf;
+ uint32_t s0, s1, s2, s3;
+ uint32_t t0, t1, t2, t3;
+ unsigned u;
+
+ buf = data;
+ s0 = br_dec32be(buf);
+ s1 = br_dec32be(buf + 4);
+ s2 = br_dec32be(buf + 8);
+ s3 = br_dec32be(buf + 12);
+ s0 ^= skey[(num_rounds << 2) + 0];
+ s1 ^= skey[(num_rounds << 2) + 1];
+ s2 ^= skey[(num_rounds << 2) + 2];
+ s3 ^= skey[(num_rounds << 2) + 3];
+ for (u = num_rounds - 1; u > 0; u --) {
+ uint32_t v0 = iSboxExt0(s0 >> 24)
+ ^ iSboxExt1((s3 >> 16) & 0xFF)
+ ^ iSboxExt2((s2 >> 8) & 0xFF)
+ ^ iSboxExt3(s1 & 0xFF);
+ uint32_t v1 = iSboxExt0(s1 >> 24)
+ ^ iSboxExt1((s0 >> 16) & 0xFF)
+ ^ iSboxExt2((s3 >> 8) & 0xFF)
+ ^ iSboxExt3(s2 & 0xFF);
+ uint32_t v2 = iSboxExt0(s2 >> 24)
+ ^ iSboxExt1((s1 >> 16) & 0xFF)
+ ^ iSboxExt2((s0 >> 8) & 0xFF)
+ ^ iSboxExt3(s3 & 0xFF);
+ uint32_t v3 = iSboxExt0(s3 >> 24)
+ ^ iSboxExt1((s2 >> 16) & 0xFF)
+ ^ iSboxExt2((s1 >> 8) & 0xFF)
+ ^ iSboxExt3(s0 & 0xFF);
+ s0 = v0;
+ s1 = v1;
+ s2 = v2;
+ s3 = v3;
+ s0 ^= skey[u << 2];
+ s1 ^= skey[(u << 2) + 1];
+ s2 ^= skey[(u << 2) + 2];
+ s3 ^= skey[(u << 2) + 3];
+ }
+ t0 = ((uint32_t)iS[s0 >> 24] << 24)
+ | ((uint32_t)iS[(s3 >> 16) & 0xFF] << 16)
+ | ((uint32_t)iS[(s2 >> 8) & 0xFF] << 8)
+ | (uint32_t)iS[s1 & 0xFF];
+ t1 = ((uint32_t)iS[s1 >> 24] << 24)
+ | ((uint32_t)iS[(s0 >> 16) & 0xFF] << 16)
+ | ((uint32_t)iS[(s3 >> 8) & 0xFF] << 8)
+ | (uint32_t)iS[s2 & 0xFF];
+ t2 = ((uint32_t)iS[s2 >> 24] << 24)
+ | ((uint32_t)iS[(s1 >> 16) & 0xFF] << 16)
+ | ((uint32_t)iS[(s0 >> 8) & 0xFF] << 8)
+ | (uint32_t)iS[s3 & 0xFF];
+ t3 = ((uint32_t)iS[s3 >> 24] << 24)
+ | ((uint32_t)iS[(s2 >> 16) & 0xFF] << 16)
+ | ((uint32_t)iS[(s1 >> 8) & 0xFF] << 8)
+ | (uint32_t)iS[s0 & 0xFF];
+ s0 = t0 ^ skey[0];
+ s1 = t1 ^ skey[1];
+ s2 = t2 ^ skey[2];
+ s3 = t3 ^ skey[3];
+ br_enc32be(buf, s0);
+ br_enc32be(buf + 4, s1);
+ br_enc32be(buf + 8, s2);
+ br_enc32be(buf + 12, s3);
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_big_dec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_big_enc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_big_enc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_big_enc.c (revision 346145)
@@ -0,0 +1,157 @@
+/*
+ * 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"
+
+#define S br_aes_S
+
+static const uint32_t Ssm0[] = {
+ 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD,
+ 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D,
+ 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D,
+ 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B,
+ 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7,
+ 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A,
+ 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4,
+ 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F,
+ 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1,
+ 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D,
+ 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E,
+ 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
+ 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E,
+ 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C,
+ 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46,
+ 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A,
+ 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7,
+ 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81,
+ 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE,
+ 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504,
+ 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A,
+ 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F,
+ 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2,
+ 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395,
+ 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E,
+ 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C,
+ 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256,
+ 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4,
+ 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4,
+ 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7,
+ 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA,
+ 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818,
+ 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1,
+ 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21,
+ 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42,
+ 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12,
+ 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158,
+ 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133,
+ 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22,
+ 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A,
+ 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631,
+ 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11,
+ 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A
+};
+
+static inline uint32_t
+rotr(uint32_t x, int n)
+{
+ return (x << (32 - n)) | (x >> n);
+}
+
+#define SboxExt0(x) (Ssm0[x])
+#define SboxExt1(x) (rotr(Ssm0[x], 8))
+#define SboxExt2(x) (rotr(Ssm0[x], 16))
+#define SboxExt3(x) (rotr(Ssm0[x], 24))
+
+
+/* see bearssl.h */
+void
+br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data)
+{
+ unsigned char *buf;
+ uint32_t s0, s1, s2, s3;
+ uint32_t t0, t1, t2, t3;
+ unsigned u;
+
+ buf = data;
+ s0 = br_dec32be(buf);
+ s1 = br_dec32be(buf + 4);
+ s2 = br_dec32be(buf + 8);
+ s3 = br_dec32be(buf + 12);
+ s0 ^= skey[0];
+ s1 ^= skey[1];
+ s2 ^= skey[2];
+ s3 ^= skey[3];
+ for (u = 1; u < num_rounds; u ++) {
+ uint32_t v0, v1, v2, v3;
+
+ v0 = SboxExt0(s0 >> 24)
+ ^ SboxExt1((s1 >> 16) & 0xFF)
+ ^ SboxExt2((s2 >> 8) & 0xFF)
+ ^ SboxExt3(s3 & 0xFF);
+ v1 = SboxExt0(s1 >> 24)
+ ^ SboxExt1((s2 >> 16) & 0xFF)
+ ^ SboxExt2((s3 >> 8) & 0xFF)
+ ^ SboxExt3(s0 & 0xFF);
+ v2 = SboxExt0(s2 >> 24)
+ ^ SboxExt1((s3 >> 16) & 0xFF)
+ ^ SboxExt2((s0 >> 8) & 0xFF)
+ ^ SboxExt3(s1 & 0xFF);
+ v3 = SboxExt0(s3 >> 24)
+ ^ SboxExt1((s0 >> 16) & 0xFF)
+ ^ SboxExt2((s1 >> 8) & 0xFF)
+ ^ SboxExt3(s2 & 0xFF);
+ s0 = v0;
+ s1 = v1;
+ s2 = v2;
+ s3 = v3;
+ s0 ^= skey[u << 2];
+ s1 ^= skey[(u << 2) + 1];
+ s2 ^= skey[(u << 2) + 2];
+ s3 ^= skey[(u << 2) + 3];
+ }
+ t0 = ((uint32_t)S[s0 >> 24] << 24)
+ | ((uint32_t)S[(s1 >> 16) & 0xFF] << 16)
+ | ((uint32_t)S[(s2 >> 8) & 0xFF] << 8)
+ | (uint32_t)S[s3 & 0xFF];
+ t1 = ((uint32_t)S[s1 >> 24] << 24)
+ | ((uint32_t)S[(s2 >> 16) & 0xFF] << 16)
+ | ((uint32_t)S[(s3 >> 8) & 0xFF] << 8)
+ | (uint32_t)S[s0 & 0xFF];
+ t2 = ((uint32_t)S[s2 >> 24] << 24)
+ | ((uint32_t)S[(s3 >> 16) & 0xFF] << 16)
+ | ((uint32_t)S[(s0 >> 8) & 0xFF] << 8)
+ | (uint32_t)S[s1 & 0xFF];
+ t3 = ((uint32_t)S[s3 >> 24] << 24)
+ | ((uint32_t)S[(s0 >> 16) & 0xFF] << 16)
+ | ((uint32_t)S[(s1 >> 8) & 0xFF] << 8)
+ | (uint32_t)S[s2 & 0xFF];
+ s0 = t0 ^ skey[num_rounds << 2];
+ s1 = t1 ^ skey[(num_rounds << 2) + 1];
+ s2 = t2 ^ skey[(num_rounds << 2) + 2];
+ s3 = t3 ^ skey[(num_rounds << 2) + 3];
+ br_enc32be(buf, s0);
+ br_enc32be(buf + 4, s1);
+ br_enc32be(buf + 8, s2);
+ br_enc32be(buf + 12, s3);
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_big_enc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_common.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_common.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_common.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+static const uint32_t Rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
+ 0x40000000, 0x80000000, 0x1B000000, 0x36000000
+};
+
+#define S br_aes_S
+
+/* see inner.h */
+const unsigned char br_aes_S[] = {
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
+ 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
+ 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
+ 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
+ 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
+ 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
+ 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
+ 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
+ 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
+ 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
+ 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
+ 0xB0, 0x54, 0xBB, 0x16
+};
+
+static uint32_t
+SubWord(uint32_t x)
+{
+ return ((uint32_t)S[x >> 24] << 24)
+ | ((uint32_t)S[(x >> 16) & 0xFF] << 16)
+ | ((uint32_t)S[(x >> 8) & 0xFF] << 8)
+ | (uint32_t)S[x & 0xFF];
+}
+
+/* see inner.h */
+unsigned
+br_aes_keysched(uint32_t *skey, const void *key, size_t key_len)
+{
+ unsigned num_rounds;
+ int i, j, k, nk, nkf;
+
+ switch (key_len) {
+ case 16:
+ num_rounds = 10;
+ break;
+ case 24:
+ num_rounds = 12;
+ break;
+ case 32:
+ num_rounds = 14;
+ break;
+ default:
+ /* abort(); */
+ return 0;
+ }
+ nk = (int)(key_len >> 2);
+ nkf = (int)((num_rounds + 1) << 2);
+ for (i = 0; i < nk; i ++) {
+ skey[i] = br_dec32be((const unsigned char *)key + (i << 2));
+ }
+ for (i = nk, j = 0, k = 0; i < nkf; i ++) {
+ uint32_t tmp;
+
+ tmp = skey[i - 1];
+ if (j == 0) {
+ tmp = (tmp << 8) | (tmp >> 24);
+ tmp = SubWord(tmp) ^ Rcon[k];
+ } else if (nk > 6 && j == 4) {
+ tmp = SubWord(tmp);
+ }
+ skey[i] = skey[i - nk] ^ tmp;
+ if (++ j == nk) {
+ j = 0;
+ k ++;
+ }
+ }
+ return num_rounds;
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_common.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct.c (revision 346145)
@@ -0,0 +1,328 @@
+/*
+ * 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_aes_ct_bitslice_Sbox(uint32_t *q)
+{
+ /*
+ * This S-box implementation is a straightforward translation of
+ * the circuit described by Boyar and Peralta in "A new
+ * combinational logic minimization technique with applications
+ * to cryptology" (https://eprint.iacr.org/2009/191.pdf).
+ *
+ * Note that variables x* (input) and s* (output) are numbered
+ * in "reverse" order (x0 is the high bit, x7 is the low bit).
+ */
+
+ uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
+ uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9;
+ uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19;
+ uint32_t y20, y21;
+ uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9;
+ uint32_t z10, z11, z12, z13, z14, z15, z16, z17;
+ uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
+ uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19;
+ uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29;
+ uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39;
+ uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49;
+ uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59;
+ uint32_t t60, t61, t62, t63, t64, t65, t66, t67;
+ uint32_t s0, s1, s2, s3, s4, s5, s6, s7;
+
+ x0 = q[7];
+ x1 = q[6];
+ x2 = q[5];
+ x3 = q[4];
+ x4 = q[3];
+ x5 = q[2];
+ x6 = q[1];
+ x7 = q[0];
+
+ /*
+ * Top linear transformation.
+ */
+ y14 = x3 ^ x5;
+ y13 = x0 ^ x6;
+ y9 = x0 ^ x3;
+ y8 = x0 ^ x5;
+ t0 = x1 ^ x2;
+ y1 = t0 ^ x7;
+ y4 = y1 ^ x3;
+ y12 = y13 ^ y14;
+ y2 = y1 ^ x0;
+ y5 = y1 ^ x6;
+ y3 = y5 ^ y8;
+ t1 = x4 ^ y12;
+ y15 = t1 ^ x5;
+ y20 = t1 ^ x1;
+ y6 = y15 ^ x7;
+ y10 = y15 ^ t0;
+ y11 = y20 ^ y9;
+ y7 = x7 ^ y11;
+ y17 = y10 ^ y11;
+ y19 = y10 ^ y8;
+ y16 = t0 ^ y11;
+ y21 = y13 ^ y16;
+ y18 = x0 ^ y16;
+
+ /*
+ * Non-linear section.
+ */
+ t2 = y12 & y15;
+ t3 = y3 & y6;
+ t4 = t3 ^ t2;
+ t5 = y4 & x7;
+ t6 = t5 ^ t2;
+ t7 = y13 & y16;
+ t8 = y5 & y1;
+ t9 = t8 ^ t7;
+ t10 = y2 & y7;
+ t11 = t10 ^ t7;
+ t12 = y9 & y11;
+ t13 = y14 & y17;
+ t14 = t13 ^ t12;
+ t15 = y8 & y10;
+ t16 = t15 ^ t12;
+ t17 = t4 ^ t14;
+ t18 = t6 ^ t16;
+ t19 = t9 ^ t14;
+ t20 = t11 ^ t16;
+ t21 = t17 ^ y20;
+ t22 = t18 ^ y19;
+ t23 = t19 ^ y21;
+ t24 = t20 ^ y18;
+
+ t25 = t21 ^ t22;
+ t26 = t21 & t23;
+ t27 = t24 ^ t26;
+ t28 = t25 & t27;
+ t29 = t28 ^ t22;
+ t30 = t23 ^ t24;
+ t31 = t22 ^ t26;
+ t32 = t31 & t30;
+ t33 = t32 ^ t24;
+ t34 = t23 ^ t33;
+ t35 = t27 ^ t33;
+ t36 = t24 & t35;
+ t37 = t36 ^ t34;
+ t38 = t27 ^ t36;
+ t39 = t29 & t38;
+ t40 = t25 ^ t39;
+
+ t41 = t40 ^ t37;
+ t42 = t29 ^ t33;
+ t43 = t29 ^ t40;
+ t44 = t33 ^ t37;
+ t45 = t42 ^ t41;
+ z0 = t44 & y15;
+ z1 = t37 & y6;
+ z2 = t33 & x7;
+ z3 = t43 & y16;
+ z4 = t40 & y1;
+ z5 = t29 & y7;
+ z6 = t42 & y11;
+ z7 = t45 & y17;
+ z8 = t41 & y10;
+ z9 = t44 & y12;
+ z10 = t37 & y3;
+ z11 = t33 & y4;
+ z12 = t43 & y13;
+ z13 = t40 & y5;
+ z14 = t29 & y2;
+ z15 = t42 & y9;
+ z16 = t45 & y14;
+ z17 = t41 & y8;
+
+ /*
+ * Bottom linear transformation.
+ */
+ t46 = z15 ^ z16;
+ t47 = z10 ^ z11;
+ t48 = z5 ^ z13;
+ t49 = z9 ^ z10;
+ t50 = z2 ^ z12;
+ t51 = z2 ^ z5;
+ t52 = z7 ^ z8;
+ t53 = z0 ^ z3;
+ t54 = z6 ^ z7;
+ t55 = z16 ^ z17;
+ t56 = z12 ^ t48;
+ t57 = t50 ^ t53;
+ t58 = z4 ^ t46;
+ t59 = z3 ^ t54;
+ t60 = t46 ^ t57;
+ t61 = z14 ^ t57;
+ t62 = t52 ^ t58;
+ t63 = t49 ^ t58;
+ t64 = z4 ^ t59;
+ t65 = t61 ^ t62;
+ t66 = z1 ^ t63;
+ s0 = t59 ^ t63;
+ s6 = t56 ^ ~t62;
+ s7 = t48 ^ ~t60;
+ t67 = t64 ^ t65;
+ s3 = t53 ^ t66;
+ s4 = t51 ^ t66;
+ s5 = t47 ^ t65;
+ s1 = t64 ^ ~s3;
+ s2 = t55 ^ ~t67;
+
+ q[7] = s0;
+ q[6] = s1;
+ q[5] = s2;
+ q[4] = s3;
+ q[3] = s4;
+ q[2] = s5;
+ q[1] = s6;
+ q[0] = s7;
+}
+
+/* see inner.h */
+void
+br_aes_ct_ortho(uint32_t *q)
+{
+#define SWAPN(cl, ch, s, x, y) do { \
+ uint32_t a, b; \
+ a = (x); \
+ b = (y); \
+ (x) = (a & (uint32_t)cl) | ((b & (uint32_t)cl) << (s)); \
+ (y) = ((a & (uint32_t)ch) >> (s)) | (b & (uint32_t)ch); \
+ } while (0)
+
+#define SWAP2(x, y) SWAPN(0x55555555, 0xAAAAAAAA, 1, x, y)
+#define SWAP4(x, y) SWAPN(0x33333333, 0xCCCCCCCC, 2, x, y)
+#define SWAP8(x, y) SWAPN(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y)
+
+ SWAP2(q[0], q[1]);
+ SWAP2(q[2], q[3]);
+ SWAP2(q[4], q[5]);
+ SWAP2(q[6], q[7]);
+
+ SWAP4(q[0], q[2]);
+ SWAP4(q[1], q[3]);
+ SWAP4(q[4], q[6]);
+ SWAP4(q[5], q[7]);
+
+ SWAP8(q[0], q[4]);
+ SWAP8(q[1], q[5]);
+ SWAP8(q[2], q[6]);
+ SWAP8(q[3], q[7]);
+}
+
+static const unsigned char Rcon[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+};
+
+static uint32_t
+sub_word(uint32_t x)
+{
+ uint32_t q[8];
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ q[i] = x;
+ }
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_Sbox(q);
+ br_aes_ct_ortho(q);
+ return q[0];
+}
+
+/* see inner.h */
+unsigned
+br_aes_ct_keysched(uint32_t *comp_skey, const void *key, size_t key_len)
+{
+ unsigned num_rounds;
+ int i, j, k, nk, nkf;
+ uint32_t tmp;
+ uint32_t skey[120];
+
+ switch (key_len) {
+ case 16:
+ num_rounds = 10;
+ break;
+ case 24:
+ num_rounds = 12;
+ break;
+ case 32:
+ num_rounds = 14;
+ break;
+ default:
+ /* abort(); */
+ return 0;
+ }
+ nk = (int)(key_len >> 2);
+ nkf = (int)((num_rounds + 1) << 2);
+ tmp = 0;
+ for (i = 0; i < nk; i ++) {
+ tmp = br_dec32le((const unsigned char *)key + (i << 2));
+ skey[(i << 1) + 0] = tmp;
+ skey[(i << 1) + 1] = tmp;
+ }
+ for (i = nk, j = 0, k = 0; i < nkf; i ++) {
+ if (j == 0) {
+ tmp = (tmp << 24) | (tmp >> 8);
+ tmp = sub_word(tmp) ^ Rcon[k];
+ } else if (nk > 6 && j == 4) {
+ tmp = sub_word(tmp);
+ }
+ tmp ^= skey[(i - nk) << 1];
+ skey[(i << 1) + 0] = tmp;
+ skey[(i << 1) + 1] = tmp;
+ if (++ j == nk) {
+ j = 0;
+ k ++;
+ }
+ }
+ for (i = 0; i < nkf; i += 4) {
+ br_aes_ct_ortho(skey + (i << 1));
+ }
+ for (i = 0, j = 0; i < nkf; i ++, j += 2) {
+ comp_skey[i] = (skey[j + 0] & 0x55555555)
+ | (skey[j + 1] & 0xAAAAAAAA);
+ }
+ return num_rounds;
+}
+
+/* see inner.h */
+void
+br_aes_ct_skey_expand(uint32_t *skey,
+ unsigned num_rounds, const uint32_t *comp_skey)
+{
+ unsigned u, v, n;
+
+ n = (num_rounds + 1) << 2;
+ for (u = 0, v = 0; u < n; u ++, v += 2) {
+ uint32_t x, y;
+
+ x = y = comp_skey[u];
+ x &= 0x55555555;
+ skey[v + 0] = x | (x << 1);
+ y &= 0xAAAAAAAA;
+ skey[v + 1] = y | (y >> 1);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct64.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct64.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct64.c (revision 346145)
@@ -0,0 +1,398 @@
+/*
+ * 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_aes_ct64_bitslice_Sbox(uint64_t *q)
+{
+ /*
+ * This S-box implementation is a straightforward translation of
+ * the circuit described by Boyar and Peralta in "A new
+ * combinational logic minimization technique with applications
+ * to cryptology" (https://eprint.iacr.org/2009/191.pdf).
+ *
+ * Note that variables x* (input) and s* (output) are numbered
+ * in "reverse" order (x0 is the high bit, x7 is the low bit).
+ */
+
+ uint64_t x0, x1, x2, x3, x4, x5, x6, x7;
+ uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9;
+ uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19;
+ uint64_t y20, y21;
+ uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9;
+ uint64_t z10, z11, z12, z13, z14, z15, z16, z17;
+ uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
+ uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19;
+ uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29;
+ uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39;
+ uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49;
+ uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59;
+ uint64_t t60, t61, t62, t63, t64, t65, t66, t67;
+ uint64_t s0, s1, s2, s3, s4, s5, s6, s7;
+
+ x0 = q[7];
+ x1 = q[6];
+ x2 = q[5];
+ x3 = q[4];
+ x4 = q[3];
+ x5 = q[2];
+ x6 = q[1];
+ x7 = q[0];
+
+ /*
+ * Top linear transformation.
+ */
+ y14 = x3 ^ x5;
+ y13 = x0 ^ x6;
+ y9 = x0 ^ x3;
+ y8 = x0 ^ x5;
+ t0 = x1 ^ x2;
+ y1 = t0 ^ x7;
+ y4 = y1 ^ x3;
+ y12 = y13 ^ y14;
+ y2 = y1 ^ x0;
+ y5 = y1 ^ x6;
+ y3 = y5 ^ y8;
+ t1 = x4 ^ y12;
+ y15 = t1 ^ x5;
+ y20 = t1 ^ x1;
+ y6 = y15 ^ x7;
+ y10 = y15 ^ t0;
+ y11 = y20 ^ y9;
+ y7 = x7 ^ y11;
+ y17 = y10 ^ y11;
+ y19 = y10 ^ y8;
+ y16 = t0 ^ y11;
+ y21 = y13 ^ y16;
+ y18 = x0 ^ y16;
+
+ /*
+ * Non-linear section.
+ */
+ t2 = y12 & y15;
+ t3 = y3 & y6;
+ t4 = t3 ^ t2;
+ t5 = y4 & x7;
+ t6 = t5 ^ t2;
+ t7 = y13 & y16;
+ t8 = y5 & y1;
+ t9 = t8 ^ t7;
+ t10 = y2 & y7;
+ t11 = t10 ^ t7;
+ t12 = y9 & y11;
+ t13 = y14 & y17;
+ t14 = t13 ^ t12;
+ t15 = y8 & y10;
+ t16 = t15 ^ t12;
+ t17 = t4 ^ t14;
+ t18 = t6 ^ t16;
+ t19 = t9 ^ t14;
+ t20 = t11 ^ t16;
+ t21 = t17 ^ y20;
+ t22 = t18 ^ y19;
+ t23 = t19 ^ y21;
+ t24 = t20 ^ y18;
+
+ t25 = t21 ^ t22;
+ t26 = t21 & t23;
+ t27 = t24 ^ t26;
+ t28 = t25 & t27;
+ t29 = t28 ^ t22;
+ t30 = t23 ^ t24;
+ t31 = t22 ^ t26;
+ t32 = t31 & t30;
+ t33 = t32 ^ t24;
+ t34 = t23 ^ t33;
+ t35 = t27 ^ t33;
+ t36 = t24 & t35;
+ t37 = t36 ^ t34;
+ t38 = t27 ^ t36;
+ t39 = t29 & t38;
+ t40 = t25 ^ t39;
+
+ t41 = t40 ^ t37;
+ t42 = t29 ^ t33;
+ t43 = t29 ^ t40;
+ t44 = t33 ^ t37;
+ t45 = t42 ^ t41;
+ z0 = t44 & y15;
+ z1 = t37 & y6;
+ z2 = t33 & x7;
+ z3 = t43 & y16;
+ z4 = t40 & y1;
+ z5 = t29 & y7;
+ z6 = t42 & y11;
+ z7 = t45 & y17;
+ z8 = t41 & y10;
+ z9 = t44 & y12;
+ z10 = t37 & y3;
+ z11 = t33 & y4;
+ z12 = t43 & y13;
+ z13 = t40 & y5;
+ z14 = t29 & y2;
+ z15 = t42 & y9;
+ z16 = t45 & y14;
+ z17 = t41 & y8;
+
+ /*
+ * Bottom linear transformation.
+ */
+ t46 = z15 ^ z16;
+ t47 = z10 ^ z11;
+ t48 = z5 ^ z13;
+ t49 = z9 ^ z10;
+ t50 = z2 ^ z12;
+ t51 = z2 ^ z5;
+ t52 = z7 ^ z8;
+ t53 = z0 ^ z3;
+ t54 = z6 ^ z7;
+ t55 = z16 ^ z17;
+ t56 = z12 ^ t48;
+ t57 = t50 ^ t53;
+ t58 = z4 ^ t46;
+ t59 = z3 ^ t54;
+ t60 = t46 ^ t57;
+ t61 = z14 ^ t57;
+ t62 = t52 ^ t58;
+ t63 = t49 ^ t58;
+ t64 = z4 ^ t59;
+ t65 = t61 ^ t62;
+ t66 = z1 ^ t63;
+ s0 = t59 ^ t63;
+ s6 = t56 ^ ~t62;
+ s7 = t48 ^ ~t60;
+ t67 = t64 ^ t65;
+ s3 = t53 ^ t66;
+ s4 = t51 ^ t66;
+ s5 = t47 ^ t65;
+ s1 = t64 ^ ~s3;
+ s2 = t55 ^ ~t67;
+
+ q[7] = s0;
+ q[6] = s1;
+ q[5] = s2;
+ q[4] = s3;
+ q[3] = s4;
+ q[2] = s5;
+ q[1] = s6;
+ q[0] = s7;
+}
+
+/* see inner.h */
+void
+br_aes_ct64_ortho(uint64_t *q)
+{
+#define SWAPN(cl, ch, s, x, y) do { \
+ uint64_t a, b; \
+ a = (x); \
+ b = (y); \
+ (x) = (a & (uint64_t)cl) | ((b & (uint64_t)cl) << (s)); \
+ (y) = ((a & (uint64_t)ch) >> (s)) | (b & (uint64_t)ch); \
+ } while (0)
+
+#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y)
+#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y)
+#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y)
+
+ SWAP2(q[0], q[1]);
+ SWAP2(q[2], q[3]);
+ SWAP2(q[4], q[5]);
+ SWAP2(q[6], q[7]);
+
+ SWAP4(q[0], q[2]);
+ SWAP4(q[1], q[3]);
+ SWAP4(q[4], q[6]);
+ SWAP4(q[5], q[7]);
+
+ SWAP8(q[0], q[4]);
+ SWAP8(q[1], q[5]);
+ SWAP8(q[2], q[6]);
+ SWAP8(q[3], q[7]);
+}
+
+/* see inner.h */
+void
+br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w)
+{
+ uint64_t x0, x1, x2, x3;
+
+ x0 = w[0];
+ x1 = w[1];
+ x2 = w[2];
+ x3 = w[3];
+ x0 |= (x0 << 16);
+ x1 |= (x1 << 16);
+ x2 |= (x2 << 16);
+ x3 |= (x3 << 16);
+ x0 &= (uint64_t)0x0000FFFF0000FFFF;
+ x1 &= (uint64_t)0x0000FFFF0000FFFF;
+ x2 &= (uint64_t)0x0000FFFF0000FFFF;
+ x3 &= (uint64_t)0x0000FFFF0000FFFF;
+ x0 |= (x0 << 8);
+ x1 |= (x1 << 8);
+ x2 |= (x2 << 8);
+ x3 |= (x3 << 8);
+ x0 &= (uint64_t)0x00FF00FF00FF00FF;
+ x1 &= (uint64_t)0x00FF00FF00FF00FF;
+ x2 &= (uint64_t)0x00FF00FF00FF00FF;
+ x3 &= (uint64_t)0x00FF00FF00FF00FF;
+ *q0 = x0 | (x2 << 8);
+ *q1 = x1 | (x3 << 8);
+}
+
+/* see inner.h */
+void
+br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1)
+{
+ uint64_t x0, x1, x2, x3;
+
+ x0 = q0 & (uint64_t)0x00FF00FF00FF00FF;
+ x1 = q1 & (uint64_t)0x00FF00FF00FF00FF;
+ x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF;
+ x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF;
+ x0 |= (x0 >> 8);
+ x1 |= (x1 >> 8);
+ x2 |= (x2 >> 8);
+ x3 |= (x3 >> 8);
+ x0 &= (uint64_t)0x0000FFFF0000FFFF;
+ x1 &= (uint64_t)0x0000FFFF0000FFFF;
+ x2 &= (uint64_t)0x0000FFFF0000FFFF;
+ x3 &= (uint64_t)0x0000FFFF0000FFFF;
+ w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16);
+ w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16);
+ w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16);
+ w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16);
+}
+
+static const unsigned char Rcon[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+};
+
+static uint32_t
+sub_word(uint32_t x)
+{
+ uint64_t q[8];
+
+ memset(q, 0, sizeof q);
+ q[0] = x;
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_Sbox(q);
+ br_aes_ct64_ortho(q);
+ return (uint32_t)q[0];
+}
+
+/* see inner.h */
+unsigned
+br_aes_ct64_keysched(uint64_t *comp_skey, const void *key, size_t key_len)
+{
+ unsigned num_rounds;
+ int i, j, k, nk, nkf;
+ uint32_t tmp;
+ uint32_t skey[60];
+
+ switch (key_len) {
+ case 16:
+ num_rounds = 10;
+ break;
+ case 24:
+ num_rounds = 12;
+ break;
+ case 32:
+ num_rounds = 14;
+ break;
+ default:
+ /* abort(); */
+ return 0;
+ }
+ nk = (int)(key_len >> 2);
+ nkf = (int)((num_rounds + 1) << 2);
+ br_range_dec32le(skey, (key_len >> 2), key);
+ tmp = skey[(key_len >> 2) - 1];
+ for (i = nk, j = 0, k = 0; i < nkf; i ++) {
+ if (j == 0) {
+ tmp = (tmp << 24) | (tmp >> 8);
+ tmp = sub_word(tmp) ^ Rcon[k];
+ } else if (nk > 6 && j == 4) {
+ tmp = sub_word(tmp);
+ }
+ tmp ^= skey[i - nk];
+ skey[i] = tmp;
+ if (++ j == nk) {
+ j = 0;
+ k ++;
+ }
+ }
+
+ for (i = 0, j = 0; i < nkf; i += 4, j += 2) {
+ uint64_t q[8];
+
+ br_aes_ct64_interleave_in(&q[0], &q[4], skey + i);
+ q[1] = q[0];
+ q[2] = q[0];
+ q[3] = q[0];
+ q[5] = q[4];
+ q[6] = q[4];
+ q[7] = q[4];
+ br_aes_ct64_ortho(q);
+ comp_skey[j + 0] =
+ (q[0] & (uint64_t)0x1111111111111111)
+ | (q[1] & (uint64_t)0x2222222222222222)
+ | (q[2] & (uint64_t)0x4444444444444444)
+ | (q[3] & (uint64_t)0x8888888888888888);
+ comp_skey[j + 1] =
+ (q[4] & (uint64_t)0x1111111111111111)
+ | (q[5] & (uint64_t)0x2222222222222222)
+ | (q[6] & (uint64_t)0x4444444444444444)
+ | (q[7] & (uint64_t)0x8888888888888888);
+ }
+ return num_rounds;
+}
+
+/* see inner.h */
+void
+br_aes_ct64_skey_expand(uint64_t *skey,
+ unsigned num_rounds, const uint64_t *comp_skey)
+{
+ unsigned u, v, n;
+
+ n = (num_rounds + 1) << 1;
+ for (u = 0, v = 0; u < n; u ++, v += 4) {
+ uint64_t x0, x1, x2, x3;
+
+ x0 = x1 = x2 = x3 = comp_skey[u];
+ x0 &= (uint64_t)0x1111111111111111;
+ x1 &= (uint64_t)0x2222222222222222;
+ x2 &= (uint64_t)0x4444444444444444;
+ x3 &= (uint64_t)0x8888888888888888;
+ x1 >>= 1;
+ x2 >>= 2;
+ x3 >>= 3;
+ skey[v + 0] = (x0 << 4) - x0;
+ skey[v + 1] = (x1 << 4) - x1;
+ skey[v + 2] = (x2 << 4) - x2;
+ skey[v + 3] = (x3 << 4) - x3;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct64.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcdec.c (revision 346145)
@@ -0,0 +1,104 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct64_cbcdec_vtable;
+ ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf;
+ uint64_t sk_exp[120];
+ uint32_t ivw[4];
+
+ br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ br_range_dec32le(ivw, 4, iv);
+ buf = data;
+ while (len > 0) {
+ uint64_t q[8];
+ uint32_t w1[16], w2[16];
+ int i;
+
+ if (len >= 64) {
+ br_range_dec32le(w1, 16, buf);
+ } else {
+ br_range_dec32le(w1, len >> 2, buf);
+ }
+ for (i = 0; i < 4; i ++) {
+ br_aes_ct64_interleave_in(
+ &q[i], &q[i + 4], w1 + (i << 2));
+ }
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_decrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ for (i = 0; i < 4; i ++) {
+ br_aes_ct64_interleave_out(
+ w2 + (i << 2), q[i], q[i + 4]);
+ }
+ for (i = 0; i < 4; i ++) {
+ w2[i] ^= ivw[i];
+ }
+ if (len >= 64) {
+ for (i = 4; i < 16; i ++) {
+ w2[i] ^= w1[i - 4];
+ }
+ memcpy(ivw, w1 + 12, sizeof ivw);
+ br_range_enc32le(buf, w2, 16);
+ } else {
+ int j;
+
+ j = (int)(len >> 2);
+ for (i = 4; i < j; i ++) {
+ w2[i] ^= w1[i - 4];
+ }
+ memcpy(ivw, w1 + j - 4, sizeof ivw);
+ br_range_enc32le(buf, w2, j);
+ break;
+ }
+ buf += 64;
+ len -= 64;
+ }
+ br_range_enc32le(iv, ivw, 4);
+}
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable = {
+ sizeof(br_aes_ct64_cbcdec_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_aes_ct64_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_aes_ct64_cbcdec_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcenc.c (revision 346145)
@@ -0,0 +1,81 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct64_cbcenc_vtable;
+ ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf;
+ uint64_t sk_exp[120];
+ uint32_t ivw[4];
+
+ br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ br_range_dec32le(ivw, 4, iv);
+ buf = data;
+ while (len > 0) {
+ uint32_t w[4];
+ uint64_t q[8];
+
+ w[0] = ivw[0] ^ br_dec32le(buf);
+ w[1] = ivw[1] ^ br_dec32le(buf + 4);
+ w[2] = ivw[2] ^ br_dec32le(buf + 8);
+ w[3] = ivw[3] ^ br_dec32le(buf + 12);
+ br_aes_ct64_interleave_in(&q[0], &q[4], w);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_interleave_out(w, q[0], q[4]);
+ memcpy(ivw, w, sizeof w);
+ br_enc32le(buf, w[0]);
+ br_enc32le(buf + 4, w[1]);
+ br_enc32le(buf + 8, w[2]);
+ br_enc32le(buf + 12, w[3]);
+ buf += 16;
+ len -= 16;
+ }
+ br_range_enc32le(iv, ivw, 4);
+}
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable = {
+ sizeof(br_aes_ct64_cbcenc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_aes_ct64_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_aes_ct64_cbcenc_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct64_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctr.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctr.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctr.c (revision 346145)
@@ -0,0 +1,114 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct64_ctr_vtable;
+ ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+uint32_t
+br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+ uint32_t ivw[16];
+ uint64_t sk_exp[120];
+
+ br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ br_range_dec32le(ivw, 3, iv);
+ memcpy(ivw + 4, ivw, 3 * sizeof(uint32_t));
+ memcpy(ivw + 8, ivw, 3 * sizeof(uint32_t));
+ memcpy(ivw + 12, ivw, 3 * sizeof(uint32_t));
+ buf = data;
+ while (len > 0) {
+ uint64_t q[8];
+ uint32_t w[16];
+ unsigned char tmp[64];
+ int i;
+
+ /*
+ * TODO: see if we can save on the first br_aes_ct64_ortho()
+ * call, since iv0/iv1/iv2 are constant for the whole run.
+ */
+ memcpy(w, ivw, sizeof ivw);
+ w[3] = br_swap32(cc);
+ w[7] = br_swap32(cc + 1);
+ w[11] = br_swap32(cc + 2);
+ w[15] = br_swap32(cc + 3);
+ for (i = 0; i < 4; i ++) {
+ br_aes_ct64_interleave_in(
+ &q[i], &q[i + 4], w + (i << 2));
+ }
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ for (i = 0; i < 4; i ++) {
+ br_aes_ct64_interleave_out(
+ w + (i << 2), q[i], q[i + 4]);
+ }
+ br_range_enc32le(tmp, w, 16);
+ if (len <= 64) {
+ xorbuf(buf, tmp, len);
+ cc += (uint32_t)len >> 4;
+ break;
+ }
+ xorbuf(buf, tmp, 64);
+ buf += 64;
+ len -= 64;
+ cc += 4;
+ }
+ return cc;
+}
+
+/* see bearssl_block.h */
+const br_block_ctr_class br_aes_ct64_ctr_vtable = {
+ sizeof(br_aes_ct64_ctr_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctr_class **, const void *, size_t))
+ &br_aes_ct64_ctr_init,
+ (uint32_t (*)(const br_block_ctr_class *const *,
+ const void *, uint32_t, void *, size_t))
+ &br_aes_ct64_ctr_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctrcbc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctrcbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctrcbc.c (revision 346145)
@@ -0,0 +1,433 @@
+/*
+ * 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"
+
+/* see bearssl_block.h */
+void
+br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct64_ctrcbc_vtable;
+ ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned char *ivbuf;
+ uint32_t iv0, iv1, iv2, iv3;
+ uint64_t sk_exp[120];
+
+ br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ /*
+ * We keep the counter as four 32-bit values, with big-endian
+ * convention, because that's what is expected for purposes of
+ * incrementing the counter value.
+ */
+ ivbuf = ctr;
+ iv0 = br_dec32be(ivbuf + 0);
+ iv1 = br_dec32be(ivbuf + 4);
+ iv2 = br_dec32be(ivbuf + 8);
+ iv3 = br_dec32be(ivbuf + 12);
+
+ buf = data;
+ while (len > 0) {
+ uint64_t q[8];
+ uint32_t w[16];
+ unsigned char tmp[64];
+ int i, j;
+
+ /*
+ * The bitslice implementation expects values in
+ * little-endian convention, so we have to byteswap them.
+ */
+ j = (len >= 64) ? 16 : (int)(len >> 2);
+ for (i = 0; i < j; i += 4) {
+ uint32_t carry;
+
+ w[i + 0] = br_swap32(iv0);
+ w[i + 1] = br_swap32(iv1);
+ w[i + 2] = br_swap32(iv2);
+ w[i + 3] = br_swap32(iv3);
+ iv3 ++;
+ carry = ~(iv3 | -iv3) >> 31;
+ iv2 += carry;
+ carry &= -(~(iv2 | -iv2) >> 31);
+ iv1 += carry;
+ carry &= -(~(iv1 | -iv1) >> 31);
+ iv0 += carry;
+ }
+ memset(w + i, 0, (16 - i) * sizeof(uint32_t));
+
+ for (i = 0; i < 4; i ++) {
+ br_aes_ct64_interleave_in(
+ &q[i], &q[i + 4], w + (i << 2));
+ }
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ for (i = 0; i < 4; i ++) {
+ br_aes_ct64_interleave_out(
+ w + (i << 2), q[i], q[i + 4]);
+ }
+
+ br_range_enc32le(tmp, w, 16);
+ if (len <= 64) {
+ xorbuf(buf, tmp, len);
+ break;
+ }
+ xorbuf(buf, tmp, 64);
+ buf += 64;
+ len -= 64;
+ }
+ br_enc32be(ivbuf + 0, iv0);
+ br_enc32be(ivbuf + 4, iv1);
+ br_enc32be(ivbuf + 8, iv2);
+ br_enc32be(ivbuf + 12, iv3);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ uint32_t cm0, cm1, cm2, cm3;
+ uint64_t q[8];
+ uint64_t sk_exp[120];
+
+ br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ cm0 = br_dec32le((unsigned char *)cbcmac + 0);
+ cm1 = br_dec32le((unsigned char *)cbcmac + 4);
+ cm2 = br_dec32le((unsigned char *)cbcmac + 8);
+ cm3 = br_dec32le((unsigned char *)cbcmac + 12);
+
+ buf = data;
+ memset(q, 0, sizeof q);
+ while (len > 0) {
+ uint32_t w[4];
+
+ w[0] = cm0 ^ br_dec32le(buf + 0);
+ w[1] = cm1 ^ br_dec32le(buf + 4);
+ w[2] = cm2 ^ br_dec32le(buf + 8);
+ w[3] = cm3 ^ br_dec32le(buf + 12);
+
+ br_aes_ct64_interleave_in(&q[0], &q[4], w);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_interleave_out(w, q[0], q[4]);
+
+ cm0 = w[0];
+ cm1 = w[1];
+ cm2 = w[2];
+ cm3 = w[3];
+ buf += 16;
+ len -= 16;
+ }
+
+ br_enc32le((unsigned char *)cbcmac + 0, cm0);
+ br_enc32le((unsigned char *)cbcmac + 4, cm1);
+ br_enc32le((unsigned char *)cbcmac + 8, cm2);
+ br_enc32le((unsigned char *)cbcmac + 12, cm3);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ /*
+ * When encrypting, the CBC-MAC processing must be lagging by
+ * one block, since it operates on the encrypted values, so
+ * it must wait for that encryption to complete.
+ */
+
+ unsigned char *buf;
+ unsigned char *ivbuf;
+ uint32_t iv0, iv1, iv2, iv3;
+ uint32_t cm0, cm1, cm2, cm3;
+ uint64_t sk_exp[120];
+ uint64_t q[8];
+ int first_iter;
+
+ br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ /*
+ * We keep the counter as four 32-bit values, with big-endian
+ * convention, because that's what is expected for purposes of
+ * incrementing the counter value.
+ */
+ ivbuf = ctr;
+ iv0 = br_dec32be(ivbuf + 0);
+ iv1 = br_dec32be(ivbuf + 4);
+ iv2 = br_dec32be(ivbuf + 8);
+ iv3 = br_dec32be(ivbuf + 12);
+
+ /*
+ * The current CBC-MAC value is kept in little-endian convention.
+ */
+ cm0 = br_dec32le((unsigned char *)cbcmac + 0);
+ cm1 = br_dec32le((unsigned char *)cbcmac + 4);
+ cm2 = br_dec32le((unsigned char *)cbcmac + 8);
+ cm3 = br_dec32le((unsigned char *)cbcmac + 12);
+
+ buf = data;
+ first_iter = 1;
+ memset(q, 0, sizeof q);
+ while (len > 0) {
+ uint32_t w[8], carry;
+
+ /*
+ * The bitslice implementation expects values in
+ * little-endian convention, so we have to byteswap them.
+ */
+ w[0] = br_swap32(iv0);
+ w[1] = br_swap32(iv1);
+ w[2] = br_swap32(iv2);
+ w[3] = br_swap32(iv3);
+ iv3 ++;
+ carry = ~(iv3 | -iv3) >> 31;
+ iv2 += carry;
+ carry &= -(~(iv2 | -iv2) >> 31);
+ iv1 += carry;
+ carry &= -(~(iv1 | -iv1) >> 31);
+ iv0 += carry;
+
+ /*
+ * The block for CBC-MAC.
+ */
+ w[4] = cm0;
+ w[5] = cm1;
+ w[6] = cm2;
+ w[7] = cm3;
+
+ br_aes_ct64_interleave_in(&q[0], &q[4], w);
+ br_aes_ct64_interleave_in(&q[1], &q[5], w + 4);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_interleave_out(w, q[0], q[4]);
+ br_aes_ct64_interleave_out(w + 4, q[1], q[5]);
+
+ /*
+ * We do the XOR with the plaintext in 32-bit registers,
+ * so that the value are available for CBC-MAC processing
+ * as well.
+ */
+ w[0] ^= br_dec32le(buf + 0);
+ w[1] ^= br_dec32le(buf + 4);
+ w[2] ^= br_dec32le(buf + 8);
+ w[3] ^= br_dec32le(buf + 12);
+ br_enc32le(buf + 0, w[0]);
+ br_enc32le(buf + 4, w[1]);
+ br_enc32le(buf + 8, w[2]);
+ br_enc32le(buf + 12, w[3]);
+
+ buf += 16;
+ len -= 16;
+
+ /*
+ * We set the cm* values to the block to encrypt in the
+ * next iteration.
+ */
+ if (first_iter) {
+ first_iter = 0;
+ cm0 ^= w[0];
+ cm1 ^= w[1];
+ cm2 ^= w[2];
+ cm3 ^= w[3];
+ } else {
+ cm0 = w[0] ^ w[4];
+ cm1 = w[1] ^ w[5];
+ cm2 = w[2] ^ w[6];
+ cm3 = w[3] ^ w[7];
+ }
+
+ /*
+ * If this was the last iteration, then compute the
+ * extra block encryption to complete CBC-MAC.
+ */
+ if (len == 0) {
+ w[0] = cm0;
+ w[1] = cm1;
+ w[2] = cm2;
+ w[3] = cm3;
+ br_aes_ct64_interleave_in(&q[0], &q[4], w);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_encrypt(
+ ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_interleave_out(w, q[0], q[4]);
+ cm0 = w[0];
+ cm1 = w[1];
+ cm2 = w[2];
+ cm3 = w[3];
+ break;
+ }
+ }
+
+ br_enc32be(ivbuf + 0, iv0);
+ br_enc32be(ivbuf + 4, iv1);
+ br_enc32be(ivbuf + 8, iv2);
+ br_enc32be(ivbuf + 12, iv3);
+ br_enc32le((unsigned char *)cbcmac + 0, cm0);
+ br_enc32le((unsigned char *)cbcmac + 4, cm1);
+ br_enc32le((unsigned char *)cbcmac + 8, cm2);
+ br_enc32le((unsigned char *)cbcmac + 12, cm3);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned char *ivbuf;
+ uint32_t iv0, iv1, iv2, iv3;
+ uint32_t cm0, cm1, cm2, cm3;
+ uint64_t sk_exp[120];
+ uint64_t q[8];
+
+ br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ /*
+ * We keep the counter as four 32-bit values, with big-endian
+ * convention, because that's what is expected for purposes of
+ * incrementing the counter value.
+ */
+ ivbuf = ctr;
+ iv0 = br_dec32be(ivbuf + 0);
+ iv1 = br_dec32be(ivbuf + 4);
+ iv2 = br_dec32be(ivbuf + 8);
+ iv3 = br_dec32be(ivbuf + 12);
+
+ /*
+ * The current CBC-MAC value is kept in little-endian convention.
+ */
+ cm0 = br_dec32le((unsigned char *)cbcmac + 0);
+ cm1 = br_dec32le((unsigned char *)cbcmac + 4);
+ cm2 = br_dec32le((unsigned char *)cbcmac + 8);
+ cm3 = br_dec32le((unsigned char *)cbcmac + 12);
+
+ buf = data;
+ memset(q, 0, sizeof q);
+ while (len > 0) {
+ uint32_t w[8], carry;
+ unsigned char tmp[16];
+
+ /*
+ * The bitslice implementation expects values in
+ * little-endian convention, so we have to byteswap them.
+ */
+ w[0] = br_swap32(iv0);
+ w[1] = br_swap32(iv1);
+ w[2] = br_swap32(iv2);
+ w[3] = br_swap32(iv3);
+ iv3 ++;
+ carry = ~(iv3 | -iv3) >> 31;
+ iv2 += carry;
+ carry &= -(~(iv2 | -iv2) >> 31);
+ iv1 += carry;
+ carry &= -(~(iv1 | -iv1) >> 31);
+ iv0 += carry;
+
+ /*
+ * The block for CBC-MAC.
+ */
+ w[4] = cm0 ^ br_dec32le(buf + 0);
+ w[5] = cm1 ^ br_dec32le(buf + 4);
+ w[6] = cm2 ^ br_dec32le(buf + 8);
+ w[7] = cm3 ^ br_dec32le(buf + 12);
+
+ br_aes_ct64_interleave_in(&q[0], &q[4], w);
+ br_aes_ct64_interleave_in(&q[1], &q[5], w + 4);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct64_ortho(q);
+ br_aes_ct64_interleave_out(w, q[0], q[4]);
+ br_aes_ct64_interleave_out(w + 4, q[1], q[5]);
+
+ br_enc32le(tmp + 0, w[0]);
+ br_enc32le(tmp + 4, w[1]);
+ br_enc32le(tmp + 8, w[2]);
+ br_enc32le(tmp + 12, w[3]);
+ xorbuf(buf, tmp, 16);
+ cm0 = w[4];
+ cm1 = w[5];
+ cm2 = w[6];
+ cm3 = w[7];
+ buf += 16;
+ len -= 16;
+ }
+
+ br_enc32be(ivbuf + 0, iv0);
+ br_enc32be(ivbuf + 4, iv1);
+ br_enc32be(ivbuf + 8, iv2);
+ br_enc32be(ivbuf + 12, iv3);
+ br_enc32le((unsigned char *)cbcmac + 0, cm0);
+ br_enc32le((unsigned char *)cbcmac + 4, cm1);
+ br_enc32le((unsigned char *)cbcmac + 8, cm2);
+ br_enc32le((unsigned char *)cbcmac + 12, cm3);
+}
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable = {
+ sizeof(br_aes_ct64_ctrcbc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
+ &br_aes_ct64_ctrcbc_init,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_ct64_ctrcbc_encrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_ct64_ctrcbc_decrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, size_t))
+ &br_aes_ct64_ctrcbc_ctr,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, const void *, size_t))
+ &br_aes_ct64_ctrcbc_mac
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct64_ctrcbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct64_dec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct64_dec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct64_dec.c (revision 346145)
@@ -0,0 +1,159 @@
+/*
+ * 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_aes_ct64_bitslice_invSbox(uint64_t *q)
+{
+ /*
+ * See br_aes_ct_bitslice_invSbox(). This is the natural extension
+ * to 64-bit registers.
+ */
+ uint64_t q0, q1, q2, q3, q4, q5, q6, q7;
+
+ q0 = ~q[0];
+ q1 = ~q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = ~q[5];
+ q6 = ~q[6];
+ q7 = q[7];
+ q[7] = q1 ^ q4 ^ q6;
+ q[6] = q0 ^ q3 ^ q5;
+ q[5] = q7 ^ q2 ^ q4;
+ q[4] = q6 ^ q1 ^ q3;
+ q[3] = q5 ^ q0 ^ q2;
+ q[2] = q4 ^ q7 ^ q1;
+ q[1] = q3 ^ q6 ^ q0;
+ q[0] = q2 ^ q5 ^ q7;
+
+ br_aes_ct64_bitslice_Sbox(q);
+
+ q0 = ~q[0];
+ q1 = ~q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = ~q[5];
+ q6 = ~q[6];
+ q7 = q[7];
+ q[7] = q1 ^ q4 ^ q6;
+ q[6] = q0 ^ q3 ^ q5;
+ q[5] = q7 ^ q2 ^ q4;
+ q[4] = q6 ^ q1 ^ q3;
+ q[3] = q5 ^ q0 ^ q2;
+ q[2] = q4 ^ q7 ^ q1;
+ q[1] = q3 ^ q6 ^ q0;
+ q[0] = q2 ^ q5 ^ q7;
+}
+
+static void
+add_round_key(uint64_t *q, const uint64_t *sk)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ q[i] ^= sk[i];
+ }
+}
+
+static void
+inv_shift_rows(uint64_t *q)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ uint64_t x;
+
+ x = q[i];
+ q[i] = (x & (uint64_t)0x000000000000FFFF)
+ | ((x & (uint64_t)0x000000000FFF0000) << 4)
+ | ((x & (uint64_t)0x00000000F0000000) >> 12)
+ | ((x & (uint64_t)0x000000FF00000000) << 8)
+ | ((x & (uint64_t)0x0000FF0000000000) >> 8)
+ | ((x & (uint64_t)0x000F000000000000) << 12)
+ | ((x & (uint64_t)0xFFF0000000000000) >> 4);
+ }
+}
+
+static inline uint64_t
+rotr32(uint64_t x)
+{
+ return (x << 32) | (x >> 32);
+}
+
+static void
+inv_mix_columns(uint64_t *q)
+{
+ uint64_t q0, q1, q2, q3, q4, q5, q6, q7;
+ uint64_t r0, r1, r2, r3, r4, r5, r6, r7;
+
+ q0 = q[0];
+ q1 = q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = q[5];
+ q6 = q[6];
+ q7 = q[7];
+ r0 = (q0 >> 16) | (q0 << 48);
+ r1 = (q1 >> 16) | (q1 << 48);
+ r2 = (q2 >> 16) | (q2 << 48);
+ r3 = (q3 >> 16) | (q3 << 48);
+ r4 = (q4 >> 16) | (q4 << 48);
+ r5 = (q5 >> 16) | (q5 << 48);
+ r6 = (q6 >> 16) | (q6 << 48);
+ r7 = (q7 >> 16) | (q7 << 48);
+
+ q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr32(q0 ^ q5 ^ q6 ^ r0 ^ r5);
+ q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6);
+ q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr32(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7);
+ q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr32(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7);
+ q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6);
+ q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7);
+ q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr32(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7);
+ q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr32(q4 ^ q5 ^ q7 ^ r4 ^ r7);
+}
+
+/* see inner.h */
+void
+br_aes_ct64_bitslice_decrypt(unsigned num_rounds,
+ const uint64_t *skey, uint64_t *q)
+{
+ unsigned u;
+
+ add_round_key(q, skey + (num_rounds << 3));
+ for (u = num_rounds - 1; u > 0; u --) {
+ inv_shift_rows(q);
+ br_aes_ct64_bitslice_invSbox(q);
+ add_round_key(q, skey + (u << 3));
+ inv_mix_columns(q);
+ }
+ inv_shift_rows(q);
+ br_aes_ct64_bitslice_invSbox(q);
+ add_round_key(q, skey);
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct64_dec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct64_enc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct64_enc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct64_enc.c (revision 346145)
@@ -0,0 +1,115 @@
+/*
+ * 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"
+
+static inline void
+add_round_key(uint64_t *q, const uint64_t *sk)
+{
+ q[0] ^= sk[0];
+ q[1] ^= sk[1];
+ q[2] ^= sk[2];
+ q[3] ^= sk[3];
+ q[4] ^= sk[4];
+ q[5] ^= sk[5];
+ q[6] ^= sk[6];
+ q[7] ^= sk[7];
+}
+
+static inline void
+shift_rows(uint64_t *q)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ uint64_t x;
+
+ x = q[i];
+ q[i] = (x & (uint64_t)0x000000000000FFFF)
+ | ((x & (uint64_t)0x00000000FFF00000) >> 4)
+ | ((x & (uint64_t)0x00000000000F0000) << 12)
+ | ((x & (uint64_t)0x0000FF0000000000) >> 8)
+ | ((x & (uint64_t)0x000000FF00000000) << 8)
+ | ((x & (uint64_t)0xF000000000000000) >> 12)
+ | ((x & (uint64_t)0x0FFF000000000000) << 4);
+ }
+}
+
+static inline uint64_t
+rotr32(uint64_t x)
+{
+ return (x << 32) | (x >> 32);
+}
+
+static inline void
+mix_columns(uint64_t *q)
+{
+ uint64_t q0, q1, q2, q3, q4, q5, q6, q7;
+ uint64_t r0, r1, r2, r3, r4, r5, r6, r7;
+
+ q0 = q[0];
+ q1 = q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = q[5];
+ q6 = q[6];
+ q7 = q[7];
+ r0 = (q0 >> 16) | (q0 << 48);
+ r1 = (q1 >> 16) | (q1 << 48);
+ r2 = (q2 >> 16) | (q2 << 48);
+ r3 = (q3 >> 16) | (q3 << 48);
+ r4 = (q4 >> 16) | (q4 << 48);
+ r5 = (q5 >> 16) | (q5 << 48);
+ r6 = (q6 >> 16) | (q6 << 48);
+ r7 = (q7 >> 16) | (q7 << 48);
+
+ q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0);
+ q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1);
+ q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2);
+ q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3);
+ q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4);
+ q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5);
+ q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6);
+ q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7);
+}
+
+/* see inner.h */
+void
+br_aes_ct64_bitslice_encrypt(unsigned num_rounds,
+ const uint64_t *skey, uint64_t *q)
+{
+ unsigned u;
+
+ add_round_key(q, skey);
+ for (u = 1; u < num_rounds; u ++) {
+ br_aes_ct64_bitslice_Sbox(q);
+ shift_rows(q);
+ mix_columns(q);
+ add_round_key(q, skey + (u << 3));
+ }
+ br_aes_ct64_bitslice_Sbox(q);
+ shift_rows(q);
+ add_round_key(q, skey + (num_rounds << 3));
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct64_enc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcdec.c (revision 346145)
@@ -0,0 +1,111 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct_cbcdec_vtable;
+ ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+ uint32_t iv0, iv1, iv2, iv3;
+ uint32_t sk_exp[120];
+
+ br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ ivbuf = iv;
+ iv0 = br_dec32le(ivbuf);
+ iv1 = br_dec32le(ivbuf + 4);
+ iv2 = br_dec32le(ivbuf + 8);
+ iv3 = br_dec32le(ivbuf + 12);
+ buf = data;
+ while (len > 0) {
+ uint32_t q[8], sq[8];
+
+ q[0] = br_dec32le(buf);
+ q[2] = br_dec32le(buf + 4);
+ q[4] = br_dec32le(buf + 8);
+ q[6] = br_dec32le(buf + 12);
+ if (len >= 32) {
+ q[1] = br_dec32le(buf + 16);
+ q[3] = br_dec32le(buf + 20);
+ q[5] = br_dec32le(buf + 24);
+ q[7] = br_dec32le(buf + 28);
+ } else {
+ q[1] = 0;
+ q[3] = 0;
+ q[5] = 0;
+ q[7] = 0;
+ }
+ memcpy(sq, q, sizeof q);
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_decrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+ br_enc32le(buf, q[0] ^ iv0);
+ br_enc32le(buf + 4, q[2] ^ iv1);
+ br_enc32le(buf + 8, q[4] ^ iv2);
+ br_enc32le(buf + 12, q[6] ^ iv3);
+ if (len < 32) {
+ iv0 = sq[0];
+ iv1 = sq[2];
+ iv2 = sq[4];
+ iv3 = sq[6];
+ break;
+ }
+ br_enc32le(buf + 16, q[1] ^ sq[0]);
+ br_enc32le(buf + 20, q[3] ^ sq[2]);
+ br_enc32le(buf + 24, q[5] ^ sq[4]);
+ br_enc32le(buf + 28, q[7] ^ sq[6]);
+ iv0 = sq[1];
+ iv1 = sq[3];
+ iv2 = sq[5];
+ iv3 = sq[7];
+ buf += 32;
+ len -= 32;
+ }
+ br_enc32le(ivbuf, iv0);
+ br_enc32le(ivbuf + 4, iv1);
+ br_enc32le(ivbuf + 8, iv2);
+ br_enc32le(ivbuf + 12, iv3);
+}
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_aes_ct_cbcdec_vtable = {
+ sizeof(br_aes_ct_cbcdec_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_aes_ct_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_aes_ct_cbcdec_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcenc.c (revision 346145)
@@ -0,0 +1,91 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct_cbcenc_vtable;
+ ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+ uint32_t q[8];
+ uint32_t iv0, iv1, iv2, iv3;
+ uint32_t sk_exp[120];
+
+ q[1] = 0;
+ q[3] = 0;
+ q[5] = 0;
+ q[7] = 0;
+ br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ ivbuf = iv;
+ iv0 = br_dec32le(ivbuf);
+ iv1 = br_dec32le(ivbuf + 4);
+ iv2 = br_dec32le(ivbuf + 8);
+ iv3 = br_dec32le(ivbuf + 12);
+ buf = data;
+ while (len > 0) {
+ q[0] = iv0 ^ br_dec32le(buf);
+ q[2] = iv1 ^ br_dec32le(buf + 4);
+ q[4] = iv2 ^ br_dec32le(buf + 8);
+ q[6] = iv3 ^ br_dec32le(buf + 12);
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+ iv0 = q[0];
+ iv1 = q[2];
+ iv2 = q[4];
+ iv3 = q[6];
+ br_enc32le(buf, iv0);
+ br_enc32le(buf + 4, iv1);
+ br_enc32le(buf + 8, iv2);
+ br_enc32le(buf + 12, iv3);
+ buf += 16;
+ len -= 16;
+ }
+ br_enc32le(ivbuf, iv0);
+ br_enc32le(ivbuf + 4, iv1);
+ br_enc32le(ivbuf + 8, iv2);
+ br_enc32le(ivbuf + 12, iv3);
+}
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_aes_ct_cbcenc_vtable = {
+ sizeof(br_aes_ct_cbcenc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_aes_ct_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_aes_ct_cbcenc_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct_ctr.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct_ctr.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct_ctr.c (revision 346145)
@@ -0,0 +1,116 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct_ctr_vtable;
+ ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+uint32_t
+br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+ const unsigned char *ivbuf;
+ uint32_t iv0, iv1, iv2;
+ uint32_t sk_exp[120];
+
+ br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ ivbuf = iv;
+ iv0 = br_dec32le(ivbuf);
+ iv1 = br_dec32le(ivbuf + 4);
+ iv2 = br_dec32le(ivbuf + 8);
+ buf = data;
+ while (len > 0) {
+ uint32_t q[8];
+ unsigned char tmp[32];
+
+ /*
+ * TODO: see if we can save on the first br_aes_ct_ortho()
+ * call, since iv0/iv1/iv2 are constant for the whole run.
+ */
+ q[0] = q[1] = iv0;
+ q[2] = q[3] = iv1;
+ q[4] = q[5] = iv2;
+ q[6] = br_swap32(cc);
+ q[7] = br_swap32(cc + 1);
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+ br_enc32le(tmp, q[0]);
+ br_enc32le(tmp + 4, q[2]);
+ br_enc32le(tmp + 8, q[4]);
+ br_enc32le(tmp + 12, q[6]);
+ br_enc32le(tmp + 16, q[1]);
+ br_enc32le(tmp + 20, q[3]);
+ br_enc32le(tmp + 24, q[5]);
+ br_enc32le(tmp + 28, q[7]);
+
+ if (len <= 32) {
+ xorbuf(buf, tmp, len);
+ cc ++;
+ if (len > 16) {
+ cc ++;
+ }
+ break;
+ }
+ xorbuf(buf, tmp, 32);
+ buf += 32;
+ len -= 32;
+ cc += 2;
+ }
+ return cc;
+}
+
+/* see bearssl_block.h */
+const br_block_ctr_class br_aes_ct_ctr_vtable = {
+ sizeof(br_aes_ct_ctr_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctr_class **, const void *, size_t))
+ &br_aes_ct_ctr_init,
+ (uint32_t (*)(const br_block_ctr_class *const *,
+ const void *, uint32_t, void *, size_t))
+ &br_aes_ct_ctr_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct_ctr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct_ctrcbc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct_ctrcbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct_ctrcbc.c (revision 346145)
@@ -0,0 +1,422 @@
+/*
+ * 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"
+
+/* see bearssl_block.h */
+void
+br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_ct_ctrcbc_vtable;
+ ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned char *ivbuf;
+ uint32_t iv0, iv1, iv2, iv3;
+ uint32_t sk_exp[120];
+
+ br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ /*
+ * We keep the counter as four 32-bit values, with big-endian
+ * convention, because that's what is expected for purposes of
+ * incrementing the counter value.
+ */
+ ivbuf = ctr;
+ iv0 = br_dec32be(ivbuf + 0);
+ iv1 = br_dec32be(ivbuf + 4);
+ iv2 = br_dec32be(ivbuf + 8);
+ iv3 = br_dec32be(ivbuf + 12);
+
+ buf = data;
+ while (len > 0) {
+ uint32_t q[8], carry;
+ unsigned char tmp[32];
+
+ /*
+ * The bitslice implementation expects values in
+ * little-endian convention, so we have to byteswap them.
+ */
+ q[0] = br_swap32(iv0);
+ q[2] = br_swap32(iv1);
+ q[4] = br_swap32(iv2);
+ q[6] = br_swap32(iv3);
+ iv3 ++;
+ carry = ~(iv3 | -iv3) >> 31;
+ iv2 += carry;
+ carry &= -(~(iv2 | -iv2) >> 31);
+ iv1 += carry;
+ carry &= -(~(iv1 | -iv1) >> 31);
+ iv0 += carry;
+ q[1] = br_swap32(iv0);
+ q[3] = br_swap32(iv1);
+ q[5] = br_swap32(iv2);
+ q[7] = br_swap32(iv3);
+ if (len > 16) {
+ iv3 ++;
+ carry = ~(iv3 | -iv3) >> 31;
+ iv2 += carry;
+ carry &= -(~(iv2 | -iv2) >> 31);
+ iv1 += carry;
+ carry &= -(~(iv1 | -iv1) >> 31);
+ iv0 += carry;
+ }
+
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+
+ br_enc32le(tmp, q[0]);
+ br_enc32le(tmp + 4, q[2]);
+ br_enc32le(tmp + 8, q[4]);
+ br_enc32le(tmp + 12, q[6]);
+ br_enc32le(tmp + 16, q[1]);
+ br_enc32le(tmp + 20, q[3]);
+ br_enc32le(tmp + 24, q[5]);
+ br_enc32le(tmp + 28, q[7]);
+
+ if (len <= 32) {
+ xorbuf(buf, tmp, len);
+ break;
+ }
+ xorbuf(buf, tmp, 32);
+ buf += 32;
+ len -= 32;
+ }
+ br_enc32be(ivbuf + 0, iv0);
+ br_enc32be(ivbuf + 4, iv1);
+ br_enc32be(ivbuf + 8, iv2);
+ br_enc32be(ivbuf + 12, iv3);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ uint32_t cm0, cm1, cm2, cm3;
+ uint32_t q[8];
+ uint32_t sk_exp[120];
+
+ br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ buf = data;
+ cm0 = br_dec32le((unsigned char *)cbcmac + 0);
+ cm1 = br_dec32le((unsigned char *)cbcmac + 4);
+ cm2 = br_dec32le((unsigned char *)cbcmac + 8);
+ cm3 = br_dec32le((unsigned char *)cbcmac + 12);
+ q[1] = 0;
+ q[3] = 0;
+ q[5] = 0;
+ q[7] = 0;
+
+ while (len > 0) {
+ q[0] = cm0 ^ br_dec32le(buf + 0);
+ q[2] = cm1 ^ br_dec32le(buf + 4);
+ q[4] = cm2 ^ br_dec32le(buf + 8);
+ q[6] = cm3 ^ br_dec32le(buf + 12);
+
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+
+ cm0 = q[0];
+ cm1 = q[2];
+ cm2 = q[4];
+ cm3 = q[6];
+ buf += 16;
+ len -= 16;
+ }
+
+ br_enc32le((unsigned char *)cbcmac + 0, cm0);
+ br_enc32le((unsigned char *)cbcmac + 4, cm1);
+ br_enc32le((unsigned char *)cbcmac + 8, cm2);
+ br_enc32le((unsigned char *)cbcmac + 12, cm3);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ /*
+ * When encrypting, the CBC-MAC processing must be lagging by
+ * one block, since it operates on the encrypted values, so
+ * it must wait for that encryption to complete.
+ */
+
+ unsigned char *buf;
+ unsigned char *ivbuf;
+ uint32_t iv0, iv1, iv2, iv3;
+ uint32_t cm0, cm1, cm2, cm3;
+ uint32_t sk_exp[120];
+ int first_iter;
+
+ br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ /*
+ * We keep the counter as four 32-bit values, with big-endian
+ * convention, because that's what is expected for purposes of
+ * incrementing the counter value.
+ */
+ ivbuf = ctr;
+ iv0 = br_dec32be(ivbuf + 0);
+ iv1 = br_dec32be(ivbuf + 4);
+ iv2 = br_dec32be(ivbuf + 8);
+ iv3 = br_dec32be(ivbuf + 12);
+
+ /*
+ * The current CBC-MAC value is kept in little-endian convention.
+ */
+ cm0 = br_dec32le((unsigned char *)cbcmac + 0);
+ cm1 = br_dec32le((unsigned char *)cbcmac + 4);
+ cm2 = br_dec32le((unsigned char *)cbcmac + 8);
+ cm3 = br_dec32le((unsigned char *)cbcmac + 12);
+
+ buf = data;
+ first_iter = 1;
+ while (len > 0) {
+ uint32_t q[8], carry;
+
+ /*
+ * The bitslice implementation expects values in
+ * little-endian convention, so we have to byteswap them.
+ */
+ q[0] = br_swap32(iv0);
+ q[2] = br_swap32(iv1);
+ q[4] = br_swap32(iv2);
+ q[6] = br_swap32(iv3);
+ iv3 ++;
+ carry = ~(iv3 | -iv3) >> 31;
+ iv2 += carry;
+ carry &= -(~(iv2 | -iv2) >> 31);
+ iv1 += carry;
+ carry &= -(~(iv1 | -iv1) >> 31);
+ iv0 += carry;
+
+ /*
+ * The odd values are used for CBC-MAC.
+ */
+ q[1] = cm0;
+ q[3] = cm1;
+ q[5] = cm2;
+ q[7] = cm3;
+
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+
+ /*
+ * We do the XOR with the plaintext in 32-bit registers,
+ * so that the value are available for CBC-MAC processing
+ * as well.
+ */
+ q[0] ^= br_dec32le(buf + 0);
+ q[2] ^= br_dec32le(buf + 4);
+ q[4] ^= br_dec32le(buf + 8);
+ q[6] ^= br_dec32le(buf + 12);
+ br_enc32le(buf + 0, q[0]);
+ br_enc32le(buf + 4, q[2]);
+ br_enc32le(buf + 8, q[4]);
+ br_enc32le(buf + 12, q[6]);
+
+ buf += 16;
+ len -= 16;
+
+ /*
+ * We set the cm* values to the block to encrypt in the
+ * next iteration.
+ */
+ if (first_iter) {
+ first_iter = 0;
+ cm0 ^= q[0];
+ cm1 ^= q[2];
+ cm2 ^= q[4];
+ cm3 ^= q[6];
+ } else {
+ cm0 = q[0] ^ q[1];
+ cm1 = q[2] ^ q[3];
+ cm2 = q[4] ^ q[5];
+ cm3 = q[6] ^ q[7];
+ }
+
+ /*
+ * If this was the last iteration, then compute the
+ * extra block encryption to complete CBC-MAC.
+ */
+ if (len == 0) {
+ q[0] = cm0;
+ q[2] = cm1;
+ q[4] = cm2;
+ q[6] = cm3;
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+ cm0 = q[0];
+ cm1 = q[2];
+ cm2 = q[4];
+ cm3 = q[6];
+ break;
+ }
+ }
+
+ br_enc32be(ivbuf + 0, iv0);
+ br_enc32be(ivbuf + 4, iv1);
+ br_enc32be(ivbuf + 8, iv2);
+ br_enc32be(ivbuf + 12, iv3);
+ br_enc32le((unsigned char *)cbcmac + 0, cm0);
+ br_enc32le((unsigned char *)cbcmac + 4, cm1);
+ br_enc32le((unsigned char *)cbcmac + 8, cm2);
+ br_enc32le((unsigned char *)cbcmac + 12, cm3);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned char *ivbuf;
+ uint32_t iv0, iv1, iv2, iv3;
+ uint32_t cm0, cm1, cm2, cm3;
+ uint32_t sk_exp[120];
+
+ br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+
+ /*
+ * We keep the counter as four 32-bit values, with big-endian
+ * convention, because that's what is expected for purposes of
+ * incrementing the counter value.
+ */
+ ivbuf = ctr;
+ iv0 = br_dec32be(ivbuf + 0);
+ iv1 = br_dec32be(ivbuf + 4);
+ iv2 = br_dec32be(ivbuf + 8);
+ iv3 = br_dec32be(ivbuf + 12);
+
+ /*
+ * The current CBC-MAC value is kept in little-endian convention.
+ */
+ cm0 = br_dec32le((unsigned char *)cbcmac + 0);
+ cm1 = br_dec32le((unsigned char *)cbcmac + 4);
+ cm2 = br_dec32le((unsigned char *)cbcmac + 8);
+ cm3 = br_dec32le((unsigned char *)cbcmac + 12);
+
+ buf = data;
+ while (len > 0) {
+ uint32_t q[8], carry;
+ unsigned char tmp[16];
+
+ /*
+ * The bitslice implementation expects values in
+ * little-endian convention, so we have to byteswap them.
+ */
+ q[0] = br_swap32(iv0);
+ q[2] = br_swap32(iv1);
+ q[4] = br_swap32(iv2);
+ q[6] = br_swap32(iv3);
+ iv3 ++;
+ carry = ~(iv3 | -iv3) >> 31;
+ iv2 += carry;
+ carry &= -(~(iv2 | -iv2) >> 31);
+ iv1 += carry;
+ carry &= -(~(iv1 | -iv1) >> 31);
+ iv0 += carry;
+
+ /*
+ * The odd values are used for CBC-MAC.
+ */
+ q[1] = cm0 ^ br_dec32le(buf + 0);
+ q[3] = cm1 ^ br_dec32le(buf + 4);
+ q[5] = cm2 ^ br_dec32le(buf + 8);
+ q[7] = cm3 ^ br_dec32le(buf + 12);
+
+ br_aes_ct_ortho(q);
+ br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q);
+ br_aes_ct_ortho(q);
+
+ br_enc32le(tmp + 0, q[0]);
+ br_enc32le(tmp + 4, q[2]);
+ br_enc32le(tmp + 8, q[4]);
+ br_enc32le(tmp + 12, q[6]);
+ xorbuf(buf, tmp, 16);
+ cm0 = q[1];
+ cm1 = q[3];
+ cm2 = q[5];
+ cm3 = q[7];
+ buf += 16;
+ len -= 16;
+ }
+
+ br_enc32be(ivbuf + 0, iv0);
+ br_enc32be(ivbuf + 4, iv1);
+ br_enc32be(ivbuf + 8, iv2);
+ br_enc32be(ivbuf + 12, iv3);
+ br_enc32le((unsigned char *)cbcmac + 0, cm0);
+ br_enc32le((unsigned char *)cbcmac + 4, cm1);
+ br_enc32le((unsigned char *)cbcmac + 8, cm2);
+ br_enc32le((unsigned char *)cbcmac + 12, cm3);
+}
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable = {
+ sizeof(br_aes_ct_ctrcbc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
+ &br_aes_ct_ctrcbc_init,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_ct_ctrcbc_encrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_ct_ctrcbc_decrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, size_t))
+ &br_aes_ct_ctrcbc_ctr,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, const void *, size_t))
+ &br_aes_ct_ctrcbc_mac
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct_ctrcbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct_dec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct_dec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct_dec.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+void
+br_aes_ct_bitslice_invSbox(uint32_t *q)
+{
+ /*
+ * AES S-box is:
+ * S(x) = A(I(x)) ^ 0x63
+ * where I() is inversion in GF(256), and A() is a linear
+ * transform (0 is formally defined to be its own inverse).
+ * Since inversion is an involution, the inverse S-box can be
+ * computed from the S-box as:
+ * iS(x) = B(S(B(x ^ 0x63)) ^ 0x63)
+ * where B() is the inverse of A(). Indeed, for any y in GF(256):
+ * iS(S(y)) = B(A(I(B(A(I(y)) ^ 0x63 ^ 0x63))) ^ 0x63 ^ 0x63) = y
+ *
+ * Note: we reuse the implementation of the forward S-box,
+ * instead of duplicating it here, so that total code size is
+ * lower. By merging the B() transforms into the S-box circuit
+ * we could make faster CBC decryption, but CBC decryption is
+ * already quite faster than CBC encryption because we can
+ * process two blocks in parallel.
+ */
+ uint32_t q0, q1, q2, q3, q4, q5, q6, q7;
+
+ q0 = ~q[0];
+ q1 = ~q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = ~q[5];
+ q6 = ~q[6];
+ q7 = q[7];
+ q[7] = q1 ^ q4 ^ q6;
+ q[6] = q0 ^ q3 ^ q5;
+ q[5] = q7 ^ q2 ^ q4;
+ q[4] = q6 ^ q1 ^ q3;
+ q[3] = q5 ^ q0 ^ q2;
+ q[2] = q4 ^ q7 ^ q1;
+ q[1] = q3 ^ q6 ^ q0;
+ q[0] = q2 ^ q5 ^ q7;
+
+ br_aes_ct_bitslice_Sbox(q);
+
+ q0 = ~q[0];
+ q1 = ~q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = ~q[5];
+ q6 = ~q[6];
+ q7 = q[7];
+ q[7] = q1 ^ q4 ^ q6;
+ q[6] = q0 ^ q3 ^ q5;
+ q[5] = q7 ^ q2 ^ q4;
+ q[4] = q6 ^ q1 ^ q3;
+ q[3] = q5 ^ q0 ^ q2;
+ q[2] = q4 ^ q7 ^ q1;
+ q[1] = q3 ^ q6 ^ q0;
+ q[0] = q2 ^ q5 ^ q7;
+}
+
+static void
+add_round_key(uint32_t *q, const uint32_t *sk)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ q[i] ^= sk[i];
+ }
+}
+
+static void
+inv_shift_rows(uint32_t *q)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ uint32_t x;
+
+ x = q[i];
+ q[i] = (x & 0x000000FF)
+ | ((x & 0x00003F00) << 2) | ((x & 0x0000C000) >> 6)
+ | ((x & 0x000F0000) << 4) | ((x & 0x00F00000) >> 4)
+ | ((x & 0x03000000) << 6) | ((x & 0xFC000000) >> 2);
+ }
+}
+
+static inline uint32_t
+rotr16(uint32_t x)
+{
+ return (x << 16) | (x >> 16);
+}
+
+static void
+inv_mix_columns(uint32_t *q)
+{
+ uint32_t q0, q1, q2, q3, q4, q5, q6, q7;
+ uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
+
+ q0 = q[0];
+ q1 = q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = q[5];
+ q6 = q[6];
+ q7 = q[7];
+ r0 = (q0 >> 8) | (q0 << 24);
+ r1 = (q1 >> 8) | (q1 << 24);
+ r2 = (q2 >> 8) | (q2 << 24);
+ r3 = (q3 >> 8) | (q3 << 24);
+ r4 = (q4 >> 8) | (q4 << 24);
+ r5 = (q5 >> 8) | (q5 << 24);
+ r6 = (q6 >> 8) | (q6 << 24);
+ r7 = (q7 >> 8) | (q7 << 24);
+
+ q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr16(q0 ^ q5 ^ q6 ^ r0 ^ r5);
+ q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6);
+ q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr16(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7);
+ q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr16(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7);
+ q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6);
+ q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7);
+ q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr16(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7);
+ q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr16(q4 ^ q5 ^ q7 ^ r4 ^ r7);
+}
+
+/* see inner.h */
+void
+br_aes_ct_bitslice_decrypt(unsigned num_rounds,
+ const uint32_t *skey, uint32_t *q)
+{
+ unsigned u;
+
+ add_round_key(q, skey + (num_rounds << 3));
+ for (u = num_rounds - 1; u > 0; u --) {
+ inv_shift_rows(q);
+ br_aes_ct_bitslice_invSbox(q);
+ add_round_key(q, skey + (u << 3));
+ inv_mix_columns(q);
+ }
+ inv_shift_rows(q);
+ br_aes_ct_bitslice_invSbox(q);
+ add_round_key(q, skey);
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct_dec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_ct_enc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_ct_enc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_ct_enc.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+static inline void
+add_round_key(uint32_t *q, const uint32_t *sk)
+{
+ q[0] ^= sk[0];
+ q[1] ^= sk[1];
+ q[2] ^= sk[2];
+ q[3] ^= sk[3];
+ q[4] ^= sk[4];
+ q[5] ^= sk[5];
+ q[6] ^= sk[6];
+ q[7] ^= sk[7];
+}
+
+static inline void
+shift_rows(uint32_t *q)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ uint32_t x;
+
+ x = q[i];
+ q[i] = (x & 0x000000FF)
+ | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6)
+ | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4)
+ | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2);
+ }
+}
+
+static inline uint32_t
+rotr16(uint32_t x)
+{
+ return (x << 16) | (x >> 16);
+}
+
+static inline void
+mix_columns(uint32_t *q)
+{
+ uint32_t q0, q1, q2, q3, q4, q5, q6, q7;
+ uint32_t r0, r1, r2, r3, r4, r5, r6, r7;
+
+ q0 = q[0];
+ q1 = q[1];
+ q2 = q[2];
+ q3 = q[3];
+ q4 = q[4];
+ q5 = q[5];
+ q6 = q[6];
+ q7 = q[7];
+ r0 = (q0 >> 8) | (q0 << 24);
+ r1 = (q1 >> 8) | (q1 << 24);
+ r2 = (q2 >> 8) | (q2 << 24);
+ r3 = (q3 >> 8) | (q3 << 24);
+ r4 = (q4 >> 8) | (q4 << 24);
+ r5 = (q5 >> 8) | (q5 << 24);
+ r6 = (q6 >> 8) | (q6 << 24);
+ r7 = (q7 >> 8) | (q7 << 24);
+
+ q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0);
+ q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1);
+ q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2);
+ q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3);
+ q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4);
+ q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5);
+ q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6);
+ q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7);
+}
+
+/* see inner.h */
+void
+br_aes_ct_bitslice_encrypt(unsigned num_rounds,
+ const uint32_t *skey, uint32_t *q)
+{
+ unsigned u;
+
+ add_round_key(q, skey);
+ for (u = 1; u < num_rounds; u ++) {
+ br_aes_ct_bitslice_Sbox(q);
+ shift_rows(q);
+ mix_columns(q);
+ add_round_key(q, skey + (u << 3));
+ }
+ br_aes_ct_bitslice_Sbox(q);
+ shift_rows(q);
+ add_round_key(q, skey + (num_rounds << 3));
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_ct_enc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_pwr8.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_pwr8.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_pwr8.c (revision 346145)
@@ -0,0 +1,445 @@
+/*
+ * 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.
+ */
+
+#define BR_POWER_ASM_MACROS 1
+#include "inner.h"
+
+/*
+ * This code contains the AES key schedule implementation using the
+ * POWER8 opcodes.
+ */
+
+#if BR_POWER8
+
+static void
+key_schedule_128(unsigned char *sk, const unsigned char *key)
+{
+ long cc;
+
+ static const uint32_t fmod[] = { 0x11B, 0x11B, 0x11B, 0x11B };
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc = 0;
+
+ /*
+ * We use the VSX instructions for loading and storing the
+ * key/subkeys, since they support unaligned accesses. The rest
+ * of the computation is VMX only. VMX register 0 is VSX
+ * register 32.
+ */
+ asm volatile (
+
+ /*
+ * v0 = all-zero word
+ * v1 = constant -8 / +8, copied into four words
+ * v2 = current subkey
+ * v3 = Rcon (x4 words)
+ * v6 = constant 8, copied into four words
+ * v7 = constant 0x11B, copied into four words
+ * v8 = constant for byteswapping words
+ */
+ vspltisw(0, 0)
+#if BR_POWER8_LE
+ vspltisw(1, -8)
+#else
+ vspltisw(1, 8)
+#endif
+ lxvw4x(34, 0, %[key])
+ vspltisw(3, 1)
+ vspltisw(6, 8)
+ lxvw4x(39, 0, %[fmod])
+#if BR_POWER8_LE
+ lxvw4x(40, 0, %[idx2be])
+#endif
+
+ /*
+ * First subkey is a copy of the key itself.
+ */
+#if BR_POWER8_LE
+ vperm(4, 2, 2, 8)
+ stxvw4x(36, 0, %[sk])
+#else
+ stxvw4x(34, 0, %[sk])
+#endif
+
+ /*
+ * Loop must run 10 times.
+ */
+ li(%[cc], 10)
+ mtctr(%[cc])
+ label(loop)
+ /* Increment subkey address */
+ addi(%[sk], %[sk], 16)
+
+ /* Compute SubWord(RotWord(temp)) xor Rcon (into v4, splat) */
+ vrlw(4, 2, 1)
+ vsbox(4, 4)
+#if BR_POWER8_LE
+ vxor(4, 4, 3)
+#else
+ vsldoi(5, 3, 0, 3)
+ vxor(4, 4, 5)
+#endif
+ vspltw(4, 4, 3)
+
+ /* XOR words for next subkey */
+ vsldoi(5, 0, 2, 12)
+ vxor(2, 2, 5)
+ vsldoi(5, 0, 2, 12)
+ vxor(2, 2, 5)
+ vsldoi(5, 0, 2, 12)
+ vxor(2, 2, 5)
+ vxor(2, 2, 4)
+
+ /* Store next subkey */
+#if BR_POWER8_LE
+ vperm(4, 2, 2, 8)
+ stxvw4x(36, 0, %[sk])
+#else
+ stxvw4x(34, 0, %[sk])
+#endif
+
+ /* Update Rcon */
+ vadduwm(3, 3, 3)
+ vsrw(4, 3, 6)
+ vsubuwm(4, 0, 4)
+ vand(4, 4, 7)
+ vxor(3, 3, 4)
+
+ bdnz(loop)
+
+: [sk] "+b" (sk), [cc] "+b" (cc)
+: [key] "b" (key), [fmod] "b" (fmod)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "ctr", "memory"
+ );
+}
+
+static void
+key_schedule_192(unsigned char *sk, const unsigned char *key)
+{
+ long cc;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc = 0;
+
+ /*
+ * We use the VSX instructions for loading and storing the
+ * key/subkeys, since they support unaligned accesses. The rest
+ * of the computation is VMX only. VMX register 0 is VSX
+ * register 32.
+ */
+ asm volatile (
+
+ /*
+ * v0 = all-zero word
+ * v1 = constant -8 / +8, copied into four words
+ * v2, v3 = current subkey
+ * v5 = Rcon (x4 words) (already shifted on big-endian)
+ * v6 = constant 8, copied into four words
+ * v8 = constant for byteswapping words
+ *
+ * The left two words of v3 are ignored.
+ */
+ vspltisw(0, 0)
+#if BR_POWER8_LE
+ vspltisw(1, -8)
+#else
+ vspltisw(1, 8)
+#endif
+ li(%[cc], 8)
+ lxvw4x(34, 0, %[key])
+ lxvw4x(35, %[cc], %[key])
+ vsldoi(3, 3, 0, 8)
+ vspltisw(5, 1)
+#if !BR_POWER8_LE
+ vsldoi(5, 5, 0, 3)
+#endif
+ vspltisw(6, 8)
+#if BR_POWER8_LE
+ lxvw4x(40, 0, %[idx2be])
+#endif
+
+ /*
+ * Loop must run 8 times. Each iteration produces 256
+ * bits of subkeys, with a 64-bit overlap.
+ */
+ li(%[cc], 8)
+ mtctr(%[cc])
+ li(%[cc], 16)
+ label(loop)
+
+ /*
+ * Last 6 words in v2:v3l. Compute next 6 words into
+ * v3r:v4.
+ */
+ vrlw(10, 3, 1)
+ vsbox(10, 10)
+ vxor(10, 10, 5)
+ vspltw(10, 10, 1)
+ vsldoi(11, 0, 10, 8)
+
+ vsldoi(12, 0, 2, 12)
+ vxor(12, 2, 12)
+ vsldoi(13, 0, 12, 12)
+ vxor(12, 12, 13)
+ vsldoi(13, 0, 12, 12)
+ vxor(12, 12, 13)
+
+ vspltw(13, 12, 3)
+ vxor(13, 13, 3)
+ vsldoi(14, 0, 3, 12)
+ vxor(13, 13, 14)
+
+ vsldoi(4, 12, 13, 8)
+ vsldoi(14, 0, 3, 8)
+ vsldoi(3, 14, 12, 8)
+
+ vxor(3, 3, 11)
+ vxor(4, 4, 10)
+
+ /*
+ * Update Rcon. Since for a 192-bit key, we use only 8
+ * such constants, we will not hit the field modulus,
+ * so a simple shift (addition) works well.
+ */
+ vadduwm(5, 5, 5)
+
+ /*
+ * Write out the two left 128-bit words
+ */
+#if BR_POWER8_LE
+ vperm(10, 2, 2, 8)
+ vperm(11, 3, 3, 8)
+ stxvw4x(42, 0, %[sk])
+ stxvw4x(43, %[cc], %[sk])
+#else
+ stxvw4x(34, 0, %[sk])
+ stxvw4x(35, %[cc], %[sk])
+#endif
+ addi(%[sk], %[sk], 24)
+
+ /*
+ * Shift words for next iteration.
+ */
+ vsldoi(2, 3, 4, 8)
+ vsldoi(3, 4, 0, 8)
+
+ bdnz(loop)
+
+ /*
+ * The loop wrote the first 50 subkey words, but we need
+ * to produce 52, so we must do one last write.
+ */
+#if BR_POWER8_LE
+ vperm(10, 2, 2, 8)
+ stxvw4x(42, 0, %[sk])
+#else
+ stxvw4x(34, 0, %[sk])
+#endif
+
+: [sk] "+b" (sk), [cc] "+b" (cc)
+: [key] "b" (key)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "ctr", "memory"
+ );
+}
+
+static void
+key_schedule_256(unsigned char *sk, const unsigned char *key)
+{
+ long cc;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc = 0;
+
+ /*
+ * We use the VSX instructions for loading and storing the
+ * key/subkeys, since they support unaligned accesses. The rest
+ * of the computation is VMX only. VMX register 0 is VSX
+ * register 32.
+ */
+ asm volatile (
+
+ /*
+ * v0 = all-zero word
+ * v1 = constant -8 / +8, copied into four words
+ * v2, v3 = current subkey
+ * v6 = Rcon (x4 words) (already shifted on big-endian)
+ * v7 = constant 8, copied into four words
+ * v8 = constant for byteswapping words
+ *
+ * The left two words of v3 are ignored.
+ */
+ vspltisw(0, 0)
+#if BR_POWER8_LE
+ vspltisw(1, -8)
+#else
+ vspltisw(1, 8)
+#endif
+ li(%[cc], 16)
+ lxvw4x(34, 0, %[key])
+ lxvw4x(35, %[cc], %[key])
+ vspltisw(6, 1)
+#if !BR_POWER8_LE
+ vsldoi(6, 6, 0, 3)
+#endif
+ vspltisw(7, 8)
+#if BR_POWER8_LE
+ lxvw4x(40, 0, %[idx2be])
+#endif
+
+ /*
+ * Loop must run 7 times. Each iteration produces two
+ * subkeys.
+ */
+ li(%[cc], 7)
+ mtctr(%[cc])
+ li(%[cc], 16)
+ label(loop)
+
+ /*
+ * Current words are in v2:v3. Compute next word in v4.
+ */
+ vrlw(10, 3, 1)
+ vsbox(10, 10)
+ vxor(10, 10, 6)
+ vspltw(10, 10, 3)
+
+ vsldoi(4, 0, 2, 12)
+ vxor(4, 2, 4)
+ vsldoi(5, 0, 4, 12)
+ vxor(4, 4, 5)
+ vsldoi(5, 0, 4, 12)
+ vxor(4, 4, 5)
+ vxor(4, 4, 10)
+
+ /*
+ * Then other word in v5.
+ */
+ vsbox(10, 4)
+ vspltw(10, 10, 3)
+
+ vsldoi(5, 0, 3, 12)
+ vxor(5, 3, 5)
+ vsldoi(11, 0, 5, 12)
+ vxor(5, 5, 11)
+ vsldoi(11, 0, 5, 12)
+ vxor(5, 5, 11)
+ vxor(5, 5, 10)
+
+ /*
+ * Update Rcon. Since for a 256-bit key, we use only 7
+ * such constants, we will not hit the field modulus,
+ * so a simple shift (addition) works well.
+ */
+ vadduwm(6, 6, 6)
+
+ /*
+ * Write out the two left 128-bit words
+ */
+#if BR_POWER8_LE
+ vperm(10, 2, 2, 8)
+ vperm(11, 3, 3, 8)
+ stxvw4x(42, 0, %[sk])
+ stxvw4x(43, %[cc], %[sk])
+#else
+ stxvw4x(34, 0, %[sk])
+ stxvw4x(35, %[cc], %[sk])
+#endif
+ addi(%[sk], %[sk], 32)
+
+ /*
+ * Replace v2:v3 with v4:v5.
+ */
+ vxor(2, 0, 4)
+ vxor(3, 0, 5)
+
+ bdnz(loop)
+
+ /*
+ * The loop wrote the first 14 subkeys, but we need 15,
+ * so we must do an extra write.
+ */
+#if BR_POWER8_LE
+ vperm(10, 2, 2, 8)
+ stxvw4x(42, 0, %[sk])
+#else
+ stxvw4x(34, 0, %[sk])
+#endif
+
+: [sk] "+b" (sk), [cc] "+b" (cc)
+: [key] "b" (key)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "ctr", "memory"
+ );
+}
+
+/* see inner.h */
+int
+br_aes_pwr8_supported(void)
+{
+ return 1;
+}
+
+/* see inner.h */
+unsigned
+br_aes_pwr8_keysched(unsigned char *sk, const void *key, size_t len)
+{
+ switch (len) {
+ case 16:
+ key_schedule_128(sk, key);
+ return 10;
+ case 24:
+ key_schedule_192(sk, key);
+ return 12;
+ default:
+ key_schedule_256(sk, key);
+ return 14;
+ }
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_pwr8.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcdec.c (revision 346145)
@@ -0,0 +1,670 @@
+/*
+ * 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.
+ */
+
+#define BR_POWER_ASM_MACROS 1
+#include "inner.h"
+
+#if BR_POWER8
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_pwr8_cbcdec_vtable;
+ ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);
+}
+
+static void
+cbcdec_128(const unsigned char *sk,
+ const unsigned char *iv, unsigned char *buf, size_t num_blocks)
+{
+ long cc0, cc1, cc2, cc3;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc0 = 0;
+ cc1 = 16;
+ cc2 = 32;
+ cc3 = 48;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v10
+ */
+ lxvw4x(32, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(33, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(34, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(35, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(36, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(37, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(38, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(39, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(40, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(41, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(42, %[cc0], %[sk])
+ li(%[cc0], 0)
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * Load IV into v24.
+ */
+ lxvw4x(56, 0, %[iv])
+#if BR_POWER8_LE
+ vperm(24, 24, 24, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Load next ciphertext words in v16..v19. Also save them
+ * in v20..v23.
+ */
+ lxvw4x(48, %[cc0], %[buf])
+ lxvw4x(49, %[cc1], %[buf])
+ lxvw4x(50, %[cc2], %[buf])
+ lxvw4x(51, %[cc3], %[buf])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+ vand(20, 16, 16)
+ vand(21, 17, 17)
+ vand(22, 18, 18)
+ vand(23, 19, 19)
+
+ /*
+ * Decrypt the blocks.
+ */
+ vxor(16, 16, 10)
+ vxor(17, 17, 10)
+ vxor(18, 18, 10)
+ vxor(19, 19, 10)
+ vncipher(16, 16, 9)
+ vncipher(17, 17, 9)
+ vncipher(18, 18, 9)
+ vncipher(19, 19, 9)
+ vncipher(16, 16, 8)
+ vncipher(17, 17, 8)
+ vncipher(18, 18, 8)
+ vncipher(19, 19, 8)
+ vncipher(16, 16, 7)
+ vncipher(17, 17, 7)
+ vncipher(18, 18, 7)
+ vncipher(19, 19, 7)
+ vncipher(16, 16, 6)
+ vncipher(17, 17, 6)
+ vncipher(18, 18, 6)
+ vncipher(19, 19, 6)
+ vncipher(16, 16, 5)
+ vncipher(17, 17, 5)
+ vncipher(18, 18, 5)
+ vncipher(19, 19, 5)
+ vncipher(16, 16, 4)
+ vncipher(17, 17, 4)
+ vncipher(18, 18, 4)
+ vncipher(19, 19, 4)
+ vncipher(16, 16, 3)
+ vncipher(17, 17, 3)
+ vncipher(18, 18, 3)
+ vncipher(19, 19, 3)
+ vncipher(16, 16, 2)
+ vncipher(17, 17, 2)
+ vncipher(18, 18, 2)
+ vncipher(19, 19, 2)
+ vncipher(16, 16, 1)
+ vncipher(17, 17, 1)
+ vncipher(18, 18, 1)
+ vncipher(19, 19, 1)
+ vncipherlast(16, 16, 0)
+ vncipherlast(17, 17, 0)
+ vncipherlast(18, 18, 0)
+ vncipherlast(19, 19, 0)
+
+ /*
+ * XOR decrypted blocks with IV / previous block.
+ */
+ vxor(16, 16, 24)
+ vxor(17, 17, 20)
+ vxor(18, 18, 21)
+ vxor(19, 19, 22)
+
+ /*
+ * Store back result (with byteswap)
+ */
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+ stxvw4x(48, %[cc0], %[buf])
+ stxvw4x(49, %[cc1], %[buf])
+ stxvw4x(50, %[cc2], %[buf])
+ stxvw4x(51, %[cc3], %[buf])
+
+ /*
+ * Fourth encrypted block is IV for next run.
+ */
+ vand(24, 23, 23)
+
+ addi(%[buf], %[buf], 64)
+
+ bdnz(loop)
+
+: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
+ [buf] "+b" (buf)
+: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+ "ctr", "memory"
+ );
+}
+
+static void
+cbcdec_192(const unsigned char *sk,
+ const unsigned char *iv, unsigned char *buf, size_t num_blocks)
+{
+ long cc0, cc1, cc2, cc3;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc0 = 0;
+ cc1 = 16;
+ cc2 = 32;
+ cc3 = 48;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v12
+ */
+ lxvw4x(32, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(33, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(34, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(35, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(36, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(37, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(38, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(39, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(40, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(41, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(42, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(43, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(44, %[cc0], %[sk])
+ li(%[cc0], 0)
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * Load IV into v24.
+ */
+ lxvw4x(56, 0, %[iv])
+#if BR_POWER8_LE
+ vperm(24, 24, 24, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Load next ciphertext words in v16..v19. Also save them
+ * in v20..v23.
+ */
+ lxvw4x(48, %[cc0], %[buf])
+ lxvw4x(49, %[cc1], %[buf])
+ lxvw4x(50, %[cc2], %[buf])
+ lxvw4x(51, %[cc3], %[buf])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+ vand(20, 16, 16)
+ vand(21, 17, 17)
+ vand(22, 18, 18)
+ vand(23, 19, 19)
+
+ /*
+ * Decrypt the blocks.
+ */
+ vxor(16, 16, 12)
+ vxor(17, 17, 12)
+ vxor(18, 18, 12)
+ vxor(19, 19, 12)
+ vncipher(16, 16, 11)
+ vncipher(17, 17, 11)
+ vncipher(18, 18, 11)
+ vncipher(19, 19, 11)
+ vncipher(16, 16, 10)
+ vncipher(17, 17, 10)
+ vncipher(18, 18, 10)
+ vncipher(19, 19, 10)
+ vncipher(16, 16, 9)
+ vncipher(17, 17, 9)
+ vncipher(18, 18, 9)
+ vncipher(19, 19, 9)
+ vncipher(16, 16, 8)
+ vncipher(17, 17, 8)
+ vncipher(18, 18, 8)
+ vncipher(19, 19, 8)
+ vncipher(16, 16, 7)
+ vncipher(17, 17, 7)
+ vncipher(18, 18, 7)
+ vncipher(19, 19, 7)
+ vncipher(16, 16, 6)
+ vncipher(17, 17, 6)
+ vncipher(18, 18, 6)
+ vncipher(19, 19, 6)
+ vncipher(16, 16, 5)
+ vncipher(17, 17, 5)
+ vncipher(18, 18, 5)
+ vncipher(19, 19, 5)
+ vncipher(16, 16, 4)
+ vncipher(17, 17, 4)
+ vncipher(18, 18, 4)
+ vncipher(19, 19, 4)
+ vncipher(16, 16, 3)
+ vncipher(17, 17, 3)
+ vncipher(18, 18, 3)
+ vncipher(19, 19, 3)
+ vncipher(16, 16, 2)
+ vncipher(17, 17, 2)
+ vncipher(18, 18, 2)
+ vncipher(19, 19, 2)
+ vncipher(16, 16, 1)
+ vncipher(17, 17, 1)
+ vncipher(18, 18, 1)
+ vncipher(19, 19, 1)
+ vncipherlast(16, 16, 0)
+ vncipherlast(17, 17, 0)
+ vncipherlast(18, 18, 0)
+ vncipherlast(19, 19, 0)
+
+ /*
+ * XOR decrypted blocks with IV / previous block.
+ */
+ vxor(16, 16, 24)
+ vxor(17, 17, 20)
+ vxor(18, 18, 21)
+ vxor(19, 19, 22)
+
+ /*
+ * Store back result (with byteswap)
+ */
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+ stxvw4x(48, %[cc0], %[buf])
+ stxvw4x(49, %[cc1], %[buf])
+ stxvw4x(50, %[cc2], %[buf])
+ stxvw4x(51, %[cc3], %[buf])
+
+ /*
+ * Fourth encrypted block is IV for next run.
+ */
+ vand(24, 23, 23)
+
+ addi(%[buf], %[buf], 64)
+
+ bdnz(loop)
+
+: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
+ [buf] "+b" (buf)
+: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+ "ctr", "memory"
+ );
+}
+
+static void
+cbcdec_256(const unsigned char *sk,
+ const unsigned char *iv, unsigned char *buf, size_t num_blocks)
+{
+ long cc0, cc1, cc2, cc3;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc0 = 0;
+ cc1 = 16;
+ cc2 = 32;
+ cc3 = 48;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v14
+ */
+ lxvw4x(32, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(33, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(34, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(35, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(36, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(37, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(38, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(39, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(40, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(41, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(42, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(43, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(44, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(45, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(46, %[cc0], %[sk])
+ li(%[cc0], 0)
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * Load IV into v24.
+ */
+ lxvw4x(56, 0, %[iv])
+#if BR_POWER8_LE
+ vperm(24, 24, 24, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Load next ciphertext words in v16..v19. Also save them
+ * in v20..v23.
+ */
+ lxvw4x(48, %[cc0], %[buf])
+ lxvw4x(49, %[cc1], %[buf])
+ lxvw4x(50, %[cc2], %[buf])
+ lxvw4x(51, %[cc3], %[buf])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+ vand(20, 16, 16)
+ vand(21, 17, 17)
+ vand(22, 18, 18)
+ vand(23, 19, 19)
+
+ /*
+ * Decrypt the blocks.
+ */
+ vxor(16, 16, 14)
+ vxor(17, 17, 14)
+ vxor(18, 18, 14)
+ vxor(19, 19, 14)
+ vncipher(16, 16, 13)
+ vncipher(17, 17, 13)
+ vncipher(18, 18, 13)
+ vncipher(19, 19, 13)
+ vncipher(16, 16, 12)
+ vncipher(17, 17, 12)
+ vncipher(18, 18, 12)
+ vncipher(19, 19, 12)
+ vncipher(16, 16, 11)
+ vncipher(17, 17, 11)
+ vncipher(18, 18, 11)
+ vncipher(19, 19, 11)
+ vncipher(16, 16, 10)
+ vncipher(17, 17, 10)
+ vncipher(18, 18, 10)
+ vncipher(19, 19, 10)
+ vncipher(16, 16, 9)
+ vncipher(17, 17, 9)
+ vncipher(18, 18, 9)
+ vncipher(19, 19, 9)
+ vncipher(16, 16, 8)
+ vncipher(17, 17, 8)
+ vncipher(18, 18, 8)
+ vncipher(19, 19, 8)
+ vncipher(16, 16, 7)
+ vncipher(17, 17, 7)
+ vncipher(18, 18, 7)
+ vncipher(19, 19, 7)
+ vncipher(16, 16, 6)
+ vncipher(17, 17, 6)
+ vncipher(18, 18, 6)
+ vncipher(19, 19, 6)
+ vncipher(16, 16, 5)
+ vncipher(17, 17, 5)
+ vncipher(18, 18, 5)
+ vncipher(19, 19, 5)
+ vncipher(16, 16, 4)
+ vncipher(17, 17, 4)
+ vncipher(18, 18, 4)
+ vncipher(19, 19, 4)
+ vncipher(16, 16, 3)
+ vncipher(17, 17, 3)
+ vncipher(18, 18, 3)
+ vncipher(19, 19, 3)
+ vncipher(16, 16, 2)
+ vncipher(17, 17, 2)
+ vncipher(18, 18, 2)
+ vncipher(19, 19, 2)
+ vncipher(16, 16, 1)
+ vncipher(17, 17, 1)
+ vncipher(18, 18, 1)
+ vncipher(19, 19, 1)
+ vncipherlast(16, 16, 0)
+ vncipherlast(17, 17, 0)
+ vncipherlast(18, 18, 0)
+ vncipherlast(19, 19, 0)
+
+ /*
+ * XOR decrypted blocks with IV / previous block.
+ */
+ vxor(16, 16, 24)
+ vxor(17, 17, 20)
+ vxor(18, 18, 21)
+ vxor(19, 19, 22)
+
+ /*
+ * Store back result (with byteswap)
+ */
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+ stxvw4x(48, %[cc0], %[buf])
+ stxvw4x(49, %[cc1], %[buf])
+ stxvw4x(50, %[cc2], %[buf])
+ stxvw4x(51, %[cc3], %[buf])
+
+ /*
+ * Fourth encrypted block is IV for next run.
+ */
+ vand(24, 23, 23)
+
+ addi(%[buf], %[buf], 64)
+
+ bdnz(loop)
+
+: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
+ [buf] "+b" (buf)
+: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+ "ctr", "memory"
+ );
+}
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char nextiv[16];
+ unsigned char *buf;
+
+ if (len == 0) {
+ return;
+ }
+ buf = data;
+ memcpy(nextiv, buf + len - 16, 16);
+ if (len >= 64) {
+ size_t num_blocks;
+ unsigned char tmp[16];
+
+ num_blocks = (len >> 4) & ~(size_t)3;
+ memcpy(tmp, buf + (num_blocks << 4) - 16, 16);
+ switch (ctx->num_rounds) {
+ case 10:
+ cbcdec_128(ctx->skey.skni, iv, buf, num_blocks);
+ break;
+ case 12:
+ cbcdec_192(ctx->skey.skni, iv, buf, num_blocks);
+ break;
+ default:
+ cbcdec_256(ctx->skey.skni, iv, buf, num_blocks);
+ break;
+ }
+ buf += num_blocks << 4;
+ len &= 63;
+ memcpy(iv, tmp, 16);
+ }
+ if (len > 0) {
+ unsigned char tmp[64];
+
+ memcpy(tmp, buf, len);
+ memset(tmp + len, 0, (sizeof tmp) - len);
+ switch (ctx->num_rounds) {
+ case 10:
+ cbcdec_128(ctx->skey.skni, iv, tmp, 4);
+ break;
+ case 12:
+ cbcdec_192(ctx->skey.skni, iv, tmp, 4);
+ break;
+ default:
+ cbcdec_256(ctx->skey.skni, iv, tmp, 4);
+ break;
+ }
+ memcpy(buf, tmp, len);
+ }
+ memcpy(iv, nextiv, 16);
+}
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable = {
+ sizeof(br_aes_pwr8_cbcdec_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_aes_pwr8_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_aes_pwr8_cbcdec_run
+};
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class *
+br_aes_pwr8_cbcdec_get_vtable(void)
+{
+ return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcdec_vtable : NULL;
+}
+
+#else
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class *
+br_aes_pwr8_cbcdec_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcenc.c (revision 346145)
@@ -0,0 +1,417 @@
+/*
+ * 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.
+ */
+
+#define BR_POWER_ASM_MACROS 1
+#include "inner.h"
+
+#if BR_POWER8
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_pwr8_cbcenc_vtable;
+ ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);
+}
+
+static void
+cbcenc_128(const unsigned char *sk,
+ const unsigned char *iv, unsigned char *buf, size_t len)
+{
+ long cc;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc = 0;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v10
+ */
+ lxvw4x(32, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(33, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(34, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(35, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(36, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(37, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(38, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(39, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(40, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(41, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(42, %[cc], %[sk])
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * Load IV into v16.
+ */
+ lxvw4x(48, 0, %[iv])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Load next plaintext word and XOR with current IV.
+ */
+ lxvw4x(49, 0, %[buf])
+#if BR_POWER8_LE
+ vperm(17, 17, 17, 15)
+#endif
+ vxor(16, 16, 17)
+
+ /*
+ * Encrypt the block.
+ */
+ vxor(16, 16, 0)
+ vcipher(16, 16, 1)
+ vcipher(16, 16, 2)
+ vcipher(16, 16, 3)
+ vcipher(16, 16, 4)
+ vcipher(16, 16, 5)
+ vcipher(16, 16, 6)
+ vcipher(16, 16, 7)
+ vcipher(16, 16, 8)
+ vcipher(16, 16, 9)
+ vcipherlast(16, 16, 10)
+
+ /*
+ * Store back result (with byteswap)
+ */
+#if BR_POWER8_LE
+ vperm(17, 16, 16, 15)
+ stxvw4x(49, 0, %[buf])
+#else
+ stxvw4x(48, 0, %[buf])
+#endif
+ addi(%[buf], %[buf], 16)
+
+ bdnz(loop)
+
+: [cc] "+b" (cc), [buf] "+b" (buf)
+: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "ctr", "memory"
+ );
+}
+
+static void
+cbcenc_192(const unsigned char *sk,
+ const unsigned char *iv, unsigned char *buf, size_t len)
+{
+ long cc;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc = 0;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v12
+ */
+ lxvw4x(32, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(33, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(34, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(35, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(36, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(37, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(38, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(39, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(40, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(41, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(42, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(43, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(44, %[cc], %[sk])
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * Load IV into v16.
+ */
+ lxvw4x(48, 0, %[iv])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Load next plaintext word and XOR with current IV.
+ */
+ lxvw4x(49, 0, %[buf])
+#if BR_POWER8_LE
+ vperm(17, 17, 17, 15)
+#endif
+ vxor(16, 16, 17)
+
+ /*
+ * Encrypt the block.
+ */
+ vxor(16, 16, 0)
+ vcipher(16, 16, 1)
+ vcipher(16, 16, 2)
+ vcipher(16, 16, 3)
+ vcipher(16, 16, 4)
+ vcipher(16, 16, 5)
+ vcipher(16, 16, 6)
+ vcipher(16, 16, 7)
+ vcipher(16, 16, 8)
+ vcipher(16, 16, 9)
+ vcipher(16, 16, 10)
+ vcipher(16, 16, 11)
+ vcipherlast(16, 16, 12)
+
+ /*
+ * Store back result (with byteswap)
+ */
+#if BR_POWER8_LE
+ vperm(17, 16, 16, 15)
+ stxvw4x(49, 0, %[buf])
+#else
+ stxvw4x(48, 0, %[buf])
+#endif
+ addi(%[buf], %[buf], 16)
+
+ bdnz(loop)
+
+: [cc] "+b" (cc), [buf] "+b" (buf)
+: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "ctr", "memory"
+ );
+}
+
+static void
+cbcenc_256(const unsigned char *sk,
+ const unsigned char *iv, unsigned char *buf, size_t len)
+{
+ long cc;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+
+ cc = 0;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v14
+ */
+ lxvw4x(32, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(33, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(34, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(35, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(36, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(37, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(38, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(39, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(40, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(41, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(42, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(43, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(44, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(45, %[cc], %[sk])
+ addi(%[cc], %[cc], 16)
+ lxvw4x(46, %[cc], %[sk])
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * Load IV into v16.
+ */
+ lxvw4x(48, 0, %[iv])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Load next plaintext word and XOR with current IV.
+ */
+ lxvw4x(49, 0, %[buf])
+#if BR_POWER8_LE
+ vperm(17, 17, 17, 15)
+#endif
+ vxor(16, 16, 17)
+
+ /*
+ * Encrypt the block.
+ */
+ vxor(16, 16, 0)
+ vcipher(16, 16, 1)
+ vcipher(16, 16, 2)
+ vcipher(16, 16, 3)
+ vcipher(16, 16, 4)
+ vcipher(16, 16, 5)
+ vcipher(16, 16, 6)
+ vcipher(16, 16, 7)
+ vcipher(16, 16, 8)
+ vcipher(16, 16, 9)
+ vcipher(16, 16, 10)
+ vcipher(16, 16, 11)
+ vcipher(16, 16, 12)
+ vcipher(16, 16, 13)
+ vcipherlast(16, 16, 14)
+
+ /*
+ * Store back result (with byteswap)
+ */
+#if BR_POWER8_LE
+ vperm(17, 16, 16, 15)
+ stxvw4x(49, 0, %[buf])
+#else
+ stxvw4x(48, 0, %[buf])
+#endif
+ addi(%[buf], %[buf], 16)
+
+ bdnz(loop)
+
+: [cc] "+b" (cc), [buf] "+b" (buf)
+: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "ctr", "memory"
+ );
+}
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ if (len > 0) {
+ switch (ctx->num_rounds) {
+ case 10:
+ cbcenc_128(ctx->skey.skni, iv, data, len);
+ break;
+ case 12:
+ cbcenc_192(ctx->skey.skni, iv, data, len);
+ break;
+ default:
+ cbcenc_256(ctx->skey.skni, iv, data, len);
+ break;
+ }
+ memcpy(iv, (unsigned char *)data + (len - 16), 16);
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable = {
+ sizeof(br_aes_pwr8_cbcenc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_aes_pwr8_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_aes_pwr8_cbcenc_run
+};
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class *
+br_aes_pwr8_cbcenc_get_vtable(void)
+{
+ return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcenc_vtable : NULL;
+}
+
+#else
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class *
+br_aes_pwr8_cbcenc_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctr.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctr.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctr.c (revision 346145)
@@ -0,0 +1,717 @@
+/*
+ * 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.
+ */
+
+#define BR_POWER_ASM_MACROS 1
+#include "inner.h"
+
+#if BR_POWER8
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_pwr8_ctr_vtable;
+ ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);
+}
+
+static void
+ctr_128(const unsigned char *sk, const unsigned char *ivbuf,
+ unsigned char *buf, size_t num_blocks)
+{
+ long cc0, cc1, cc2, cc3;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+ static const uint32_t ctrinc[] = {
+ 0, 0, 0, 4
+ };
+
+ cc0 = 0;
+ cc1 = 16;
+ cc2 = 32;
+ cc3 = 48;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v10
+ */
+ lxvw4x(32, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(33, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(34, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(35, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(36, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(37, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(38, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(39, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(40, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(41, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(42, %[cc0], %[sk])
+ li(%[cc0], 0)
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * v28 = increment for IV counter.
+ */
+ lxvw4x(60, 0, %[ctrinc])
+
+ /*
+ * Load IV into v16..v19
+ */
+ lxvw4x(48, %[cc0], %[ivbuf])
+ lxvw4x(49, %[cc1], %[ivbuf])
+ lxvw4x(50, %[cc2], %[ivbuf])
+ lxvw4x(51, %[cc3], %[ivbuf])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Compute next IV into v24..v27
+ */
+ vadduwm(24, 16, 28)
+ vadduwm(25, 17, 28)
+ vadduwm(26, 18, 28)
+ vadduwm(27, 19, 28)
+
+ /*
+ * Load next data blocks. We do this early on but we
+ * won't need them until IV encryption is done.
+ */
+ lxvw4x(52, %[cc0], %[buf])
+ lxvw4x(53, %[cc1], %[buf])
+ lxvw4x(54, %[cc2], %[buf])
+ lxvw4x(55, %[cc3], %[buf])
+
+ /*
+ * Encrypt the current IV.
+ */
+ vxor(16, 16, 0)
+ vxor(17, 17, 0)
+ vxor(18, 18, 0)
+ vxor(19, 19, 0)
+ vcipher(16, 16, 1)
+ vcipher(17, 17, 1)
+ vcipher(18, 18, 1)
+ vcipher(19, 19, 1)
+ vcipher(16, 16, 2)
+ vcipher(17, 17, 2)
+ vcipher(18, 18, 2)
+ vcipher(19, 19, 2)
+ vcipher(16, 16, 3)
+ vcipher(17, 17, 3)
+ vcipher(18, 18, 3)
+ vcipher(19, 19, 3)
+ vcipher(16, 16, 4)
+ vcipher(17, 17, 4)
+ vcipher(18, 18, 4)
+ vcipher(19, 19, 4)
+ vcipher(16, 16, 5)
+ vcipher(17, 17, 5)
+ vcipher(18, 18, 5)
+ vcipher(19, 19, 5)
+ vcipher(16, 16, 6)
+ vcipher(17, 17, 6)
+ vcipher(18, 18, 6)
+ vcipher(19, 19, 6)
+ vcipher(16, 16, 7)
+ vcipher(17, 17, 7)
+ vcipher(18, 18, 7)
+ vcipher(19, 19, 7)
+ vcipher(16, 16, 8)
+ vcipher(17, 17, 8)
+ vcipher(18, 18, 8)
+ vcipher(19, 19, 8)
+ vcipher(16, 16, 9)
+ vcipher(17, 17, 9)
+ vcipher(18, 18, 9)
+ vcipher(19, 19, 9)
+ vcipherlast(16, 16, 10)
+ vcipherlast(17, 17, 10)
+ vcipherlast(18, 18, 10)
+ vcipherlast(19, 19, 10)
+
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+
+ /*
+ * Load next plaintext word and XOR with encrypted IV.
+ */
+ vxor(16, 20, 16)
+ vxor(17, 21, 17)
+ vxor(18, 22, 18)
+ vxor(19, 23, 19)
+ stxvw4x(48, %[cc0], %[buf])
+ stxvw4x(49, %[cc1], %[buf])
+ stxvw4x(50, %[cc2], %[buf])
+ stxvw4x(51, %[cc3], %[buf])
+
+ addi(%[buf], %[buf], 64)
+
+ /*
+ * Update IV.
+ */
+ vand(16, 24, 24)
+ vand(17, 25, 25)
+ vand(18, 26, 26)
+ vand(19, 27, 27)
+
+ bdnz(loop)
+
+: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
+ [buf] "+b" (buf)
+: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2),
+ [ctrinc] "b" (ctrinc)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+ "ctr", "memory"
+ );
+}
+
+static void
+ctr_192(const unsigned char *sk, const unsigned char *ivbuf,
+ unsigned char *buf, size_t num_blocks)
+{
+ long cc0, cc1, cc2, cc3;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+ static const uint32_t ctrinc[] = {
+ 0, 0, 0, 4
+ };
+
+ cc0 = 0;
+ cc1 = 16;
+ cc2 = 32;
+ cc3 = 48;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v12
+ */
+ lxvw4x(32, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(33, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(34, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(35, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(36, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(37, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(38, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(39, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(40, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(41, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(42, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(43, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(44, %[cc0], %[sk])
+ li(%[cc0], 0)
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * v28 = increment for IV counter.
+ */
+ lxvw4x(60, 0, %[ctrinc])
+
+ /*
+ * Load IV into v16..v19
+ */
+ lxvw4x(48, %[cc0], %[ivbuf])
+ lxvw4x(49, %[cc1], %[ivbuf])
+ lxvw4x(50, %[cc2], %[ivbuf])
+ lxvw4x(51, %[cc3], %[ivbuf])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Compute next IV into v24..v27
+ */
+ vadduwm(24, 16, 28)
+ vadduwm(25, 17, 28)
+ vadduwm(26, 18, 28)
+ vadduwm(27, 19, 28)
+
+ /*
+ * Load next data blocks. We do this early on but we
+ * won't need them until IV encryption is done.
+ */
+ lxvw4x(52, %[cc0], %[buf])
+ lxvw4x(53, %[cc1], %[buf])
+ lxvw4x(54, %[cc2], %[buf])
+ lxvw4x(55, %[cc3], %[buf])
+
+ /*
+ * Encrypt the current IV.
+ */
+ vxor(16, 16, 0)
+ vxor(17, 17, 0)
+ vxor(18, 18, 0)
+ vxor(19, 19, 0)
+ vcipher(16, 16, 1)
+ vcipher(17, 17, 1)
+ vcipher(18, 18, 1)
+ vcipher(19, 19, 1)
+ vcipher(16, 16, 2)
+ vcipher(17, 17, 2)
+ vcipher(18, 18, 2)
+ vcipher(19, 19, 2)
+ vcipher(16, 16, 3)
+ vcipher(17, 17, 3)
+ vcipher(18, 18, 3)
+ vcipher(19, 19, 3)
+ vcipher(16, 16, 4)
+ vcipher(17, 17, 4)
+ vcipher(18, 18, 4)
+ vcipher(19, 19, 4)
+ vcipher(16, 16, 5)
+ vcipher(17, 17, 5)
+ vcipher(18, 18, 5)
+ vcipher(19, 19, 5)
+ vcipher(16, 16, 6)
+ vcipher(17, 17, 6)
+ vcipher(18, 18, 6)
+ vcipher(19, 19, 6)
+ vcipher(16, 16, 7)
+ vcipher(17, 17, 7)
+ vcipher(18, 18, 7)
+ vcipher(19, 19, 7)
+ vcipher(16, 16, 8)
+ vcipher(17, 17, 8)
+ vcipher(18, 18, 8)
+ vcipher(19, 19, 8)
+ vcipher(16, 16, 9)
+ vcipher(17, 17, 9)
+ vcipher(18, 18, 9)
+ vcipher(19, 19, 9)
+ vcipher(16, 16, 10)
+ vcipher(17, 17, 10)
+ vcipher(18, 18, 10)
+ vcipher(19, 19, 10)
+ vcipher(16, 16, 11)
+ vcipher(17, 17, 11)
+ vcipher(18, 18, 11)
+ vcipher(19, 19, 11)
+ vcipherlast(16, 16, 12)
+ vcipherlast(17, 17, 12)
+ vcipherlast(18, 18, 12)
+ vcipherlast(19, 19, 12)
+
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+
+ /*
+ * Load next plaintext word and XOR with encrypted IV.
+ */
+ vxor(16, 20, 16)
+ vxor(17, 21, 17)
+ vxor(18, 22, 18)
+ vxor(19, 23, 19)
+ stxvw4x(48, %[cc0], %[buf])
+ stxvw4x(49, %[cc1], %[buf])
+ stxvw4x(50, %[cc2], %[buf])
+ stxvw4x(51, %[cc3], %[buf])
+
+ addi(%[buf], %[buf], 64)
+
+ /*
+ * Update IV.
+ */
+ vand(16, 24, 24)
+ vand(17, 25, 25)
+ vand(18, 26, 26)
+ vand(19, 27, 27)
+
+ bdnz(loop)
+
+: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
+ [buf] "+b" (buf)
+: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2),
+ [ctrinc] "b" (ctrinc)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+ "ctr", "memory"
+ );
+}
+
+static void
+ctr_256(const unsigned char *sk, const unsigned char *ivbuf,
+ unsigned char *buf, size_t num_blocks)
+{
+ long cc0, cc1, cc2, cc3;
+
+#if BR_POWER8_LE
+ static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+ };
+#endif
+ static const uint32_t ctrinc[] = {
+ 0, 0, 0, 4
+ };
+
+ cc0 = 0;
+ cc1 = 16;
+ cc2 = 32;
+ cc3 = 48;
+ asm volatile (
+
+ /*
+ * Load subkeys into v0..v14
+ */
+ lxvw4x(32, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(33, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(34, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(35, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(36, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(37, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(38, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(39, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(40, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(41, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(42, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(43, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(44, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(45, %[cc0], %[sk])
+ addi(%[cc0], %[cc0], 16)
+ lxvw4x(46, %[cc0], %[sk])
+ li(%[cc0], 0)
+
+#if BR_POWER8_LE
+ /*
+ * v15 = constant for byteswapping words
+ */
+ lxvw4x(47, 0, %[idx2be])
+#endif
+ /*
+ * v28 = increment for IV counter.
+ */
+ lxvw4x(60, 0, %[ctrinc])
+
+ /*
+ * Load IV into v16..v19
+ */
+ lxvw4x(48, %[cc0], %[ivbuf])
+ lxvw4x(49, %[cc1], %[ivbuf])
+ lxvw4x(50, %[cc2], %[ivbuf])
+ lxvw4x(51, %[cc3], %[ivbuf])
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+
+ mtctr(%[num_blocks])
+ label(loop)
+ /*
+ * Compute next IV into v24..v27
+ */
+ vadduwm(24, 16, 28)
+ vadduwm(25, 17, 28)
+ vadduwm(26, 18, 28)
+ vadduwm(27, 19, 28)
+
+ /*
+ * Load next data blocks. We do this early on but we
+ * won't need them until IV encryption is done.
+ */
+ lxvw4x(52, %[cc0], %[buf])
+ lxvw4x(53, %[cc1], %[buf])
+ lxvw4x(54, %[cc2], %[buf])
+ lxvw4x(55, %[cc3], %[buf])
+
+ /*
+ * Encrypt the current IV.
+ */
+ vxor(16, 16, 0)
+ vxor(17, 17, 0)
+ vxor(18, 18, 0)
+ vxor(19, 19, 0)
+ vcipher(16, 16, 1)
+ vcipher(17, 17, 1)
+ vcipher(18, 18, 1)
+ vcipher(19, 19, 1)
+ vcipher(16, 16, 2)
+ vcipher(17, 17, 2)
+ vcipher(18, 18, 2)
+ vcipher(19, 19, 2)
+ vcipher(16, 16, 3)
+ vcipher(17, 17, 3)
+ vcipher(18, 18, 3)
+ vcipher(19, 19, 3)
+ vcipher(16, 16, 4)
+ vcipher(17, 17, 4)
+ vcipher(18, 18, 4)
+ vcipher(19, 19, 4)
+ vcipher(16, 16, 5)
+ vcipher(17, 17, 5)
+ vcipher(18, 18, 5)
+ vcipher(19, 19, 5)
+ vcipher(16, 16, 6)
+ vcipher(17, 17, 6)
+ vcipher(18, 18, 6)
+ vcipher(19, 19, 6)
+ vcipher(16, 16, 7)
+ vcipher(17, 17, 7)
+ vcipher(18, 18, 7)
+ vcipher(19, 19, 7)
+ vcipher(16, 16, 8)
+ vcipher(17, 17, 8)
+ vcipher(18, 18, 8)
+ vcipher(19, 19, 8)
+ vcipher(16, 16, 9)
+ vcipher(17, 17, 9)
+ vcipher(18, 18, 9)
+ vcipher(19, 19, 9)
+ vcipher(16, 16, 10)
+ vcipher(17, 17, 10)
+ vcipher(18, 18, 10)
+ vcipher(19, 19, 10)
+ vcipher(16, 16, 11)
+ vcipher(17, 17, 11)
+ vcipher(18, 18, 11)
+ vcipher(19, 19, 11)
+ vcipher(16, 16, 12)
+ vcipher(17, 17, 12)
+ vcipher(18, 18, 12)
+ vcipher(19, 19, 12)
+ vcipher(16, 16, 13)
+ vcipher(17, 17, 13)
+ vcipher(18, 18, 13)
+ vcipher(19, 19, 13)
+ vcipherlast(16, 16, 14)
+ vcipherlast(17, 17, 14)
+ vcipherlast(18, 18, 14)
+ vcipherlast(19, 19, 14)
+
+#if BR_POWER8_LE
+ vperm(16, 16, 16, 15)
+ vperm(17, 17, 17, 15)
+ vperm(18, 18, 18, 15)
+ vperm(19, 19, 19, 15)
+#endif
+
+ /*
+ * Load next plaintext word and XOR with encrypted IV.
+ */
+ vxor(16, 20, 16)
+ vxor(17, 21, 17)
+ vxor(18, 22, 18)
+ vxor(19, 23, 19)
+ stxvw4x(48, %[cc0], %[buf])
+ stxvw4x(49, %[cc1], %[buf])
+ stxvw4x(50, %[cc2], %[buf])
+ stxvw4x(51, %[cc3], %[buf])
+
+ addi(%[buf], %[buf], 64)
+
+ /*
+ * Update IV.
+ */
+ vand(16, 24, 24)
+ vand(17, 25, 25)
+ vand(18, 26, 26)
+ vand(19, 27, 27)
+
+ bdnz(loop)
+
+: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3),
+ [buf] "+b" (buf)
+: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2),
+ [ctrinc] "b" (ctrinc)
+#if BR_POWER8_LE
+ , [idx2be] "b" (idx2be)
+#endif
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
+ "ctr", "memory"
+ );
+}
+
+/* see bearssl_block.h */
+uint32_t
+br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned char ivbuf[64];
+
+ buf = data;
+ memcpy(ivbuf + 0, iv, 12);
+ memcpy(ivbuf + 16, iv, 12);
+ memcpy(ivbuf + 32, iv, 12);
+ memcpy(ivbuf + 48, iv, 12);
+ if (len >= 64) {
+ br_enc32be(ivbuf + 12, cc + 0);
+ br_enc32be(ivbuf + 28, cc + 1);
+ br_enc32be(ivbuf + 44, cc + 2);
+ br_enc32be(ivbuf + 60, cc + 3);
+ switch (ctx->num_rounds) {
+ case 10:
+ ctr_128(ctx->skey.skni, ivbuf, buf,
+ (len >> 4) & ~(size_t)3);
+ break;
+ case 12:
+ ctr_192(ctx->skey.skni, ivbuf, buf,
+ (len >> 4) & ~(size_t)3);
+ break;
+ default:
+ ctr_256(ctx->skey.skni, ivbuf, buf,
+ (len >> 4) & ~(size_t)3);
+ break;
+ }
+ cc += (len >> 4) & ~(size_t)3;
+ buf += len & ~(size_t)63;
+ len &= 63;
+ }
+ if (len > 0) {
+ unsigned char tmp[64];
+
+ memcpy(tmp, buf, len);
+ memset(tmp + len, 0, (sizeof tmp) - len);
+ br_enc32be(ivbuf + 12, cc + 0);
+ br_enc32be(ivbuf + 28, cc + 1);
+ br_enc32be(ivbuf + 44, cc + 2);
+ br_enc32be(ivbuf + 60, cc + 3);
+ switch (ctx->num_rounds) {
+ case 10:
+ ctr_128(ctx->skey.skni, ivbuf, tmp, 4);
+ break;
+ case 12:
+ ctr_192(ctx->skey.skni, ivbuf, tmp, 4);
+ break;
+ default:
+ ctr_256(ctx->skey.skni, ivbuf, tmp, 4);
+ break;
+ }
+ memcpy(buf, tmp, len);
+ cc += (len + 15) >> 4;
+ }
+ return cc;
+}
+
+/* see bearssl_block.h */
+const br_block_ctr_class br_aes_pwr8_ctr_vtable = {
+ sizeof(br_aes_pwr8_ctr_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctr_class **, const void *, size_t))
+ &br_aes_pwr8_ctr_init,
+ (uint32_t (*)(const br_block_ctr_class *const *,
+ const void *, uint32_t, void *, size_t))
+ &br_aes_pwr8_ctr_run
+};
+
+/* see bearssl_block.h */
+const br_block_ctr_class *
+br_aes_pwr8_ctr_get_vtable(void)
+{
+ return br_aes_pwr8_supported() ? &br_aes_pwr8_ctr_vtable : NULL;
+}
+
+#else
+
+/* see bearssl_block.h */
+const br_block_ctr_class *
+br_aes_pwr8_ctr_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctrcbc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctrcbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctrcbc.c (revision 346145)
@@ -0,0 +1,946 @@
+/*
+ * 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.
+ */
+
+#define BR_POWER_ASM_MACROS 1
+#include "inner.h"
+
+#if BR_POWER8
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class *
+br_aes_pwr8_ctrcbc_get_vtable(void)
+{
+ return br_aes_pwr8_supported() ? &br_aes_pwr8_ctrcbc_vtable : NULL;
+}
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_pwr8_ctrcbc_vtable;
+ ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len);
+}
+
+/*
+ * Register conventions for CTR + CBC-MAC:
+ *
+ * AES subkeys are in registers 0 to 10/12/14 (depending on keys size)
+ * Register v15 contains the byteswap index register (little-endian only)
+ * Register v16 contains the CTR counter value
+ * Register v17 contains the CBC-MAC current value
+ * Registers v18 to v27 are scratch
+ * Counter increment uses v28, v29 and v30
+ *
+ * For CTR alone:
+ *
+ * AES subkeys are in registers 0 to 10/12/14 (depending on keys size)
+ * Register v15 contains the byteswap index register (little-endian only)
+ * Registers v16 to v19 contain the CTR counter values (four blocks)
+ * Registers v20 to v27 are scratch
+ * Counter increment uses v28, v29 and v30
+ */
+
+#define LOAD_SUBKEYS_128 \
+ lxvw4x(32, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(33, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(34, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(35, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(36, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(37, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(38, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(39, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(40, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(41, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(42, %[cc], %[sk])
+
+#define LOAD_SUBKEYS_192 \
+ LOAD_SUBKEYS_128 \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(43, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(44, %[cc], %[sk])
+
+#define LOAD_SUBKEYS_256 \
+ LOAD_SUBKEYS_192 \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(45, %[cc], %[sk]) \
+ addi(%[cc], %[cc], 16) \
+ lxvw4x(46, %[cc], %[sk])
+
+#define BLOCK_ENCRYPT_128(x) \
+ vxor(x, x, 0) \
+ vcipher(x, x, 1) \
+ vcipher(x, x, 2) \
+ vcipher(x, x, 3) \
+ vcipher(x, x, 4) \
+ vcipher(x, x, 5) \
+ vcipher(x, x, 6) \
+ vcipher(x, x, 7) \
+ vcipher(x, x, 8) \
+ vcipher(x, x, 9) \
+ vcipherlast(x, x, 10)
+
+#define BLOCK_ENCRYPT_192(x) \
+ vxor(x, x, 0) \
+ vcipher(x, x, 1) \
+ vcipher(x, x, 2) \
+ vcipher(x, x, 3) \
+ vcipher(x, x, 4) \
+ vcipher(x, x, 5) \
+ vcipher(x, x, 6) \
+ vcipher(x, x, 7) \
+ vcipher(x, x, 8) \
+ vcipher(x, x, 9) \
+ vcipher(x, x, 10) \
+ vcipher(x, x, 11) \
+ vcipherlast(x, x, 12)
+
+#define BLOCK_ENCRYPT_256(x) \
+ vxor(x, x, 0) \
+ vcipher(x, x, 1) \
+ vcipher(x, x, 2) \
+ vcipher(x, x, 3) \
+ vcipher(x, x, 4) \
+ vcipher(x, x, 5) \
+ vcipher(x, x, 6) \
+ vcipher(x, x, 7) \
+ vcipher(x, x, 8) \
+ vcipher(x, x, 9) \
+ vcipher(x, x, 10) \
+ vcipher(x, x, 11) \
+ vcipher(x, x, 12) \
+ vcipher(x, x, 13) \
+ vcipherlast(x, x, 14)
+
+#define BLOCK_ENCRYPT_X2_128(x, y) \
+ vxor(x, x, 0) \
+ vxor(y, y, 0) \
+ vcipher(x, x, 1) \
+ vcipher(y, y, 1) \
+ vcipher(x, x, 2) \
+ vcipher(y, y, 2) \
+ vcipher(x, x, 3) \
+ vcipher(y, y, 3) \
+ vcipher(x, x, 4) \
+ vcipher(y, y, 4) \
+ vcipher(x, x, 5) \
+ vcipher(y, y, 5) \
+ vcipher(x, x, 6) \
+ vcipher(y, y, 6) \
+ vcipher(x, x, 7) \
+ vcipher(y, y, 7) \
+ vcipher(x, x, 8) \
+ vcipher(y, y, 8) \
+ vcipher(x, x, 9) \
+ vcipher(y, y, 9) \
+ vcipherlast(x, x, 10) \
+ vcipherlast(y, y, 10)
+
+#define BLOCK_ENCRYPT_X2_192(x, y) \
+ vxor(x, x, 0) \
+ vxor(y, y, 0) \
+ vcipher(x, x, 1) \
+ vcipher(y, y, 1) \
+ vcipher(x, x, 2) \
+ vcipher(y, y, 2) \
+ vcipher(x, x, 3) \
+ vcipher(y, y, 3) \
+ vcipher(x, x, 4) \
+ vcipher(y, y, 4) \
+ vcipher(x, x, 5) \
+ vcipher(y, y, 5) \
+ vcipher(x, x, 6) \
+ vcipher(y, y, 6) \
+ vcipher(x, x, 7) \
+ vcipher(y, y, 7) \
+ vcipher(x, x, 8) \
+ vcipher(y, y, 8) \
+ vcipher(x, x, 9) \
+ vcipher(y, y, 9) \
+ vcipher(x, x, 10) \
+ vcipher(y, y, 10) \
+ vcipher(x, x, 11) \
+ vcipher(y, y, 11) \
+ vcipherlast(x, x, 12) \
+ vcipherlast(y, y, 12)
+
+#define BLOCK_ENCRYPT_X2_256(x, y) \
+ vxor(x, x, 0) \
+ vxor(y, y, 0) \
+ vcipher(x, x, 1) \
+ vcipher(y, y, 1) \
+ vcipher(x, x, 2) \
+ vcipher(y, y, 2) \
+ vcipher(x, x, 3) \
+ vcipher(y, y, 3) \
+ vcipher(x, x, 4) \
+ vcipher(y, y, 4) \
+ vcipher(x, x, 5) \
+ vcipher(y, y, 5) \
+ vcipher(x, x, 6) \
+ vcipher(y, y, 6) \
+ vcipher(x, x, 7) \
+ vcipher(y, y, 7) \
+ vcipher(x, x, 8) \
+ vcipher(y, y, 8) \
+ vcipher(x, x, 9) \
+ vcipher(y, y, 9) \
+ vcipher(x, x, 10) \
+ vcipher(y, y, 10) \
+ vcipher(x, x, 11) \
+ vcipher(y, y, 11) \
+ vcipher(x, x, 12) \
+ vcipher(y, y, 12) \
+ vcipher(x, x, 13) \
+ vcipher(y, y, 13) \
+ vcipherlast(x, x, 14) \
+ vcipherlast(y, y, 14)
+
+#define BLOCK_ENCRYPT_X4_128(x0, x1, x2, x3) \
+ vxor(x0, x0, 0) \
+ vxor(x1, x1, 0) \
+ vxor(x2, x2, 0) \
+ vxor(x3, x3, 0) \
+ vcipher(x0, x0, 1) \
+ vcipher(x1, x1, 1) \
+ vcipher(x2, x2, 1) \
+ vcipher(x3, x3, 1) \
+ vcipher(x0, x0, 2) \
+ vcipher(x1, x1, 2) \
+ vcipher(x2, x2, 2) \
+ vcipher(x3, x3, 2) \
+ vcipher(x0, x0, 3) \
+ vcipher(x1, x1, 3) \
+ vcipher(x2, x2, 3) \
+ vcipher(x3, x3, 3) \
+ vcipher(x0, x0, 4) \
+ vcipher(x1, x1, 4) \
+ vcipher(x2, x2, 4) \
+ vcipher(x3, x3, 4) \
+ vcipher(x0, x0, 5) \
+ vcipher(x1, x1, 5) \
+ vcipher(x2, x2, 5) \
+ vcipher(x3, x3, 5) \
+ vcipher(x0, x0, 6) \
+ vcipher(x1, x1, 6) \
+ vcipher(x2, x2, 6) \
+ vcipher(x3, x3, 6) \
+ vcipher(x0, x0, 7) \
+ vcipher(x1, x1, 7) \
+ vcipher(x2, x2, 7) \
+ vcipher(x3, x3, 7) \
+ vcipher(x0, x0, 8) \
+ vcipher(x1, x1, 8) \
+ vcipher(x2, x2, 8) \
+ vcipher(x3, x3, 8) \
+ vcipher(x0, x0, 9) \
+ vcipher(x1, x1, 9) \
+ vcipher(x2, x2, 9) \
+ vcipher(x3, x3, 9) \
+ vcipherlast(x0, x0, 10) \
+ vcipherlast(x1, x1, 10) \
+ vcipherlast(x2, x2, 10) \
+ vcipherlast(x3, x3, 10)
+
+#define BLOCK_ENCRYPT_X4_192(x0, x1, x2, x3) \
+ vxor(x0, x0, 0) \
+ vxor(x1, x1, 0) \
+ vxor(x2, x2, 0) \
+ vxor(x3, x3, 0) \
+ vcipher(x0, x0, 1) \
+ vcipher(x1, x1, 1) \
+ vcipher(x2, x2, 1) \
+ vcipher(x3, x3, 1) \
+ vcipher(x0, x0, 2) \
+ vcipher(x1, x1, 2) \
+ vcipher(x2, x2, 2) \
+ vcipher(x3, x3, 2) \
+ vcipher(x0, x0, 3) \
+ vcipher(x1, x1, 3) \
+ vcipher(x2, x2, 3) \
+ vcipher(x3, x3, 3) \
+ vcipher(x0, x0, 4) \
+ vcipher(x1, x1, 4) \
+ vcipher(x2, x2, 4) \
+ vcipher(x3, x3, 4) \
+ vcipher(x0, x0, 5) \
+ vcipher(x1, x1, 5) \
+ vcipher(x2, x2, 5) \
+ vcipher(x3, x3, 5) \
+ vcipher(x0, x0, 6) \
+ vcipher(x1, x1, 6) \
+ vcipher(x2, x2, 6) \
+ vcipher(x3, x3, 6) \
+ vcipher(x0, x0, 7) \
+ vcipher(x1, x1, 7) \
+ vcipher(x2, x2, 7) \
+ vcipher(x3, x3, 7) \
+ vcipher(x0, x0, 8) \
+ vcipher(x1, x1, 8) \
+ vcipher(x2, x2, 8) \
+ vcipher(x3, x3, 8) \
+ vcipher(x0, x0, 9) \
+ vcipher(x1, x1, 9) \
+ vcipher(x2, x2, 9) \
+ vcipher(x3, x3, 9) \
+ vcipher(x0, x0, 10) \
+ vcipher(x1, x1, 10) \
+ vcipher(x2, x2, 10) \
+ vcipher(x3, x3, 10) \
+ vcipher(x0, x0, 11) \
+ vcipher(x1, x1, 11) \
+ vcipher(x2, x2, 11) \
+ vcipher(x3, x3, 11) \
+ vcipherlast(x0, x0, 12) \
+ vcipherlast(x1, x1, 12) \
+ vcipherlast(x2, x2, 12) \
+ vcipherlast(x3, x3, 12)
+
+#define BLOCK_ENCRYPT_X4_256(x0, x1, x2, x3) \
+ vxor(x0, x0, 0) \
+ vxor(x1, x1, 0) \
+ vxor(x2, x2, 0) \
+ vxor(x3, x3, 0) \
+ vcipher(x0, x0, 1) \
+ vcipher(x1, x1, 1) \
+ vcipher(x2, x2, 1) \
+ vcipher(x3, x3, 1) \
+ vcipher(x0, x0, 2) \
+ vcipher(x1, x1, 2) \
+ vcipher(x2, x2, 2) \
+ vcipher(x3, x3, 2) \
+ vcipher(x0, x0, 3) \
+ vcipher(x1, x1, 3) \
+ vcipher(x2, x2, 3) \
+ vcipher(x3, x3, 3) \
+ vcipher(x0, x0, 4) \
+ vcipher(x1, x1, 4) \
+ vcipher(x2, x2, 4) \
+ vcipher(x3, x3, 4) \
+ vcipher(x0, x0, 5) \
+ vcipher(x1, x1, 5) \
+ vcipher(x2, x2, 5) \
+ vcipher(x3, x3, 5) \
+ vcipher(x0, x0, 6) \
+ vcipher(x1, x1, 6) \
+ vcipher(x2, x2, 6) \
+ vcipher(x3, x3, 6) \
+ vcipher(x0, x0, 7) \
+ vcipher(x1, x1, 7) \
+ vcipher(x2, x2, 7) \
+ vcipher(x3, x3, 7) \
+ vcipher(x0, x0, 8) \
+ vcipher(x1, x1, 8) \
+ vcipher(x2, x2, 8) \
+ vcipher(x3, x3, 8) \
+ vcipher(x0, x0, 9) \
+ vcipher(x1, x1, 9) \
+ vcipher(x2, x2, 9) \
+ vcipher(x3, x3, 9) \
+ vcipher(x0, x0, 10) \
+ vcipher(x1, x1, 10) \
+ vcipher(x2, x2, 10) \
+ vcipher(x3, x3, 10) \
+ vcipher(x0, x0, 11) \
+ vcipher(x1, x1, 11) \
+ vcipher(x2, x2, 11) \
+ vcipher(x3, x3, 11) \
+ vcipher(x0, x0, 12) \
+ vcipher(x1, x1, 12) \
+ vcipher(x2, x2, 12) \
+ vcipher(x3, x3, 12) \
+ vcipher(x0, x0, 13) \
+ vcipher(x1, x1, 13) \
+ vcipher(x2, x2, 13) \
+ vcipher(x3, x3, 13) \
+ vcipherlast(x0, x0, 14) \
+ vcipherlast(x1, x1, 14) \
+ vcipherlast(x2, x2, 14) \
+ vcipherlast(x3, x3, 14)
+
+#if BR_POWER8_LE
+static const uint32_t idx2be[] = {
+ 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
+};
+#define BYTESWAP_INIT lxvw4x(47, 0, %[idx2be])
+#define BYTESWAP(x) vperm(x, x, x, 15)
+#define BYTESWAPX(d, s) vperm(d, s, s, 15)
+#define BYTESWAP_REG , [idx2be] "b" (idx2be)
+#else
+#define BYTESWAP_INIT
+#define BYTESWAP(x)
+#define BYTESWAPX(d, s) vand(d, s, s)
+#define BYTESWAP_REG
+#endif
+
+static const uint32_t ctrinc[] = {
+ 0, 0, 0, 1
+};
+static const uint32_t ctrinc_x4[] = {
+ 0, 0, 0, 4
+};
+#define INCR_128_INIT lxvw4x(60, 0, %[ctrinc])
+#define INCR_128_X4_INIT lxvw4x(60, 0, %[ctrinc_x4])
+#define INCR_128(d, s) \
+ vaddcuw(29, s, 28) \
+ vadduwm(d, s, 28) \
+ vsldoi(30, 29, 29, 4) \
+ vaddcuw(29, d, 30) \
+ vadduwm(d, d, 30) \
+ vsldoi(30, 29, 29, 4) \
+ vaddcuw(29, d, 30) \
+ vadduwm(d, d, 30) \
+ vsldoi(30, 29, 29, 4) \
+ vadduwm(d, d, 30)
+
+#define MKCTR(size) \
+static void \
+ctr_ ## size(const unsigned char *sk, \
+ unsigned char *ctrbuf, unsigned char *buf, size_t num_blocks_x4) \
+{ \
+ long cc, cc0, cc1, cc2, cc3; \
+ \
+ cc = 0; \
+ cc0 = 0; \
+ cc1 = 16; \
+ cc2 = 32; \
+ cc3 = 48; \
+ asm volatile ( \
+ \
+ /* \
+ * Load subkeys into v0..v10 \
+ */ \
+ LOAD_SUBKEYS_ ## size \
+ li(%[cc], 0) \
+ \
+ BYTESWAP_INIT \
+ INCR_128_X4_INIT \
+ \
+ /* \
+ * Load current CTR counters into v16 to v19. \
+ */ \
+ lxvw4x(48, %[cc0], %[ctrbuf]) \
+ lxvw4x(49, %[cc1], %[ctrbuf]) \
+ lxvw4x(50, %[cc2], %[ctrbuf]) \
+ lxvw4x(51, %[cc3], %[ctrbuf]) \
+ BYTESWAP(16) \
+ BYTESWAP(17) \
+ BYTESWAP(18) \
+ BYTESWAP(19) \
+ \
+ mtctr(%[num_blocks_x4]) \
+ \
+ label(loop) \
+ /* \
+ * Compute next counter values into v20..v23. \
+ */ \
+ INCR_128(20, 16) \
+ INCR_128(21, 17) \
+ INCR_128(22, 18) \
+ INCR_128(23, 19) \
+ \
+ /* \
+ * Encrypt counter values and XOR into next data blocks. \
+ */ \
+ lxvw4x(56, %[cc0], %[buf]) \
+ lxvw4x(57, %[cc1], %[buf]) \
+ lxvw4x(58, %[cc2], %[buf]) \
+ lxvw4x(59, %[cc3], %[buf]) \
+ BYTESWAP(24) \
+ BYTESWAP(25) \
+ BYTESWAP(26) \
+ BYTESWAP(27) \
+ BLOCK_ENCRYPT_X4_ ## size(16, 17, 18, 19) \
+ vxor(16, 16, 24) \
+ vxor(17, 17, 25) \
+ vxor(18, 18, 26) \
+ vxor(19, 19, 27) \
+ BYTESWAP(16) \
+ BYTESWAP(17) \
+ BYTESWAP(18) \
+ BYTESWAP(19) \
+ stxvw4x(48, %[cc0], %[buf]) \
+ stxvw4x(49, %[cc1], %[buf]) \
+ stxvw4x(50, %[cc2], %[buf]) \
+ stxvw4x(51, %[cc3], %[buf]) \
+ \
+ /* \
+ * Update counters and data pointer. \
+ */ \
+ vand(16, 20, 20) \
+ vand(17, 21, 21) \
+ vand(18, 22, 22) \
+ vand(19, 23, 23) \
+ addi(%[buf], %[buf], 64) \
+ \
+ bdnz(loop) \
+ \
+ /* \
+ * Write back new counter values. \
+ */ \
+ BYTESWAP(16) \
+ BYTESWAP(17) \
+ BYTESWAP(18) \
+ BYTESWAP(19) \
+ stxvw4x(48, %[cc0], %[ctrbuf]) \
+ stxvw4x(49, %[cc1], %[ctrbuf]) \
+ stxvw4x(50, %[cc2], %[ctrbuf]) \
+ stxvw4x(51, %[cc3], %[ctrbuf]) \
+ \
+: [cc] "+b" (cc), [buf] "+b" (buf), \
+ [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3) \
+: [sk] "b" (sk), [ctrbuf] "b" (ctrbuf), \
+ [num_blocks_x4] "b" (num_blocks_x4), [ctrinc_x4] "b" (ctrinc_x4) \
+ BYTESWAP_REG \
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
+ "v30", "ctr", "memory" \
+ ); \
+}
+
+MKCTR(128)
+MKCTR(192)
+MKCTR(256)
+
+#define MKCBCMAC(size) \
+static void \
+cbcmac_ ## size(const unsigned char *sk, \
+ unsigned char *cbcmac, const unsigned char *buf, size_t num_blocks) \
+{ \
+ long cc; \
+ \
+ cc = 0; \
+ asm volatile ( \
+ \
+ /* \
+ * Load subkeys into v0..v10 \
+ */ \
+ LOAD_SUBKEYS_ ## size \
+ li(%[cc], 0) \
+ \
+ BYTESWAP_INIT \
+ \
+ /* \
+ * Load current CBC-MAC value into v16. \
+ */ \
+ lxvw4x(48, %[cc], %[cbcmac]) \
+ BYTESWAP(16) \
+ \
+ mtctr(%[num_blocks]) \
+ \
+ label(loop) \
+ /* \
+ * Load next block, XOR into current CBC-MAC value, \
+ * and then encrypt it. \
+ */ \
+ lxvw4x(49, %[cc], %[buf]) \
+ BYTESWAP(17) \
+ vxor(16, 16, 17) \
+ BLOCK_ENCRYPT_ ## size(16) \
+ addi(%[buf], %[buf], 16) \
+ \
+ bdnz(loop) \
+ \
+ /* \
+ * Write back new CBC-MAC value. \
+ */ \
+ BYTESWAP(16) \
+ stxvw4x(48, %[cc], %[cbcmac]) \
+ \
+: [cc] "+b" (cc), [buf] "+b" (buf) \
+: [sk] "b" (sk), [cbcmac] "b" (cbcmac), [num_blocks] "b" (num_blocks) \
+ BYTESWAP_REG \
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
+ "v30", "ctr", "memory" \
+ ); \
+}
+
+MKCBCMAC(128)
+MKCBCMAC(192)
+MKCBCMAC(256)
+
+#define MKENCRYPT(size) \
+static void \
+ctrcbc_ ## size ## _encrypt(const unsigned char *sk, \
+ unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \
+ size_t num_blocks) \
+{ \
+ long cc; \
+ \
+ cc = 0; \
+ asm volatile ( \
+ \
+ /* \
+ * Load subkeys into v0..v10 \
+ */ \
+ LOAD_SUBKEYS_ ## size \
+ li(%[cc], 0) \
+ \
+ BYTESWAP_INIT \
+ INCR_128_INIT \
+ \
+ /* \
+ * Load current CTR counter into v16, and current \
+ * CBC-MAC IV into v17. \
+ */ \
+ lxvw4x(48, %[cc], %[ctr]) \
+ lxvw4x(49, %[cc], %[cbcmac]) \
+ BYTESWAP(16) \
+ BYTESWAP(17) \
+ \
+ /* \
+ * At each iteration, we do two parallel encryption: \
+ * - new counter value for encryption of the next block; \
+ * - CBC-MAC over the previous encrypted block. \
+ * Thus, each plaintext block implies two AES instances, \
+ * over two successive iterations. This requires a single \
+ * counter encryption before the loop, and a single \
+ * CBC-MAC encryption after the loop. \
+ */ \
+ \
+ /* \
+ * Encrypt first block (into v20). \
+ */ \
+ lxvw4x(52, %[cc], %[buf]) \
+ BYTESWAP(20) \
+ INCR_128(22, 16) \
+ BLOCK_ENCRYPT_ ## size(16) \
+ vxor(20, 20, 16) \
+ BYTESWAPX(21, 20) \
+ stxvw4x(53, %[cc], %[buf]) \
+ vand(16, 22, 22) \
+ addi(%[buf], %[buf], 16) \
+ \
+ /* \
+ * Load loop counter; skip the loop if there is only \
+ * one block in total (already handled by the boundary \
+ * conditions). \
+ */ \
+ mtctr(%[num_blocks]) \
+ bdz(fastexit) \
+ \
+ label(loop) \
+ /* \
+ * Upon loop entry: \
+ * v16 counter value for next block \
+ * v17 current CBC-MAC value \
+ * v20 encrypted previous block \
+ */ \
+ vxor(17, 17, 20) \
+ INCR_128(22, 16) \
+ lxvw4x(52, %[cc], %[buf]) \
+ BYTESWAP(20) \
+ BLOCK_ENCRYPT_X2_ ## size(16, 17) \
+ vxor(20, 20, 16) \
+ BYTESWAPX(21, 20) \
+ stxvw4x(53, %[cc], %[buf]) \
+ addi(%[buf], %[buf], 16) \
+ vand(16, 22, 22) \
+ \
+ bdnz(loop) \
+ \
+ label(fastexit) \
+ vxor(17, 17, 20) \
+ BLOCK_ENCRYPT_ ## size(17) \
+ BYTESWAP(16) \
+ BYTESWAP(17) \
+ stxvw4x(48, %[cc], %[ctr]) \
+ stxvw4x(49, %[cc], %[cbcmac]) \
+ \
+: [cc] "+b" (cc), [buf] "+b" (buf) \
+: [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \
+ [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \
+ BYTESWAP_REG \
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
+ "v30", "ctr", "memory" \
+ ); \
+}
+
+MKENCRYPT(128)
+MKENCRYPT(192)
+MKENCRYPT(256)
+
+#define MKDECRYPT(size) \
+static void \
+ctrcbc_ ## size ## _decrypt(const unsigned char *sk, \
+ unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \
+ size_t num_blocks) \
+{ \
+ long cc; \
+ \
+ cc = 0; \
+ asm volatile ( \
+ \
+ /* \
+ * Load subkeys into v0..v10 \
+ */ \
+ LOAD_SUBKEYS_ ## size \
+ li(%[cc], 0) \
+ \
+ BYTESWAP_INIT \
+ INCR_128_INIT \
+ \
+ /* \
+ * Load current CTR counter into v16, and current \
+ * CBC-MAC IV into v17. \
+ */ \
+ lxvw4x(48, %[cc], %[ctr]) \
+ lxvw4x(49, %[cc], %[cbcmac]) \
+ BYTESWAP(16) \
+ BYTESWAP(17) \
+ \
+ /* \
+ * At each iteration, we do two parallel encryption: \
+ * - new counter value for decryption of the next block; \
+ * - CBC-MAC over the next encrypted block. \
+ * Each iteration performs the two AES instances related \
+ * to the current block; there is thus no need for some \
+ * extra pre-loop and post-loop work as in encryption. \
+ */ \
+ \
+ mtctr(%[num_blocks]) \
+ \
+ label(loop) \
+ /* \
+ * Upon loop entry: \
+ * v16 counter value for next block \
+ * v17 current CBC-MAC value \
+ */ \
+ lxvw4x(52, %[cc], %[buf]) \
+ BYTESWAP(20) \
+ vxor(17, 17, 20) \
+ INCR_128(22, 16) \
+ BLOCK_ENCRYPT_X2_ ## size(16, 17) \
+ vxor(20, 20, 16) \
+ BYTESWAPX(21, 20) \
+ stxvw4x(53, %[cc], %[buf]) \
+ addi(%[buf], %[buf], 16) \
+ vand(16, 22, 22) \
+ \
+ bdnz(loop) \
+ \
+ /* \
+ * Store back counter and CBC-MAC value. \
+ */ \
+ BYTESWAP(16) \
+ BYTESWAP(17) \
+ stxvw4x(48, %[cc], %[ctr]) \
+ stxvw4x(49, %[cc], %[cbcmac]) \
+ \
+: [cc] "+b" (cc), [buf] "+b" (buf) \
+: [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \
+ [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \
+ BYTESWAP_REG \
+: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \
+ "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \
+ "v30", "ctr", "memory" \
+ ); \
+}
+
+MKDECRYPT(128)
+MKDECRYPT(192)
+MKDECRYPT(256)
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ if (len == 0) {
+ return;
+ }
+ switch (ctx->num_rounds) {
+ case 10:
+ ctrcbc_128_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
+ break;
+ case 12:
+ ctrcbc_192_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
+ break;
+ default:
+ ctrcbc_256_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
+ break;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ if (len == 0) {
+ return;
+ }
+ switch (ctx->num_rounds) {
+ case 10:
+ ctrcbc_128_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
+ break;
+ case 12:
+ ctrcbc_192_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
+ break;
+ default:
+ ctrcbc_256_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4);
+ break;
+ }
+}
+
+static inline void
+incr_ctr(void *dst, const void *src)
+{
+ uint64_t hi, lo;
+
+ hi = br_dec64be(src);
+ lo = br_dec64be((const unsigned char *)src + 8);
+ lo ++;
+ hi += ((lo | -lo) >> 63) ^ (uint64_t)1;
+ br_enc64be(dst, hi);
+ br_enc64be((unsigned char *)dst + 8, lo);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len)
+{
+ unsigned char ctrbuf[64];
+
+ memcpy(ctrbuf, ctr, 16);
+ incr_ctr(ctrbuf + 16, ctrbuf);
+ incr_ctr(ctrbuf + 32, ctrbuf + 16);
+ incr_ctr(ctrbuf + 48, ctrbuf + 32);
+ if (len >= 64) {
+ switch (ctx->num_rounds) {
+ case 10:
+ ctr_128(ctx->skey.skni, ctrbuf, data, len >> 6);
+ break;
+ case 12:
+ ctr_192(ctx->skey.skni, ctrbuf, data, len >> 6);
+ break;
+ default:
+ ctr_256(ctx->skey.skni, ctrbuf, data, len >> 6);
+ break;
+ }
+ data = (unsigned char *)data + (len & ~(size_t)63);
+ len &= 63;
+ }
+ if (len > 0) {
+ unsigned char tmp[64];
+
+ if (len >= 32) {
+ if (len >= 48) {
+ memcpy(ctr, ctrbuf + 48, 16);
+ } else {
+ memcpy(ctr, ctrbuf + 32, 16);
+ }
+ } else {
+ if (len >= 16) {
+ memcpy(ctr, ctrbuf + 16, 16);
+ }
+ }
+ memcpy(tmp, data, len);
+ memset(tmp + len, 0, (sizeof tmp) - len);
+ switch (ctx->num_rounds) {
+ case 10:
+ ctr_128(ctx->skey.skni, ctrbuf, tmp, 1);
+ break;
+ case 12:
+ ctr_192(ctx->skey.skni, ctrbuf, tmp, 1);
+ break;
+ default:
+ ctr_256(ctx->skey.skni, ctrbuf, tmp, 1);
+ break;
+ }
+ memcpy(data, tmp, len);
+ } else {
+ memcpy(ctr, ctrbuf, 16);
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len)
+{
+ if (len > 0) {
+ switch (ctx->num_rounds) {
+ case 10:
+ cbcmac_128(ctx->skey.skni, cbcmac, data, len >> 4);
+ break;
+ case 12:
+ cbcmac_192(ctx->skey.skni, cbcmac, data, len >> 4);
+ break;
+ default:
+ cbcmac_256(ctx->skey.skni, cbcmac, data, len >> 4);
+ break;
+ }
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable = {
+ sizeof(br_aes_pwr8_ctrcbc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
+ &br_aes_pwr8_ctrcbc_init,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_pwr8_ctrcbc_encrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_pwr8_ctrcbc_decrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, size_t))
+ &br_aes_pwr8_ctrcbc_ctr,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, const void *, size_t))
+ &br_aes_pwr8_ctrcbc_mac
+};
+
+#else
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class *
+br_aes_pwr8_ctrcbc_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_pwr8_ctrcbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_small_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_small_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_small_cbcdec.c (revision 346145)
@@ -0,0 +1,69 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_small_cbcdec_vtable;
+ ctx->num_rounds = br_aes_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[16];
+ int i;
+
+ memcpy(tmp, buf, 16);
+ br_aes_small_decrypt(ctx->num_rounds, ctx->skey, buf);
+ for (i = 0; i < 16; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ memcpy(ivbuf, tmp, 16);
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_aes_small_cbcdec_vtable = {
+ sizeof(br_aes_small_cbcdec_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_aes_small_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_aes_small_cbcdec_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_small_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_small_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_small_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_small_cbcenc.c (revision 346145)
@@ -0,0 +1,67 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_small_cbcenc_vtable;
+ ctx->num_rounds = br_aes_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ int i;
+
+ for (i = 0; i < 16; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ br_aes_small_encrypt(ctx->num_rounds, ctx->skey, buf);
+ memcpy(ivbuf, buf, 16);
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_aes_small_cbcenc_vtable = {
+ sizeof(br_aes_small_cbcenc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_aes_small_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_aes_small_cbcenc_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_small_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_small_ctr.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_small_ctr.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_small_ctr.c (revision 346145)
@@ -0,0 +1,84 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_small_ctr_vtable;
+ ctx->num_rounds = br_aes_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+uint32_t
+br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[16];
+
+ memcpy(tmp, iv, 12);
+ br_enc32be(tmp + 12, cc ++);
+ br_aes_small_encrypt(ctx->num_rounds, ctx->skey, tmp);
+ if (len <= 16) {
+ xorbuf(buf, tmp, len);
+ break;
+ }
+ xorbuf(buf, tmp, 16);
+ buf += 16;
+ len -= 16;
+ }
+ return cc;
+}
+
+/* see bearssl_block.h */
+const br_block_ctr_class br_aes_small_ctr_vtable = {
+ sizeof(br_aes_small_ctr_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctr_class **, const void *, size_t))
+ &br_aes_small_ctr_init,
+ (uint32_t (*)(const br_block_ctr_class *const *,
+ const void *, uint32_t, void *, size_t))
+ &br_aes_small_ctr_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_small_ctr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_small_ctrcbc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_small_ctrcbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_small_ctrcbc.c (revision 346145)
@@ -0,0 +1,142 @@
+/*
+ * 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"
+
+/* see bearssl_block.h */
+void
+br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_small_ctrcbc_vtable;
+ ctx->num_rounds = br_aes_keysched(ctx->skey, key, len);
+}
+
+static void
+xorbuf(void *dst, const void *src, size_t len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+
+ d = dst;
+ s = src;
+ while (len -- > 0) {
+ *d ++ ^= *s ++;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len)
+{
+ unsigned char *buf, *bctr;
+ uint32_t cc0, cc1, cc2, cc3;
+
+ buf = data;
+ bctr = ctr;
+ cc3 = br_dec32be(bctr + 0);
+ cc2 = br_dec32be(bctr + 4);
+ cc1 = br_dec32be(bctr + 8);
+ cc0 = br_dec32be(bctr + 12);
+ while (len > 0) {
+ unsigned char tmp[16];
+ uint32_t carry;
+
+ br_enc32be(tmp + 0, cc3);
+ br_enc32be(tmp + 4, cc2);
+ br_enc32be(tmp + 8, cc1);
+ br_enc32be(tmp + 12, cc0);
+ br_aes_small_encrypt(ctx->num_rounds, ctx->skey, tmp);
+ xorbuf(buf, tmp, 16);
+ buf += 16;
+ len -= 16;
+ cc0 ++;
+ carry = (~(cc0 | -cc0)) >> 31;
+ cc1 += carry;
+ carry &= (~(cc1 | -cc1)) >> 31;
+ cc2 += carry;
+ carry &= (~(cc2 | -cc2)) >> 31;
+ cc3 += carry;
+ }
+ br_enc32be(bctr + 0, cc3);
+ br_enc32be(bctr + 4, cc2);
+ br_enc32be(bctr + 8, cc1);
+ br_enc32be(bctr + 12, cc0);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len)
+{
+ const unsigned char *buf;
+
+ buf = data;
+ while (len > 0) {
+ xorbuf(cbcmac, buf, 16);
+ br_aes_small_encrypt(ctx->num_rounds, ctx->skey, cbcmac);
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ br_aes_small_ctrcbc_ctr(ctx, ctr, data, len);
+ br_aes_small_ctrcbc_mac(ctx, cbcmac, data, len);
+}
+
+/* see bearssl_block.h */
+void
+br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ br_aes_small_ctrcbc_mac(ctx, cbcmac, data, len);
+ br_aes_small_ctrcbc_ctr(ctx, ctr, data, len);
+}
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable = {
+ sizeof(br_aes_small_ctrcbc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
+ &br_aes_small_ctrcbc_init,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_small_ctrcbc_encrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_small_ctrcbc_decrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, size_t))
+ &br_aes_small_ctrcbc_ctr,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, const void *, size_t))
+ &br_aes_small_ctrcbc_mac
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_small_ctrcbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_small_dec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_small_dec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_small_dec.c (revision 346145)
@@ -0,0 +1,176 @@
+/*
+ * 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"
+
+/*
+ * Inverse S-box.
+ */
+static const unsigned char iS[] = {
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
+ 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
+ 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
+ 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
+ 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
+ 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
+ 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
+ 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
+ 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
+ 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
+ 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
+ 0x55, 0x21, 0x0C, 0x7D
+};
+
+static void
+add_round_key(unsigned *state, const uint32_t *skeys)
+{
+ int i;
+
+ for (i = 0; i < 16; i += 4) {
+ uint32_t k;
+
+ k = *skeys ++;
+ state[i + 0] ^= (unsigned)(k >> 24);
+ state[i + 1] ^= (unsigned)(k >> 16) & 0xFF;
+ state[i + 2] ^= (unsigned)(k >> 8) & 0xFF;
+ state[i + 3] ^= (unsigned)k & 0xFF;
+ }
+}
+
+static void
+inv_sub_bytes(unsigned *state)
+{
+ int i;
+
+ for (i = 0; i < 16; i ++) {
+ state[i] = iS[state[i]];
+ }
+}
+
+static void
+inv_shift_rows(unsigned *state)
+{
+ unsigned tmp;
+
+ tmp = state[13];
+ state[13] = state[9];
+ state[9] = state[5];
+ state[5] = state[1];
+ state[1] = tmp;
+
+ tmp = state[2];
+ state[2] = state[10];
+ state[10] = tmp;
+ tmp = state[6];
+ state[6] = state[14];
+ state[14] = tmp;
+
+ tmp = state[3];
+ state[3] = state[7];
+ state[7] = state[11];
+ state[11] = state[15];
+ state[15] = tmp;
+}
+
+static inline unsigned
+gf256red(unsigned x)
+{
+ unsigned y;
+
+ y = x >> 8;
+ return (x ^ y ^ (y << 1) ^ (y << 3) ^ (y << 4)) & 0xFF;
+}
+
+static void
+inv_mix_columns(unsigned *state)
+{
+ int i;
+
+ for (i = 0; i < 16; i += 4) {
+ unsigned s0, s1, s2, s3;
+ unsigned t0, t1, t2, t3;
+
+ s0 = state[i + 0];
+ s1 = state[i + 1];
+ s2 = state[i + 2];
+ s3 = state[i + 3];
+ t0 = (s0 << 1) ^ (s0 << 2) ^ (s0 << 3)
+ ^ s1 ^ (s1 << 1) ^ (s1 << 3)
+ ^ s2 ^ (s2 << 2) ^ (s2 << 3)
+ ^ s3 ^ (s3 << 3);
+ t1 = s0 ^ (s0 << 3)
+ ^ (s1 << 1) ^ (s1 << 2) ^ (s1 << 3)
+ ^ s2 ^ (s2 << 1) ^ (s2 << 3)
+ ^ s3 ^ (s3 << 2) ^ (s3 << 3);
+ t2 = s0 ^ (s0 << 2) ^ (s0 << 3)
+ ^ s1 ^ (s1 << 3)
+ ^ (s2 << 1) ^ (s2 << 2) ^ (s2 << 3)
+ ^ s3 ^ (s3 << 1) ^ (s3 << 3);
+ t3 = s0 ^ (s0 << 1) ^ (s0 << 3)
+ ^ s1 ^ (s1 << 2) ^ (s1 << 3)
+ ^ s2 ^ (s2 << 3)
+ ^ (s3 << 1) ^ (s3 << 2) ^ (s3 << 3);
+ state[i + 0] = gf256red(t0);
+ state[i + 1] = gf256red(t1);
+ state[i + 2] = gf256red(t2);
+ state[i + 3] = gf256red(t3);
+ }
+}
+
+/* see inner.h */
+void
+br_aes_small_decrypt(unsigned num_rounds, const uint32_t *skey, void *data)
+{
+ unsigned char *buf;
+ unsigned state[16];
+ unsigned u;
+
+ buf = data;
+ for (u = 0; u < 16; u ++) {
+ state[u] = buf[u];
+ }
+ add_round_key(state, skey + (num_rounds << 2));
+ for (u = num_rounds - 1; u > 0; u --) {
+ inv_shift_rows(state);
+ inv_sub_bytes(state);
+ add_round_key(state, skey + (u << 2));
+ inv_mix_columns(state);
+ }
+ inv_shift_rows(state);
+ inv_sub_bytes(state);
+ add_round_key(state, skey);
+ for (u = 0; u < 16; u ++) {
+ buf[u] = state[u];
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_small_dec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_small_enc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_small_enc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_small_enc.c (revision 346145)
@@ -0,0 +1,129 @@
+/*
+ * 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"
+
+#define S br_aes_S
+
+static void
+add_round_key(unsigned *state, const uint32_t *skeys)
+{
+ int i;
+
+ for (i = 0; i < 16; i += 4) {
+ uint32_t k;
+
+ k = *skeys ++;
+ state[i + 0] ^= (unsigned)(k >> 24);
+ state[i + 1] ^= (unsigned)(k >> 16) & 0xFF;
+ state[i + 2] ^= (unsigned)(k >> 8) & 0xFF;
+ state[i + 3] ^= (unsigned)k & 0xFF;
+ }
+}
+
+static void
+sub_bytes(unsigned *state)
+{
+ int i;
+
+ for (i = 0; i < 16; i ++) {
+ state[i] = S[state[i]];
+ }
+}
+
+static void
+shift_rows(unsigned *state)
+{
+ unsigned tmp;
+
+ tmp = state[1];
+ state[1] = state[5];
+ state[5] = state[9];
+ state[9] = state[13];
+ state[13] = tmp;
+
+ tmp = state[2];
+ state[2] = state[10];
+ state[10] = tmp;
+ tmp = state[6];
+ state[6] = state[14];
+ state[14] = tmp;
+
+ tmp = state[15];
+ state[15] = state[11];
+ state[11] = state[7];
+ state[7] = state[3];
+ state[3] = tmp;
+}
+
+static void
+mix_columns(unsigned *state)
+{
+ int i;
+
+ for (i = 0; i < 16; i += 4) {
+ unsigned s0, s1, s2, s3;
+ unsigned t0, t1, t2, t3;
+
+ s0 = state[i + 0];
+ s1 = state[i + 1];
+ s2 = state[i + 2];
+ s3 = state[i + 3];
+ t0 = (s0 << 1) ^ s1 ^ (s1 << 1) ^ s2 ^ s3;
+ t1 = s0 ^ (s1 << 1) ^ s2 ^ (s2 << 1) ^ s3;
+ t2 = s0 ^ s1 ^ (s2 << 1) ^ s3 ^ (s3 << 1);
+ t3 = s0 ^ (s0 << 1) ^ s1 ^ s2 ^ (s3 << 1);
+ state[i + 0] = t0 ^ ((unsigned)(-(int)(t0 >> 8)) & 0x11B);
+ state[i + 1] = t1 ^ ((unsigned)(-(int)(t1 >> 8)) & 0x11B);
+ state[i + 2] = t2 ^ ((unsigned)(-(int)(t2 >> 8)) & 0x11B);
+ state[i + 3] = t3 ^ ((unsigned)(-(int)(t3 >> 8)) & 0x11B);
+ }
+}
+
+/* see inner.h */
+void
+br_aes_small_encrypt(unsigned num_rounds, const uint32_t *skey, void *data)
+{
+ unsigned char *buf;
+ unsigned state[16];
+ unsigned u;
+
+ buf = data;
+ for (u = 0; u < 16; u ++) {
+ state[u] = buf[u];
+ }
+ add_round_key(state, skey);
+ for (u = 1; u < num_rounds; u ++) {
+ sub_bytes(state);
+ shift_rows(state);
+ mix_columns(state);
+ add_round_key(state, skey + (u << 2));
+ }
+ sub_bytes(state);
+ shift_rows(state);
+ add_round_key(state, skey + (num_rounds << 2));
+ for (u = 0; u < 16; u ++) {
+ buf[u] = state[u];
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_small_enc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_x86ni.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_x86ni.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_x86ni.c (revision 346145)
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+/*
+ * This code contains the AES key schedule implementation using the
+ * AES-NI opcodes.
+ */
+
+#if BR_AES_X86NI
+
+/* see inner.h */
+int
+br_aes_x86ni_supported(void)
+{
+ /*
+ * Bit mask for features in ECX:
+ * 19 SSE4.1 (used for _mm_insert_epi32(), for AES-CTR)
+ * 25 AES-NI
+ */
+ return br_cpuid(0, 0, 0x02080000, 0);
+}
+
+BR_TARGETS_X86_UP
+
+BR_TARGET("sse2,aes")
+static inline __m128i
+expand_step128(__m128i k, __m128i k2)
+{
+ k = _mm_xor_si128(k, _mm_slli_si128(k, 4));
+ k = _mm_xor_si128(k, _mm_slli_si128(k, 4));
+ k = _mm_xor_si128(k, _mm_slli_si128(k, 4));
+ k2 = _mm_shuffle_epi32(k2, 0xFF);
+ return _mm_xor_si128(k, k2);
+}
+
+BR_TARGET("sse2,aes")
+static inline void
+expand_step192(__m128i *t1, __m128i *t2, __m128i *t3)
+{
+ __m128i t4;
+
+ *t2 = _mm_shuffle_epi32(*t2, 0x55);
+ t4 = _mm_slli_si128(*t1, 0x4);
+ *t1 = _mm_xor_si128(*t1, t4);
+ t4 = _mm_slli_si128(t4, 0x4);
+ *t1 = _mm_xor_si128(*t1, t4);
+ t4 = _mm_slli_si128(t4, 0x4);
+ *t1 = _mm_xor_si128(*t1, t4);
+ *t1 = _mm_xor_si128(*t1, *t2);
+ *t2 = _mm_shuffle_epi32(*t1, 0xFF);
+ t4 = _mm_slli_si128(*t3, 0x4);
+ *t3 = _mm_xor_si128(*t3, t4);
+ *t3 = _mm_xor_si128(*t3, *t2);
+}
+
+BR_TARGET("sse2,aes")
+static inline void
+expand_step256_1(__m128i *t1, __m128i *t2)
+{
+ __m128i t4;
+
+ *t2 = _mm_shuffle_epi32(*t2, 0xFF);
+ t4 = _mm_slli_si128(*t1, 0x4);
+ *t1 = _mm_xor_si128(*t1, t4);
+ t4 = _mm_slli_si128(t4, 0x4);
+ *t1 = _mm_xor_si128(*t1, t4);
+ t4 = _mm_slli_si128(t4, 0x4);
+ *t1 = _mm_xor_si128(*t1, t4);
+ *t1 = _mm_xor_si128(*t1, *t2);
+}
+
+BR_TARGET("sse2,aes")
+static inline void
+expand_step256_2(__m128i *t1, __m128i *t3)
+{
+ __m128i t2, t4;
+
+ t4 = _mm_aeskeygenassist_si128(*t1, 0x0);
+ t2 = _mm_shuffle_epi32(t4, 0xAA);
+ t4 = _mm_slli_si128(*t3, 0x4);
+ *t3 = _mm_xor_si128(*t3, t4);
+ t4 = _mm_slli_si128(t4, 0x4);
+ *t3 = _mm_xor_si128(*t3, t4);
+ t4 = _mm_slli_si128(t4, 0x4);
+ *t3 = _mm_xor_si128(*t3, t4);
+ *t3 = _mm_xor_si128(*t3, t2);
+}
+
+/*
+ * Perform key schedule for AES, encryption direction. Subkeys are written
+ * in sk[], and the number of rounds is returned. Key length MUST be 16,
+ * 24 or 32 bytes.
+ */
+BR_TARGET("sse2,aes")
+static unsigned
+x86ni_keysched(__m128i *sk, const void *key, size_t len)
+{
+ const unsigned char *kb;
+
+#define KEXP128(k, i, rcon) do { \
+ k = expand_step128(k, _mm_aeskeygenassist_si128(k, rcon)); \
+ sk[i] = k; \
+ } while (0)
+
+#define KEXP192(i, rcon1, rcon2) do { \
+ sk[(i) + 0] = t1; \
+ sk[(i) + 1] = t3; \
+ t2 = _mm_aeskeygenassist_si128(t3, rcon1); \
+ expand_step192(&t1, &t2, &t3); \
+ sk[(i) + 1] = _mm_castpd_si128(_mm_shuffle_pd( \
+ _mm_castsi128_pd(sk[(i) + 1]), \
+ _mm_castsi128_pd(t1), 0)); \
+ sk[(i) + 2] = _mm_castpd_si128(_mm_shuffle_pd( \
+ _mm_castsi128_pd(t1), \
+ _mm_castsi128_pd(t3), 1)); \
+ t2 = _mm_aeskeygenassist_si128(t3, rcon2); \
+ expand_step192(&t1, &t2, &t3); \
+ } while (0)
+
+#define KEXP256(i, rcon) do { \
+ sk[(i) + 0] = t3; \
+ t2 = _mm_aeskeygenassist_si128(t3, rcon); \
+ expand_step256_1(&t1, &t2); \
+ sk[(i) + 1] = t1; \
+ expand_step256_2(&t1, &t3); \
+ } while (0)
+
+ kb = key;
+ switch (len) {
+ __m128i t1, t2, t3;
+
+ case 16:
+ t1 = _mm_loadu_si128((const void *)kb);
+ sk[0] = t1;
+ KEXP128(t1, 1, 0x01);
+ KEXP128(t1, 2, 0x02);
+ KEXP128(t1, 3, 0x04);
+ KEXP128(t1, 4, 0x08);
+ KEXP128(t1, 5, 0x10);
+ KEXP128(t1, 6, 0x20);
+ KEXP128(t1, 7, 0x40);
+ KEXP128(t1, 8, 0x80);
+ KEXP128(t1, 9, 0x1B);
+ KEXP128(t1, 10, 0x36);
+ return 10;
+
+ case 24:
+ t1 = _mm_loadu_si128((const void *)kb);
+ t3 = _mm_loadu_si128((const void *)(kb + 8));
+ t3 = _mm_shuffle_epi32(t3, 0x4E);
+ KEXP192(0, 0x01, 0x02);
+ KEXP192(3, 0x04, 0x08);
+ KEXP192(6, 0x10, 0x20);
+ KEXP192(9, 0x40, 0x80);
+ sk[12] = t1;
+ return 12;
+
+ case 32:
+ t1 = _mm_loadu_si128((const void *)kb);
+ t3 = _mm_loadu_si128((const void *)(kb + 16));
+ sk[0] = t1;
+ KEXP256( 1, 0x01);
+ KEXP256( 3, 0x02);
+ KEXP256( 5, 0x04);
+ KEXP256( 7, 0x08);
+ KEXP256( 9, 0x10);
+ KEXP256(11, 0x20);
+ sk[13] = t3;
+ t2 = _mm_aeskeygenassist_si128(t3, 0x40);
+ expand_step256_1(&t1, &t2);
+ sk[14] = t1;
+ return 14;
+
+ default:
+ return 0;
+ }
+
+#undef KEXP128
+#undef KEXP192
+#undef KEXP256
+}
+
+/* see inner.h */
+BR_TARGET("sse2,aes")
+unsigned
+br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len)
+{
+ __m128i sk[15];
+ unsigned num_rounds;
+
+ num_rounds = x86ni_keysched(sk, key, len);
+ memcpy(skni, sk, (num_rounds + 1) << 4);
+ return num_rounds;
+}
+
+/* see inner.h */
+BR_TARGET("sse2,aes")
+unsigned
+br_aes_x86ni_keysched_dec(unsigned char *skni, const void *key, size_t len)
+{
+ __m128i sk[15];
+ unsigned u, num_rounds;
+
+ num_rounds = x86ni_keysched(sk, key, len);
+ _mm_storeu_si128((void *)skni, sk[num_rounds]);
+ for (u = 1; u < num_rounds; u ++) {
+ _mm_storeu_si128((void *)(skni + (u << 4)),
+ _mm_aesimc_si128(sk[num_rounds - u]));
+ }
+ _mm_storeu_si128((void *)(skni + (num_rounds << 4)), sk[0]);
+ return num_rounds;
+}
+
+BR_TARGETS_X86_DOWN
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_x86ni.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcdec.c (revision 346145)
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+#if BR_AES_X86NI
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class *
+br_aes_x86ni_cbcdec_get_vtable(void)
+{
+ return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcdec_vtable : NULL;
+}
+
+/* see bearssl_block.h */
+void
+br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_x86ni_cbcdec_vtable;
+ ctx->num_rounds = br_aes_x86ni_keysched_dec(ctx->skey.skni, key, len);
+}
+
+BR_TARGETS_X86_UP
+
+/* see bearssl_block.h */
+BR_TARGET("sse2,aes")
+void
+br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned num_rounds;
+ __m128i sk[15], ivx;
+ unsigned u;
+
+ buf = data;
+ ivx = _mm_loadu_si128(iv);
+ num_rounds = ctx->num_rounds;
+ for (u = 0; u <= num_rounds; u ++) {
+ sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
+ }
+ while (len > 0) {
+ __m128i x0, x1, x2, x3, e0, e1, e2, e3;
+
+ x0 = _mm_loadu_si128((void *)(buf + 0));
+ if (len >= 64) {
+ x1 = _mm_loadu_si128((void *)(buf + 16));
+ x2 = _mm_loadu_si128((void *)(buf + 32));
+ x3 = _mm_loadu_si128((void *)(buf + 48));
+ } else {
+ x0 = _mm_loadu_si128((void *)(buf + 0));
+ if (len >= 32) {
+ x1 = _mm_loadu_si128((void *)(buf + 16));
+ if (len >= 48) {
+ x2 = _mm_loadu_si128(
+ (void *)(buf + 32));
+ x3 = x2;
+ } else {
+ x2 = x0;
+ x3 = x1;
+ }
+ } else {
+ x1 = x0;
+ x2 = x0;
+ x3 = x0;
+ }
+ }
+ e0 = x0;
+ e1 = x1;
+ e2 = x2;
+ e3 = x3;
+ x0 = _mm_xor_si128(x0, sk[0]);
+ x1 = _mm_xor_si128(x1, sk[0]);
+ x2 = _mm_xor_si128(x2, sk[0]);
+ x3 = _mm_xor_si128(x3, sk[0]);
+ x0 = _mm_aesdec_si128(x0, sk[1]);
+ x1 = _mm_aesdec_si128(x1, sk[1]);
+ x2 = _mm_aesdec_si128(x2, sk[1]);
+ x3 = _mm_aesdec_si128(x3, sk[1]);
+ x0 = _mm_aesdec_si128(x0, sk[2]);
+ x1 = _mm_aesdec_si128(x1, sk[2]);
+ x2 = _mm_aesdec_si128(x2, sk[2]);
+ x3 = _mm_aesdec_si128(x3, sk[2]);
+ x0 = _mm_aesdec_si128(x0, sk[3]);
+ x1 = _mm_aesdec_si128(x1, sk[3]);
+ x2 = _mm_aesdec_si128(x2, sk[3]);
+ x3 = _mm_aesdec_si128(x3, sk[3]);
+ x0 = _mm_aesdec_si128(x0, sk[4]);
+ x1 = _mm_aesdec_si128(x1, sk[4]);
+ x2 = _mm_aesdec_si128(x2, sk[4]);
+ x3 = _mm_aesdec_si128(x3, sk[4]);
+ x0 = _mm_aesdec_si128(x0, sk[5]);
+ x1 = _mm_aesdec_si128(x1, sk[5]);
+ x2 = _mm_aesdec_si128(x2, sk[5]);
+ x3 = _mm_aesdec_si128(x3, sk[5]);
+ x0 = _mm_aesdec_si128(x0, sk[6]);
+ x1 = _mm_aesdec_si128(x1, sk[6]);
+ x2 = _mm_aesdec_si128(x2, sk[6]);
+ x3 = _mm_aesdec_si128(x3, sk[6]);
+ x0 = _mm_aesdec_si128(x0, sk[7]);
+ x1 = _mm_aesdec_si128(x1, sk[7]);
+ x2 = _mm_aesdec_si128(x2, sk[7]);
+ x3 = _mm_aesdec_si128(x3, sk[7]);
+ x0 = _mm_aesdec_si128(x0, sk[8]);
+ x1 = _mm_aesdec_si128(x1, sk[8]);
+ x2 = _mm_aesdec_si128(x2, sk[8]);
+ x3 = _mm_aesdec_si128(x3, sk[8]);
+ x0 = _mm_aesdec_si128(x0, sk[9]);
+ x1 = _mm_aesdec_si128(x1, sk[9]);
+ x2 = _mm_aesdec_si128(x2, sk[9]);
+ x3 = _mm_aesdec_si128(x3, sk[9]);
+ if (num_rounds == 10) {
+ x0 = _mm_aesdeclast_si128(x0, sk[10]);
+ x1 = _mm_aesdeclast_si128(x1, sk[10]);
+ x2 = _mm_aesdeclast_si128(x2, sk[10]);
+ x3 = _mm_aesdeclast_si128(x3, sk[10]);
+ } else if (num_rounds == 12) {
+ x0 = _mm_aesdec_si128(x0, sk[10]);
+ x1 = _mm_aesdec_si128(x1, sk[10]);
+ x2 = _mm_aesdec_si128(x2, sk[10]);
+ x3 = _mm_aesdec_si128(x3, sk[10]);
+ x0 = _mm_aesdec_si128(x0, sk[11]);
+ x1 = _mm_aesdec_si128(x1, sk[11]);
+ x2 = _mm_aesdec_si128(x2, sk[11]);
+ x3 = _mm_aesdec_si128(x3, sk[11]);
+ x0 = _mm_aesdeclast_si128(x0, sk[12]);
+ x1 = _mm_aesdeclast_si128(x1, sk[12]);
+ x2 = _mm_aesdeclast_si128(x2, sk[12]);
+ x3 = _mm_aesdeclast_si128(x3, sk[12]);
+ } else {
+ x0 = _mm_aesdec_si128(x0, sk[10]);
+ x1 = _mm_aesdec_si128(x1, sk[10]);
+ x2 = _mm_aesdec_si128(x2, sk[10]);
+ x3 = _mm_aesdec_si128(x3, sk[10]);
+ x0 = _mm_aesdec_si128(x0, sk[11]);
+ x1 = _mm_aesdec_si128(x1, sk[11]);
+ x2 = _mm_aesdec_si128(x2, sk[11]);
+ x3 = _mm_aesdec_si128(x3, sk[11]);
+ x0 = _mm_aesdec_si128(x0, sk[12]);
+ x1 = _mm_aesdec_si128(x1, sk[12]);
+ x2 = _mm_aesdec_si128(x2, sk[12]);
+ x3 = _mm_aesdec_si128(x3, sk[12]);
+ x0 = _mm_aesdec_si128(x0, sk[13]);
+ x1 = _mm_aesdec_si128(x1, sk[13]);
+ x2 = _mm_aesdec_si128(x2, sk[13]);
+ x3 = _mm_aesdec_si128(x3, sk[13]);
+ x0 = _mm_aesdeclast_si128(x0, sk[14]);
+ x1 = _mm_aesdeclast_si128(x1, sk[14]);
+ x2 = _mm_aesdeclast_si128(x2, sk[14]);
+ x3 = _mm_aesdeclast_si128(x3, sk[14]);
+ }
+ x0 = _mm_xor_si128(x0, ivx);
+ x1 = _mm_xor_si128(x1, e0);
+ x2 = _mm_xor_si128(x2, e1);
+ x3 = _mm_xor_si128(x3, e2);
+ ivx = e3;
+ _mm_storeu_si128((void *)(buf + 0), x0);
+ if (len >= 64) {
+ _mm_storeu_si128((void *)(buf + 16), x1);
+ _mm_storeu_si128((void *)(buf + 32), x2);
+ _mm_storeu_si128((void *)(buf + 48), x3);
+ buf += 64;
+ len -= 64;
+ } else {
+ if (len >= 32) {
+ _mm_storeu_si128((void *)(buf + 16), x1);
+ if (len >= 48) {
+ _mm_storeu_si128(
+ (void *)(buf + 32), x2);
+ }
+ }
+ break;
+ }
+ }
+ _mm_storeu_si128(iv, ivx);
+}
+
+BR_TARGETS_X86_DOWN
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable = {
+ sizeof(br_aes_x86ni_cbcdec_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_aes_x86ni_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_aes_x86ni_cbcdec_run
+};
+
+#else
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class *
+br_aes_x86ni_cbcdec_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcenc.c (revision 346145)
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+#if BR_AES_X86NI
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class *
+br_aes_x86ni_cbcenc_get_vtable(void)
+{
+ return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcenc_vtable : NULL;
+}
+
+/* see bearssl_block.h */
+void
+br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_x86ni_cbcenc_vtable;
+ ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len);
+}
+
+BR_TARGETS_X86_UP
+
+/* see bearssl_block.h */
+BR_TARGET("sse2,aes")
+void
+br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned num_rounds;
+ __m128i sk[15], ivx;
+ unsigned u;
+
+ buf = data;
+ ivx = _mm_loadu_si128(iv);
+ num_rounds = ctx->num_rounds;
+ for (u = 0; u <= num_rounds; u ++) {
+ sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
+ }
+ while (len > 0) {
+ __m128i x;
+
+ x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx);
+ x = _mm_xor_si128(x, sk[0]);
+ x = _mm_aesenc_si128(x, sk[1]);
+ x = _mm_aesenc_si128(x, sk[2]);
+ x = _mm_aesenc_si128(x, sk[3]);
+ x = _mm_aesenc_si128(x, sk[4]);
+ x = _mm_aesenc_si128(x, sk[5]);
+ x = _mm_aesenc_si128(x, sk[6]);
+ x = _mm_aesenc_si128(x, sk[7]);
+ x = _mm_aesenc_si128(x, sk[8]);
+ x = _mm_aesenc_si128(x, sk[9]);
+ if (num_rounds == 10) {
+ x = _mm_aesenclast_si128(x, sk[10]);
+ } else if (num_rounds == 12) {
+ x = _mm_aesenc_si128(x, sk[10]);
+ x = _mm_aesenc_si128(x, sk[11]);
+ x = _mm_aesenclast_si128(x, sk[12]);
+ } else {
+ x = _mm_aesenc_si128(x, sk[10]);
+ x = _mm_aesenc_si128(x, sk[11]);
+ x = _mm_aesenc_si128(x, sk[12]);
+ x = _mm_aesenc_si128(x, sk[13]);
+ x = _mm_aesenclast_si128(x, sk[14]);
+ }
+ ivx = x;
+ _mm_storeu_si128((void *)buf, x);
+ buf += 16;
+ len -= 16;
+ }
+ _mm_storeu_si128(iv, ivx);
+}
+
+BR_TARGETS_X86_DOWN
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable = {
+ sizeof(br_aes_x86ni_cbcenc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_aes_x86ni_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_aes_x86ni_cbcenc_run
+};
+
+#else
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class *
+br_aes_x86ni_cbcenc_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctr.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctr.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctr.c (revision 346145)
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+#if BR_AES_X86NI
+
+/* see bearssl_block.h */
+const br_block_ctr_class *
+br_aes_x86ni_ctr_get_vtable(void)
+{
+ return br_aes_x86ni_supported() ? &br_aes_x86ni_ctr_vtable : NULL;
+}
+
+/* see bearssl_block.h */
+void
+br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_x86ni_ctr_vtable;
+ ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len);
+}
+
+BR_TARGETS_X86_UP
+
+/* see bearssl_block.h */
+BR_TARGET("sse2,sse4.1,aes")
+uint32_t
+br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned char ivbuf[16];
+ unsigned num_rounds;
+ __m128i sk[15];
+ __m128i ivx;
+ unsigned u;
+
+ buf = data;
+ memcpy(ivbuf, iv, 12);
+ num_rounds = ctx->num_rounds;
+ for (u = 0; u <= num_rounds; u ++) {
+ sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
+ }
+ ivx = _mm_loadu_si128((void *)ivbuf);
+ while (len > 0) {
+ __m128i x0, x1, x2, x3;
+
+ x0 = _mm_insert_epi32(ivx, br_bswap32(cc + 0), 3);
+ x1 = _mm_insert_epi32(ivx, br_bswap32(cc + 1), 3);
+ x2 = _mm_insert_epi32(ivx, br_bswap32(cc + 2), 3);
+ x3 = _mm_insert_epi32(ivx, br_bswap32(cc + 3), 3);
+ x0 = _mm_xor_si128(x0, sk[0]);
+ x1 = _mm_xor_si128(x1, sk[0]);
+ x2 = _mm_xor_si128(x2, sk[0]);
+ x3 = _mm_xor_si128(x3, sk[0]);
+ x0 = _mm_aesenc_si128(x0, sk[1]);
+ x1 = _mm_aesenc_si128(x1, sk[1]);
+ x2 = _mm_aesenc_si128(x2, sk[1]);
+ x3 = _mm_aesenc_si128(x3, sk[1]);
+ x0 = _mm_aesenc_si128(x0, sk[2]);
+ x1 = _mm_aesenc_si128(x1, sk[2]);
+ x2 = _mm_aesenc_si128(x2, sk[2]);
+ x3 = _mm_aesenc_si128(x3, sk[2]);
+ x0 = _mm_aesenc_si128(x0, sk[3]);
+ x1 = _mm_aesenc_si128(x1, sk[3]);
+ x2 = _mm_aesenc_si128(x2, sk[3]);
+ x3 = _mm_aesenc_si128(x3, sk[3]);
+ x0 = _mm_aesenc_si128(x0, sk[4]);
+ x1 = _mm_aesenc_si128(x1, sk[4]);
+ x2 = _mm_aesenc_si128(x2, sk[4]);
+ x3 = _mm_aesenc_si128(x3, sk[4]);
+ x0 = _mm_aesenc_si128(x0, sk[5]);
+ x1 = _mm_aesenc_si128(x1, sk[5]);
+ x2 = _mm_aesenc_si128(x2, sk[5]);
+ x3 = _mm_aesenc_si128(x3, sk[5]);
+ x0 = _mm_aesenc_si128(x0, sk[6]);
+ x1 = _mm_aesenc_si128(x1, sk[6]);
+ x2 = _mm_aesenc_si128(x2, sk[6]);
+ x3 = _mm_aesenc_si128(x3, sk[6]);
+ x0 = _mm_aesenc_si128(x0, sk[7]);
+ x1 = _mm_aesenc_si128(x1, sk[7]);
+ x2 = _mm_aesenc_si128(x2, sk[7]);
+ x3 = _mm_aesenc_si128(x3, sk[7]);
+ x0 = _mm_aesenc_si128(x0, sk[8]);
+ x1 = _mm_aesenc_si128(x1, sk[8]);
+ x2 = _mm_aesenc_si128(x2, sk[8]);
+ x3 = _mm_aesenc_si128(x3, sk[8]);
+ x0 = _mm_aesenc_si128(x0, sk[9]);
+ x1 = _mm_aesenc_si128(x1, sk[9]);
+ x2 = _mm_aesenc_si128(x2, sk[9]);
+ x3 = _mm_aesenc_si128(x3, sk[9]);
+ if (num_rounds == 10) {
+ x0 = _mm_aesenclast_si128(x0, sk[10]);
+ x1 = _mm_aesenclast_si128(x1, sk[10]);
+ x2 = _mm_aesenclast_si128(x2, sk[10]);
+ x3 = _mm_aesenclast_si128(x3, sk[10]);
+ } else if (num_rounds == 12) {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x2 = _mm_aesenc_si128(x2, sk[10]);
+ x3 = _mm_aesenc_si128(x3, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x2 = _mm_aesenc_si128(x2, sk[11]);
+ x3 = _mm_aesenc_si128(x3, sk[11]);
+ x0 = _mm_aesenclast_si128(x0, sk[12]);
+ x1 = _mm_aesenclast_si128(x1, sk[12]);
+ x2 = _mm_aesenclast_si128(x2, sk[12]);
+ x3 = _mm_aesenclast_si128(x3, sk[12]);
+ } else {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x2 = _mm_aesenc_si128(x2, sk[10]);
+ x3 = _mm_aesenc_si128(x3, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x2 = _mm_aesenc_si128(x2, sk[11]);
+ x3 = _mm_aesenc_si128(x3, sk[11]);
+ x0 = _mm_aesenc_si128(x0, sk[12]);
+ x1 = _mm_aesenc_si128(x1, sk[12]);
+ x2 = _mm_aesenc_si128(x2, sk[12]);
+ x3 = _mm_aesenc_si128(x3, sk[12]);
+ x0 = _mm_aesenc_si128(x0, sk[13]);
+ x1 = _mm_aesenc_si128(x1, sk[13]);
+ x2 = _mm_aesenc_si128(x2, sk[13]);
+ x3 = _mm_aesenc_si128(x3, sk[13]);
+ x0 = _mm_aesenclast_si128(x0, sk[14]);
+ x1 = _mm_aesenclast_si128(x1, sk[14]);
+ x2 = _mm_aesenclast_si128(x2, sk[14]);
+ x3 = _mm_aesenclast_si128(x3, sk[14]);
+ }
+ if (len >= 64) {
+ x0 = _mm_xor_si128(x0,
+ _mm_loadu_si128((void *)(buf + 0)));
+ x1 = _mm_xor_si128(x1,
+ _mm_loadu_si128((void *)(buf + 16)));
+ x2 = _mm_xor_si128(x2,
+ _mm_loadu_si128((void *)(buf + 32)));
+ x3 = _mm_xor_si128(x3,
+ _mm_loadu_si128((void *)(buf + 48)));
+ _mm_storeu_si128((void *)(buf + 0), x0);
+ _mm_storeu_si128((void *)(buf + 16), x1);
+ _mm_storeu_si128((void *)(buf + 32), x2);
+ _mm_storeu_si128((void *)(buf + 48), x3);
+ buf += 64;
+ len -= 64;
+ cc += 4;
+ } else {
+ unsigned char tmp[64];
+
+ _mm_storeu_si128((void *)(tmp + 0), x0);
+ _mm_storeu_si128((void *)(tmp + 16), x1);
+ _mm_storeu_si128((void *)(tmp + 32), x2);
+ _mm_storeu_si128((void *)(tmp + 48), x3);
+ for (u = 0; u < len; u ++) {
+ buf[u] ^= tmp[u];
+ }
+ cc += (uint32_t)len >> 4;
+ break;
+ }
+ }
+ return cc;
+}
+
+BR_TARGETS_X86_DOWN
+
+/* see bearssl_block.h */
+const br_block_ctr_class br_aes_x86ni_ctr_vtable = {
+ sizeof(br_aes_x86ni_ctr_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctr_class **, const void *, size_t))
+ &br_aes_x86ni_ctr_init,
+ (uint32_t (*)(const br_block_ctr_class *const *,
+ const void *, uint32_t, void *, size_t))
+ &br_aes_x86ni_ctr_run
+};
+
+#else
+
+/* see bearssl_block.h */
+const br_block_ctr_class *
+br_aes_x86ni_ctr_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctrcbc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctrcbc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctrcbc.c (revision 346145)
@@ -0,0 +1,596 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+#if BR_AES_X86NI
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class *
+br_aes_x86ni_ctrcbc_get_vtable(void)
+{
+ return br_aes_x86ni_supported() ? &br_aes_x86ni_ctrcbc_vtable : NULL;
+}
+
+/* see bearssl_block.h */
+void
+br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_aes_x86ni_ctrcbc_vtable;
+ ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len);
+}
+
+BR_TARGETS_X86_UP
+
+/* see bearssl_block.h */
+BR_TARGET("sse2,sse4.1,aes")
+void
+br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *ctr, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned num_rounds;
+ __m128i sk[15];
+ __m128i ivx0, ivx1, ivx2, ivx3;
+ __m128i erev, zero, one, four, notthree;
+ unsigned u;
+
+ buf = data;
+ num_rounds = ctx->num_rounds;
+ for (u = 0; u <= num_rounds; u ++) {
+ sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
+ }
+
+ /*
+ * Some SSE2 constants.
+ */
+ erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15);
+ zero = _mm_setzero_si128();
+ one = _mm_set_epi64x(0, 1);
+ four = _mm_set_epi64x(0, 4);
+ notthree = _mm_sub_epi64(zero, four);
+
+ /*
+ * Decode the counter in big-endian and pre-increment the other
+ * three counters.
+ */
+ ivx0 = _mm_shuffle_epi8(_mm_loadu_si128((void *)ctr), erev);
+ ivx1 = _mm_add_epi64(ivx0, one);
+ ivx1 = _mm_sub_epi64(ivx1,
+ _mm_slli_si128(_mm_cmpeq_epi64(ivx1, zero), 8));
+ ivx2 = _mm_add_epi64(ivx1, one);
+ ivx2 = _mm_sub_epi64(ivx2,
+ _mm_slli_si128(_mm_cmpeq_epi64(ivx2, zero), 8));
+ ivx3 = _mm_add_epi64(ivx2, one);
+ ivx3 = _mm_sub_epi64(ivx3,
+ _mm_slli_si128(_mm_cmpeq_epi64(ivx3, zero), 8));
+ while (len > 0) {
+ __m128i x0, x1, x2, x3;
+
+ /*
+ * Load counter values; we need to byteswap them because
+ * the specification says that they use big-endian.
+ */
+ x0 = _mm_shuffle_epi8(ivx0, erev);
+ x1 = _mm_shuffle_epi8(ivx1, erev);
+ x2 = _mm_shuffle_epi8(ivx2, erev);
+ x3 = _mm_shuffle_epi8(ivx3, erev);
+
+ x0 = _mm_xor_si128(x0, sk[0]);
+ x1 = _mm_xor_si128(x1, sk[0]);
+ x2 = _mm_xor_si128(x2, sk[0]);
+ x3 = _mm_xor_si128(x3, sk[0]);
+ x0 = _mm_aesenc_si128(x0, sk[1]);
+ x1 = _mm_aesenc_si128(x1, sk[1]);
+ x2 = _mm_aesenc_si128(x2, sk[1]);
+ x3 = _mm_aesenc_si128(x3, sk[1]);
+ x0 = _mm_aesenc_si128(x0, sk[2]);
+ x1 = _mm_aesenc_si128(x1, sk[2]);
+ x2 = _mm_aesenc_si128(x2, sk[2]);
+ x3 = _mm_aesenc_si128(x3, sk[2]);
+ x0 = _mm_aesenc_si128(x0, sk[3]);
+ x1 = _mm_aesenc_si128(x1, sk[3]);
+ x2 = _mm_aesenc_si128(x2, sk[3]);
+ x3 = _mm_aesenc_si128(x3, sk[3]);
+ x0 = _mm_aesenc_si128(x0, sk[4]);
+ x1 = _mm_aesenc_si128(x1, sk[4]);
+ x2 = _mm_aesenc_si128(x2, sk[4]);
+ x3 = _mm_aesenc_si128(x3, sk[4]);
+ x0 = _mm_aesenc_si128(x0, sk[5]);
+ x1 = _mm_aesenc_si128(x1, sk[5]);
+ x2 = _mm_aesenc_si128(x2, sk[5]);
+ x3 = _mm_aesenc_si128(x3, sk[5]);
+ x0 = _mm_aesenc_si128(x0, sk[6]);
+ x1 = _mm_aesenc_si128(x1, sk[6]);
+ x2 = _mm_aesenc_si128(x2, sk[6]);
+ x3 = _mm_aesenc_si128(x3, sk[6]);
+ x0 = _mm_aesenc_si128(x0, sk[7]);
+ x1 = _mm_aesenc_si128(x1, sk[7]);
+ x2 = _mm_aesenc_si128(x2, sk[7]);
+ x3 = _mm_aesenc_si128(x3, sk[7]);
+ x0 = _mm_aesenc_si128(x0, sk[8]);
+ x1 = _mm_aesenc_si128(x1, sk[8]);
+ x2 = _mm_aesenc_si128(x2, sk[8]);
+ x3 = _mm_aesenc_si128(x3, sk[8]);
+ x0 = _mm_aesenc_si128(x0, sk[9]);
+ x1 = _mm_aesenc_si128(x1, sk[9]);
+ x2 = _mm_aesenc_si128(x2, sk[9]);
+ x3 = _mm_aesenc_si128(x3, sk[9]);
+ if (num_rounds == 10) {
+ x0 = _mm_aesenclast_si128(x0, sk[10]);
+ x1 = _mm_aesenclast_si128(x1, sk[10]);
+ x2 = _mm_aesenclast_si128(x2, sk[10]);
+ x3 = _mm_aesenclast_si128(x3, sk[10]);
+ } else if (num_rounds == 12) {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x2 = _mm_aesenc_si128(x2, sk[10]);
+ x3 = _mm_aesenc_si128(x3, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x2 = _mm_aesenc_si128(x2, sk[11]);
+ x3 = _mm_aesenc_si128(x3, sk[11]);
+ x0 = _mm_aesenclast_si128(x0, sk[12]);
+ x1 = _mm_aesenclast_si128(x1, sk[12]);
+ x2 = _mm_aesenclast_si128(x2, sk[12]);
+ x3 = _mm_aesenclast_si128(x3, sk[12]);
+ } else {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x2 = _mm_aesenc_si128(x2, sk[10]);
+ x3 = _mm_aesenc_si128(x3, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x2 = _mm_aesenc_si128(x2, sk[11]);
+ x3 = _mm_aesenc_si128(x3, sk[11]);
+ x0 = _mm_aesenc_si128(x0, sk[12]);
+ x1 = _mm_aesenc_si128(x1, sk[12]);
+ x2 = _mm_aesenc_si128(x2, sk[12]);
+ x3 = _mm_aesenc_si128(x3, sk[12]);
+ x0 = _mm_aesenc_si128(x0, sk[13]);
+ x1 = _mm_aesenc_si128(x1, sk[13]);
+ x2 = _mm_aesenc_si128(x2, sk[13]);
+ x3 = _mm_aesenc_si128(x3, sk[13]);
+ x0 = _mm_aesenclast_si128(x0, sk[14]);
+ x1 = _mm_aesenclast_si128(x1, sk[14]);
+ x2 = _mm_aesenclast_si128(x2, sk[14]);
+ x3 = _mm_aesenclast_si128(x3, sk[14]);
+ }
+ if (len >= 64) {
+ x0 = _mm_xor_si128(x0,
+ _mm_loadu_si128((void *)(buf + 0)));
+ x1 = _mm_xor_si128(x1,
+ _mm_loadu_si128((void *)(buf + 16)));
+ x2 = _mm_xor_si128(x2,
+ _mm_loadu_si128((void *)(buf + 32)));
+ x3 = _mm_xor_si128(x3,
+ _mm_loadu_si128((void *)(buf + 48)));
+ _mm_storeu_si128((void *)(buf + 0), x0);
+ _mm_storeu_si128((void *)(buf + 16), x1);
+ _mm_storeu_si128((void *)(buf + 32), x2);
+ _mm_storeu_si128((void *)(buf + 48), x3);
+ buf += 64;
+ len -= 64;
+ } else {
+ unsigned char tmp[64];
+
+ _mm_storeu_si128((void *)(tmp + 0), x0);
+ _mm_storeu_si128((void *)(tmp + 16), x1);
+ _mm_storeu_si128((void *)(tmp + 32), x2);
+ _mm_storeu_si128((void *)(tmp + 48), x3);
+ for (u = 0; u < len; u ++) {
+ buf[u] ^= tmp[u];
+ }
+ switch (len) {
+ case 16:
+ ivx0 = ivx1;
+ break;
+ case 32:
+ ivx0 = ivx2;
+ break;
+ case 48:
+ ivx0 = ivx3;
+ break;
+ }
+ break;
+ }
+
+ /*
+ * Add 4 to each counter value. For carry propagation
+ * into the upper 64-bit words, we would need to compare
+ * the results with 4, but SSE2+ has only _signed_
+ * comparisons. Instead, we mask out the low two bits,
+ * and check whether the remaining bits are zero.
+ */
+ ivx0 = _mm_add_epi64(ivx0, four);
+ ivx1 = _mm_add_epi64(ivx1, four);
+ ivx2 = _mm_add_epi64(ivx2, four);
+ ivx3 = _mm_add_epi64(ivx3, four);
+ ivx0 = _mm_sub_epi64(ivx0,
+ _mm_slli_si128(_mm_cmpeq_epi64(
+ _mm_and_si128(ivx0, notthree), zero), 8));
+ ivx1 = _mm_sub_epi64(ivx1,
+ _mm_slli_si128(_mm_cmpeq_epi64(
+ _mm_and_si128(ivx1, notthree), zero), 8));
+ ivx2 = _mm_sub_epi64(ivx2,
+ _mm_slli_si128(_mm_cmpeq_epi64(
+ _mm_and_si128(ivx2, notthree), zero), 8));
+ ivx3 = _mm_sub_epi64(ivx3,
+ _mm_slli_si128(_mm_cmpeq_epi64(
+ _mm_and_si128(ivx3, notthree), zero), 8));
+ }
+
+ /*
+ * Write back new counter value. The loop took care to put the
+ * right counter value in ivx0.
+ */
+ _mm_storeu_si128((void *)ctr, _mm_shuffle_epi8(ivx0, erev));
+}
+
+/* see bearssl_block.h */
+BR_TARGET("sse2,sse4.1,aes")
+void
+br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *cbcmac, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ unsigned num_rounds;
+ __m128i sk[15], ivx;
+ unsigned u;
+
+ buf = data;
+ ivx = _mm_loadu_si128(cbcmac);
+ num_rounds = ctx->num_rounds;
+ for (u = 0; u <= num_rounds; u ++) {
+ sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
+ }
+ while (len > 0) {
+ __m128i x;
+
+ x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx);
+ x = _mm_xor_si128(x, sk[0]);
+ x = _mm_aesenc_si128(x, sk[1]);
+ x = _mm_aesenc_si128(x, sk[2]);
+ x = _mm_aesenc_si128(x, sk[3]);
+ x = _mm_aesenc_si128(x, sk[4]);
+ x = _mm_aesenc_si128(x, sk[5]);
+ x = _mm_aesenc_si128(x, sk[6]);
+ x = _mm_aesenc_si128(x, sk[7]);
+ x = _mm_aesenc_si128(x, sk[8]);
+ x = _mm_aesenc_si128(x, sk[9]);
+ if (num_rounds == 10) {
+ x = _mm_aesenclast_si128(x, sk[10]);
+ } else if (num_rounds == 12) {
+ x = _mm_aesenc_si128(x, sk[10]);
+ x = _mm_aesenc_si128(x, sk[11]);
+ x = _mm_aesenclast_si128(x, sk[12]);
+ } else {
+ x = _mm_aesenc_si128(x, sk[10]);
+ x = _mm_aesenc_si128(x, sk[11]);
+ x = _mm_aesenc_si128(x, sk[12]);
+ x = _mm_aesenc_si128(x, sk[13]);
+ x = _mm_aesenclast_si128(x, sk[14]);
+ }
+ ivx = x;
+ buf += 16;
+ len -= 16;
+ }
+ _mm_storeu_si128(cbcmac, ivx);
+}
+
+/* see bearssl_block.h */
+BR_TARGET("sse2,sse4.1,aes")
+void
+br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned num_rounds;
+ __m128i sk[15];
+ __m128i ivx, cmx;
+ __m128i erev, zero, one;
+ unsigned u;
+ int first_iter;
+
+ num_rounds = ctx->num_rounds;
+ for (u = 0; u <= num_rounds; u ++) {
+ sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
+ }
+
+ /*
+ * Some SSE2 constants.
+ */
+ erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15);
+ zero = _mm_setzero_si128();
+ one = _mm_set_epi64x(0, 1);
+
+ /*
+ * Decode the counter in big-endian.
+ */
+ ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev);
+ cmx = _mm_loadu_si128(cbcmac);
+
+ buf = data;
+ first_iter = 1;
+ while (len > 0) {
+ __m128i dx, x0, x1;
+
+ /*
+ * Load initial values:
+ * dx encrypted block of data
+ * x0 counter (for CTR encryption)
+ * x1 input for CBC-MAC
+ */
+ dx = _mm_loadu_si128((void *)buf);
+ x0 = _mm_shuffle_epi8(ivx, erev);
+ x1 = cmx;
+
+ x0 = _mm_xor_si128(x0, sk[0]);
+ x1 = _mm_xor_si128(x1, sk[0]);
+ x0 = _mm_aesenc_si128(x0, sk[1]);
+ x1 = _mm_aesenc_si128(x1, sk[1]);
+ x0 = _mm_aesenc_si128(x0, sk[2]);
+ x1 = _mm_aesenc_si128(x1, sk[2]);
+ x0 = _mm_aesenc_si128(x0, sk[3]);
+ x1 = _mm_aesenc_si128(x1, sk[3]);
+ x0 = _mm_aesenc_si128(x0, sk[4]);
+ x1 = _mm_aesenc_si128(x1, sk[4]);
+ x0 = _mm_aesenc_si128(x0, sk[5]);
+ x1 = _mm_aesenc_si128(x1, sk[5]);
+ x0 = _mm_aesenc_si128(x0, sk[6]);
+ x1 = _mm_aesenc_si128(x1, sk[6]);
+ x0 = _mm_aesenc_si128(x0, sk[7]);
+ x1 = _mm_aesenc_si128(x1, sk[7]);
+ x0 = _mm_aesenc_si128(x0, sk[8]);
+ x1 = _mm_aesenc_si128(x1, sk[8]);
+ x0 = _mm_aesenc_si128(x0, sk[9]);
+ x1 = _mm_aesenc_si128(x1, sk[9]);
+ if (num_rounds == 10) {
+ x0 = _mm_aesenclast_si128(x0, sk[10]);
+ x1 = _mm_aesenclast_si128(x1, sk[10]);
+ } else if (num_rounds == 12) {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x0 = _mm_aesenclast_si128(x0, sk[12]);
+ x1 = _mm_aesenclast_si128(x1, sk[12]);
+ } else {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x0 = _mm_aesenc_si128(x0, sk[12]);
+ x1 = _mm_aesenc_si128(x1, sk[12]);
+ x0 = _mm_aesenc_si128(x0, sk[13]);
+ x1 = _mm_aesenc_si128(x1, sk[13]);
+ x0 = _mm_aesenclast_si128(x0, sk[14]);
+ x1 = _mm_aesenclast_si128(x1, sk[14]);
+ }
+
+ x0 = _mm_xor_si128(x0, dx);
+ if (first_iter) {
+ cmx = _mm_xor_si128(cmx, x0);
+ first_iter = 0;
+ } else {
+ cmx = _mm_xor_si128(x1, x0);
+ }
+ _mm_storeu_si128((void *)buf, x0);
+
+ buf += 16;
+ len -= 16;
+
+ /*
+ * Increment the counter value.
+ */
+ ivx = _mm_add_epi64(ivx, one);
+ ivx = _mm_sub_epi64(ivx,
+ _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8));
+
+ /*
+ * If this was the last iteration, then compute the
+ * extra block encryption to complete CBC-MAC.
+ */
+ if (len == 0) {
+ cmx = _mm_xor_si128(cmx, sk[0]);
+ cmx = _mm_aesenc_si128(cmx, sk[1]);
+ cmx = _mm_aesenc_si128(cmx, sk[2]);
+ cmx = _mm_aesenc_si128(cmx, sk[3]);
+ cmx = _mm_aesenc_si128(cmx, sk[4]);
+ cmx = _mm_aesenc_si128(cmx, sk[5]);
+ cmx = _mm_aesenc_si128(cmx, sk[6]);
+ cmx = _mm_aesenc_si128(cmx, sk[7]);
+ cmx = _mm_aesenc_si128(cmx, sk[8]);
+ cmx = _mm_aesenc_si128(cmx, sk[9]);
+ if (num_rounds == 10) {
+ cmx = _mm_aesenclast_si128(cmx, sk[10]);
+ } else if (num_rounds == 12) {
+ cmx = _mm_aesenc_si128(cmx, sk[10]);
+ cmx = _mm_aesenc_si128(cmx, sk[11]);
+ cmx = _mm_aesenclast_si128(cmx, sk[12]);
+ } else {
+ cmx = _mm_aesenc_si128(cmx, sk[10]);
+ cmx = _mm_aesenc_si128(cmx, sk[11]);
+ cmx = _mm_aesenc_si128(cmx, sk[12]);
+ cmx = _mm_aesenc_si128(cmx, sk[13]);
+ cmx = _mm_aesenclast_si128(cmx, sk[14]);
+ }
+ break;
+ }
+ }
+
+ /*
+ * Write back new counter value and CBC-MAC value.
+ */
+ _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev));
+ _mm_storeu_si128(cbcmac, cmx);
+}
+
+/* see bearssl_block.h */
+BR_TARGET("sse2,sse4.1,aes")
+void
+br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
+ void *ctr, void *cbcmac, void *data, size_t len)
+{
+ unsigned char *buf;
+ unsigned num_rounds;
+ __m128i sk[15];
+ __m128i ivx, cmx;
+ __m128i erev, zero, one;
+ unsigned u;
+
+ num_rounds = ctx->num_rounds;
+ for (u = 0; u <= num_rounds; u ++) {
+ sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
+ }
+
+ /*
+ * Some SSE2 constants.
+ */
+ erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15);
+ zero = _mm_setzero_si128();
+ one = _mm_set_epi64x(0, 1);
+
+ /*
+ * Decode the counter in big-endian.
+ */
+ ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev);
+ cmx = _mm_loadu_si128(cbcmac);
+
+ buf = data;
+ while (len > 0) {
+ __m128i dx, x0, x1;
+
+ /*
+ * Load initial values:
+ * dx encrypted block of data
+ * x0 counter (for CTR encryption)
+ * x1 input for CBC-MAC
+ */
+ dx = _mm_loadu_si128((void *)buf);
+ x0 = _mm_shuffle_epi8(ivx, erev);
+ x1 = _mm_xor_si128(cmx, dx);
+
+ x0 = _mm_xor_si128(x0, sk[0]);
+ x1 = _mm_xor_si128(x1, sk[0]);
+ x0 = _mm_aesenc_si128(x0, sk[1]);
+ x1 = _mm_aesenc_si128(x1, sk[1]);
+ x0 = _mm_aesenc_si128(x0, sk[2]);
+ x1 = _mm_aesenc_si128(x1, sk[2]);
+ x0 = _mm_aesenc_si128(x0, sk[3]);
+ x1 = _mm_aesenc_si128(x1, sk[3]);
+ x0 = _mm_aesenc_si128(x0, sk[4]);
+ x1 = _mm_aesenc_si128(x1, sk[4]);
+ x0 = _mm_aesenc_si128(x0, sk[5]);
+ x1 = _mm_aesenc_si128(x1, sk[5]);
+ x0 = _mm_aesenc_si128(x0, sk[6]);
+ x1 = _mm_aesenc_si128(x1, sk[6]);
+ x0 = _mm_aesenc_si128(x0, sk[7]);
+ x1 = _mm_aesenc_si128(x1, sk[7]);
+ x0 = _mm_aesenc_si128(x0, sk[8]);
+ x1 = _mm_aesenc_si128(x1, sk[8]);
+ x0 = _mm_aesenc_si128(x0, sk[9]);
+ x1 = _mm_aesenc_si128(x1, sk[9]);
+ if (num_rounds == 10) {
+ x0 = _mm_aesenclast_si128(x0, sk[10]);
+ x1 = _mm_aesenclast_si128(x1, sk[10]);
+ } else if (num_rounds == 12) {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x0 = _mm_aesenclast_si128(x0, sk[12]);
+ x1 = _mm_aesenclast_si128(x1, sk[12]);
+ } else {
+ x0 = _mm_aesenc_si128(x0, sk[10]);
+ x1 = _mm_aesenc_si128(x1, sk[10]);
+ x0 = _mm_aesenc_si128(x0, sk[11]);
+ x1 = _mm_aesenc_si128(x1, sk[11]);
+ x0 = _mm_aesenc_si128(x0, sk[12]);
+ x1 = _mm_aesenc_si128(x1, sk[12]);
+ x0 = _mm_aesenc_si128(x0, sk[13]);
+ x1 = _mm_aesenc_si128(x1, sk[13]);
+ x0 = _mm_aesenclast_si128(x0, sk[14]);
+ x1 = _mm_aesenclast_si128(x1, sk[14]);
+ }
+ x0 = _mm_xor_si128(x0, dx);
+ cmx = x1;
+ _mm_storeu_si128((void *)buf, x0);
+
+ buf += 16;
+ len -= 16;
+
+ /*
+ * Increment the counter value.
+ */
+ ivx = _mm_add_epi64(ivx, one);
+ ivx = _mm_sub_epi64(ivx,
+ _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8));
+ }
+
+ /*
+ * Write back new counter value and CBC-MAC value.
+ */
+ _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev));
+ _mm_storeu_si128(cbcmac, cmx);
+}
+
+BR_TARGETS_X86_DOWN
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable = {
+ sizeof(br_aes_x86ni_ctrcbc_keys),
+ 16,
+ 4,
+ (void (*)(const br_block_ctrcbc_class **, const void *, size_t))
+ &br_aes_x86ni_ctrcbc_init,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_x86ni_ctrcbc_encrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, void *, size_t))
+ &br_aes_x86ni_ctrcbc_decrypt,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, void *, size_t))
+ &br_aes_x86ni_ctrcbc_ctr,
+ (void (*)(const br_block_ctrcbc_class *const *,
+ void *, const void *, size_t))
+ &br_aes_x86ni_ctrcbc_mac
+};
+
+#else
+
+/* see bearssl_block.h */
+const br_block_ctrcbc_class *
+br_aes_x86ni_ctrcbc_get_vtable(void)
+{
+ return NULL;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/aes_x86ni_ctrcbc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/chacha20_ct.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/chacha20_ct.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/chacha20_ct.c (revision 346145)
@@ -0,0 +1,106 @@
+/*
+ * 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 bearssl_block.h */
+uint32_t
+br_chacha20_ct_run(const void *key,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+ uint32_t kw[8], ivw[3];
+ size_t u;
+
+ static const uint32_t CW[] = {
+ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
+ };
+
+ buf = data;
+ for (u = 0; u < 8; u ++) {
+ kw[u] = br_dec32le((const unsigned char *)key + (u << 2));
+ }
+ for (u = 0; u < 3; u ++) {
+ ivw[u] = br_dec32le((const unsigned char *)iv + (u << 2));
+ }
+ while (len > 0) {
+ uint32_t state[16];
+ int i;
+ size_t clen;
+ unsigned char tmp[64];
+
+ memcpy(&state[0], CW, sizeof CW);
+ memcpy(&state[4], kw, sizeof kw);
+ state[12] = cc;
+ memcpy(&state[13], ivw, sizeof ivw);
+ for (i = 0; i < 10; i ++) {
+
+#define QROUND(a, b, c, d) do { \
+ state[a] += state[b]; \
+ state[d] ^= state[a]; \
+ state[d] = (state[d] << 16) | (state[d] >> 16); \
+ state[c] += state[d]; \
+ state[b] ^= state[c]; \
+ state[b] = (state[b] << 12) | (state[b] >> 20); \
+ state[a] += state[b]; \
+ state[d] ^= state[a]; \
+ state[d] = (state[d] << 8) | (state[d] >> 24); \
+ state[c] += state[d]; \
+ state[b] ^= state[c]; \
+ state[b] = (state[b] << 7) | (state[b] >> 25); \
+ } while (0)
+
+ QROUND( 0, 4, 8, 12);
+ QROUND( 1, 5, 9, 13);
+ QROUND( 2, 6, 10, 14);
+ QROUND( 3, 7, 11, 15);
+ QROUND( 0, 5, 10, 15);
+ QROUND( 1, 6, 11, 12);
+ QROUND( 2, 7, 8, 13);
+ QROUND( 3, 4, 9, 14);
+
+#undef QROUND
+
+ }
+ for (u = 0; u < 4; u ++) {
+ br_enc32le(&tmp[u << 2], state[u] + CW[u]);
+ }
+ for (u = 4; u < 12; u ++) {
+ br_enc32le(&tmp[u << 2], state[u] + kw[u - 4]);
+ }
+ br_enc32le(&tmp[48], state[12] + cc);
+ for (u = 13; u < 16; u ++) {
+ br_enc32le(&tmp[u << 2], state[u] + ivw[u - 13]);
+ }
+
+ clen = len < 64 ? len : 64;
+ for (u = 0; u < clen; u ++) {
+ buf[u] ^= tmp[u];
+ }
+ buf += clen;
+ len -= clen;
+ cc ++;
+ }
+ return cc;
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/chacha20_ct.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/chacha20_sse2.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/chacha20_sse2.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/chacha20_sse2.c (revision 346145)
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+#define BR_ENABLE_INTRINSICS 1
+#include "inner.h"
+
+#if BR_SSE2
+
+/*
+ * This file contains a ChaCha20 implementation that leverages SSE2
+ * opcodes for better performance.
+ */
+
+/* see bearssl_block.h */
+br_chacha20_run
+br_chacha20_sse2_get(void)
+{
+ /*
+ * If using 64-bit mode, then SSE2 opcodes should be automatically
+ * available, since they are part of the ABI.
+ *
+ * In 32-bit mode, we use CPUID to detect the SSE2 feature.
+ */
+
+#if BR_amd64
+ return &br_chacha20_sse2_run;
+#else
+
+ /*
+ * SSE2 support is indicated by bit 26 in EDX.
+ */
+ if (br_cpuid(0, 0, 0, 0x04000000)) {
+ return &br_chacha20_sse2_run;
+ } else {
+ return 0;
+ }
+#endif
+}
+
+BR_TARGETS_X86_UP
+
+/* see bearssl_block.h */
+BR_TARGET("sse2")
+uint32_t
+br_chacha20_sse2_run(const void *key,
+ const void *iv, uint32_t cc, void *data, size_t len)
+{
+ unsigned char *buf;
+ uint32_t ivtmp[4];
+ __m128i kw0, kw1;
+ __m128i iw, cw;
+ __m128i one;
+
+ static const uint32_t CW[] = {
+ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
+ };
+
+ buf = data;
+ kw0 = _mm_loadu_si128(key);
+ kw1 = _mm_loadu_si128((const void *)((const unsigned char *)key + 16));
+ ivtmp[0] = cc;
+ memcpy(ivtmp + 1, iv, 12);
+ iw = _mm_loadu_si128((const void *)ivtmp);
+ cw = _mm_loadu_si128((const void *)CW);
+ one = _mm_set_epi32(0, 0, 0, 1);
+
+ while (len > 0) {
+ /*
+ * sj contains state words 4*j to 4*j+3.
+ */
+ __m128i s0, s1, s2, s3;
+ int i;
+
+ s0 = cw;
+ s1 = kw0;
+ s2 = kw1;
+ s3 = iw;
+ for (i = 0; i < 10; i ++) {
+ /*
+ * Even round is straightforward application on
+ * the state words.
+ */
+ s0 = _mm_add_epi32(s0, s1);
+ s3 = _mm_xor_si128(s3, s0);
+ s3 = _mm_or_si128(
+ _mm_slli_epi32(s3, 16),
+ _mm_srli_epi32(s3, 16));
+
+ s2 = _mm_add_epi32(s2, s3);
+ s1 = _mm_xor_si128(s1, s2);
+ s1 = _mm_or_si128(
+ _mm_slli_epi32(s1, 12),
+ _mm_srli_epi32(s1, 20));
+
+ s0 = _mm_add_epi32(s0, s1);
+ s3 = _mm_xor_si128(s3, s0);
+ s3 = _mm_or_si128(
+ _mm_slli_epi32(s3, 8),
+ _mm_srli_epi32(s3, 24));
+
+ s2 = _mm_add_epi32(s2, s3);
+ s1 = _mm_xor_si128(s1, s2);
+ s1 = _mm_or_si128(
+ _mm_slli_epi32(s1, 7),
+ _mm_srli_epi32(s1, 25));
+
+ /*
+ * For the odd round, we must rotate some state
+ * words so that the computations apply on the
+ * right combinations of words.
+ */
+ s1 = _mm_shuffle_epi32(s1, 0x39);
+ s2 = _mm_shuffle_epi32(s2, 0x4E);
+ s3 = _mm_shuffle_epi32(s3, 0x93);
+
+ s0 = _mm_add_epi32(s0, s1);
+ s3 = _mm_xor_si128(s3, s0);
+ s3 = _mm_or_si128(
+ _mm_slli_epi32(s3, 16),
+ _mm_srli_epi32(s3, 16));
+
+ s2 = _mm_add_epi32(s2, s3);
+ s1 = _mm_xor_si128(s1, s2);
+ s1 = _mm_or_si128(
+ _mm_slli_epi32(s1, 12),
+ _mm_srli_epi32(s1, 20));
+
+ s0 = _mm_add_epi32(s0, s1);
+ s3 = _mm_xor_si128(s3, s0);
+ s3 = _mm_or_si128(
+ _mm_slli_epi32(s3, 8),
+ _mm_srli_epi32(s3, 24));
+
+ s2 = _mm_add_epi32(s2, s3);
+ s1 = _mm_xor_si128(s1, s2);
+ s1 = _mm_or_si128(
+ _mm_slli_epi32(s1, 7),
+ _mm_srli_epi32(s1, 25));
+
+ /*
+ * After the odd round, we rotate back the values
+ * to undo the rotate at the start of the odd round.
+ */
+ s1 = _mm_shuffle_epi32(s1, 0x93);
+ s2 = _mm_shuffle_epi32(s2, 0x4E);
+ s3 = _mm_shuffle_epi32(s3, 0x39);
+ }
+
+ /*
+ * Addition with the initial state.
+ */
+ s0 = _mm_add_epi32(s0, cw);
+ s1 = _mm_add_epi32(s1, kw0);
+ s2 = _mm_add_epi32(s2, kw1);
+ s3 = _mm_add_epi32(s3, iw);
+
+ /*
+ * Increment block counter.
+ */
+ iw = _mm_add_epi32(iw, one);
+
+ /*
+ * XOR final state with the data.
+ */
+ if (len < 64) {
+ unsigned char tmp[64];
+ size_t u;
+
+ _mm_storeu_si128((void *)(tmp + 0), s0);
+ _mm_storeu_si128((void *)(tmp + 16), s1);
+ _mm_storeu_si128((void *)(tmp + 32), s2);
+ _mm_storeu_si128((void *)(tmp + 48), s3);
+ for (u = 0; u < len; u ++) {
+ buf[u] ^= tmp[u];
+ }
+ break;
+ } else {
+ __m128i b0, b1, b2, b3;
+
+ b0 = _mm_loadu_si128((const void *)(buf + 0));
+ b1 = _mm_loadu_si128((const void *)(buf + 16));
+ b2 = _mm_loadu_si128((const void *)(buf + 32));
+ b3 = _mm_loadu_si128((const void *)(buf + 48));
+ b0 = _mm_xor_si128(b0, s0);
+ b1 = _mm_xor_si128(b1, s1);
+ b2 = _mm_xor_si128(b2, s2);
+ b3 = _mm_xor_si128(b3, s3);
+ _mm_storeu_si128((void *)(buf + 0), b0);
+ _mm_storeu_si128((void *)(buf + 16), b1);
+ _mm_storeu_si128((void *)(buf + 32), b2);
+ _mm_storeu_si128((void *)(buf + 48), b3);
+ buf += 64;
+ len -= 64;
+ }
+ }
+
+ /*
+ * _mm_extract_epi32() requires SSE4.1. We prefer to stick to
+ * raw SSE2, thus we use _mm_extract_epi16().
+ */
+ return (uint32_t)_mm_extract_epi16(iw, 0)
+ | ((uint32_t)_mm_extract_epi16(iw, 1) << 16);
+}
+
+BR_TARGETS_X86_DOWN
+
+#else
+
+/* see bearssl_block.h */
+br_chacha20_run
+br_chacha20_sse2_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/chacha20_sse2.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/des_ct.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/des_ct.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/des_ct.c (revision 346145)
@@ -0,0 +1,411 @@
+/*
+ * 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"
+
+/*
+ * During key schedule, we need to apply bit extraction PC-2 then permute
+ * things into our bitslice representation. PC-2 extracts 48 bits out
+ * of two 28-bit words (kl and kr), and we store these bits into two
+ * 32-bit words sk0 and sk1.
+ *
+ * -- bit 16+x of sk0 comes from bit QL0[x] of kl
+ * -- bit x of sk0 comes from bit QR0[x] of kr
+ * -- bit 16+x of sk1 comes from bit QL1[x] of kl
+ * -- bit x of sk1 comes from bit QR1[x] of kr
+ */
+
+static const unsigned char QL0[] = {
+ 17, 4, 27, 23, 13, 22, 7, 18,
+ 16, 24, 2, 20, 1, 8, 15, 26
+};
+
+static const unsigned char QR0[] = {
+ 25, 19, 9, 1, 5, 11, 23, 8,
+ 17, 0, 22, 3, 6, 20, 27, 24
+};
+
+static const unsigned char QL1[] = {
+ 28, 28, 14, 11, 28, 28, 25, 0,
+ 28, 28, 5, 9, 28, 28, 12, 21
+};
+
+static const unsigned char QR1[] = {
+ 28, 28, 15, 4, 28, 28, 26, 16,
+ 28, 28, 12, 7, 28, 28, 10, 14
+};
+
+/*
+ * 32-bit rotation. The C compiler is supposed to recognize it as a
+ * rotation and use the local architecture rotation opcode (if available).
+ */
+static inline uint32_t
+rotl(uint32_t x, int n)
+{
+ return (x << n) | (x >> (32 - n));
+}
+
+/*
+ * Compute key schedule for 8 key bytes (produces 32 subkey words).
+ */
+static void
+keysched_unit(uint32_t *skey, const void *key)
+{
+ int i;
+
+ br_des_keysched_unit(skey, key);
+
+ /*
+ * Apply PC-2 + bitslicing.
+ */
+ for (i = 0; i < 16; i ++) {
+ uint32_t kl, kr, sk0, sk1;
+ int j;
+
+ kl = skey[(i << 1) + 0];
+ kr = skey[(i << 1) + 1];
+ sk0 = 0;
+ sk1 = 0;
+ for (j = 0; j < 16; j ++) {
+ sk0 <<= 1;
+ sk1 <<= 1;
+ sk0 |= ((kl >> QL0[j]) & (uint32_t)1) << 16;
+ sk0 |= (kr >> QR0[j]) & (uint32_t)1;
+ sk1 |= ((kl >> QL1[j]) & (uint32_t)1) << 16;
+ sk1 |= (kr >> QR1[j]) & (uint32_t)1;
+ }
+
+ skey[(i << 1) + 0] = sk0;
+ skey[(i << 1) + 1] = sk1;
+ }
+
+#if 0
+ /*
+ * Speed-optimized version for PC-2 + bitslicing.
+ * (Unused. Kept for reference only.)
+ */
+ sk0 = kl & (uint32_t)0x00100000;
+ sk0 |= (kl & (uint32_t)0x08008000) << 2;
+ sk0 |= (kl & (uint32_t)0x00400000) << 4;
+ sk0 |= (kl & (uint32_t)0x00800000) << 5;
+ sk0 |= (kl & (uint32_t)0x00040000) << 6;
+ sk0 |= (kl & (uint32_t)0x00010000) << 7;
+ sk0 |= (kl & (uint32_t)0x00000100) << 10;
+ sk0 |= (kl & (uint32_t)0x00022000) << 14;
+ sk0 |= (kl & (uint32_t)0x00000082) << 18;
+ sk0 |= (kl & (uint32_t)0x00000004) << 19;
+ sk0 |= (kl & (uint32_t)0x04000000) >> 10;
+ sk0 |= (kl & (uint32_t)0x00000010) << 26;
+ sk0 |= (kl & (uint32_t)0x01000000) >> 2;
+
+ sk0 |= kr & (uint32_t)0x00000100;
+ sk0 |= (kr & (uint32_t)0x00000008) << 1;
+ sk0 |= (kr & (uint32_t)0x00000200) << 4;
+ sk0 |= rotl(kr & (uint32_t)0x08000021, 6);
+ sk0 |= (kr & (uint32_t)0x01000000) >> 24;
+ sk0 |= (kr & (uint32_t)0x00000002) << 11;
+ sk0 |= (kr & (uint32_t)0x00100000) >> 18;
+ sk0 |= (kr & (uint32_t)0x00400000) >> 17;
+ sk0 |= (kr & (uint32_t)0x00800000) >> 14;
+ sk0 |= (kr & (uint32_t)0x02020000) >> 10;
+ sk0 |= (kr & (uint32_t)0x00080000) >> 5;
+ sk0 |= (kr & (uint32_t)0x00000040) >> 3;
+ sk0 |= (kr & (uint32_t)0x00000800) >> 1;
+
+ sk1 = kl & (uint32_t)0x02000000;
+ sk1 |= (kl & (uint32_t)0x00001000) << 5;
+ sk1 |= (kl & (uint32_t)0x00000200) << 11;
+ sk1 |= (kl & (uint32_t)0x00004000) << 15;
+ sk1 |= (kl & (uint32_t)0x00000020) << 16;
+ sk1 |= (kl & (uint32_t)0x00000800) << 17;
+ sk1 |= (kl & (uint32_t)0x00000001) << 24;
+ sk1 |= (kl & (uint32_t)0x00200000) >> 5;
+
+ sk1 |= (kr & (uint32_t)0x00000010) << 8;
+ sk1 |= (kr & (uint32_t)0x04000000) >> 17;
+ sk1 |= (kr & (uint32_t)0x00004000) >> 14;
+ sk1 |= (kr & (uint32_t)0x00000400) >> 9;
+ sk1 |= (kr & (uint32_t)0x00010000) >> 8;
+ sk1 |= (kr & (uint32_t)0x00001000) >> 7;
+ sk1 |= (kr & (uint32_t)0x00000080) >> 3;
+ sk1 |= (kr & (uint32_t)0x00008000) >> 2;
+#endif
+}
+
+/* see inner.h */
+unsigned
+br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len)
+{
+ switch (key_len) {
+ case 8:
+ keysched_unit(skey, key);
+ return 1;
+ case 16:
+ keysched_unit(skey, key);
+ keysched_unit(skey + 32, (const unsigned char *)key + 8);
+ br_des_rev_skey(skey + 32);
+ memcpy(skey + 64, skey, 32 * sizeof *skey);
+ return 3;
+ default:
+ keysched_unit(skey, key);
+ keysched_unit(skey + 32, (const unsigned char *)key + 8);
+ br_des_rev_skey(skey + 32);
+ keysched_unit(skey + 64, (const unsigned char *)key + 16);
+ return 3;
+ }
+}
+
+/*
+ * DES confusion function. This function performs expansion E (32 to
+ * 48 bits), XOR with subkey, S-boxes, and permutation P.
+ */
+static inline uint32_t
+Fconf(uint32_t r0, const uint32_t *sk)
+{
+ /*
+ * Each 6->4 S-box is virtually turned into four 6->1 boxes; we
+ * thus end up with 32 boxes that we call "T-boxes" here. We will
+ * evaluate them with bitslice code.
+ *
+ * Each T-box is a circuit of multiplexers (sort of) and thus
+ * takes 70 inputs: the 6 actual T-box inputs, and 64 constants
+ * that describe the T-box output for all combinations of the
+ * 6 inputs. With this model, all T-boxes are identical (with
+ * distinct inputs) and thus can be executed in parallel with
+ * bitslice code.
+ *
+ * T-boxes are numbered from 0 to 31, in least-to-most
+ * significant order. Thus, S-box S1 corresponds to T-boxes 31,
+ * 30, 29 and 28, in that order. T-box 'n' is computed with the
+ * bits at rank 'n' in the 32-bit words.
+ *
+ * Words x0 to x5 contain the T-box inputs 0 to 5.
+ */
+ uint32_t x0, x1, x2, x3, x4, x5, z0;
+ uint32_t y0, y1, y2, y3, y4, y5, y6, y7, y8, y9;
+ uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19;
+ uint32_t y20, y21, y22, y23, y24, y25, y26, y27, y28, y29;
+ uint32_t y30;
+
+ /*
+ * Spread input bits over the 6 input words x*.
+ */
+ x1 = r0 & (uint32_t)0x11111111;
+ x2 = (r0 >> 1) & (uint32_t)0x11111111;
+ x3 = (r0 >> 2) & (uint32_t)0x11111111;
+ x4 = (r0 >> 3) & (uint32_t)0x11111111;
+ x1 = (x1 << 4) - x1;
+ x2 = (x2 << 4) - x2;
+ x3 = (x3 << 4) - x3;
+ x4 = (x4 << 4) - x4;
+ x0 = (x4 << 4) | (x4 >> 28);
+ x5 = (x1 >> 4) | (x1 << 28);
+
+ /*
+ * XOR with the subkey for this round.
+ */
+ x0 ^= sk[0];
+ x1 ^= sk[1];
+ x2 ^= sk[2];
+ x3 ^= sk[3];
+ x4 ^= sk[4];
+ x5 ^= sk[5];
+
+ /*
+ * The T-boxes are done in parallel, since they all use a
+ * "tree of multiplexer". We use "fake multiplexers":
+ *
+ * y = a ^ (x & b)
+ *
+ * computes y as either 'a' (if x == 0) or 'a ^ b' (if x == 1).
+ */
+ y0 = (uint32_t)0xEFA72C4D ^ (x0 & (uint32_t)0xEC7AC69C);
+ y1 = (uint32_t)0xAEAAEDFF ^ (x0 & (uint32_t)0x500FB821);
+ y2 = (uint32_t)0x37396665 ^ (x0 & (uint32_t)0x40EFA809);
+ y3 = (uint32_t)0x68D7B833 ^ (x0 & (uint32_t)0xA5EC0B28);
+ y4 = (uint32_t)0xC9C755BB ^ (x0 & (uint32_t)0x252CF820);
+ y5 = (uint32_t)0x73FC3606 ^ (x0 & (uint32_t)0x40205801);
+ y6 = (uint32_t)0xA2A0A918 ^ (x0 & (uint32_t)0xE220F929);
+ y7 = (uint32_t)0x8222BD90 ^ (x0 & (uint32_t)0x44A3F9E1);
+ y8 = (uint32_t)0xD6B6AC77 ^ (x0 & (uint32_t)0x794F104A);
+ y9 = (uint32_t)0x3069300C ^ (x0 & (uint32_t)0x026F320B);
+ y10 = (uint32_t)0x6CE0D5CC ^ (x0 & (uint32_t)0x7640B01A);
+ y11 = (uint32_t)0x59A9A22D ^ (x0 & (uint32_t)0x238F1572);
+ y12 = (uint32_t)0xAC6D0BD4 ^ (x0 & (uint32_t)0x7A63C083);
+ y13 = (uint32_t)0x21C83200 ^ (x0 & (uint32_t)0x11CCA000);
+ y14 = (uint32_t)0xA0E62188 ^ (x0 & (uint32_t)0x202F69AA);
+ /* y15 = (uint32_t)0x00000000 ^ (x0 & (uint32_t)0x00000000); */
+ y16 = (uint32_t)0xAF7D655A ^ (x0 & (uint32_t)0x51B33BE9);
+ y17 = (uint32_t)0xF0168AA3 ^ (x0 & (uint32_t)0x3B0FE8AE);
+ y18 = (uint32_t)0x90AA30C6 ^ (x0 & (uint32_t)0x90BF8816);
+ y19 = (uint32_t)0x5AB2750A ^ (x0 & (uint32_t)0x09E34F9B);
+ y20 = (uint32_t)0x5391BE65 ^ (x0 & (uint32_t)0x0103BE88);
+ y21 = (uint32_t)0x93372BAF ^ (x0 & (uint32_t)0x49AC8E25);
+ y22 = (uint32_t)0xF288210C ^ (x0 & (uint32_t)0x922C313D);
+ y23 = (uint32_t)0x920AF5C0 ^ (x0 & (uint32_t)0x70EF31B0);
+ y24 = (uint32_t)0x63D312C0 ^ (x0 & (uint32_t)0x6A707100);
+ y25 = (uint32_t)0x537B3006 ^ (x0 & (uint32_t)0xB97C9011);
+ y26 = (uint32_t)0xA2EFB0A5 ^ (x0 & (uint32_t)0xA320C959);
+ y27 = (uint32_t)0xBC8F96A5 ^ (x0 & (uint32_t)0x6EA0AB4A);
+ y28 = (uint32_t)0xFAD176A5 ^ (x0 & (uint32_t)0x6953DDF8);
+ y29 = (uint32_t)0x665A14A3 ^ (x0 & (uint32_t)0xF74F3E2B);
+ y30 = (uint32_t)0xF2EFF0CC ^ (x0 & (uint32_t)0xF0306CAD);
+ /* y31 = (uint32_t)0x00000000 ^ (x0 & (uint32_t)0x00000000); */
+
+ y0 = y0 ^ (x1 & y1);
+ y1 = y2 ^ (x1 & y3);
+ y2 = y4 ^ (x1 & y5);
+ y3 = y6 ^ (x1 & y7);
+ y4 = y8 ^ (x1 & y9);
+ y5 = y10 ^ (x1 & y11);
+ y6 = y12 ^ (x1 & y13);
+ y7 = y14; /* was: y14 ^ (x1 & y15) */
+ y8 = y16 ^ (x1 & y17);
+ y9 = y18 ^ (x1 & y19);
+ y10 = y20 ^ (x1 & y21);
+ y11 = y22 ^ (x1 & y23);
+ y12 = y24 ^ (x1 & y25);
+ y13 = y26 ^ (x1 & y27);
+ y14 = y28 ^ (x1 & y29);
+ y15 = y30; /* was: y30 ^ (x1 & y31) */
+
+ y0 = y0 ^ (x2 & y1);
+ y1 = y2 ^ (x2 & y3);
+ y2 = y4 ^ (x2 & y5);
+ y3 = y6 ^ (x2 & y7);
+ y4 = y8 ^ (x2 & y9);
+ y5 = y10 ^ (x2 & y11);
+ y6 = y12 ^ (x2 & y13);
+ y7 = y14 ^ (x2 & y15);
+
+ y0 = y0 ^ (x3 & y1);
+ y1 = y2 ^ (x3 & y3);
+ y2 = y4 ^ (x3 & y5);
+ y3 = y6 ^ (x3 & y7);
+
+ y0 = y0 ^ (x4 & y1);
+ y1 = y2 ^ (x4 & y3);
+
+ y0 = y0 ^ (x5 & y1);
+
+ /*
+ * The P permutation:
+ * -- Each bit move is converted into a mask + left rotation.
+ * -- Rotations that use the same movement are coalesced together.
+ * -- Left and right shifts are used as alternatives to a rotation
+ * where appropriate (this will help architectures that do not have
+ * a rotation opcode).
+ */
+ z0 = (y0 & (uint32_t)0x00000004) << 3;
+ z0 |= (y0 & (uint32_t)0x00004000) << 4;
+ z0 |= rotl(y0 & 0x12020120, 5);
+ z0 |= (y0 & (uint32_t)0x00100000) << 6;
+ z0 |= (y0 & (uint32_t)0x00008000) << 9;
+ z0 |= (y0 & (uint32_t)0x04000000) >> 22;
+ z0 |= (y0 & (uint32_t)0x00000001) << 11;
+ z0 |= rotl(y0 & 0x20000200, 12);
+ z0 |= (y0 & (uint32_t)0x00200000) >> 19;
+ z0 |= (y0 & (uint32_t)0x00000040) << 14;
+ z0 |= (y0 & (uint32_t)0x00010000) << 15;
+ z0 |= (y0 & (uint32_t)0x00000002) << 16;
+ z0 |= rotl(y0 & 0x40801800, 17);
+ z0 |= (y0 & (uint32_t)0x00080000) >> 13;
+ z0 |= (y0 & (uint32_t)0x00000010) << 21;
+ z0 |= (y0 & (uint32_t)0x01000000) >> 10;
+ z0 |= rotl(y0 & 0x88000008, 24);
+ z0 |= (y0 & (uint32_t)0x00000480) >> 7;
+ z0 |= (y0 & (uint32_t)0x00442000) >> 6;
+ return z0;
+}
+
+/*
+ * Process one block through 16 successive rounds, omitting the swap
+ * in the final round.
+ */
+static void
+process_block_unit(uint32_t *pl, uint32_t *pr, const uint32_t *sk_exp)
+{
+ int i;
+ uint32_t l, r;
+
+ l = *pl;
+ r = *pr;
+ for (i = 0; i < 16; i ++) {
+ uint32_t t;
+
+ t = l ^ Fconf(r, sk_exp);
+ l = r;
+ r = t;
+ sk_exp += 6;
+ }
+ *pl = r;
+ *pr = l;
+}
+
+/* see inner.h */
+void
+br_des_ct_process_block(unsigned num_rounds,
+ const uint32_t *sk_exp, void *block)
+{
+ unsigned char *buf;
+ uint32_t l, r;
+
+ buf = block;
+ l = br_dec32be(buf);
+ r = br_dec32be(buf + 4);
+ br_des_do_IP(&l, &r);
+ while (num_rounds -- > 0) {
+ process_block_unit(&l, &r, sk_exp);
+ sk_exp += 96;
+ }
+ br_des_do_invIP(&l, &r);
+ br_enc32be(buf, l);
+ br_enc32be(buf + 4, r);
+}
+
+/* see inner.h */
+void
+br_des_ct_skey_expand(uint32_t *sk_exp,
+ unsigned num_rounds, const uint32_t *skey)
+{
+ num_rounds <<= 4;
+ while (num_rounds -- > 0) {
+ uint32_t v, w0, w1, w2, w3;
+
+ v = *skey ++;
+ w0 = v & 0x11111111;
+ w1 = (v >> 1) & 0x11111111;
+ w2 = (v >> 2) & 0x11111111;
+ w3 = (v >> 3) & 0x11111111;
+ *sk_exp ++ = (w0 << 4) - w0;
+ *sk_exp ++ = (w1 << 4) - w1;
+ *sk_exp ++ = (w2 << 4) - w2;
+ *sk_exp ++ = (w3 << 4) - w3;
+ v = *skey ++;
+ w0 = v & 0x11111111;
+ w1 = (v >> 1) & 0x11111111;
+ *sk_exp ++ = (w0 << 4) - w0;
+ *sk_exp ++ = (w1 << 4) - w1;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/des_ct.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/des_ct_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/des_ct_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/des_ct_cbcdec.c (revision 346145)
@@ -0,0 +1,87 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_des_ct_cbcdec_vtable;
+ ctx->num_rounds = br_des_ct_keysched(ctx->skey, key, len);
+ if (len == 8) {
+ br_des_rev_skey(ctx->skey);
+ } else {
+ int i;
+
+ for (i = 0; i < 48; i += 2) {
+ uint32_t t;
+
+ t = ctx->skey[i];
+ ctx->skey[i] = ctx->skey[94 - i];
+ ctx->skey[94 - i] = t;
+ t = ctx->skey[i + 1];
+ ctx->skey[i + 1] = ctx->skey[95 - i];
+ ctx->skey[95 - i] = t;
+ }
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+ uint32_t sk_exp[288];
+
+ br_des_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[8];
+ int i;
+
+ memcpy(tmp, buf, 8);
+ br_des_ct_process_block(ctx->num_rounds, sk_exp, buf);
+ for (i = 0; i < 8; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ memcpy(ivbuf, tmp, 8);
+ buf += 8;
+ len -= 8;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_des_ct_cbcdec_vtable = {
+ sizeof(br_des_ct_cbcdec_keys),
+ 8,
+ 3,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_des_ct_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_des_ct_cbcdec_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/des_ct_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/des_ct_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/des_ct_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/des_ct_cbcenc.c (revision 346145)
@@ -0,0 +1,69 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_des_ct_cbcenc_vtable;
+ ctx->num_rounds = br_des_ct_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+ uint32_t sk_exp[288];
+
+ br_des_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey);
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ br_des_ct_process_block(ctx->num_rounds, sk_exp, buf);
+ memcpy(ivbuf, buf, 8);
+ buf += 8;
+ len -= 8;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_des_ct_cbcenc_vtable = {
+ sizeof(br_des_ct_cbcenc_keys),
+ 8,
+ 3,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_des_ct_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_des_ct_cbcenc_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/des_ct_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/des_support.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/des_support.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/des_support.c (revision 346145)
@@ -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 "inner.h"
+
+/* see inner.h */
+void
+br_des_do_IP(uint32_t *xl, uint32_t *xr)
+{
+ /*
+ * Permutation algorithm is initially from Richard Outerbridge;
+ * implementation here is adapted from Crypto++ "des.cpp" file
+ * (which is in public domain).
+ */
+ uint32_t l, r, t;
+
+ l = *xl;
+ r = *xr;
+ t = ((l >> 4) ^ r) & (uint32_t)0x0F0F0F0F;
+ r ^= t;
+ l ^= t << 4;
+ t = ((l >> 16) ^ r) & (uint32_t)0x0000FFFF;
+ r ^= t;
+ l ^= t << 16;
+ t = ((r >> 2) ^ l) & (uint32_t)0x33333333;
+ l ^= t;
+ r ^= t << 2;
+ t = ((r >> 8) ^ l) & (uint32_t)0x00FF00FF;
+ l ^= t;
+ r ^= t << 8;
+ t = ((l >> 1) ^ r) & (uint32_t)0x55555555;
+ r ^= t;
+ l ^= t << 1;
+ *xl = l;
+ *xr = r;
+}
+
+/* see inner.h */
+void
+br_des_do_invIP(uint32_t *xl, uint32_t *xr)
+{
+ /*
+ * See br_des_do_IP().
+ */
+ uint32_t l, r, t;
+
+ l = *xl;
+ r = *xr;
+ t = ((l >> 1) ^ r) & 0x55555555;
+ r ^= t;
+ l ^= t << 1;
+ t = ((r >> 8) ^ l) & 0x00FF00FF;
+ l ^= t;
+ r ^= t << 8;
+ t = ((r >> 2) ^ l) & 0x33333333;
+ l ^= t;
+ r ^= t << 2;
+ t = ((l >> 16) ^ r) & 0x0000FFFF;
+ r ^= t;
+ l ^= t << 16;
+ t = ((l >> 4) ^ r) & 0x0F0F0F0F;
+ r ^= t;
+ l ^= t << 4;
+ *xl = l;
+ *xr = r;
+}
+
+/* see inner.h */
+void
+br_des_keysched_unit(uint32_t *skey, const void *key)
+{
+ uint32_t xl, xr, kl, kr;
+ int i;
+
+ xl = br_dec32be(key);
+ xr = br_dec32be((const unsigned char *)key + 4);
+
+ /*
+ * Permutation PC-1 is quite similar to the IP permutation.
+ * Definition of IP (in FIPS 46-3 notations) is:
+ * 58 50 42 34 26 18 10 2
+ * 60 52 44 36 28 20 12 4
+ * 62 54 46 38 30 22 14 6
+ * 64 56 48 40 32 24 16 8
+ * 57 49 41 33 25 17 9 1
+ * 59 51 43 35 27 19 11 3
+ * 61 53 45 37 29 21 13 5
+ * 63 55 47 39 31 23 15 7
+ *
+ * Definition of PC-1 is:
+ * 57 49 41 33 25 17 9 1
+ * 58 50 42 34 26 18 10 2
+ * 59 51 43 35 27 19 11 3
+ * 60 52 44 36
+ * 63 55 47 39 31 23 15 7
+ * 62 54 46 38 30 22 14 6
+ * 61 53 45 37 29 21 13 5
+ * 28 20 12 4
+ */
+ br_des_do_IP(&xl, &xr);
+ kl = ((xr & (uint32_t)0xFF000000) >> 4)
+ | ((xl & (uint32_t)0xFF000000) >> 12)
+ | ((xr & (uint32_t)0x00FF0000) >> 12)
+ | ((xl & (uint32_t)0x00FF0000) >> 20);
+ kr = ((xr & (uint32_t)0x000000FF) << 20)
+ | ((xl & (uint32_t)0x0000FF00) << 4)
+ | ((xr & (uint32_t)0x0000FF00) >> 4)
+ | ((xl & (uint32_t)0x000F0000) >> 16);
+
+ /*
+ * For each round, rotate the two 28-bit words kl and kr.
+ * The extraction of the 48-bit subkey (PC-2) is not done yet.
+ */
+ for (i = 0; i < 16; i ++) {
+ if ((1 << i) & 0x8103) {
+ kl = (kl << 1) | (kl >> 27);
+ kr = (kr << 1) | (kr >> 27);
+ } else {
+ kl = (kl << 2) | (kl >> 26);
+ kr = (kr << 2) | (kr >> 26);
+ }
+ kl &= (uint32_t)0x0FFFFFFF;
+ kr &= (uint32_t)0x0FFFFFFF;
+ skey[(i << 1) + 0] = kl;
+ skey[(i << 1) + 1] = kr;
+ }
+}
+
+/* see inner.h */
+void
+br_des_rev_skey(uint32_t *skey)
+{
+ int i;
+
+ for (i = 0; i < 16; i += 2) {
+ uint32_t t;
+
+ t = skey[i + 0];
+ skey[i + 0] = skey[30 - i];
+ skey[30 - i] = t;
+ t = skey[i + 1];
+ skey[i + 1] = skey[31 - i];
+ skey[31 - i] = t;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/des_support.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/des_tab.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/des_tab.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/des_tab.c (revision 346145)
@@ -0,0 +1,310 @@
+/*
+ * 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"
+
+/*
+ * PC2left[x] tells where bit x goes when applying PC-2. 'x' is a bit
+ * position in the left rotated key word. Both position are in normal
+ * order (rightmost bit is 0).
+ */
+static const unsigned char PC2left[] = {
+ 16, 3, 7, 24, 20, 11, 24,
+ 13, 2, 10, 24, 22, 5, 15,
+ 23, 1, 9, 21, 12, 24, 6,
+ 4, 14, 18, 8, 17, 0, 19
+};
+
+/*
+ * Similar to PC2left[x], for the right rotated key word.
+ */
+static const unsigned char PC2right[] = {
+ 8, 18, 24, 6, 22, 15, 3,
+ 10, 12, 19, 5, 14, 11, 24,
+ 4, 23, 16, 9, 24, 20, 2,
+ 24, 7, 13, 0, 21, 17, 1
+};
+
+/*
+ * S-boxes and PC-1 merged.
+ */
+static const uint32_t S1[] = {
+ 0x00808200, 0x00000000, 0x00008000, 0x00808202,
+ 0x00808002, 0x00008202, 0x00000002, 0x00008000,
+ 0x00000200, 0x00808200, 0x00808202, 0x00000200,
+ 0x00800202, 0x00808002, 0x00800000, 0x00000002,
+ 0x00000202, 0x00800200, 0x00800200, 0x00008200,
+ 0x00008200, 0x00808000, 0x00808000, 0x00800202,
+ 0x00008002, 0x00800002, 0x00800002, 0x00008002,
+ 0x00000000, 0x00000202, 0x00008202, 0x00800000,
+ 0x00008000, 0x00808202, 0x00000002, 0x00808000,
+ 0x00808200, 0x00800000, 0x00800000, 0x00000200,
+ 0x00808002, 0x00008000, 0x00008200, 0x00800002,
+ 0x00000200, 0x00000002, 0x00800202, 0x00008202,
+ 0x00808202, 0x00008002, 0x00808000, 0x00800202,
+ 0x00800002, 0x00000202, 0x00008202, 0x00808200,
+ 0x00000202, 0x00800200, 0x00800200, 0x00000000,
+ 0x00008002, 0x00008200, 0x00000000, 0x00808002
+};
+
+static const uint32_t S2[] = {
+ 0x40084010, 0x40004000, 0x00004000, 0x00084010,
+ 0x00080000, 0x00000010, 0x40080010, 0x40004010,
+ 0x40000010, 0x40084010, 0x40084000, 0x40000000,
+ 0x40004000, 0x00080000, 0x00000010, 0x40080010,
+ 0x00084000, 0x00080010, 0x40004010, 0x00000000,
+ 0x40000000, 0x00004000, 0x00084010, 0x40080000,
+ 0x00080010, 0x40000010, 0x00000000, 0x00084000,
+ 0x00004010, 0x40084000, 0x40080000, 0x00004010,
+ 0x00000000, 0x00084010, 0x40080010, 0x00080000,
+ 0x40004010, 0x40080000, 0x40084000, 0x00004000,
+ 0x40080000, 0x40004000, 0x00000010, 0x40084010,
+ 0x00084010, 0x00000010, 0x00004000, 0x40000000,
+ 0x00004010, 0x40084000, 0x00080000, 0x40000010,
+ 0x00080010, 0x40004010, 0x40000010, 0x00080010,
+ 0x00084000, 0x00000000, 0x40004000, 0x00004010,
+ 0x40000000, 0x40080010, 0x40084010, 0x00084000
+};
+
+static const uint32_t S3[] = {
+ 0x00000104, 0x04010100, 0x00000000, 0x04010004,
+ 0x04000100, 0x00000000, 0x00010104, 0x04000100,
+ 0x00010004, 0x04000004, 0x04000004, 0x00010000,
+ 0x04010104, 0x00010004, 0x04010000, 0x00000104,
+ 0x04000000, 0x00000004, 0x04010100, 0x00000100,
+ 0x00010100, 0x04010000, 0x04010004, 0x00010104,
+ 0x04000104, 0x00010100, 0x00010000, 0x04000104,
+ 0x00000004, 0x04010104, 0x00000100, 0x04000000,
+ 0x04010100, 0x04000000, 0x00010004, 0x00000104,
+ 0x00010000, 0x04010100, 0x04000100, 0x00000000,
+ 0x00000100, 0x00010004, 0x04010104, 0x04000100,
+ 0x04000004, 0x00000100, 0x00000000, 0x04010004,
+ 0x04000104, 0x00010000, 0x04000000, 0x04010104,
+ 0x00000004, 0x00010104, 0x00010100, 0x04000004,
+ 0x04010000, 0x04000104, 0x00000104, 0x04010000,
+ 0x00010104, 0x00000004, 0x04010004, 0x00010100
+};
+
+static const uint32_t S4[] = {
+ 0x80401000, 0x80001040, 0x80001040, 0x00000040,
+ 0x00401040, 0x80400040, 0x80400000, 0x80001000,
+ 0x00000000, 0x00401000, 0x00401000, 0x80401040,
+ 0x80000040, 0x00000000, 0x00400040, 0x80400000,
+ 0x80000000, 0x00001000, 0x00400000, 0x80401000,
+ 0x00000040, 0x00400000, 0x80001000, 0x00001040,
+ 0x80400040, 0x80000000, 0x00001040, 0x00400040,
+ 0x00001000, 0x00401040, 0x80401040, 0x80000040,
+ 0x00400040, 0x80400000, 0x00401000, 0x80401040,
+ 0x80000040, 0x00000000, 0x00000000, 0x00401000,
+ 0x00001040, 0x00400040, 0x80400040, 0x80000000,
+ 0x80401000, 0x80001040, 0x80001040, 0x00000040,
+ 0x80401040, 0x80000040, 0x80000000, 0x00001000,
+ 0x80400000, 0x80001000, 0x00401040, 0x80400040,
+ 0x80001000, 0x00001040, 0x00400000, 0x80401000,
+ 0x00000040, 0x00400000, 0x00001000, 0x00401040
+};
+
+static const uint32_t S5[] = {
+ 0x00000080, 0x01040080, 0x01040000, 0x21000080,
+ 0x00040000, 0x00000080, 0x20000000, 0x01040000,
+ 0x20040080, 0x00040000, 0x01000080, 0x20040080,
+ 0x21000080, 0x21040000, 0x00040080, 0x20000000,
+ 0x01000000, 0x20040000, 0x20040000, 0x00000000,
+ 0x20000080, 0x21040080, 0x21040080, 0x01000080,
+ 0x21040000, 0x20000080, 0x00000000, 0x21000000,
+ 0x01040080, 0x01000000, 0x21000000, 0x00040080,
+ 0x00040000, 0x21000080, 0x00000080, 0x01000000,
+ 0x20000000, 0x01040000, 0x21000080, 0x20040080,
+ 0x01000080, 0x20000000, 0x21040000, 0x01040080,
+ 0x20040080, 0x00000080, 0x01000000, 0x21040000,
+ 0x21040080, 0x00040080, 0x21000000, 0x21040080,
+ 0x01040000, 0x00000000, 0x20040000, 0x21000000,
+ 0x00040080, 0x01000080, 0x20000080, 0x00040000,
+ 0x00000000, 0x20040000, 0x01040080, 0x20000080
+};
+
+static const uint32_t S6[] = {
+ 0x10000008, 0x10200000, 0x00002000, 0x10202008,
+ 0x10200000, 0x00000008, 0x10202008, 0x00200000,
+ 0x10002000, 0x00202008, 0x00200000, 0x10000008,
+ 0x00200008, 0x10002000, 0x10000000, 0x00002008,
+ 0x00000000, 0x00200008, 0x10002008, 0x00002000,
+ 0x00202000, 0x10002008, 0x00000008, 0x10200008,
+ 0x10200008, 0x00000000, 0x00202008, 0x10202000,
+ 0x00002008, 0x00202000, 0x10202000, 0x10000000,
+ 0x10002000, 0x00000008, 0x10200008, 0x00202000,
+ 0x10202008, 0x00200000, 0x00002008, 0x10000008,
+ 0x00200000, 0x10002000, 0x10000000, 0x00002008,
+ 0x10000008, 0x10202008, 0x00202000, 0x10200000,
+ 0x00202008, 0x10202000, 0x00000000, 0x10200008,
+ 0x00000008, 0x00002000, 0x10200000, 0x00202008,
+ 0x00002000, 0x00200008, 0x10002008, 0x00000000,
+ 0x10202000, 0x10000000, 0x00200008, 0x10002008
+};
+
+static const uint32_t S7[] = {
+ 0x00100000, 0x02100001, 0x02000401, 0x00000000,
+ 0x00000400, 0x02000401, 0x00100401, 0x02100400,
+ 0x02100401, 0x00100000, 0x00000000, 0x02000001,
+ 0x00000001, 0x02000000, 0x02100001, 0x00000401,
+ 0x02000400, 0x00100401, 0x00100001, 0x02000400,
+ 0x02000001, 0x02100000, 0x02100400, 0x00100001,
+ 0x02100000, 0x00000400, 0x00000401, 0x02100401,
+ 0x00100400, 0x00000001, 0x02000000, 0x00100400,
+ 0x02000000, 0x00100400, 0x00100000, 0x02000401,
+ 0x02000401, 0x02100001, 0x02100001, 0x00000001,
+ 0x00100001, 0x02000000, 0x02000400, 0x00100000,
+ 0x02100400, 0x00000401, 0x00100401, 0x02100400,
+ 0x00000401, 0x02000001, 0x02100401, 0x02100000,
+ 0x00100400, 0x00000000, 0x00000001, 0x02100401,
+ 0x00000000, 0x00100401, 0x02100000, 0x00000400,
+ 0x02000001, 0x02000400, 0x00000400, 0x00100001
+};
+
+static const uint32_t S8[] = {
+ 0x08000820, 0x00000800, 0x00020000, 0x08020820,
+ 0x08000000, 0x08000820, 0x00000020, 0x08000000,
+ 0x00020020, 0x08020000, 0x08020820, 0x00020800,
+ 0x08020800, 0x00020820, 0x00000800, 0x00000020,
+ 0x08020000, 0x08000020, 0x08000800, 0x00000820,
+ 0x00020800, 0x00020020, 0x08020020, 0x08020800,
+ 0x00000820, 0x00000000, 0x00000000, 0x08020020,
+ 0x08000020, 0x08000800, 0x00020820, 0x00020000,
+ 0x00020820, 0x00020000, 0x08020800, 0x00000800,
+ 0x00000020, 0x08020020, 0x00000800, 0x00020820,
+ 0x08000800, 0x00000020, 0x08000020, 0x08020000,
+ 0x08020020, 0x08000000, 0x00020000, 0x08000820,
+ 0x00000000, 0x08020820, 0x00020020, 0x08000020,
+ 0x08020000, 0x08000800, 0x08000820, 0x00000000,
+ 0x08020820, 0x00020800, 0x00020800, 0x00000820,
+ 0x00000820, 0x00020020, 0x08000000, 0x08020800
+};
+
+static inline uint32_t
+Fconf(uint32_t r0, uint32_t skl, uint32_t skr)
+{
+ uint32_t r1;
+
+ r1 = (r0 << 16) | (r0 >> 16);
+ return
+ S1[((r1 >> 11) ^ (skl >> 18)) & 0x3F]
+ | S2[((r0 >> 23) ^ (skl >> 12)) & 0x3F]
+ | S3[((r0 >> 19) ^ (skl >> 6)) & 0x3F]
+ | S4[((r0 >> 15) ^ (skl )) & 0x3F]
+ | S5[((r0 >> 11) ^ (skr >> 18)) & 0x3F]
+ | S6[((r0 >> 7) ^ (skr >> 12)) & 0x3F]
+ | S7[((r0 >> 3) ^ (skr >> 6)) & 0x3F]
+ | S8[((r1 >> 15) ^ (skr )) & 0x3F];
+}
+
+static void
+process_block_unit(uint32_t *pl, uint32_t *pr, const uint32_t *skey)
+{
+ int i;
+ uint32_t l, r;
+
+ l = *pl;
+ r = *pr;
+ for (i = 0; i < 16; i ++) {
+ uint32_t t;
+
+ t = l ^ Fconf(r, skey[(i << 1) + 0], skey[(i << 1) + 1]);
+ l = r;
+ r = t;
+ }
+ *pl = r;
+ *pr = l;
+}
+
+/* see inner.h */
+void
+br_des_tab_process_block(unsigned num_rounds, const uint32_t *skey, void *block)
+{
+ unsigned char *buf;
+ uint32_t l, r;
+
+ buf = block;
+ l = br_dec32be(buf);
+ r = br_dec32be(buf + 4);
+ br_des_do_IP(&l, &r);
+ while (num_rounds -- > 0) {
+ process_block_unit(&l, &r, skey);
+ skey += 32;
+ }
+ br_des_do_invIP(&l, &r);
+ br_enc32be(buf, l);
+ br_enc32be(buf + 4, r);
+}
+
+static void
+keysched_unit(uint32_t *skey, const void *key)
+{
+ int i;
+
+ br_des_keysched_unit(skey, key);
+
+ /*
+ * Apply PC-2 to get the 48-bit subkeys.
+ */
+ for (i = 0; i < 16; i ++) {
+ uint32_t xl, xr, ul, ur;
+ int j;
+
+ xl = skey[(i << 1) + 0];
+ xr = skey[(i << 1) + 1];
+ ul = 0;
+ ur = 0;
+ for (j = 0; j < 28; j ++) {
+ ul |= (xl & 1) << PC2left[j];
+ ur |= (xr & 1) << PC2right[j];
+ xl >>= 1;
+ xr >>= 1;
+ }
+ skey[(i << 1) + 0] = ul;
+ skey[(i << 1) + 1] = ur;
+ }
+}
+
+/* see inner.h */
+unsigned
+br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len)
+{
+ switch (key_len) {
+ case 8:
+ keysched_unit(skey, key);
+ return 1;
+ case 16:
+ keysched_unit(skey, key);
+ keysched_unit(skey + 32, (const unsigned char *)key + 8);
+ br_des_rev_skey(skey + 32);
+ memcpy(skey + 64, skey, 32 * sizeof *skey);
+ return 3;
+ default:
+ keysched_unit(skey, key);
+ keysched_unit(skey + 32, (const unsigned char *)key + 8);
+ br_des_rev_skey(skey + 32);
+ keysched_unit(skey + 64, (const unsigned char *)key + 16);
+ return 3;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/des_tab.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/des_tab_cbcdec.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/des_tab_cbcdec.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/des_tab_cbcdec.c (revision 346145)
@@ -0,0 +1,85 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_des_tab_cbcdec_vtable;
+ ctx->num_rounds = br_des_tab_keysched(ctx->skey, key, len);
+ if (len == 8) {
+ br_des_rev_skey(ctx->skey);
+ } else {
+ int i;
+
+ for (i = 0; i < 48; i += 2) {
+ uint32_t t;
+
+ t = ctx->skey[i];
+ ctx->skey[i] = ctx->skey[94 - i];
+ ctx->skey[94 - i] = t;
+ t = ctx->skey[i + 1];
+ ctx->skey[i + 1] = ctx->skey[95 - i];
+ ctx->skey[95 - i] = t;
+ }
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[8];
+ int i;
+
+ memcpy(tmp, buf, 8);
+ br_des_tab_process_block(ctx->num_rounds, ctx->skey, buf);
+ for (i = 0; i < 8; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ memcpy(ivbuf, tmp, 8);
+ buf += 8;
+ len -= 8;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcdec_class br_des_tab_cbcdec_vtable = {
+ sizeof(br_des_tab_cbcdec_keys),
+ 8,
+ 3,
+ (void (*)(const br_block_cbcdec_class **, const void *, size_t))
+ &br_des_tab_cbcdec_init,
+ (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
+ &br_des_tab_cbcdec_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/des_tab_cbcdec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/des_tab_cbcenc.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/des_tab_cbcenc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/des_tab_cbcenc.c (revision 346145)
@@ -0,0 +1,67 @@
+/*
+ * 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 bearssl_block.h */
+void
+br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx,
+ const void *key, size_t len)
+{
+ ctx->vtable = &br_des_tab_cbcenc_vtable;
+ ctx->num_rounds = br_des_tab_keysched(ctx->skey, key, len);
+}
+
+/* see bearssl_block.h */
+void
+br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx,
+ void *iv, void *data, size_t len)
+{
+ unsigned char *buf, *ivbuf;
+
+ ivbuf = iv;
+ buf = data;
+ while (len > 0) {
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ buf[i] ^= ivbuf[i];
+ }
+ br_des_tab_process_block(ctx->num_rounds, ctx->skey, buf);
+ memcpy(ivbuf, buf, 8);
+ buf += 8;
+ len -= 8;
+ }
+}
+
+/* see bearssl_block.h */
+const br_block_cbcenc_class br_des_tab_cbcenc_vtable = {
+ sizeof(br_des_tab_cbcenc_keys),
+ 8,
+ 3,
+ (void (*)(const br_block_cbcenc_class **, const void *, size_t))
+ &br_des_tab_cbcenc_init,
+ (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
+ &br_des_tab_cbcenc_run
+};
Property changes on: stable/12/contrib/bearssl/src/symcipher/des_tab_cbcenc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul.c (revision 346145)
@@ -0,0 +1,260 @@
+/*
+ * 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"
+
+/*
+ * Perform the inner processing of blocks for Poly1305. The accumulator
+ * and the r key are provided as arrays of 26-bit words (these words
+ * are allowed to have an extra bit, i.e. use 27 bits).
+ *
+ * On output, all accumulator words fit on 26 bits, except acc[1], which
+ * may be slightly larger (but by a very small amount only).
+ */
+static void
+poly1305_inner(uint32_t *acc, const uint32_t *r, const void *data, size_t len)
+{
+ /*
+ * Implementation notes: we split the 130-bit values into five
+ * 26-bit words. This gives us some space for carries.
+ *
+ * This code is inspired from the public-domain code available
+ * on:
+ * https://github.com/floodyberry/poly1305-donna
+ *
+ * Since we compute modulo 2^130-5, the "upper words" become
+ * low words with a factor of 5; that is, x*2^130 = x*5 mod p.
+ */
+ const unsigned char *buf;
+ uint32_t a0, a1, a2, a3, a4;
+ uint32_t r0, r1, r2, r3, r4;
+ uint32_t u1, u2, u3, u4;
+
+ r0 = r[0];
+ r1 = r[1];
+ r2 = r[2];
+ r3 = r[3];
+ r4 = r[4];
+
+ u1 = r1 * 5;
+ u2 = r2 * 5;
+ u3 = r3 * 5;
+ u4 = r4 * 5;
+
+ a0 = acc[0];
+ a1 = acc[1];
+ a2 = acc[2];
+ a3 = acc[3];
+ a4 = acc[4];
+
+ buf = data;
+ while (len > 0) {
+ uint64_t w0, w1, w2, w3, w4;
+ uint64_t c;
+ unsigned char tmp[16];
+
+ /*
+ * If there is a partial block, right-pad it with zeros.
+ */
+ if (len < 16) {
+ memset(tmp, 0, sizeof tmp);
+ memcpy(tmp, buf, len);
+ buf = tmp;
+ len = 16;
+ }
+
+ /*
+ * Decode next block and apply the "high bit"; that value
+ * is added to the accumulator.
+ */
+ a0 += br_dec32le(buf) & 0x03FFFFFF;
+ a1 += (br_dec32le(buf + 3) >> 2) & 0x03FFFFFF;
+ a2 += (br_dec32le(buf + 6) >> 4) & 0x03FFFFFF;
+ a3 += (br_dec32le(buf + 9) >> 6) & 0x03FFFFFF;
+ a4 += (br_dec32le(buf + 12) >> 8) | 0x01000000;
+
+ /*
+ * Compute multiplication.
+ */
+#define M(x, y) ((uint64_t)(x) * (uint64_t)(y))
+
+ w0 = M(a0, r0) + M(a1, u4) + M(a2, u3) + M(a3, u2) + M(a4, u1);
+ w1 = M(a0, r1) + M(a1, r0) + M(a2, u4) + M(a3, u3) + M(a4, u2);
+ w2 = M(a0, r2) + M(a1, r1) + M(a2, r0) + M(a3, u4) + M(a4, u3);
+ w3 = M(a0, r3) + M(a1, r2) + M(a2, r1) + M(a3, r0) + M(a4, u4);
+ w4 = M(a0, r4) + M(a1, r3) + M(a2, r2) + M(a3, r1) + M(a4, r0);
+
+#undef M
+ /*
+ * Perform some (partial) modular reduction. This step is
+ * enough to keep values in ranges such that there won't
+ * be carry overflows. Most of the reduction was done in
+ * the multiplication step (by using the 'u*' values, and
+ * using the fact that 2^130 = -5 mod p); here we perform
+ * some carry propagation.
+ */
+ c = w0 >> 26;
+ a0 = (uint32_t)w0 & 0x3FFFFFF;
+ w1 += c;
+ c = w1 >> 26;
+ a1 = (uint32_t)w1 & 0x3FFFFFF;
+ w2 += c;
+ c = w2 >> 26;
+ a2 = (uint32_t)w2 & 0x3FFFFFF;
+ w3 += c;
+ c = w3 >> 26;
+ a3 = (uint32_t)w3 & 0x3FFFFFF;
+ w4 += c;
+ c = w4 >> 26;
+ a4 = (uint32_t)w4 & 0x3FFFFFF;
+ a0 += (uint32_t)c * 5;
+ a1 += a0 >> 26;
+ a0 &= 0x3FFFFFF;
+
+ buf += 16;
+ len -= 16;
+ }
+
+ acc[0] = a0;
+ acc[1] = a1;
+ acc[2] = a2;
+ acc[3] = a3;
+ acc[4] = a4;
+}
+
+/* see bearssl_block.h */
+void
+br_poly1305_ctmul_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt)
+{
+ unsigned char pkey[32], foot[16];
+ uint32_t r[5], acc[5], cc, ctl, hi;
+ uint64_t w;
+ int i;
+
+ /*
+ * Compute the MAC key. The 'r' value is the first 16 bytes of
+ * pkey[].
+ */
+ memset(pkey, 0, sizeof pkey);
+ ichacha(key, iv, 0, pkey, sizeof pkey);
+
+ /*
+ * If encrypting, ChaCha20 must run first, followed by Poly1305.
+ * When decrypting, the operations are reversed.
+ */
+ if (encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+
+ /*
+ * Run Poly1305. We must process the AAD, then ciphertext, then
+ * the footer (with the lengths). Note that the AAD and ciphertext
+ * are meant to be padded with zeros up to the next multiple of 16,
+ * and the length of the footer is 16 bytes as well.
+ */
+
+ /*
+ * Decode the 'r' value into 26-bit words, with the "clamping"
+ * operation applied.
+ */
+ r[0] = br_dec32le(pkey) & 0x03FFFFFF;
+ r[1] = (br_dec32le(pkey + 3) >> 2) & 0x03FFFF03;
+ r[2] = (br_dec32le(pkey + 6) >> 4) & 0x03FFC0FF;
+ r[3] = (br_dec32le(pkey + 9) >> 6) & 0x03F03FFF;
+ r[4] = (br_dec32le(pkey + 12) >> 8) & 0x000FFFFF;
+
+ /*
+ * Accumulator is 0.
+ */
+ memset(acc, 0, sizeof acc);
+
+ /*
+ * Process the additional authenticated data, ciphertext, and
+ * footer in due order.
+ */
+ br_enc64le(foot, (uint64_t)aad_len);
+ br_enc64le(foot + 8, (uint64_t)len);
+ poly1305_inner(acc, r, aad, aad_len);
+ poly1305_inner(acc, r, data, len);
+ poly1305_inner(acc, r, foot, sizeof foot);
+
+ /*
+ * Finalise modular reduction. This is done with carry propagation
+ * and applying the '2^130 = -5 mod p' rule. Note that the output
+ * of poly1035_inner() is already mostly reduced, since only
+ * acc[1] may be (very slightly) above 2^26. A single loop back
+ * to acc[1] will be enough to make the value fit in 130 bits.
+ */
+ cc = 0;
+ for (i = 1; i <= 6; i ++) {
+ int j;
+
+ j = (i >= 5) ? i - 5 : i;
+ acc[j] += cc;
+ cc = acc[j] >> 26;
+ acc[j] &= 0x03FFFFFF;
+ }
+
+ /*
+ * We may still have a value in the 2^130-5..2^130-1 range, in
+ * which case we must reduce it again. The code below selects,
+ * in constant-time, between 'acc' and 'acc-p',
+ */
+ ctl = GT(acc[0], 0x03FFFFFA);
+ for (i = 1; i < 5; i ++) {
+ ctl &= EQ(acc[i], 0x03FFFFFF);
+ }
+ cc = 5;
+ for (i = 0; i < 5; i ++) {
+ uint32_t t;
+
+ t = (acc[i] + cc);
+ cc = t >> 26;
+ t &= 0x03FFFFFF;
+ acc[i] = MUX(ctl, t, acc[i]);
+ }
+
+ /*
+ * Convert back the accumulator to 32-bit words, and add the
+ * 's' value (second half of pkey[]). That addition is done
+ * modulo 2^128.
+ */
+ w = (uint64_t)acc[0] + ((uint64_t)acc[1] << 26) + br_dec32le(pkey + 16);
+ br_enc32le((unsigned char *)tag, (uint32_t)w);
+ w = (w >> 32) + ((uint64_t)acc[2] << 20) + br_dec32le(pkey + 20);
+ br_enc32le((unsigned char *)tag + 4, (uint32_t)w);
+ w = (w >> 32) + ((uint64_t)acc[3] << 14) + br_dec32le(pkey + 24);
+ br_enc32le((unsigned char *)tag + 8, (uint32_t)w);
+ hi = (uint32_t)(w >> 32) + (acc[4] << 8) + br_dec32le(pkey + 28);
+ br_enc32le((unsigned char *)tag + 12, hi);
+
+ /*
+ * If decrypting, then ChaCha20 runs _after_ Poly1305.
+ */
+ if (!encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul32.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul32.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul32.c (revision 346145)
@@ -0,0 +1,297 @@
+/*
+ * 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"
+
+/*
+ * Perform the inner processing of blocks for Poly1305.
+ */
+static void
+poly1305_inner(uint32_t *a, const uint32_t *r, const void *data, size_t len)
+{
+ /*
+ * Implementation notes: we split the 130-bit values into ten
+ * 13-bit words. This gives us some space for carries and allows
+ * using only 32x32->32 multiplications, which are way faster than
+ * 32x32->64 multiplications on the ARM Cortex-M0/M0+, and also
+ * help in making constant-time code on the Cortex-M3.
+ *
+ * Since we compute modulo 2^130-5, the "upper words" become
+ * low words with a factor of 5; that is, x*2^130 = x*5 mod p.
+ * This has already been integrated in the r[] array, which
+ * is extended to the 0..18 range.
+ *
+ * In each loop iteration, a[] and r[] words are 13-bit each,
+ * except a[1] which may use 14 bits.
+ */
+ const unsigned char *buf;
+
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[16];
+ uint32_t b[10];
+ unsigned u, v;
+ uint32_t z, cc1, cc2;
+
+ /*
+ * If there is a partial block, right-pad it with zeros.
+ */
+ if (len < 16) {
+ memset(tmp, 0, sizeof tmp);
+ memcpy(tmp, buf, len);
+ buf = tmp;
+ len = 16;
+ }
+
+ /*
+ * Decode next block and apply the "high bit"; that value
+ * is added to the accumulator.
+ */
+ v = br_dec16le(buf);
+ a[0] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[2] << 3;
+ v |= buf[3] << 11;
+ a[1] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[4] << 6;
+ a[2] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[5] << 1;
+ v |= buf[6] << 9;
+ a[3] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[7] << 4;
+ v |= buf[8] << 12;
+ a[4] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[9] << 7;
+ a[5] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[10] << 2;
+ v |= buf[11] << 10;
+ a[6] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[12] << 5;
+ a[7] += v & 0x01FFF;
+ v = br_dec16le(buf + 13);
+ a[8] += v & 0x01FFF;
+ v >>= 13;
+ v |= buf[15] << 3;
+ a[9] += v | 0x00800;
+
+ /*
+ * At that point, all a[] values fit on 14 bits, while
+ * all r[] values fit on 13 bits. Thus products fit on
+ * 27 bits, and we can accumulate up to 31 of them in
+ * a 32-bit word and still have some room for carries.
+ */
+
+ /*
+ * Now a[] contains words with values up to 14 bits each.
+ * We perform the multiplication with r[].
+ *
+ * The extended words of r[] may be larger than 13 bits
+ * (they are 5 times a 13-bit word) so the full summation
+ * may yield values up to 46 times a 27-bit word, which
+ * does not fit on a 32-bit word. To avoid that issue, we
+ * must split the loop below in two, with a carry
+ * propagation operation in the middle.
+ */
+ cc1 = 0;
+ for (u = 0; u < 10; u ++) {
+ uint32_t s;
+
+ s = cc1
+ + MUL15(a[0], r[u + 9 - 0])
+ + MUL15(a[1], r[u + 9 - 1])
+ + MUL15(a[2], r[u + 9 - 2])
+ + MUL15(a[3], r[u + 9 - 3])
+ + MUL15(a[4], r[u + 9 - 4]);
+ b[u] = s & 0x1FFF;
+ cc1 = s >> 13;
+ }
+ cc2 = 0;
+ for (u = 0; u < 10; u ++) {
+ uint32_t s;
+
+ s = b[u] + cc2
+ + MUL15(a[5], r[u + 9 - 5])
+ + MUL15(a[6], r[u + 9 - 6])
+ + MUL15(a[7], r[u + 9 - 7])
+ + MUL15(a[8], r[u + 9 - 8])
+ + MUL15(a[9], r[u + 9 - 9]);
+ b[u] = s & 0x1FFF;
+ cc2 = s >> 13;
+ }
+ memcpy(a, b, sizeof b);
+
+ /*
+ * The two carries "loop back" with a factor of 5. We
+ * propagate them into a[0] and a[1].
+ */
+ z = cc1 + cc2;
+ z += (z << 2) + a[0];
+ a[0] = z & 0x1FFF;
+ a[1] += z >> 13;
+
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_poly1305_ctmul32_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt)
+{
+ unsigned char pkey[32], foot[16];
+ uint32_t z, r[19], acc[10], cc, ctl;
+ int i;
+
+ /*
+ * Compute the MAC key. The 'r' value is the first 16 bytes of
+ * pkey[].
+ */
+ memset(pkey, 0, sizeof pkey);
+ ichacha(key, iv, 0, pkey, sizeof pkey);
+
+ /*
+ * If encrypting, ChaCha20 must run first, followed by Poly1305.
+ * When decrypting, the operations are reversed.
+ */
+ if (encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+
+ /*
+ * Run Poly1305. We must process the AAD, then ciphertext, then
+ * the footer (with the lengths). Note that the AAD and ciphertext
+ * are meant to be padded with zeros up to the next multiple of 16,
+ * and the length of the footer is 16 bytes as well.
+ */
+
+ /*
+ * Decode the 'r' value into 13-bit words, with the "clamping"
+ * operation applied.
+ */
+ z = br_dec32le(pkey) & 0x03FFFFFF;
+ r[9] = z & 0x1FFF;
+ r[10] = z >> 13;
+ z = (br_dec32le(pkey + 3) >> 2) & 0x03FFFF03;
+ r[11] = z & 0x1FFF;
+ r[12] = z >> 13;
+ z = (br_dec32le(pkey + 6) >> 4) & 0x03FFC0FF;
+ r[13] = z & 0x1FFF;
+ r[14] = z >> 13;
+ z = (br_dec32le(pkey + 9) >> 6) & 0x03F03FFF;
+ r[15] = z & 0x1FFF;
+ r[16] = z >> 13;
+ z = (br_dec32le(pkey + 12) >> 8) & 0x000FFFFF;
+ r[17] = z & 0x1FFF;
+ r[18] = z >> 13;
+
+ /*
+ * Extend r[] with the 5x factor pre-applied.
+ */
+ for (i = 0; i < 9; i ++) {
+ r[i] = MUL15(5, r[i + 10]);
+ }
+
+ /*
+ * Accumulator is 0.
+ */
+ memset(acc, 0, sizeof acc);
+
+ /*
+ * Process the additional authenticated data, ciphertext, and
+ * footer in due order.
+ */
+ br_enc64le(foot, (uint64_t)aad_len);
+ br_enc64le(foot + 8, (uint64_t)len);
+ poly1305_inner(acc, r, aad, aad_len);
+ poly1305_inner(acc, r, data, len);
+ poly1305_inner(acc, r, foot, sizeof foot);
+
+ /*
+ * Finalise modular reduction. This is done with carry propagation
+ * and applying the '2^130 = -5 mod p' rule. Note that the output
+ * of poly1035_inner() is already mostly reduced, since only
+ * acc[1] may be (very slightly) above 2^13. A single loop back
+ * to acc[1] will be enough to make the value fit in 130 bits.
+ */
+ cc = 0;
+ for (i = 1; i < 10; i ++) {
+ z = acc[i] + cc;
+ acc[i] = z & 0x1FFF;
+ cc = z >> 13;
+ }
+ z = acc[0] + cc + (cc << 2);
+ acc[0] = z & 0x1FFF;
+ acc[1] += z >> 13;
+
+ /*
+ * We may still have a value in the 2^130-5..2^130-1 range, in
+ * which case we must reduce it again. The code below selects,
+ * in constant-time, between 'acc' and 'acc-p',
+ */
+ ctl = GT(acc[0], 0x1FFA);
+ for (i = 1; i < 10; i ++) {
+ ctl &= EQ(acc[i], 0x1FFF);
+ }
+ acc[0] = MUX(ctl, acc[0] - 0x1FFB, acc[0]);
+ for (i = 1; i < 10; i ++) {
+ acc[i] &= ~(-ctl);
+ }
+
+ /*
+ * Convert back the accumulator to 32-bit words, and add the
+ * 's' value (second half of pkey[]). That addition is done
+ * modulo 2^128.
+ */
+ z = acc[0] + (acc[1] << 13) + br_dec16le(pkey + 16);
+ br_enc16le((unsigned char *)tag, z & 0xFFFF);
+ z = (z >> 16) + (acc[2] << 10) + br_dec16le(pkey + 18);
+ br_enc16le((unsigned char *)tag + 2, z & 0xFFFF);
+ z = (z >> 16) + (acc[3] << 7) + br_dec16le(pkey + 20);
+ br_enc16le((unsigned char *)tag + 4, z & 0xFFFF);
+ z = (z >> 16) + (acc[4] << 4) + br_dec16le(pkey + 22);
+ br_enc16le((unsigned char *)tag + 6, z & 0xFFFF);
+ z = (z >> 16) + (acc[5] << 1) + (acc[6] << 14) + br_dec16le(pkey + 24);
+ br_enc16le((unsigned char *)tag + 8, z & 0xFFFF);
+ z = (z >> 16) + (acc[7] << 11) + br_dec16le(pkey + 26);
+ br_enc16le((unsigned char *)tag + 10, z & 0xFFFF);
+ z = (z >> 16) + (acc[8] << 8) + br_dec16le(pkey + 28);
+ br_enc16le((unsigned char *)tag + 12, z & 0xFFFF);
+ z = (z >> 16) + (acc[9] << 5) + br_dec16le(pkey + 30);
+ br_enc16le((unsigned char *)tag + 14, z & 0xFFFF);
+
+ /*
+ * If decrypting, then ChaCha20 runs _after_ Poly1305.
+ */
+ if (!encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/poly1305_ctmul32.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/poly1305_ctmulq.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/poly1305_ctmulq.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/poly1305_ctmulq.c (revision 346145)
@@ -0,0 +1,475 @@
+/*
+ * 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"
+
+#if BR_INT128 || BR_UMUL128
+
+#if BR_INT128
+
+#define MUL128(hi, lo, x, y) do { \
+ unsigned __int128 mul128tmp; \
+ mul128tmp = (unsigned __int128)(x) * (unsigned __int128)(y); \
+ (hi) = (uint64_t)(mul128tmp >> 64); \
+ (lo) = (uint64_t)mul128tmp; \
+ } while (0)
+
+#elif BR_UMUL128
+
+#include <intrin.h>
+
+#define MUL128(hi, lo, x, y) do { \
+ (lo) = _umul128((x), (y), &(hi)); \
+ } while (0)
+
+#endif
+
+#define MASK42 ((uint64_t)0x000003FFFFFFFFFF)
+#define MASK44 ((uint64_t)0x00000FFFFFFFFFFF)
+
+/*
+ * The "accumulator" word is nominally a 130-bit value. We split it into
+ * words of 44 bits, each held in a 64-bit variable.
+ *
+ * If the current accumulator is a = a0 + a1*W + a2*W^2 (where W = 2^44)
+ * and r = r0 + r1*W + r2*W^2, then:
+ *
+ * a*r = (a0*r0)
+ * + (a0*r1 + a1*r0) * W
+ * + (a0*r2 + a1*r1 + a2*r0) * W^2
+ * + (a1*r2 + a2*r1) * W^3
+ * + (a2*r2) * W^4
+ *
+ * We want to reduce that value modulo p = 2^130-5, so W^3 = 20 mod p,
+ * and W^4 = 20*W mod p. Thus, if we define u1 = 20*r1 and u2 = 20*r2,
+ * then the equations above become:
+ *
+ * b0 = a0*r0 + a1*u2 + a2*u1
+ * b1 = a0*r1 + a1*r0 + a2*u2
+ * b2 = a0*r2 + a1*r1 + a2*r0
+ *
+ * In order to make u1 fit in 44 bits, we can change these equations
+ * into:
+ *
+ * b0 = a0*r0 + a1*u2 + a2*t1
+ * b1 = a0*r1 + a1*r0 + a2*t2
+ * b2 = a0*r2 + a1*r1 + a2*r0
+ *
+ * Where t1 is u1 truncated to 44 bits, and t2 is u2 added to the extra
+ * bits of u1. Note that since r is clamped down to a 124-bit value, the
+ * values u2 and t2 fit on 44 bits too.
+ *
+ * The bx values are larger than 44 bits, so we may split them into a
+ * lower half (cx, 44 bits) and an upper half (dx). The new values for
+ * the accumulator are then:
+ *
+ * e0 = c0 + 20*d2
+ * e1 = c1 + d0
+ * e2 = c2 + d1
+ *
+ * The equations allow for some room, i.e. the ax values may be larger
+ * than 44 bits. Similarly, the ex values will usually be larger than
+ * the ax. Thus, some sort of carry propagation must be done regularly,
+ * though not necessarily at each iteration. In particular, we do not
+ * need to compute the additions (for the bx values) over 128-bit
+ * quantities; we can stick to 64-bit computations.
+ *
+ *
+ * Since the 128-bit result of a 64x64 multiplication is actually
+ * represented over two 64-bit registers, it is cheaper to arrange for
+ * any split that happens between the "high" and "low" halves to be on
+ * that 64-bit boundary. This is done by left shifting the rx, ux and tx
+ * by 20 bits (since they all fit on 44 bits each, this shift is
+ * always possible).
+ */
+
+static void
+poly1305_inner_big(uint64_t *acc, uint64_t *r, const void *data, size_t len)
+{
+
+#define MX(hi, lo, m0, m1, m2) do { \
+ uint64_t mxhi, mxlo; \
+ MUL128(mxhi, mxlo, a0, m0); \
+ (hi) = mxhi; \
+ (lo) = mxlo >> 20; \
+ MUL128(mxhi, mxlo, a1, m1); \
+ (hi) += mxhi; \
+ (lo) += mxlo >> 20; \
+ MUL128(mxhi, mxlo, a2, m2); \
+ (hi) += mxhi; \
+ (lo) += mxlo >> 20; \
+ } while (0)
+
+ const unsigned char *buf;
+ uint64_t a0, a1, a2;
+ uint64_t r0, r1, r2, t1, t2, u2;
+
+ r0 = r[0];
+ r1 = r[1];
+ r2 = r[2];
+ t1 = r[3];
+ t2 = r[4];
+ u2 = r[5];
+ a0 = acc[0];
+ a1 = acc[1];
+ a2 = acc[2];
+ buf = data;
+
+ while (len > 0) {
+ uint64_t v0, v1, v2;
+ uint64_t c0, c1, c2, d0, d1, d2;
+
+ v0 = br_dec64le(buf + 0);
+ v1 = br_dec64le(buf + 8);
+ v2 = v1 >> 24;
+ v1 = ((v0 >> 44) | (v1 << 20)) & MASK44;
+ v0 &= MASK44;
+ a0 += v0;
+ a1 += v1;
+ a2 += v2 + ((uint64_t)1 << 40);
+ MX(d0, c0, r0, u2, t1);
+ MX(d1, c1, r1, r0, t2);
+ MX(d2, c2, r2, r1, r0);
+ a0 = c0 + 20 * d2;
+ a1 = c1 + d0;
+ a2 = c2 + d1;
+
+ v0 = br_dec64le(buf + 16);
+ v1 = br_dec64le(buf + 24);
+ v2 = v1 >> 24;
+ v1 = ((v0 >> 44) | (v1 << 20)) & MASK44;
+ v0 &= MASK44;
+ a0 += v0;
+ a1 += v1;
+ a2 += v2 + ((uint64_t)1 << 40);
+ MX(d0, c0, r0, u2, t1);
+ MX(d1, c1, r1, r0, t2);
+ MX(d2, c2, r2, r1, r0);
+ a0 = c0 + 20 * d2;
+ a1 = c1 + d0;
+ a2 = c2 + d1;
+
+ v0 = br_dec64le(buf + 32);
+ v1 = br_dec64le(buf + 40);
+ v2 = v1 >> 24;
+ v1 = ((v0 >> 44) | (v1 << 20)) & MASK44;
+ v0 &= MASK44;
+ a0 += v0;
+ a1 += v1;
+ a2 += v2 + ((uint64_t)1 << 40);
+ MX(d0, c0, r0, u2, t1);
+ MX(d1, c1, r1, r0, t2);
+ MX(d2, c2, r2, r1, r0);
+ a0 = c0 + 20 * d2;
+ a1 = c1 + d0;
+ a2 = c2 + d1;
+
+ v0 = br_dec64le(buf + 48);
+ v1 = br_dec64le(buf + 56);
+ v2 = v1 >> 24;
+ v1 = ((v0 >> 44) | (v1 << 20)) & MASK44;
+ v0 &= MASK44;
+ a0 += v0;
+ a1 += v1;
+ a2 += v2 + ((uint64_t)1 << 40);
+ MX(d0, c0, r0, u2, t1);
+ MX(d1, c1, r1, r0, t2);
+ MX(d2, c2, r2, r1, r0);
+ a0 = c0 + 20 * d2;
+ a1 = c1 + d0;
+ a2 = c2 + d1;
+
+ a1 += a0 >> 44;
+ a0 &= MASK44;
+ a2 += a1 >> 44;
+ a1 &= MASK44;
+ a0 += 20 * (a2 >> 44);
+ a2 &= MASK44;
+
+ buf += 64;
+ len -= 64;
+ }
+ acc[0] = a0;
+ acc[1] = a1;
+ acc[2] = a2;
+
+#undef MX
+}
+
+static void
+poly1305_inner_small(uint64_t *acc, uint64_t *r, const void *data, size_t len)
+{
+ const unsigned char *buf;
+ uint64_t a0, a1, a2;
+ uint64_t r0, r1, r2, t1, t2, u2;
+
+ r0 = r[0];
+ r1 = r[1];
+ r2 = r[2];
+ t1 = r[3];
+ t2 = r[4];
+ u2 = r[5];
+ a0 = acc[0];
+ a1 = acc[1];
+ a2 = acc[2];
+ buf = data;
+
+ while (len > 0) {
+ uint64_t v0, v1, v2;
+ uint64_t c0, c1, c2, d0, d1, d2;
+ unsigned char tmp[16];
+
+ if (len < 16) {
+ memcpy(tmp, buf, len);
+ memset(tmp + len, 0, (sizeof tmp) - len);
+ buf = tmp;
+ len = 16;
+ }
+ v0 = br_dec64le(buf + 0);
+ v1 = br_dec64le(buf + 8);
+
+ v2 = v1 >> 24;
+ v1 = ((v0 >> 44) | (v1 << 20)) & MASK44;
+ v0 &= MASK44;
+
+ a0 += v0;
+ a1 += v1;
+ a2 += v2 + ((uint64_t)1 << 40);
+
+#define MX(hi, lo, m0, m1, m2) do { \
+ uint64_t mxhi, mxlo; \
+ MUL128(mxhi, mxlo, a0, m0); \
+ (hi) = mxhi; \
+ (lo) = mxlo >> 20; \
+ MUL128(mxhi, mxlo, a1, m1); \
+ (hi) += mxhi; \
+ (lo) += mxlo >> 20; \
+ MUL128(mxhi, mxlo, a2, m2); \
+ (hi) += mxhi; \
+ (lo) += mxlo >> 20; \
+ } while (0)
+
+ MX(d0, c0, r0, u2, t1);
+ MX(d1, c1, r1, r0, t2);
+ MX(d2, c2, r2, r1, r0);
+
+#undef MX
+
+ a0 = c0 + 20 * d2;
+ a1 = c1 + d0;
+ a2 = c2 + d1;
+
+ a1 += a0 >> 44;
+ a0 &= MASK44;
+ a2 += a1 >> 44;
+ a1 &= MASK44;
+ a0 += 20 * (a2 >> 44);
+ a2 &= MASK44;
+
+ buf += 16;
+ len -= 16;
+ }
+ acc[0] = a0;
+ acc[1] = a1;
+ acc[2] = a2;
+}
+
+static inline void
+poly1305_inner(uint64_t *acc, uint64_t *r, const void *data, size_t len)
+{
+ if (len >= 64) {
+ size_t len2;
+
+ len2 = len & ~(size_t)63;
+ poly1305_inner_big(acc, r, data, len2);
+ data = (const unsigned char *)data + len2;
+ len -= len2;
+ }
+ if (len > 0) {
+ poly1305_inner_small(acc, r, data, len);
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_poly1305_ctmulq_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt)
+{
+ unsigned char pkey[32], foot[16];
+ uint64_t r[6], acc[3], r0, r1;
+ uint32_t v0, v1, v2, v3, v4;
+ uint64_t w0, w1, w2, w3;
+ uint32_t ctl;
+
+ /*
+ * Compute the MAC key. The 'r' value is the first 16 bytes of
+ * pkey[].
+ */
+ memset(pkey, 0, sizeof pkey);
+ ichacha(key, iv, 0, pkey, sizeof pkey);
+
+ /*
+ * If encrypting, ChaCha20 must run first, followed by Poly1305.
+ * When decrypting, the operations are reversed.
+ */
+ if (encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+
+ /*
+ * Run Poly1305. We must process the AAD, then ciphertext, then
+ * the footer (with the lengths). Note that the AAD and ciphertext
+ * are meant to be padded with zeros up to the next multiple of 16,
+ * and the length of the footer is 16 bytes as well.
+ */
+
+ /*
+ * Apply the "clamping" on r.
+ */
+ pkey[ 3] &= 0x0F;
+ pkey[ 4] &= 0xFC;
+ pkey[ 7] &= 0x0F;
+ pkey[ 8] &= 0xFC;
+ pkey[11] &= 0x0F;
+ pkey[12] &= 0xFC;
+ pkey[15] &= 0x0F;
+
+ /*
+ * Decode the 'r' value into 44-bit words, left-shifted by 20 bits.
+ * Also compute the u1 and u2 values.
+ */
+ r0 = br_dec64le(pkey + 0);
+ r1 = br_dec64le(pkey + 8);
+ r[0] = r0 << 20;
+ r[1] = ((r0 >> 24) | (r1 << 40)) & ~(uint64_t)0xFFFFF;
+ r[2] = (r1 >> 4) & ~(uint64_t)0xFFFFF;
+ r1 = 20 * (r[1] >> 20);
+ r[3] = r1 << 20;
+ r[5] = 20 * r[2];
+ r[4] = (r[5] + (r1 >> 24)) & ~(uint64_t)0xFFFFF;
+
+ /*
+ * Accumulator is 0.
+ */
+ acc[0] = 0;
+ acc[1] = 0;
+ acc[2] = 0;
+
+ /*
+ * Process the additional authenticated data, ciphertext, and
+ * footer in due order.
+ */
+ br_enc64le(foot, (uint64_t)aad_len);
+ br_enc64le(foot + 8, (uint64_t)len);
+ poly1305_inner(acc, r, aad, aad_len);
+ poly1305_inner(acc, r, data, len);
+ poly1305_inner_small(acc, r, foot, sizeof foot);
+
+ /*
+ * Finalise modular reduction. At that point, the value consists
+ * in three 44-bit values (the lowest one might be slightly above
+ * 2^44). Two loops shall be sufficient.
+ */
+ acc[1] += (acc[0] >> 44);
+ acc[0] &= MASK44;
+ acc[2] += (acc[1] >> 44);
+ acc[1] &= MASK44;
+ acc[0] += 5 * (acc[2] >> 42);
+ acc[2] &= MASK42;
+ acc[1] += (acc[0] >> 44);
+ acc[0] &= MASK44;
+ acc[2] += (acc[1] >> 44);
+ acc[1] &= MASK44;
+ acc[0] += 5 * (acc[2] >> 42);
+ acc[2] &= MASK42;
+
+ /*
+ * The value may still fall in the 2^130-5..2^130-1 range, in
+ * which case we must reduce it again. The code below selects,
+ * in constant-time, between 'acc' and 'acc-p'. We encode the
+ * value over four 32-bit integers to finish the operation.
+ */
+ v0 = (uint32_t)acc[0];
+ v1 = (uint32_t)(acc[0] >> 32) | ((uint32_t)acc[1] << 12);
+ v2 = (uint32_t)(acc[1] >> 20) | ((uint32_t)acc[2] << 24);
+ v3 = (uint32_t)(acc[2] >> 8);
+ v4 = (uint32_t)(acc[2] >> 40);
+
+ ctl = GT(v0, 0xFFFFFFFA);
+ ctl &= EQ(v1, 0xFFFFFFFF);
+ ctl &= EQ(v2, 0xFFFFFFFF);
+ ctl &= EQ(v3, 0xFFFFFFFF);
+ ctl &= EQ(v4, 0x00000003);
+ v0 = MUX(ctl, v0 + 5, v0);
+ v1 = MUX(ctl, 0, v1);
+ v2 = MUX(ctl, 0, v2);
+ v3 = MUX(ctl, 0, v3);
+
+ /*
+ * Add the "s" value. This is done modulo 2^128. Don't forget
+ * carry propagation...
+ */
+ w0 = (uint64_t)v0 + (uint64_t)br_dec32le(pkey + 16);
+ w1 = (uint64_t)v1 + (uint64_t)br_dec32le(pkey + 20) + (w0 >> 32);
+ w2 = (uint64_t)v2 + (uint64_t)br_dec32le(pkey + 24) + (w1 >> 32);
+ w3 = (uint64_t)v3 + (uint64_t)br_dec32le(pkey + 28) + (w2 >> 32);
+ v0 = (uint32_t)w0;
+ v1 = (uint32_t)w1;
+ v2 = (uint32_t)w2;
+ v3 = (uint32_t)w3;
+
+ /*
+ * Encode the tag.
+ */
+ br_enc32le((unsigned char *)tag + 0, v0);
+ br_enc32le((unsigned char *)tag + 4, v1);
+ br_enc32le((unsigned char *)tag + 8, v2);
+ br_enc32le((unsigned char *)tag + 12, v3);
+
+ /*
+ * If decrypting, then ChaCha20 runs _after_ Poly1305.
+ */
+ if (!encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+}
+
+/* see bearssl_block.h */
+br_poly1305_run
+br_poly1305_ctmulq_get(void)
+{
+ return &br_poly1305_ctmulq_run;
+}
+
+#else
+
+/* see bearssl_block.h */
+br_poly1305_run
+br_poly1305_ctmulq_get(void)
+{
+ return 0;
+}
+
+#endif
Property changes on: stable/12/contrib/bearssl/src/symcipher/poly1305_ctmulq.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/symcipher/poly1305_i15.c
===================================================================
--- stable/12/contrib/bearssl/src/symcipher/poly1305_i15.c (nonexistent)
+++ stable/12/contrib/bearssl/src/symcipher/poly1305_i15.c (revision 346145)
@@ -0,0 +1,221 @@
+/*
+ * 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"
+
+/*
+ * This is a "reference" implementation of Poly1305 that uses the
+ * generic "i15" code for big integers. It is slow, but it handles all
+ * big-integer operations with generic code, thereby avoiding most
+ * tricky situations with carry propagation and modular reduction.
+ */
+
+/*
+ * Modulus: 2^130-5.
+ */
+static const uint16_t P1305[] = {
+ 0x008A,
+ 0x7FFB, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x03FF
+};
+
+/*
+ * -p mod 2^15.
+ */
+#define P0I 0x4CCD
+
+/*
+ * R^2 mod p, for conversion to Montgomery representation (R = 2^135,
+ * since we use 9 words of 15 bits each, and 15*9 = 135).
+ */
+static const uint16_t R2[] = {
+ 0x008A,
+ 0x6400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+/*
+ * Perform the inner processing of blocks for Poly1305. The "r" array
+ * is in Montgomery representation, while the "a" array is not.
+ */
+static void
+poly1305_inner(uint16_t *a, const uint16_t *r, const void *data, size_t len)
+{
+ const unsigned char *buf;
+
+ buf = data;
+ while (len > 0) {
+ unsigned char tmp[16], rev[16];
+ uint16_t b[10];
+ uint32_t ctl;
+ int i;
+
+ /*
+ * If there is a partial block, right-pad it with zeros.
+ */
+ if (len < 16) {
+ memset(tmp, 0, sizeof tmp);
+ memcpy(tmp, buf, len);
+ buf = tmp;
+ len = 16;
+ }
+
+ /*
+ * Decode next block and apply the "high bit". Since
+ * decoding is little-endian, we must byte-swap the buffer.
+ */
+ for (i = 0; i < 16; i ++) {
+ rev[i] = buf[15 - i];
+ }
+ br_i15_decode_mod(b, rev, sizeof rev, P1305);
+ b[9] |= 0x0100;
+
+ /*
+ * Add the accumulator to the decoded block (modular
+ * addition).
+ */
+ ctl = br_i15_add(b, a, 1);
+ ctl |= NOT(br_i15_sub(b, P1305, 0));
+ br_i15_sub(b, P1305, ctl);
+
+ /*
+ * Multiply by r, result is the new accumulator value.
+ */
+ br_i15_montymul(a, b, r, P1305, P0I);
+
+ buf += 16;
+ len -= 16;
+ }
+}
+
+/*
+ * Byteswap a 16-byte value.
+ */
+static void
+byteswap16(unsigned char *buf)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++) {
+ unsigned x;
+
+ x = buf[i];
+ buf[i] = buf[15 - i];
+ buf[15 - i] = x;
+ }
+}
+
+/* see bearssl_block.h */
+void
+br_poly1305_i15_run(const void *key, const void *iv,
+ void *data, size_t len, const void *aad, size_t aad_len,
+ void *tag, br_chacha20_run ichacha, int encrypt)
+{
+ unsigned char pkey[32], foot[16];
+ uint16_t t[10], r[10], acc[10];
+
+ /*
+ * Compute the MAC key. The 'r' value is the first 16 bytes of
+ * pkey[].
+ */
+ memset(pkey, 0, sizeof pkey);
+ ichacha(key, iv, 0, pkey, sizeof pkey);
+
+ /*
+ * If encrypting, ChaCha20 must run first, followed by Poly1305.
+ * When decrypting, the operations are reversed.
+ */
+ if (encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+
+ /*
+ * Run Poly1305. We must process the AAD, then ciphertext, then
+ * the footer (with the lengths). Note that the AAD and ciphertext
+ * are meant to be padded with zeros up to the next multiple of 16,
+ * and the length of the footer is 16 bytes as well.
+ */
+
+ /*
+ * Apply the "clamping" operation on the encoded 'r' value.
+ */
+ pkey[ 3] &= 0x0F;
+ pkey[ 7] &= 0x0F;
+ pkey[11] &= 0x0F;
+ pkey[15] &= 0x0F;
+ pkey[ 4] &= 0xFC;
+ pkey[ 8] &= 0xFC;
+ pkey[12] &= 0xFC;
+
+ /*
+ * Decode the clamped 'r' value. Decoding should use little-endian
+ * so we must byteswap the value first.
+ */
+ byteswap16(pkey);
+ br_i15_decode_mod(t, pkey, 16, P1305);
+
+ /*
+ * Convert 'r' to Montgomery representation.
+ */
+ br_i15_montymul(r, t, R2, P1305, P0I);
+
+ /*
+ * Accumulator is 0.
+ */
+ br_i15_zero(acc, 0x8A);
+
+ /*
+ * Process the additional authenticated data, ciphertext, and
+ * footer in due order.
+ */
+ br_enc64le(foot, (uint64_t)aad_len);
+ br_enc64le(foot + 8, (uint64_t)len);
+ poly1305_inner(acc, r, aad, aad_len);
+ poly1305_inner(acc, r, data, len);
+ poly1305_inner(acc, r, foot, sizeof foot);
+
+ /*
+ * Decode the value 's'. Again, a byteswap is needed.
+ */
+ byteswap16(pkey + 16);
+ br_i15_decode_mod(t, pkey + 16, 16, P1305);
+
+ /*
+ * Add the value 's' to the accumulator. That addition is done
+ * modulo 2^128, so we just ignore the carry.
+ */
+ br_i15_add(acc, t, 1);
+
+ /*
+ * Encode the result (128 low bits) to the tag. Encoding should
+ * be little-endian.
+ */
+ br_i15_encode(tag, 16, acc);
+ byteswap16(tag);
+
+ /*
+ * If decrypting, then ChaCha20 runs _after_ Poly1305.
+ */
+ if (!encrypt) {
+ ichacha(key, iv, 1, data, len);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/symcipher/poly1305_i15.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/asn1.t0
===================================================================
--- stable/12/contrib/bearssl/src/x509/asn1.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/asn1.t0 (revision 346145)
@@ -0,0 +1,757 @@
+\ 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.
+
+\ =======================================================================
+
+\ This file contains code which is common to all engines that do some
+\ ASN.1 decoding. It should not be compiled on its own, but only along
+\ with another file (e.g. x509_minimal.t0) which uses it.
+\
+\ Users must define several things:
+\
+\ -- In the preamble, a macro called "CTX" that evaluates to the current
+\ context structure.
+\
+\ -- In the preamble, a macro called "CONTEXT_NAME" that evaluates to the
+\ context structure type. This will be invoked during compilation.
+\
+\ -- A word called "read8-low" ( -- x ) that reads the next byte, or -1
+\ if the input buffer is empty. That word is usually written in C.
+\
+\ -- A word called "read-blob-inner" ( addr len -- addr len ) that is
+\ the multi-byte version of read8-low.
+\
+\ -- A word called "skip-remaining-inner" ( lim -- lim ) which reads but
+\ drops some input bytes.
+
+preamble {
+
+#include "inner.h"
+
+}
+
+\ Read next source character, skipping blanks.
+: skip-blanks begin char dup 32 > if ret then drop again ;
+
+: fail-oid
+ "Invalid OID" puts cr exitvm ;
+
+\ Read a decimal integer, followed by either a dot or whitespace.
+\ Note: this does not check for overflows.
+: parse-number ( -- val nextchar )
+ char decval
+ begin
+ char
+ dup dup `. = swap 32 <= or if ret then
+ decval swap 10 * +
+ again ;
+
+\ Encode a number in unsigned 7E format.
+: encode7E ( val -- )
+ 0 encode7E-inner ;
+
+: encode7E-inner ( val eb -- )
+ swap dup 0x7F > if
+ dup 7 u>> 0x80 encode7E-inner 0x7F and
+ then
+ or data-add8 ;
+
+\ Decode an OID from source, and encode it. First byte is length,
+\ followed by encoded ASN.1 DER value. The OID is encoded in the
+\ current data block.
+: OID
+ \ Get current data address, and push a 0 for length.
+ current-data 0 data-add8
+ \ Skip blanks and get first digit, which must be 0, 1 or 2.
+ skip-blanks decval dup 2 > if fail-oid then
+ 40 *
+ \ Next character must be a dot.
+ char `. <> if fail-oid then
+ \ Second group must be one or two digits.
+ parse-number { nextchar }
+ dup 40 >= if fail-oid then
+ + encode7E
+ \ While next character is a dot, keep encoding numbers.
+ begin nextchar `. = while
+ parse-number >nextchar
+ encode7E
+ repeat
+ \ Write back length in the first byte.
+ dup current-data swap - 1- swap data-set8
+ ; immediate
+
+\ Define a new data word for an encoded OID. The OID is read from the
+\ source.
+: OID:
+ new-data-block next-word define-data-word postpone OID ;
+
+\ Define a word that evaluates to the address of a field within the
+\ context.
+: addr:
+ next-word { field }
+ "addr-" field + 0 1 define-word
+ 0 8191 "offsetof(CONTEXT_NAME, " field + ")" + make-CX
+ postpone literal postpone ; ;
+
+addr: pad
+
+\ Define a word that evaluates to an error code through a macro name.
+: err:
+ next-word { name }
+ name 0 1 define-word
+ 0 63 "BR_" name + make-CX postpone literal postpone ; ;
+
+err: ERR_X509_INVALID_VALUE
+err: ERR_X509_TRUNCATED
+err: ERR_X509_EMPTY_CHAIN
+err: ERR_X509_INNER_TRUNC
+err: ERR_X509_BAD_TAG_CLASS
+err: ERR_X509_BAD_TAG_VALUE
+err: ERR_X509_INDEFINITE_LENGTH
+err: ERR_X509_EXTRA_ELEMENT
+err: ERR_X509_UNEXPECTED
+err: ERR_X509_NOT_CONSTRUCTED
+err: ERR_X509_NOT_PRIMITIVE
+err: ERR_X509_PARTIAL_BYTE
+err: ERR_X509_BAD_BOOLEAN
+err: ERR_X509_OVERFLOW
+err: ERR_X509_BAD_DN
+err: ERR_X509_BAD_TIME
+err: ERR_X509_UNSUPPORTED
+err: ERR_X509_LIMIT_EXCEEDED
+err: ERR_X509_WRONG_KEY_TYPE
+err: ERR_X509_BAD_SIGNATURE
+err: ERR_X509_EXPIRED
+err: ERR_X509_DN_MISMATCH
+err: ERR_X509_BAD_SERVER_NAME
+err: ERR_X509_CRITICAL_EXTENSION
+err: ERR_X509_NOT_CA
+err: ERR_X509_FORBIDDEN_KEY_USAGE
+err: ERR_X509_WEAK_PUBLIC_KEY
+
+: KEYTYPE_RSA CX 0 15 { BR_KEYTYPE_RSA } ;
+: KEYTYPE_EC CX 0 15 { BR_KEYTYPE_EC } ;
+
+cc: fail ( err -- ! ) {
+ CTX->err = T0_POPi();
+ T0_CO();
+}
+
+\ Read one byte from the stream.
+: read8-nc ( -- x )
+ begin
+ read8-low dup 0 >= if ret then
+ drop co
+ again ;
+
+\ Read one byte, enforcing current read limit.
+: read8 ( lim -- lim x )
+ dup ifnot ERR_X509_INNER_TRUNC fail then
+ 1- read8-nc ;
+
+\ Read a 16-bit value, big-endian encoding.
+: read16be ( lim -- lim x )
+ read8 8 << swap read8 rot + ;
+
+\ Read a 16-bit value, little-endian encoding.
+: read16le ( lim -- lim x )
+ read8 swap read8 8 << rot + ;
+
+\ Read all bytes from the current element, then close it (i.e. drop the
+\ limit). Destination address is an offset within the context.
+: read-blob ( lim addr -- )
+ swap
+ begin dup while read-blob-inner dup if co then repeat
+ 2drop ;
+
+\ Skip remaining bytes in the current structure, but do not close it
+\ (thus, this leaves the value 0 on the stack).
+: skip-remaining ( lim -- lim )
+ begin dup while skip-remaining-inner dup if co then repeat ;
+
+: skip-remaining-inner ( lim -- lim )
+ 0 over read-blob-inner -rot 2drop ;
+
+cc: set8 ( val addr -- ) {
+ uint32_t addr = T0_POP();
+ *((unsigned char *)CTX + addr) = (unsigned char)T0_POP();
+}
+
+cc: set16 ( val addr -- ) {
+ uint32_t addr = T0_POP();
+ *(uint16_t *)(void *)((unsigned char *)CTX + addr) = T0_POP();
+}
+
+cc: set32 ( val addr -- ) {
+ uint32_t addr = T0_POP();
+ *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP();
+}
+
+cc: get8 ( addr -- val ) {
+ uint32_t addr = T0_POP();
+ T0_PUSH(*((unsigned char *)CTX + addr));
+}
+
+cc: get16 ( addr -- val ) {
+ uint32_t addr = T0_POP();
+ T0_PUSH(*(uint16_t *)(void *)((unsigned char *)CTX + addr));
+}
+
+cc: get32 ( addr -- val ) {
+ uint32_t addr = T0_POP();
+ T0_PUSH(*(uint32_t *)(void *)((unsigned char *)CTX + addr));
+}
+
+\ Read an ASN.1 tag. This function returns the "constructed" status
+\ and the tag value. The constructed status is a boolean (-1 for
+\ constructed, 0 for primitive). The tag value is either 0 to 31 for
+\ a universal tag, or 32+x for a contextual tag of value x. Tag classes
+\ "application" and "private" are rejected. Universal tags beyond 30
+\ are rejected. Contextual tags beyond 30 are rejected. Thus, accepted
+\ tags will necessarily fit on exactly one byte. This does not support
+\ the whole of ASN.1/BER, but is sufficient for certificate parsing.
+: read-tag ( lim -- lim constructed value )
+ read8 { fb }
+
+ \ Constructed flag is bit 5.
+ fb 5 >> 0x01 and neg
+
+ \ Class is in bits 6 and 7. Accepted classes are 00 (universal)
+ \ and 10 (context). We check that bit 6 is 0, and shift back
+ \ bit 7 so that we get 0 (universal) or 32 (context).
+ fb 6 >> dup 0x01 and if ERR_X509_BAD_TAG_CLASS fail then
+ 4 <<
+
+ \ Tag value is in bits 0..4. If the value is 31, then this is
+ \ an extended tag, encoded over subsequent bytes, and we do
+ \ not support that.
+ fb 0x1F and dup 0x1F = if ERR_X509_BAD_TAG_VALUE fail then
+ + ;
+
+\ Read a tag, but only if not at the end of the current object. If there
+\ is no room for another element (limit is zero), then this will push a
+\ synthetic "no tag" value (primitive, with value -1).
+: read-tag-or-end ( lim -- lim constructed value )
+ dup ifnot 0 -1 ret then
+ read-tag ;
+
+\ Compare the read tag with the provided value. If equal, then the
+\ element is skipped, and a new tag is read (or end of object).
+: iftag-skip ( lim constructed value ref -- lim constructed value )
+ over = if
+ 2drop
+ read-length-open-elt skip-close-elt
+ read-tag-or-end
+ then ;
+
+\ Read an ASN.1 length. This supports only definite lengths (theoretically,
+\ certificates may use an indefinite length for the outer structure, using
+\ DER only in the TBS, but this never happens in practice, except in a
+\ single example certificate from 15 years ago that also fails to decode
+\ properly for other reasons).
+: read-length ( lim -- lim length )
+ read8
+ \ Lengths in 0x00..0x7F get encoded as a single byte.
+ dup 0x80 < if ret then
+
+ \ If the byte is 0x80 then this is an indefinite length, and we
+ \ do not support that.
+ 0x80 - dup ifnot ERR_X509_INDEFINITE_LENGTH fail then
+
+ \ Masking out bit 7, this yields the number of bytes over which
+ \ the value is encoded. Since the total certificate length must
+ \ fit over 3 bytes (this is a consequence of SSL/TLS message
+ \ format), we can reject big lengths and keep the length in a
+ \ single integer.
+ { n } 0
+ begin n 0 > while n 1- >n
+ dup 0x7FFFFF > if ERR_X509_INNER_TRUNC fail then
+ 8 << swap read8 rot +
+ repeat ;
+
+\ Open a sub-structure. This subtracts the length from the limit, and
+\ pushes the length back as new limit.
+: open-elt ( lim length -- lim_outer lim_inner )
+ dup2 < if ERR_X509_INNER_TRUNC fail then
+ dup { len } - len ;
+
+\ Read a length and open the value as a sub-structure.
+: read-length-open-elt ( lim -- lim_outer lim_inner )
+ read-length open-elt ;
+
+\ Close a sub-structure. This verifies that there is no remaining
+\ element to read.
+: close-elt ( lim -- )
+ if ERR_X509_EXTRA_ELEMENT fail then ;
+
+\ Skip remaining bytes in the current structure, then close it.
+: skip-close-elt ( lim -- )
+ skip-remaining drop ;
+
+\ Read a length and then skip the value.
+: read-length-skip ( lim -- lim )
+ read-length-open-elt skip-close-elt ;
+
+\ Check that a given tag is constructed and has the expected value.
+: check-tag-constructed ( constructed value refvalue -- )
+ = ifnot ERR_X509_UNEXPECTED fail then
+ check-constructed ;
+
+\ Check that the top value is true; report a "not constructed"
+\ error otherwise.
+: check-constructed ( constructed -- )
+ ifnot ERR_X509_NOT_CONSTRUCTED fail then ;
+
+\ Check that a given tag is primitive and has the expected value.
+: check-tag-primitive ( constructed value refvalue -- )
+ = ifnot ERR_X509_UNEXPECTED fail then
+ check-primitive ;
+
+\ Check that the top value is true; report a "not primitive"
+\ error otherwise.
+: check-primitive ( constructed -- )
+ if ERR_X509_NOT_PRIMITIVE fail then ;
+
+\ Check that the tag is for a constructed SEQUENCE.
+: check-sequence ( constructed value -- )
+ 0x10 check-tag-constructed ;
+
+\ Read a tag, check that it is for a constructed SEQUENCE, and open
+\ it as a sub-element.
+: read-sequence-open ( lim -- lim_outer lim_inner )
+ read-tag check-sequence read-length-open-elt ;
+
+\ Read the next element as a BIT STRING with no ignore bits, and open
+\ it as a sub-element.
+: read-bits-open ( lim -- lim_outer lim_inner )
+ read-tag 0x03 check-tag-primitive
+ read-length-open-elt
+ read8 if ERR_X509_PARTIAL_BYTE fail then ;
+
+OID: rsaEncryption 1.2.840.113549.1.1.1
+
+OID: sha1WithRSAEncryption 1.2.840.113549.1.1.5
+OID: sha224WithRSAEncryption 1.2.840.113549.1.1.14
+OID: sha256WithRSAEncryption 1.2.840.113549.1.1.11
+OID: sha384WithRSAEncryption 1.2.840.113549.1.1.12
+OID: sha512WithRSAEncryption 1.2.840.113549.1.1.13
+
+OID: id-sha1 1.3.14.3.2.26
+OID: id-sha224 2.16.840.1.101.3.4.2.4
+OID: id-sha256 2.16.840.1.101.3.4.2.1
+OID: id-sha384 2.16.840.1.101.3.4.2.2
+OID: id-sha512 2.16.840.1.101.3.4.2.3
+
+OID: id-ecPublicKey 1.2.840.10045.2.1
+
+OID: ansix9p256r1 1.2.840.10045.3.1.7
+OID: ansix9p384r1 1.3.132.0.34
+OID: ansix9p521r1 1.3.132.0.35
+
+OID: ecdsa-with-SHA1 1.2.840.10045.4.1
+OID: ecdsa-with-SHA224 1.2.840.10045.4.3.1
+OID: ecdsa-with-SHA256 1.2.840.10045.4.3.2
+OID: ecdsa-with-SHA384 1.2.840.10045.4.3.3
+OID: ecdsa-with-SHA512 1.2.840.10045.4.3.4
+
+OID: id-at-commonName 2.5.4.3
+
+\ Read a "small value". This assumes that the tag has just been read
+\ and processed, but not the length. The first pad byte is set to the
+\ value length; the encoded value itself follows. If the value length
+\ exceeds 255 bytes, then a single 0 is written in the pad, and this
+\ method returns false (0). Otherwise, it returns true (-1).
+\ Either way, the element is fully read.
+: read-small-value ( lim -- lim bool )
+ read-length-open-elt
+ dup 255 > if skip-close-elt 0 addr-pad set8 0 ret then
+ dup addr-pad set8
+ addr-pad 1+ read-blob
+ -1 ;
+
+\ Read an OID as a "small value" (tag, length and value). A boolean
+\ value is returned, which is true (-1) if the OID value fits on the pad,
+\ false (0) otherwise.
+: read-OID ( lim -- lim bool )
+ read-tag 0x06 check-tag-primitive read-small-value ;
+
+\ Read a UTF-8 code point. On error, return 0. Reading a code point of
+\ value 0 is considered to be an error.
+: read-UTF8 ( lim -- lim val )
+ read8
+ choice
+ dup 0x80 < uf ret enduf
+ dup 0xC0 < uf drop 0 ret enduf
+ dup 0xE0 < uf 0x1F and 1 read-UTF8-next 0x80 0x7FF enduf
+ dup 0xF0 < uf 0x0F and 2 read-UTF8-next 0x800 0xFFFF enduf
+ dup 0xF8 < uf 0x07 and 3 read-UTF8-next 0x10000 0x10FFFF enduf
+ drop 0 ret
+ endchoice
+ between? ifnot drop 0 then
+ ;
+
+\ Read n subsequent bytes to complete the provided first byte. The final
+\ value is -1 on error, or the code point numerical value. The final
+\ value is duplicated.
+: read-UTF8-next ( lim val n -- lim val val )
+ begin dup while
+ -rot
+ read-UTF8-chunk
+ rot 1-
+ repeat
+ drop dup ;
+
+\ Read one byte, that should be a trailing UTF-8 byte, and complement the
+\ current value. On error, value is set to -1.
+: read-UTF8-chunk ( lim val -- lim val )
+ swap
+ \ If we are at the end of the value, report an error but don't fail.
+ dup ifnot 2drop 0 -1 ret then
+ read8 rot
+ dup 0< if swap drop ret then 6 <<
+ swap dup 6 >> 2 <> if 2drop -1 ret then
+ 0x3F and + ;
+
+: high-surrogate? ( x -- x bool )
+ dup 0xD800 0xDBFF between? ;
+
+: low-surrogate? ( x -- x bool )
+ dup 0xDC00 0xDFFF between? ;
+
+: assemble-surrogate-pair ( hi lim lo -- lim val )
+ low-surrogate? ifnot rot 2drop 0 ret then
+ rot 10 << + 0x35FDC00 - ;
+
+\ Read a UTF-16 code point (big-endian). Returned value is 0 on error.
+: read-UTF16BE ( lim -- lim val )
+ read16be
+ choice
+ high-surrogate? uf
+ swap dup ifnot 2drop 0 0 ret then
+ read16be assemble-surrogate-pair
+ enduf
+ low-surrogate? uf
+ drop 0
+ enduf
+ endchoice ;
+
+\ Read a UTF-16 code point (little-endian). Returned value is 0 on error.
+: read-UTF16LE ( lim -- lim val )
+ read16le
+ choice
+ high-surrogate? uf
+ swap dup ifnot 2drop 0 0 ret then
+ read16le assemble-surrogate-pair
+ enduf
+ low-surrogate? uf
+ drop 0
+ enduf
+ endchoice ;
+
+\ Add byte to current pad value. Offset is updated, or set to 0 on error.
+: pad-append ( off val -- off )
+ over dup 0= swap 256 >= or if 2drop 0 ret then
+ over addr-pad + set8 1+ ;
+
+\ Add UTF-8 chunk byte to the pad. The 'nn' parameter is the shift count.
+: pad-append-UTF8-chunk ( off val nn -- off )
+ >> 0x3F and 0x80 or pad-append ;
+
+\ Test whether a code point is invalid when encoding. This rejects the
+\ 66 noncharacters, and also the surrogate range; this function does NOT
+\ check that the value is in the 0..10FFFF range.
+: valid-unicode? ( val -- bool )
+ dup 0xFDD0 0xFEDF between? if drop 0 ret then
+ dup 0xD800 0xDFFF between? if drop 0 ret then
+ 0xFFFF and 0xFFFE < ;
+
+\ Encode a code point in UTF-8. Offset is in the pad; it is updated, or
+\ set to 0 on error. Leading BOM are ignored.
+: encode-UTF8 ( val off -- off )
+ \ Skip leading BOM (U+FEFF when off is 1).
+ dup2 1 = swap 0xFEFF = and if swap drop ret then
+
+ swap dup { val }
+ dup valid-unicode? ifnot 2drop 0 ret then
+ choice
+ dup 0x80 < uf pad-append enduf
+ dup 0x800 < uf
+ 6 >> 0xC0 or pad-append
+ val 0 pad-append-UTF8-chunk
+ enduf
+ dup 0xFFFF < uf
+ 12 >> 0xE0 or pad-append
+ val 6 pad-append-UTF8-chunk
+ val 0 pad-append-UTF8-chunk
+ enduf
+ 18 >> 0xF0 or pad-append
+ val 12 pad-append-UTF8-chunk
+ val 6 pad-append-UTF8-chunk
+ val 0 pad-append-UTF8-chunk
+ endchoice ;
+
+\ Read a string value into the pad; this function checks that the source
+\ characters are UTF-8 and non-zero. The string length (in bytes) is
+\ written in the first pad byte. Returned value is true (-1) on success,
+\ false (0) on error.
+: read-value-UTF8 ( lim -- lim bool )
+ read-length-open-elt
+ 1 { off }
+ begin dup while
+ read-UTF8 dup ifnot drop skip-close-elt 0 ret then
+ off encode-UTF8 >off
+ repeat
+ drop off dup ifnot ret then 1- addr-pad set8 -1 ;
+
+\ Decode a UTF-16 string into the pad. The string is converted to UTF-8,
+\ and the length is written in the first pad byte. A leading BOM is
+\ honoured (big-endian is assumed if there is no BOM). A code point of
+\ value 0 is an error. Returned value is true (-1) on success, false (0)
+\ on error.
+: read-value-UTF16 ( lim -- lim bool )
+ read-length-open-elt
+ dup ifnot addr-pad set8 -1 ret then
+ 1 { off }
+ read-UTF16BE dup 0xFFFE = if
+ \ Leading BOM, and indicates little-endian.
+ drop
+ begin dup while
+ read-UTF16LE dup ifnot drop skip-close-elt 0 ret then
+ off encode-UTF8 >off
+ repeat
+ else
+ dup ifnot drop skip-close-elt 0 ret then
+ \ Big-endian BOM, or no BOM.
+ begin
+ off encode-UTF8 >off
+ dup while
+ read-UTF16BE dup ifnot drop skip-close-elt 0 ret then
+ repeat
+ then
+ drop off dup ifnot ret then 1- addr-pad set8 -1 ;
+
+\ Decode a latin-1 string into the pad. The string is converted to UTF-8,
+\ and the length is written in the first pad byte. A source byte of
+\ value 0 is an error. Returned value is true (-1) on success, false (0)
+\ on error.
+: read-value-latin1 ( lim -- lim bool )
+ read-length-open-elt
+ 1 { off }
+ begin dup while
+ read8 dup ifnot drop skip-close-elt 0 ret then
+ off encode-UTF8 >off
+ repeat
+ drop off dup ifnot ret then 1- addr-pad set8 -1 ;
+
+\ Read a value and interpret it as an INTEGER or ENUMERATED value. If
+\ the integer value does not fit on an unsigned 32-bit value, an error
+\ is reported. This function assumes that the tag has just been read
+\ and processed, but not the length.
+: read-small-int-value ( lim -- lim x )
+ read-length-open-elt
+ dup ifnot ERR_X509_OVERFLOW fail then
+ read8 dup 0x80 >= if ERR_X509_OVERFLOW fail then
+ { x }
+ begin dup while
+ read8 x dup 0xFFFFFF >= if ERR_X509_OVERFLOW fail then
+ 8 << + >x
+ repeat
+ drop x ;
+
+\ Compare the OID in the pad with an OID in the constant data block.
+\ Returned value is -1 on equality, 0 otherwise.
+cc: eqOID ( addrConst -- bool ) {
+ const unsigned char *a2 = &t0_datablock[T0_POP()];
+ const unsigned char *a1 = &CTX->pad[0];
+ size_t len = a1[0];
+ int x;
+ if (len == a2[0]) {
+ x = -(memcmp(a1 + 1, a2 + 1, len) == 0);
+ } else {
+ x = 0;
+ }
+ T0_PUSH((uint32_t)x);
+}
+
+\ Compare two blobs in the context. Returned value is -1 on equality, 0
+\ otherwise.
+cc: eqblob ( addr1 addr2 len -- bool ) {
+ size_t len = T0_POP();
+ const unsigned char *a2 = (const unsigned char *)CTX + T0_POP();
+ const unsigned char *a1 = (const unsigned char *)CTX + T0_POP();
+ T0_PUSHi(-(memcmp(a1, a2, len) == 0));
+}
+
+\ Check that a value is in a given range (inclusive).
+: between? ( x min max -- bool )
+ { min max } dup min >= swap max <= and ;
+
+\ Convert the provided byte value into a number in the 0..9 range,
+\ assuming that it is an ASCII digit. A non-digit triggers an error
+\ (a "bad time" error since this is used in date/time decoding).
+: digit-dec ( char -- value )
+ `0 - dup 0 9 between? ifnot ERR_X509_BAD_TIME fail then ;
+
+\ Read two ASCII digits and return the value in the 0..99 range. An
+\ error is reported if the characters are not ASCII digits.
+: read-dec2 ( lim -- lim x )
+ read8 digit-dec 10 * { x } read8 digit-dec x + ;
+
+\ Read two ASCII digits and check that the value is in the provided
+\ range (inclusive).
+: read-dec2-range ( lim min max -- lim x )
+ { min max }
+ read-dec2 dup min max between? ifnot ERR_X509_BAD_TIME fail then ;
+
+\ Maximum days in a month and accumulated day count. Each
+\ 16-bit value contains the month day count in its lower 5 bits. The first
+\ 12 values are for a normal year, the other 12 for a leap year.
+data: month-to-days
+hexb| 001F 03FC 077F 0B5E 0F1F 12FE 16BF 1A9F 1E7E 223F 261E 29DF |
+hexb| 001F 03FD 079F 0B7E 0F3F 131E 16DF 1ABF 1E9E 225F 263E 29FF |
+
+\ Read a date (UTCTime or GeneralizedTime). The date value is converted
+\ to a day count and a second count. The day count starts at 0 for
+\ January 1st, 0 AD (that's they year before 1 AD, also known as 1 BC)
+\ in a proleptic Gregorian calendar (i.e. Gregorian rules are assumed to
+\ extend indefinitely in the past). The second count is between 0 and
+\ 86400 (inclusive, in case of a leap second).
+: read-date ( lim -- lim days seconds )
+ \ Read tag; must be UTCTime or GeneralizedTime. Year count is
+ \ 4 digits with GeneralizedTime, 2 digits with UTCTime.
+ read-tag
+ dup 0x17 0x18 between? ifnot ERR_X509_BAD_TIME fail then
+ 0x18 = { y4d }
+ check-primitive
+ read-length-open-elt
+
+ \ We compute the days and seconds counts during decoding, in
+ \ order to minimize the number of needed temporary variables.
+ { ; days seconds x }
+
+ \ Year is 4-digit with GeneralizedTime. With UTCTime, the year
+ \ is in the 1950..2049 range, and only the last two digits are
+ \ present in the encoding.
+ read-dec2
+ y4d if
+ 100 * >x read-dec2 x +
+ else
+ dup 50 < if 100 + then 1900 +
+ then
+ >x
+ x 365 * x 3 + 4 / + x 99 + 100 / - x 399 + 400 / + >days
+
+ \ Month is 1..12. Number of days in a months depend on the
+ \ month and on the year (year count is in x at that point).
+ 1 12 read-dec2-range
+ 1- 1 <<
+ x 4 % 0= x 100 % 0<> x 400 % 0= or and if 24 + then
+ month-to-days + data-get16
+ dup 5 >> days + >days
+ 0x1F and
+
+ \ Day. At this point, the TOS contains the maximum day count for
+ \ the current month.
+ 1 swap read-dec2-range
+ days + 1- >days
+
+ \ Hour, minute and seconds. Count of seconds is allowed to go to
+ \ 60 in case of leap seconds (in practice, leap seconds really
+ \ occur only at the very end of the day, so this computation is
+ \ exact for a real leap second, and a spurious leap second only
+ \ implies a one-second shift that we can ignore).
+ 0 23 read-dec2-range 3600 * >seconds
+ 0 59 read-dec2-range 60 * seconds + >seconds
+ 0 60 read-dec2-range seconds + >seconds
+
+ \ At this point, we may have fractional seconds. This should
+ \ happen only with GeneralizedTime, but we accept it for UTCTime
+ \ too (and, anyway, we ignore these fractional seconds).
+ read8 dup `. = if
+ drop
+ begin read8 dup `0 `9 between? while drop repeat
+ then
+
+ \ The time zone should be 'Z', not followed by anything. Other
+ \ time zone indications are not DER and thus not supposed to
+ \ appear in certificates.
+ `Z <> if ERR_X509_BAD_TIME fail then
+ close-elt
+ days seconds ;
+
+\ Read an INTEGER (tag, length and value). The INTEGER is supposed to be
+\ positive; its unsigned big-endian encoding is stored in the provided
+\ in-context buffer. Returned value is the decoded length. If the integer
+\ did not fit, or the value is negative, then an error is reported.
+: read-integer ( lim addr len -- lim dlen )
+ rot read-tag 0x02 check-tag-primitive -rot
+ read-integer-next ;
+
+\ Identical to read-integer, but the tag has already been read and checked.
+: read-integer-next ( lim addr len -- lim dlen )
+ dup { addr len origlen }
+ read-length-open-elt
+ \ Read first byte; sign bit must be 0.
+ read8 dup 0x80 >= if ERR_X509_OVERFLOW fail then
+ \ Skip leading bytes of value 0. If there are only bytes of
+ \ value 0, then return.
+ begin dup 0 = while
+ drop dup ifnot drop 0 ret then
+ read8
+ repeat
+ \ At that point, we have the first non-zero byte on the stack.
+ begin
+ len dup ifnot ERR_X509_LIMIT_EXCEEDED fail then 1- >len
+ addr set8 addr 1+ >addr
+ dup while read8
+ repeat
+ drop origlen len - ;
+
+\ Read a BOOLEAN value. This should be called immediately after reading
+\ the tag.
+: read-boolean ( lim constructed value -- lim bool )
+ 0x01 check-tag-primitive
+ read-length 1 <> if ERR_X509_BAD_BOOLEAN fail then
+ read8 0<> ;
+
+\ Identify an elliptic curve: read the OID, then check it against the
+\ known curve OID.
+: read-curve-ID ( lim -- lim curve )
+ read-OID ifnot ERR_X509_UNSUPPORTED fail then
+ choice
+ ansix9p256r1 eqOID uf 23 enduf
+ ansix9p384r1 eqOID uf 24 enduf
+ ansix9p521r1 eqOID uf 25 enduf
+ ERR_X509_UNSUPPORTED fail
+ endchoice ;
+
+\ A convenient debug word: print the current data stack contents.
+cc: DEBUG ( -- ) {
+ extern int printf(const char *fmt, ...);
+ uint32_t *p;
+
+ printf("<stack:");
+ for (p = &CTX->dp_stack[0]; p != dp; p ++) {
+ printf(" %lu", (unsigned long)*p);
+ }
+ printf(" >\n");
+}
Index: stable/12/contrib/bearssl/src/x509/asn1enc.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/asn1enc.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/asn1enc.c (revision 346145)
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+br_asn1_uint
+br_asn1_uint_prepare(const void *xdata, size_t xlen)
+{
+ const unsigned char *x;
+ br_asn1_uint t;
+
+ x = xdata;
+ while (xlen > 0 && *x == 0) {
+ x ++;
+ xlen --;
+ }
+ t.data = x;
+ t.len = xlen;
+ t.asn1len = xlen;
+ if (xlen == 0 || x[0] >= 0x80) {
+ t.asn1len ++;
+ }
+ return t;
+}
+
+/* see inner.h */
+size_t
+br_asn1_encode_length(void *dest, size_t len)
+{
+ unsigned char *buf;
+ size_t z;
+ int i, j;
+
+ buf = dest;
+ if (len < 0x80) {
+ if (buf != NULL) {
+ *buf = len;
+ }
+ return 1;
+ }
+ i = 0;
+ for (z = len; z != 0; z >>= 8) {
+ i ++;
+ }
+ if (buf != NULL) {
+ *buf ++ = 0x80 + i;
+ for (j = i - 1; j >= 0; j --) {
+ *buf ++ = len >> (j << 3);
+ }
+ }
+ return i + 1;
+}
+
+/* see inner.h */
+size_t
+br_asn1_encode_uint(void *dest, br_asn1_uint pp)
+{
+ unsigned char *buf;
+ size_t lenlen;
+
+ if (dest == NULL) {
+ return 1 + br_asn1_encode_length(NULL, pp.asn1len) + pp.asn1len;
+ }
+ buf = dest;
+ *buf ++ = 0x02;
+ lenlen = br_asn1_encode_length(buf, pp.asn1len);
+ buf += lenlen;
+ *buf = 0x00;
+ memcpy(buf + pp.asn1len - pp.len, pp.data, pp.len);
+ return 1 + lenlen + pp.asn1len;
+}
Property changes on: stable/12/contrib/bearssl/src/x509/asn1enc.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/encode_ec_pk8der.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/encode_ec_pk8der.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/encode_ec_pk8der.c (revision 346145)
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_x509.h */
+size_t
+br_encode_ec_pkcs8_der(void *dest,
+ const br_ec_private_key *sk, const br_ec_public_key *pk)
+{
+ /*
+ * ASN.1 format:
+ *
+ * OneAsymmetricKey ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] Attributes OPTIONAL,
+ * ...,
+ * [[2: publicKey [1] PublicKey OPTIONAL ]],
+ * ...
+ * }
+ *
+ * We don't include attributes or public key (the public key
+ * is included in the private key value instead). The
+ * 'version' field is an INTEGER that we will set to 0
+ * (meaning 'v1', compatible with previous versions of PKCS#8).
+ * The 'privateKeyAlgorithm' structure is an AlgorithmIdentifier
+ * whose OID should be id-ecPublicKey, with, as parameters, the
+ * curve OID. The 'privateKey' is an OCTET STRING, whose value
+ * is the "raw DER" encoding of the key pair.
+ */
+
+ /*
+ * OID id-ecPublicKey (1.2.840.10045.2.1), DER-encoded (with
+ * the tag).
+ */
+ static const unsigned char OID_ECPUBKEY[] = {
+ 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01
+ };
+
+ size_t len_version, len_privateKeyAlgorithm, len_privateKeyValue;
+ size_t len_privateKey, len_seq;
+ const unsigned char *oid;
+
+ oid = br_get_curve_OID(sk->curve);
+ if (oid == NULL) {
+ return 0;
+ }
+ len_version = 3;
+ len_privateKeyAlgorithm = 2 + sizeof OID_ECPUBKEY + 2 + oid[0];
+ len_privateKeyValue = br_encode_ec_raw_der_inner(NULL, sk, pk, 0);
+ len_privateKey = 1 + len_of_len(len_privateKeyValue)
+ + len_privateKeyValue;
+ len_seq = len_version + len_privateKeyAlgorithm + len_privateKey;
+
+ if (dest == NULL) {
+ return 1 + len_of_len(len_seq) + len_seq;
+ } else {
+ unsigned char *buf;
+ size_t lenlen;
+
+ buf = dest;
+ *buf ++ = 0x30; /* SEQUENCE tag */
+ lenlen = br_asn1_encode_length(buf, len_seq);
+ buf += lenlen;
+
+ /* version */
+ *buf ++ = 0x02;
+ *buf ++ = 0x01;
+ *buf ++ = 0x00;
+
+ /* privateKeyAlgorithm */
+ *buf ++ = 0x30;
+ *buf ++ = (sizeof OID_ECPUBKEY) + 2 + oid[0];
+ memcpy(buf, OID_ECPUBKEY, sizeof OID_ECPUBKEY);
+ buf += sizeof OID_ECPUBKEY;
+ *buf ++ = 0x06;
+ memcpy(buf, oid, 1 + oid[0]);
+ buf += 1 + oid[0];
+
+ /* privateKey */
+ *buf ++ = 0x04;
+ buf += br_asn1_encode_length(buf, len_privateKeyValue);
+ br_encode_ec_raw_der_inner(buf, sk, pk, 0);
+
+ return 1 + lenlen + len_seq;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/x509/encode_ec_pk8der.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/encode_ec_rawder.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/encode_ec_rawder.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/encode_ec_rawder.c (revision 346145)
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see inner.h */
+const unsigned char *
+br_get_curve_OID(int curve)
+{
+ static const unsigned char OID_secp256r1[] = {
+ 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
+ };
+ static const unsigned char OID_secp384r1[] = {
+ 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
+ };
+ static const unsigned char OID_secp521r1[] = {
+ 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23
+ };
+
+ switch (curve) {
+ case BR_EC_secp256r1: return OID_secp256r1;
+ case BR_EC_secp384r1: return OID_secp384r1;
+ case BR_EC_secp521r1: return OID_secp521r1;
+ default:
+ return NULL;
+ }
+}
+
+/* see inner.h */
+size_t
+br_encode_ec_raw_der_inner(void *dest,
+ const br_ec_private_key *sk, const br_ec_public_key *pk,
+ int include_curve_oid)
+{
+ /*
+ * ASN.1 format:
+ *
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL
+ * }
+ *
+ * The tages '[0]' and '[1]' are explicit. The 'ECParameters'
+ * is a CHOICE; in our case, it will always be an OBJECT IDENTIFIER
+ * that identifies the curve.
+ *
+ * The value of the 'privateKey' field is the raw unsigned big-endian
+ * encoding of the private key (integer modulo the curve subgroup
+ * order); there is no INTEGER tag, and the leading bit may be 1.
+ * Also, leading bytes of value 0x00 are _not_ removed.
+ *
+ * The 'publicKey' contents are the raw encoded public key point,
+ * normally uncompressed (leading byte of value 0x04, followed
+ * by the unsigned big-endian encodings of the X and Y coordinates,
+ * padded to the full field length if necessary).
+ */
+
+ size_t len_version, len_privateKey, len_parameters, len_publicKey;
+ size_t len_publicKey_bits, len_seq;
+ const unsigned char *oid;
+
+ if (include_curve_oid) {
+ oid = br_get_curve_OID(sk->curve);
+ if (oid == NULL) {
+ return 0;
+ }
+ } else {
+ oid = NULL;
+ }
+ len_version = 3;
+ len_privateKey = 1 + len_of_len(sk->xlen) + sk->xlen;
+ if (include_curve_oid) {
+ len_parameters = 4 + oid[0];
+ } else {
+ len_parameters = 0;
+ }
+ if (pk == NULL) {
+ len_publicKey = 0;
+ len_publicKey_bits = 0;
+ } else {
+ len_publicKey_bits = 2 + len_of_len(pk->qlen) + pk->qlen;
+ len_publicKey = 1 + len_of_len(len_publicKey_bits)
+ + len_publicKey_bits;
+ }
+ len_seq = len_version + len_privateKey + len_parameters + len_publicKey;
+ if (dest == NULL) {
+ return 1 + len_of_len(len_seq) + len_seq;
+ } else {
+ unsigned char *buf;
+ size_t lenlen;
+
+ buf = dest;
+ *buf ++ = 0x30; /* SEQUENCE tag */
+ lenlen = br_asn1_encode_length(buf, len_seq);
+ buf += lenlen;
+
+ /* version */
+ *buf ++ = 0x02;
+ *buf ++ = 0x01;
+ *buf ++ = 0x01;
+
+ /* privateKey */
+ *buf ++ = 0x04;
+ buf += br_asn1_encode_length(buf, sk->xlen);
+ memcpy(buf, sk->x, sk->xlen);
+ buf += sk->xlen;
+
+ /* parameters */
+ if (include_curve_oid) {
+ *buf ++ = 0xA0;
+ *buf ++ = oid[0] + 2;
+ *buf ++ = 0x06;
+ memcpy(buf, oid, oid[0] + 1);
+ buf += oid[0] + 1;
+ }
+
+ /* publicKey */
+ if (pk != NULL) {
+ *buf ++ = 0xA1;
+ buf += br_asn1_encode_length(buf, len_publicKey_bits);
+ *buf ++ = 0x03;
+ buf += br_asn1_encode_length(buf, pk->qlen + 1);
+ *buf ++ = 0x00;
+ memcpy(buf, pk->q, pk->qlen);
+ /* buf += pk->qlen; */
+ }
+
+ return 1 + lenlen + len_seq;
+ }
+}
+
+/* see bearssl_x509.h */
+size_t
+br_encode_ec_raw_der(void *dest,
+ const br_ec_private_key *sk, const br_ec_public_key *pk)
+{
+ return br_encode_ec_raw_der_inner(dest, sk, pk, 1);
+}
Property changes on: stable/12/contrib/bearssl/src/x509/encode_ec_rawder.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/encode_rsa_pk8der.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/encode_rsa_pk8der.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/encode_rsa_pk8der.c (revision 346145)
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_x509.h */
+size_t
+br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk,
+ const br_rsa_public_key *pk, const void *d, size_t dlen)
+{
+ /*
+ * ASN.1 format:
+ *
+ * OneAsymmetricKey ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] Attributes OPTIONAL,
+ * ...,
+ * [[2: publicKey [1] PublicKey OPTIONAL ]],
+ * ...
+ * }
+ *
+ * We don't include attributes or public key. The 'version' field
+ * is an INTEGER that we will set to 0 (meaning 'v1', compatible
+ * with previous versions of PKCS#8). The 'privateKeyAlgorithm'
+ * structure is an AlgorithmIdentifier whose OID should be
+ * rsaEncryption, with NULL parameters. The 'privateKey' is an
+ * OCTET STRING, whose value is the "raw DER" encoding of the
+ * key pair.
+ *
+ * Since the private key value comes last, this function really
+ * adds a header, which is mostly fixed (only some lengths have
+ * to be modified.
+ */
+
+ /*
+ * Concatenation of:
+ * - DER encoding of an INTEGER of value 0 (the 'version' field)
+ * - DER encoding of a PrivateKeyAlgorithmIdentifier that uses
+ * the rsaEncryption OID, and NULL parameters
+ * - An OCTET STRING tag
+ */
+ static const unsigned char PK8_HEAD[] = {
+ 0x02, 0x01, 0x00,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+ 0x04
+ };
+
+ size_t len_raw, len_seq;
+
+ len_raw = br_encode_rsa_raw_der(NULL, sk, pk, d, dlen);
+ len_seq = (sizeof PK8_HEAD) + len_of_len(len_raw) + len_raw;
+ if (dest == NULL) {
+ return 1 + len_of_len(len_seq) + len_seq;
+ } else {
+ unsigned char *buf;
+ size_t lenlen;
+
+ buf = dest;
+ *buf ++ = 0x30; /* SEQUENCE tag */
+ lenlen = br_asn1_encode_length(buf, len_seq);
+ buf += lenlen;
+
+ /* version, privateKeyAlgorithm, privateKey tag */
+ memcpy(buf, PK8_HEAD, sizeof PK8_HEAD);
+ buf += sizeof PK8_HEAD;
+
+ /* privateKey */
+ buf += br_asn1_encode_length(buf, len_raw);
+ br_encode_rsa_raw_der(buf, sk, pk, d, dlen);
+
+ return 1 + lenlen + len_seq;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/x509/encode_rsa_pk8der.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/encode_rsa_rawder.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/encode_rsa_rawder.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/encode_rsa_rawder.c (revision 346145)
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_x509.h */
+size_t
+br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk,
+ const br_rsa_public_key *pk, const void *d, size_t dlen)
+{
+ /*
+ * ASN.1 format:
+ *
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ *
+ * The 'version' field is an INTEGER of value 0 (meaning: there
+ * are exactly two prime factors), and 'otherPrimeInfos' will
+ * be absent (because there are exactly two prime factors).
+ */
+
+ br_asn1_uint num[9];
+ size_t u, slen;
+
+ /*
+ * For all INTEGER values, get the pointer and length for the
+ * data bytes.
+ */
+ num[0] = br_asn1_uint_prepare(NULL, 0);
+ num[1] = br_asn1_uint_prepare(pk->n, pk->nlen);
+ num[2] = br_asn1_uint_prepare(pk->e, pk->elen);
+ num[3] = br_asn1_uint_prepare(d, dlen);
+ num[4] = br_asn1_uint_prepare(sk->p, sk->plen);
+ num[5] = br_asn1_uint_prepare(sk->q, sk->qlen);
+ num[6] = br_asn1_uint_prepare(sk->dp, sk->dplen);
+ num[7] = br_asn1_uint_prepare(sk->dq, sk->dqlen);
+ num[8] = br_asn1_uint_prepare(sk->iq, sk->iqlen);
+
+ /*
+ * Get the length of the SEQUENCE contents.
+ */
+ slen = 0;
+ for (u = 0; u < 9; u ++) {
+ uint32_t ilen;
+
+ ilen = num[u].asn1len;
+ slen += 1 + len_of_len(ilen) + ilen;
+ }
+
+ if (dest == NULL) {
+ return 1 + len_of_len(slen) + slen;
+ } else {
+ unsigned char *buf;
+ size_t lenlen;
+
+ buf = dest;
+ *buf ++ = 0x30; /* SEQUENCE tag */
+ lenlen = br_asn1_encode_length(buf, slen);
+ buf += lenlen;
+ for (u = 0; u < 9; u ++) {
+ buf += br_asn1_encode_uint(buf, num[u]);
+ }
+ return 1 + lenlen + slen;
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/x509/encode_rsa_rawder.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/skey_decoder.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/skey_decoder.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/skey_decoder.c (revision 346145)
@@ -0,0 +1,650 @@
+/* Automatically generated code; do not modify directly. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+} t0_context;
+
+static uint32_t
+t0_parse7E_unsigned(const unsigned char **p)
+{
+ uint32_t x;
+
+ x = 0;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ return x;
+ }
+ }
+}
+
+static int32_t
+t0_parse7E_signed(const unsigned char **p)
+{
+ int neg;
+ uint32_t x;
+
+ neg = ((**p) >> 6) & 1;
+ x = (uint32_t)-neg;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ if (neg) {
+ return -(int32_t)~x - 1;
+ } else {
+ return (int32_t)x;
+ }
+ }
+ }
+}
+
+#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
+#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
+#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
+#define T0_INT1(x) T0_FBYTE(x, 0)
+#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+
+/* static const unsigned char t0_datablock[]; */
+
+
+void br_skey_decoder_init_main(void *t0ctx);
+
+void br_skey_decoder_run(void *t0ctx);
+
+
+
+#include "inner.h"
+
+
+
+
+
+#include "inner.h"
+
+#define CTX ((br_skey_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_skey_decoder_context, cpu)))
+#define CONTEXT_NAME br_skey_decoder_context
+
+/* see bearssl_x509.h */
+void
+br_skey_decoder_init(br_skey_decoder_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->cpu.dp = &ctx->dp_stack[0];
+ ctx->cpu.rp = &ctx->rp_stack[0];
+ br_skey_decoder_init_main(&ctx->cpu);
+ br_skey_decoder_run(&ctx->cpu);
+}
+
+/* see bearssl_x509.h */
+void
+br_skey_decoder_push(br_skey_decoder_context *ctx,
+ const void *data, size_t len)
+{
+ ctx->hbuf = data;
+ ctx->hlen = len;
+ br_skey_decoder_run(&ctx->cpu);
+}
+
+
+
+static const unsigned char t0_datablock[] = {
+ 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x07,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x05, 0x2B,
+ 0x81, 0x04, 0x00, 0x23
+};
+
+static const unsigned char t0_codeblock[] = {
+ 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x13,
+ 0x13, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00,
+ 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_INVALID_VALUE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_data)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_type)), 0x00, 0x00,
+ 0x33, 0x48, 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, pad)),
+ 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x01, 0x1C, 0x00, 0x00, 0x01, 0x22,
+ 0x00, 0x00, 0x05, 0x02, 0x2C, 0x16, 0x00, 0x00, 0x06, 0x02, 0x2D, 0x16,
+ 0x00, 0x00, 0x01, 0x10, 0x3D, 0x00, 0x00, 0x0D, 0x05, 0x02, 0x2F, 0x16,
+ 0x3A, 0x00, 0x00, 0x0D, 0x05, 0x02, 0x2F, 0x16, 0x3B, 0x00, 0x00, 0x06,
+ 0x02, 0x27, 0x16, 0x00, 0x01, 0x03, 0x00, 0x54, 0x57, 0x01, 0x02, 0x3E,
+ 0x55, 0x23, 0x06, 0x02, 0x30, 0x16, 0x57, 0x01, 0x04, 0x3E, 0x02, 0x00,
+ 0x41, 0x3F, 0x00, 0x02, 0x03, 0x00, 0x53, 0x14, 0x14, 0x03, 0x01, 0x48,
+ 0x0E, 0x06, 0x02, 0x30, 0x16, 0x33, 0x4C, 0x58, 0x01, 0x7F, 0x19, 0x0D,
+ 0x06, 0x04, 0x13, 0x13, 0x04, 0x29, 0x01, 0x20, 0x19, 0x0D, 0x06, 0x16,
+ 0x13, 0x3A, 0x53, 0x4D, 0x02, 0x00, 0x06, 0x09, 0x02, 0x00, 0x0C, 0x06,
+ 0x02, 0x2A, 0x16, 0x04, 0x02, 0x03, 0x00, 0x3F, 0x04, 0x0D, 0x01, 0x21,
+ 0x19, 0x0D, 0x06, 0x04, 0x13, 0x3A, 0x04, 0x03, 0x30, 0x16, 0x13, 0x5D,
+ 0x02, 0x00, 0x05, 0x02, 0x30, 0x16, 0x02, 0x00, 0x02, 0x01, 0x1D, 0x00,
+ 0x02, 0x53, 0x4B, 0x05, 0x02, 0x30, 0x16, 0x5B, 0x15, 0x06, 0x07, 0x5D,
+ 0x01, 0x7F, 0x03, 0x01, 0x04, 0x16, 0x46, 0x15, 0x06, 0x10, 0x01, 0x00,
+ 0x03, 0x01, 0x14, 0x06, 0x03, 0x4D, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00,
+ 0x04, 0x02, 0x30, 0x16, 0x3F, 0x57, 0x01, 0x04, 0x3E, 0x53, 0x02, 0x01,
+ 0x06, 0x03, 0x43, 0x04, 0x03, 0x02, 0x00, 0x40, 0x3F, 0x5D, 0x02, 0x01,
+ 0x06, 0x03, 0x32, 0x04, 0x01, 0x31, 0x00, 0x00, 0x54, 0x57, 0x01, 0x02,
+ 0x3E, 0x55, 0x06, 0x02, 0x30, 0x16, 0x57, 0x01, 0x02, 0x3E, 0x44, 0x3F,
+ 0x00, 0x07, 0x35, 0x50, 0x14, 0x05, 0x02, 0x2F, 0x16, 0x23, 0x01, 0x03,
+ 0x0B, 0x33, 0x17, 0x47, 0x07, 0x03, 0x00, 0x4F, 0x4F, 0x35, 0x4E, 0x14,
+ 0x14, 0x03, 0x01, 0x03, 0x02, 0x51, 0x14, 0x03, 0x03, 0x02, 0x02, 0x07,
+ 0x14, 0x03, 0x02, 0x51, 0x14, 0x03, 0x04, 0x02, 0x02, 0x07, 0x14, 0x03,
+ 0x02, 0x51, 0x14, 0x03, 0x05, 0x02, 0x02, 0x07, 0x14, 0x03, 0x02, 0x51,
+ 0x03, 0x06, 0x02, 0x00, 0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05,
+ 0x02, 0x06, 0x1E, 0x00, 0x00, 0x19, 0x19, 0x00, 0x00, 0x01, 0x0B, 0x00,
+ 0x00, 0x01, 0x00, 0x20, 0x14, 0x06, 0x08, 0x01, 0x01, 0x21, 0x20, 0x22,
+ 0x20, 0x04, 0x75, 0x13, 0x00, 0x00, 0x01,
+ T0_INT2(3 * BR_X509_BUFSIZE_KEY), 0x00, 0x01, 0x01, 0x87, 0xFF, 0xFF,
+ 0x7F, 0x54, 0x57, 0x01, 0x02, 0x3E, 0x55, 0x01, 0x01, 0x0E, 0x06, 0x02,
+ 0x30, 0x16, 0x57, 0x01, 0x02, 0x19, 0x0D, 0x06, 0x06, 0x13, 0x3B, 0x44,
+ 0x32, 0x04, 0x1C, 0x01, 0x04, 0x19, 0x0D, 0x06, 0x08, 0x13, 0x3B, 0x01,
+ 0x00, 0x41, 0x31, 0x04, 0x0E, 0x01, 0x10, 0x19, 0x0D, 0x06, 0x05, 0x13,
+ 0x3A, 0x42, 0x04, 0x03, 0x30, 0x16, 0x13, 0x03, 0x00, 0x3F, 0x02, 0x00,
+ 0x34, 0x1F, 0x5A, 0x27, 0x16, 0x00, 0x01, 0x45, 0x0A, 0x06, 0x02, 0x29,
+ 0x16, 0x14, 0x03, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x57, 0x01, 0x06,
+ 0x3E, 0x56, 0x00, 0x00, 0x20, 0x14, 0x06, 0x07, 0x1A, 0x14, 0x06, 0x01,
+ 0x12, 0x04, 0x76, 0x24, 0x00, 0x00, 0x4B, 0x05, 0x02, 0x30, 0x16, 0x37,
+ 0x15, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x38, 0x15, 0x06, 0x04, 0x01,
+ 0x18, 0x04, 0x0A, 0x39, 0x15, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x30,
+ 0x16, 0x00, 0x00, 0x1C, 0x57, 0x01, 0x02, 0x3E, 0x09, 0x50, 0x00, 0x00,
+ 0x35, 0x4E, 0x13, 0x00, 0x03, 0x14, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02,
+ 0x53, 0x59, 0x14, 0x01, 0x81, 0x00, 0x0F, 0x06, 0x02, 0x2E, 0x16, 0x14,
+ 0x01, 0x00, 0x0D, 0x06, 0x0B, 0x13, 0x14, 0x05, 0x04, 0x13, 0x01, 0x00,
+ 0x00, 0x59, 0x04, 0x6F, 0x02, 0x01, 0x14, 0x05, 0x02, 0x2B, 0x16, 0x23,
+ 0x03, 0x01, 0x02, 0x02, 0x1F, 0x02, 0x02, 0x22, 0x03, 0x02, 0x14, 0x06,
+ 0x03, 0x59, 0x04, 0x68, 0x13, 0x02, 0x00, 0x02, 0x01, 0x08, 0x00, 0x00,
+ 0x14, 0x35, 0x1C, 0x08, 0x20, 0x1C, 0x07, 0x20, 0x4E, 0x00, 0x01, 0x59,
+ 0x14, 0x01, 0x81, 0x00, 0x0A, 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x08,
+ 0x14, 0x05, 0x02, 0x28, 0x16, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01,
+ 0x00, 0x0E, 0x06, 0x19, 0x02, 0x00, 0x23, 0x03, 0x00, 0x14, 0x01, 0x83,
+ 0xFF, 0xFF, 0x7F, 0x0E, 0x06, 0x02, 0x29, 0x16, 0x01, 0x08, 0x0B, 0x20,
+ 0x59, 0x1C, 0x07, 0x04, 0x60, 0x00, 0x00, 0x52, 0x4A, 0x00, 0x00, 0x57,
+ 0x3C, 0x53, 0x00, 0x01, 0x53, 0x14, 0x05, 0x02, 0x2E, 0x16, 0x59, 0x14,
+ 0x01, 0x81, 0x00, 0x0F, 0x06, 0x02, 0x2E, 0x16, 0x03, 0x00, 0x14, 0x06,
+ 0x16, 0x59, 0x02, 0x00, 0x14, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x0F, 0x06,
+ 0x02, 0x2E, 0x16, 0x01, 0x08, 0x0B, 0x07, 0x03, 0x00, 0x04, 0x67, 0x13,
+ 0x02, 0x00, 0x00, 0x00, 0x53, 0x14, 0x01, 0x81, 0x7F, 0x0E, 0x06, 0x08,
+ 0x5C, 0x01, 0x00, 0x36, 0x1F, 0x01, 0x00, 0x00, 0x14, 0x36, 0x1F, 0x36,
+ 0x22, 0x4C, 0x01, 0x7F, 0x00, 0x01, 0x59, 0x03, 0x00, 0x02, 0x00, 0x01,
+ 0x05, 0x10, 0x01, 0x01, 0x11, 0x18, 0x02, 0x00, 0x01, 0x06, 0x10, 0x14,
+ 0x01, 0x01, 0x11, 0x06, 0x02, 0x25, 0x16, 0x01, 0x04, 0x0B, 0x02, 0x00,
+ 0x01, 0x1F, 0x11, 0x14, 0x01, 0x1F, 0x0D, 0x06, 0x02, 0x26, 0x16, 0x07,
+ 0x00, 0x00, 0x14, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x57, 0x00,
+ 0x00, 0x14, 0x05, 0x02, 0x29, 0x16, 0x23, 0x5A, 0x00, 0x00, 0x1B, 0x14,
+ 0x01, 0x00, 0x0F, 0x06, 0x01, 0x00, 0x13, 0x12, 0x04, 0x74, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, 0x14, 0x06, 0x07, 0x5E, 0x14,
+ 0x06, 0x01, 0x12, 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x19, 0x1A, 0x09,
+ 0x24, 0x00
+};
+
+static const uint16_t t0_caddr[] = {
+ 0,
+ 5,
+ 10,
+ 14,
+ 18,
+ 22,
+ 26,
+ 30,
+ 34,
+ 38,
+ 42,
+ 46,
+ 50,
+ 54,
+ 58,
+ 62,
+ 66,
+ 70,
+ 75,
+ 80,
+ 84,
+ 89,
+ 93,
+ 97,
+ 101,
+ 107,
+ 113,
+ 118,
+ 126,
+ 134,
+ 140,
+ 163,
+ 244,
+ 311,
+ 329,
+ 404,
+ 408,
+ 412,
+ 429,
+ 434,
+ 505,
+ 519,
+ 526,
+ 540,
+ 573,
+ 582,
+ 587,
+ 654,
+ 665,
+ 721,
+ 725,
+ 730,
+ 778,
+ 804,
+ 848,
+ 859,
+ 868,
+ 881,
+ 885,
+ 889,
+ 901
+};
+
+#define T0_INTERPRETED 34
+
+#define T0_ENTER(ip, rp, slot) do { \
+ const unsigned char *t0_newip; \
+ uint32_t t0_lnum; \
+ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
+ t0_lnum = t0_parse7E_unsigned(&t0_newip); \
+ (rp) += t0_lnum; \
+ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
+ (ip) = t0_newip; \
+ } while (0)
+
+#define T0_DEFENTRY(name, slot) \
+void \
+name(void *ctx) \
+{ \
+ t0_context *t0ctx = ctx; \
+ t0ctx->ip = &t0_codeblock[0]; \
+ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
+}
+
+T0_DEFENTRY(br_skey_decoder_init_main, 73)
+
+#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
+
+void
+br_skey_decoder_run(void *t0ctx)
+{
+ uint32_t *dp, *rp;
+ const unsigned char *ip;
+
+#define T0_LOCAL(x) (*(rp - 2 - (x)))
+#define T0_POP() (*-- dp)
+#define T0_POPi() (*(int32_t *)(-- dp))
+#define T0_PEEK(x) (*(dp - 1 - (x)))
+#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
+#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
+#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
+#define T0_RPOP() (*-- rp)
+#define T0_RPOPi() (*(int32_t *)(-- rp))
+#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
+#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
+#define T0_ROLL(x) do { \
+ size_t t0len = (size_t)(x); \
+ uint32_t t0tmp = *(dp - 1 - t0len); \
+ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_SWAP() do { \
+ uint32_t t0tmp = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_ROT() do { \
+ uint32_t t0tmp = *(dp - 3); \
+ *(dp - 3) = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_NROT() do { \
+ uint32_t t0tmp = *(dp - 1); \
+ *(dp - 1) = *(dp - 2); \
+ *(dp - 2) = *(dp - 3); \
+ *(dp - 3) = t0tmp; \
+} while (0)
+#define T0_PICK(x) do { \
+ uint32_t t0depth = (x); \
+ T0_PUSH(T0_PEEK(t0depth)); \
+} while (0)
+#define T0_CO() do { \
+ goto t0_exit; \
+} while (0)
+#define T0_RET() goto t0_next
+
+ dp = ((t0_context *)t0ctx)->dp;
+ rp = ((t0_context *)t0ctx)->rp;
+ ip = ((t0_context *)t0ctx)->ip;
+ goto t0_next;
+ for (;;) {
+ uint32_t t0x;
+
+ t0_next:
+ t0x = T0_NEXT(&ip);
+ if (t0x < T0_INTERPRETED) {
+ switch (t0x) {
+ int32_t t0off;
+
+ case 0: /* ret */
+ t0x = T0_RPOP();
+ rp -= (t0x >> 16);
+ t0x &= 0xFFFF;
+ if (t0x == 0) {
+ ip = NULL;
+ goto t0_exit;
+ }
+ ip = &t0_codeblock[t0x];
+ break;
+ case 1: /* literal constant */
+ T0_PUSHi(t0_parse7E_signed(&ip));
+ break;
+ case 2: /* read local */
+ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
+ break;
+ case 3: /* write local */
+ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
+ break;
+ case 4: /* jump */
+ t0off = t0_parse7E_signed(&ip);
+ ip += t0off;
+ break;
+ case 5: /* jump if */
+ t0off = t0_parse7E_signed(&ip);
+ if (T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 6: /* jump if not */
+ t0off = t0_parse7E_signed(&ip);
+ if (!T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 7: {
+ /* + */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a + b);
+
+ }
+ break;
+ case 8: {
+ /* - */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a - b);
+
+ }
+ break;
+ case 9: {
+ /* -rot */
+ T0_NROT();
+ }
+ break;
+ case 10: {
+ /* < */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a < b));
+
+ }
+ break;
+ case 11: {
+ /* << */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x << c);
+
+ }
+ break;
+ case 12: {
+ /* <> */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a != b));
+
+ }
+ break;
+ case 13: {
+ /* = */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a == b));
+
+ }
+ break;
+ case 14: {
+ /* > */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a > b));
+
+ }
+ break;
+ case 15: {
+ /* >= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a >= b));
+
+ }
+ break;
+ case 16: {
+ /* >> */
+
+ int c = (int)T0_POPi();
+ int32_t x = T0_POPi();
+ T0_PUSHi(x >> c);
+
+ }
+ break;
+ case 17: {
+ /* and */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a & b);
+
+ }
+ break;
+ case 18: {
+ /* co */
+ T0_CO();
+ }
+ break;
+ case 19: {
+ /* drop */
+ (void)T0_POP();
+ }
+ break;
+ case 20: {
+ /* dup */
+ T0_PUSH(T0_PEEK(0));
+ }
+ break;
+ case 21: {
+ /* eqOID */
+
+ const unsigned char *a2 = &t0_datablock[T0_POP()];
+ const unsigned char *a1 = &CTX->pad[0];
+ size_t len = a1[0];
+ int x;
+ if (len == a2[0]) {
+ x = -(memcmp(a1 + 1, a2 + 1, len) == 0);
+ } else {
+ x = 0;
+ }
+ T0_PUSH((uint32_t)x);
+
+ }
+ break;
+ case 22: {
+ /* fail */
+
+ CTX->err = T0_POPi();
+ T0_CO();
+
+ }
+ break;
+ case 23: {
+ /* get8 */
+
+ uint32_t addr = T0_POP();
+ T0_PUSH(*((unsigned char *)CTX + addr));
+
+ }
+ break;
+ case 24: {
+ /* neg */
+
+ uint32_t a = T0_POP();
+ T0_PUSH(-a);
+
+ }
+ break;
+ case 25: {
+ /* over */
+ T0_PUSH(T0_PEEK(1));
+ }
+ break;
+ case 26: {
+ /* read-blob-inner */
+
+ uint32_t len = T0_POP();
+ uint32_t addr = T0_POP();
+ size_t clen = CTX->hlen;
+ if (clen > len) {
+ clen = (size_t)len;
+ }
+ if (addr != 0) {
+ memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
+ }
+ CTX->hbuf += clen;
+ CTX->hlen -= clen;
+ T0_PUSH(addr + clen);
+ T0_PUSH(len - clen);
+
+ }
+ break;
+ case 27: {
+ /* read8-low */
+
+ if (CTX->hlen == 0) {
+ T0_PUSHi(-1);
+ } else {
+ CTX->hlen --;
+ T0_PUSH(*CTX->hbuf ++);
+ }
+
+ }
+ break;
+ case 28: {
+ /* rot */
+ T0_ROT();
+ }
+ break;
+ case 29: {
+ /* set-ec-key */
+
+ size_t xlen = T0_POP();
+ uint32_t curve = T0_POP();
+ CTX->key.ec.curve = curve;
+ CTX->key.ec.x = CTX->key_data;
+ CTX->key.ec.xlen = xlen;
+
+ }
+ break;
+ case 30: {
+ /* set-rsa-key */
+
+ size_t iqlen = T0_POP();
+ size_t dqlen = T0_POP();
+ size_t dplen = T0_POP();
+ size_t qlen = T0_POP();
+ size_t plen = T0_POP();
+ uint32_t n_bitlen = T0_POP();
+ size_t off;
+
+ CTX->key.rsa.n_bitlen = n_bitlen;
+ CTX->key.rsa.p = CTX->key_data;
+ CTX->key.rsa.plen = plen;
+ off = plen;
+ CTX->key.rsa.q = CTX->key_data + off;
+ CTX->key.rsa.qlen = qlen;
+ off += qlen;
+ CTX->key.rsa.dp = CTX->key_data + off;
+ CTX->key.rsa.dplen = dplen;
+ off += dplen;
+ CTX->key.rsa.dq = CTX->key_data + off;
+ CTX->key.rsa.dqlen = dqlen;
+ off += dqlen;
+ CTX->key.rsa.iq = CTX->key_data + off;
+ CTX->key.rsa.iqlen = iqlen;
+
+ }
+ break;
+ case 31: {
+ /* set8 */
+
+ uint32_t addr = T0_POP();
+ *((unsigned char *)CTX + addr) = (unsigned char)T0_POP();
+
+ }
+ break;
+ case 32: {
+ /* swap */
+ T0_SWAP();
+ }
+ break;
+ case 33: {
+ /* u>> */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x >> c);
+
+ }
+ break;
+ }
+
+ } else {
+ T0_ENTER(ip, rp, t0x);
+ }
+ }
+t0_exit:
+ ((t0_context *)t0ctx)->dp = dp;
+ ((t0_context *)t0ctx)->rp = rp;
+ ((t0_context *)t0ctx)->ip = ip;
+}
Property changes on: stable/12/contrib/bearssl/src/x509/skey_decoder.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/skey_decoder.t0
===================================================================
--- stable/12/contrib/bearssl/src/x509/skey_decoder.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/skey_decoder.t0 (revision 346145)
@@ -0,0 +1,373 @@
+\ 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.
+
+preamble {
+
+#include "inner.h"
+
+#define CTX ((br_skey_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_skey_decoder_context, cpu)))
+#define CONTEXT_NAME br_skey_decoder_context
+
+/* see bearssl_x509.h */
+void
+br_skey_decoder_init(br_skey_decoder_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->cpu.dp = &ctx->dp_stack[0];
+ ctx->cpu.rp = &ctx->rp_stack[0];
+ br_skey_decoder_init_main(&ctx->cpu);
+ br_skey_decoder_run(&ctx->cpu);
+}
+
+/* see bearssl_x509.h */
+void
+br_skey_decoder_push(br_skey_decoder_context *ctx,
+ const void *data, size_t len)
+{
+ ctx->hbuf = data;
+ ctx->hlen = len;
+ br_skey_decoder_run(&ctx->cpu);
+}
+
+}
+
+addr: key_type
+addr: key_data
+
+cc: read8-low ( -- x ) {
+ if (CTX->hlen == 0) {
+ T0_PUSHi(-1);
+ } else {
+ CTX->hlen --;
+ T0_PUSH(*CTX->hbuf ++);
+ }
+}
+
+cc: read-blob-inner ( addr len -- addr len ) {
+ uint32_t len = T0_POP();
+ uint32_t addr = T0_POP();
+ size_t clen = CTX->hlen;
+ if (clen > len) {
+ clen = (size_t)len;
+ }
+ if (addr != 0) {
+ memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
+ }
+ CTX->hbuf += clen;
+ CTX->hlen -= clen;
+ T0_PUSH(addr + clen);
+ T0_PUSH(len - clen);
+}
+
+\ Get the length of the key_data buffer.
+: len-key_data
+ CX 0 8191 { 3 * BR_X509_BUFSIZE_KEY } ;
+
+\ Get the address and length for the key_data buffer.
+: addr-len-key_data ( -- addr len )
+ addr-key_data len-key_data ;
+
+\ Set the private key (RSA).
+cc: set-rsa-key ( n_bitlen plen qlen dplen dqlen iqlen -- ) {
+ size_t iqlen = T0_POP();
+ size_t dqlen = T0_POP();
+ size_t dplen = T0_POP();
+ size_t qlen = T0_POP();
+ size_t plen = T0_POP();
+ uint32_t n_bitlen = T0_POP();
+ size_t off;
+
+ CTX->key.rsa.n_bitlen = n_bitlen;
+ CTX->key.rsa.p = CTX->key_data;
+ CTX->key.rsa.plen = plen;
+ off = plen;
+ CTX->key.rsa.q = CTX->key_data + off;
+ CTX->key.rsa.qlen = qlen;
+ off += qlen;
+ CTX->key.rsa.dp = CTX->key_data + off;
+ CTX->key.rsa.dplen = dplen;
+ off += dplen;
+ CTX->key.rsa.dq = CTX->key_data + off;
+ CTX->key.rsa.dqlen = dqlen;
+ off += dqlen;
+ CTX->key.rsa.iq = CTX->key_data + off;
+ CTX->key.rsa.iqlen = iqlen;
+}
+
+\ Set the private key (EC).
+cc: set-ec-key ( curve xlen -- ) {
+ size_t xlen = T0_POP();
+ uint32_t curve = T0_POP();
+ CTX->key.ec.curve = curve;
+ CTX->key.ec.x = CTX->key_data;
+ CTX->key.ec.xlen = xlen;
+}
+
+\ Get the bit length for an integer (unsigned).
+: int-bit-length ( x -- bitlen )
+ 0 swap
+ begin dup while 1 u>> swap 1+ swap repeat
+ drop ;
+
+\ Read an INTEGER into the key_data buffer, but then ignore it.
+: read-integer-ignore ( lim -- lim )
+ addr-len-key_data read-integer drop ;
+
+\ Read an INTEGER into the key_data buffer, at the provided offset.
+\ Returned value is the integer length (in bytes).
+: read-integer-off ( lim off -- lim dlen )
+ dup addr-len-key_data rot - swap rot + swap read-integer ;
+
+\ Decode RSA key, starting with the SEQUENCE tag.
+: decode-RSA ( lim -- lim )
+ read-sequence-open
+
+ \ Version should be 0.
+ read-tag 0x02 check-tag-primitive read-small-int-value if
+ ERR_X509_UNSUPPORTED fail
+ then
+
+ \ Read tag for the modulus; should be INTEGER. Then use the
+ \ decode-RSA-next function for the remainder of the key.
+ read-tag 0x02 check-tag-primitive
+ decode-RSA-next
+
+ \ Close the SEQUENCE.
+ close-elt ;
+
+\ Decode RSA key; the version, and the tag for the modulus, have been
+\ read.
+: decode-RSA-next ( lim -- lim )
+ \ Modulus: we read it but we do not keep it; we merely gather
+ \ the modulus bit length.
+ addr-len-key_data read-integer-next
+ dup ifnot ERR_X509_UNEXPECTED fail then
+ 1- 3 << addr-key_data get8 int-bit-length + { n_bitlen }
+
+ \ Public exponent: read but skip.
+ read-integer-ignore
+
+ \ Private exponent: read but skip.
+ read-integer-ignore
+
+ \ First prime factor.
+ addr-len-key_data read-integer dup dup { off plen }
+
+ \ Second prime factor.
+ read-integer-off dup { qlen } off + dup >off
+
+ \ First reduced private exponent.
+ read-integer-off dup { dplen } off + dup >off
+
+ \ Second reduced private exponent.
+ read-integer-off dup { dqlen } off + dup >off
+
+ \ CRT coefficient.
+ read-integer-off { iqlen }
+
+ \ Set RSA key.
+ n_bitlen plen qlen dplen dqlen iqlen set-rsa-key
+
+ \ The caller will close the sequence, thereby validating that there
+ \ is no extra field.
+ ;
+
+\ Decode an EC key, starting with the SEQUENCE tag.
+: decode-EC ( lim curve -- lim )
+ { curve }
+ read-sequence-open
+
+ \ Version should be 1.
+ read-tag 0x02 check-tag-primitive read-small-int-value 1- if
+ ERR_X509_UNSUPPORTED fail
+ then
+
+ \ Read tag for the private key; should be OCTET STRING. Then use the
+ \ decode-EC-next function for the remainder of the key.
+ read-tag 0x04 check-tag-primitive
+ curve decode-EC-next
+
+ \ Close the SEQUENCE.
+ close-elt ;
+
+\ Decode an EC key; the version, and the tag for the OCTET STRING, have
+\ already been read. The curve ID is provided (0 if unknown).
+: decode-EC-next ( lim curve -- lim )
+ { curve }
+
+ \ Read the private key proper.
+ read-length-open-elt
+ dup dup { xlen } len-key_data > if ERR_X509_UNSUPPORTED fail then
+ addr-key_data read-blob
+
+ \ Next element might be the curve identifier.
+ read-tag-or-end
+ case
+
+ \ End of structure.
+ -1 of drop endof
+
+ \ Curve parameters; we support only named curves.
+ 0x20 of
+ check-constructed read-length-open-elt
+ read-curve-ID
+ curve if
+ curve <> if ERR_X509_INVALID_VALUE fail then
+ else
+ >curve
+ then
+ close-elt
+ endof
+
+ \ Public key. We ignore it.
+ 0x21 of check-constructed endof
+
+ ERR_X509_UNSUPPORTED fail
+ endcase
+ skip-remaining
+
+ \ The curve must have been defined one way or another.
+ curve ifnot ERR_X509_UNSUPPORTED fail then
+
+ \ Set the EC key.
+ curve xlen set-ec-key
+
+ \ The caller will close the sequence.
+ ;
+
+\ Decode a PKCS#8 object. The version and the tag for the AlgorithmIdentifier
+\ structure have already been read. This function returns the key type.
+: decode-PKCS8-next ( lim -- lim keytype )
+ \ Decode the AlgorithmIdentifier.
+ read-length-open-elt
+ read-OID ifnot ERR_X509_UNSUPPORTED fail then
+ { ; is-rsa curve }
+ choice
+ rsaEncryption eqOID uf
+ \ RSA private key. We ignore the parameters.
+ skip-remaining -1 >is-rsa
+ enduf
+ id-ecPublicKey eqOID uf
+ \ EC private key. Parameters, if present, shall
+ \ identify the curve.
+ 0 >is-rsa
+ dup if read-curve-ID else 0 then >curve
+ enduf
+
+ ERR_X509_UNSUPPORTED fail
+ endchoice
+ close-elt
+
+ \ Open private key value and decode it.
+ read-tag 0x04 check-tag-primitive
+ read-length-open-elt
+ is-rsa if
+ decode-RSA
+ else
+ curve decode-EC
+ then
+ close-elt
+
+ \ We ignore any extra field, i.e. attributes or public key.
+ skip-remaining
+
+ \ Return the key type.
+ is-rsa if KEYTYPE_RSA else KEYTYPE_EC then
+ ;
+
+\ Decode a private key.
+: main ( -- ! )
+ \ RSA private key format is defined in PKCS#1 (RFC 3447):
+ \ RSAPrivateKey ::= SEQUENCE {
+ \ version INTEGER, -- 0 or 1
+ \ n INTEGER,
+ \ e INTEGER,
+ \ d INTEGER,
+ \ p INTEGER,
+ \ q INTEGER,
+ \ dp INTEGER,
+ \ dq INTEGER,
+ \ iq INTEGER,
+ \ other OtherPrimeInfos OPTIONAL
+ \ }
+ \ We do not support keys with more than two primes (these have
+ \ version 1); thus, we expect the version field to be 0, and
+ \ the 'other' field to be absent.
+ \
+ \ EC private key format is defined in RFC 5915:
+ \ ECPrivateKey ::= SEQUENCE {
+ \ version INTEGER, -- always 1
+ \ privateKey OCTET STRING,
+ \ parameters [0] EXPLICIT OBJECT IDENTIFIER OPTIONAL,
+ \ publicKey [1] EXPLICIT BIT STRING OPTIONAL
+ \ }
+ \ The "parameters" might conceptually be a complex curve description
+ \ structure but we support only named curves. The private key
+ \ contents are the unsigned big-endian encoding of the key value,
+ \ which is exactly what we want.
+ \
+ \ PKCS#8 (unencrypted) is:
+ \ OneAsymmetricKey ::= SEQUENCE {
+ \ version INTEGER, -- 0 or 1
+ \ algorithm AlgorithmIdentifier,
+ \ privateKey OCTET STRING,
+ \ attributes [0] IMPLICIT Attributes OPTIONAL,
+ \ publicKey [1] IMPLICIT BIT STRING OPTIONAL
+ \ }
+ \ The 'publicKey' field is an add-on from RFC 5958 and may be
+ \ present only if the 'version' is v2 (i.e. has value 1). We
+ \ ignore it anyway.
+
+ \ An arbitrary upper limit on the private key size.
+ 0xFFFFFF
+
+ \ Open the outer SEQUENCE.
+ read-sequence-open
+
+ \ All our schemas begin with a small INTEGER which is either 0 or
+ \ 1. We don't care which it is.
+ read-tag 0x02 check-tag-primitive read-small-int-value 1 > if
+ ERR_X509_UNSUPPORTED fail
+ then
+
+ \ Get next tag: it should be either an INTEGER (RSA private key),
+ \ an OCTET STRING (EC private key), or a SEQUENCE (for an
+ \ AlgorithmIdentifier, in a PKCS#8 object).
+ read-tag
+ case
+ 0x02 of check-primitive decode-RSA-next KEYTYPE_RSA endof
+ 0x04 of check-primitive 0 decode-EC-next KEYTYPE_EC endof
+ 0x10 of check-constructed decode-PKCS8-next endof
+ ERR_X509_UNSUPPORTED fail
+ endcase
+ { key-type }
+
+ \ Close the SEQUENCE.
+ close-elt
+
+ \ Set the key type, which marks the decoding as a success.
+ key-type addr-key_type set8
+
+ \ Read one byte, then fail: if the read succeeds, then there is
+ \ some trailing byte.
+ read8-nc ERR_X509_EXTRA_ELEMENT fail
+ ;
Index: stable/12/contrib/bearssl/src/x509/x509_decoder.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/x509_decoder.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/x509_decoder.c (revision 346145)
@@ -0,0 +1,773 @@
+/* Automatically generated code; do not modify directly. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+} t0_context;
+
+static uint32_t
+t0_parse7E_unsigned(const unsigned char **p)
+{
+ uint32_t x;
+
+ x = 0;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ return x;
+ }
+ }
+}
+
+static int32_t
+t0_parse7E_signed(const unsigned char **p)
+{
+ int neg;
+ uint32_t x;
+
+ neg = ((**p) >> 6) & 1;
+ x = (uint32_t)-neg;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ if (neg) {
+ return -(int32_t)~x - 1;
+ } else {
+ return (int32_t)x;
+ }
+ }
+ }
+}
+
+#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
+#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
+#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
+#define T0_INT1(x) T0_FBYTE(x, 0)
+#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+
+/* static const unsigned char t0_datablock[]; */
+
+
+void br_x509_decoder_init_main(void *t0ctx);
+
+void br_x509_decoder_run(void *t0ctx);
+
+
+
+#include "inner.h"
+
+
+
+
+
+#include "inner.h"
+
+#define CTX ((br_x509_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_decoder_context, cpu)))
+#define CONTEXT_NAME br_x509_decoder_context
+
+/* see bearssl_x509.h */
+void
+br_x509_decoder_init(br_x509_decoder_context *ctx,
+ void (*append_dn)(void *ctx, const void *buf, size_t len),
+ void *append_dn_ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ /* obsolete
+ ctx->err = 0;
+ ctx->hbuf = NULL;
+ ctx->hlen = 0;
+ */
+ ctx->append_dn = append_dn;
+ ctx->append_dn_ctx = append_dn_ctx;
+ ctx->cpu.dp = &ctx->dp_stack[0];
+ ctx->cpu.rp = &ctx->rp_stack[0];
+ br_x509_decoder_init_main(&ctx->cpu);
+ br_x509_decoder_run(&ctx->cpu);
+}
+
+/* see bearssl_x509.h */
+void
+br_x509_decoder_push(br_x509_decoder_context *ctx,
+ const void *data, size_t len)
+{
+ ctx->hbuf = data;
+ ctx->hlen = len;
+ br_x509_decoder_run(&ctx->cpu);
+}
+
+
+
+static const unsigned char t0_datablock[] = {
+ 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x09, 0x2A, 0x86,
+ 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+ 0x01, 0x01, 0x0C, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
+ 0x0D, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86,
+ 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22,
+ 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x04, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x08,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x08, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04,
+ 0x03, 0x04, 0x00, 0x1F, 0x03, 0xFC, 0x07, 0x7F, 0x0B, 0x5E, 0x0F, 0x1F,
+ 0x12, 0xFE, 0x16, 0xBF, 0x1A, 0x9F, 0x1E, 0x7E, 0x22, 0x3F, 0x26, 0x1E,
+ 0x29, 0xDF, 0x00, 0x1F, 0x03, 0xFD, 0x07, 0x9F, 0x0B, 0x7E, 0x0F, 0x3F,
+ 0x13, 0x1E, 0x16, 0xDF, 0x1A, 0xBF, 0x1E, 0x9E, 0x22, 0x5F, 0x26, 0x3E,
+ 0x29, 0xFF, 0x03, 0x55, 0x1D, 0x13
+};
+
+static const unsigned char t0_codeblock[] = {
+ 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x01,
+ 0x01, 0x09, 0x00, 0x00, 0x01, 0x01, 0x0A, 0x00, 0x00, 0x1A, 0x1A, 0x00,
+ 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_BOOLEAN), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_TIME), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_PARTIAL_BYTE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, copy_dn)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(CONTEXT_NAME, decoded)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, isCA)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_x509_decoder_context, pkey_data)), 0x01,
+ T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, notafter_days)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, notafter_seconds)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, notbefore_days)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, notbefore_seconds)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, signer_hash_id)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, signer_key_type)), 0x00, 0x00, 0x01,
+ 0x80, 0x45, 0x00, 0x00, 0x01, 0x80, 0x4E, 0x00, 0x00, 0x01, 0x80, 0x54,
+ 0x00, 0x00, 0x01, 0x81, 0x36, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x1B,
+ 0x02, 0x01, 0x13, 0x26, 0x02, 0x00, 0x0F, 0x15, 0x00, 0x00, 0x05, 0x02,
+ 0x34, 0x1D, 0x00, 0x00, 0x06, 0x02, 0x35, 0x1D, 0x00, 0x00, 0x01, 0x10,
+ 0x4F, 0x00, 0x00, 0x11, 0x05, 0x02, 0x38, 0x1D, 0x4C, 0x00, 0x00, 0x11,
+ 0x05, 0x02, 0x38, 0x1D, 0x4D, 0x00, 0x00, 0x06, 0x02, 0x30, 0x1D, 0x00,
+ 0x00, 0x1B, 0x19, 0x01, 0x08, 0x0E, 0x26, 0x29, 0x19, 0x09, 0x00, 0x00,
+ 0x01, 0x30, 0x0A, 0x1B, 0x01, 0x00, 0x01, 0x09, 0x4B, 0x05, 0x02, 0x2F,
+ 0x1D, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x01, 0x80, 0x5A, 0x00, 0x00,
+ 0x01, 0x80, 0x62, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x80,
+ 0x74, 0x00, 0x00, 0x01, 0x80, 0x7D, 0x00, 0x00, 0x01, 0x3D, 0x00, 0x00,
+ 0x20, 0x11, 0x06, 0x04, 0x2B, 0x6B, 0x7A, 0x71, 0x00, 0x04, 0x01, 0x00,
+ 0x3D, 0x25, 0x01, 0x00, 0x3C, 0x25, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x6D,
+ 0x6D, 0x70, 0x1B, 0x01, 0x20, 0x11, 0x06, 0x11, 0x1A, 0x4C, 0x6B, 0x70,
+ 0x01, 0x02, 0x50, 0x6E, 0x01, 0x02, 0x12, 0x06, 0x02, 0x39, 0x1D, 0x51,
+ 0x70, 0x01, 0x02, 0x50, 0x6C, 0x6D, 0x7A, 0x6D, 0x7A, 0x6D, 0x65, 0x43,
+ 0x24, 0x42, 0x24, 0x65, 0x41, 0x24, 0x40, 0x24, 0x51, 0x01, 0x01, 0x3C,
+ 0x25, 0x6D, 0x7A, 0x01, 0x00, 0x3C, 0x25, 0x6D, 0x6D, 0x60, 0x05, 0x02,
+ 0x39, 0x1D, 0x74, 0x1C, 0x06, 0x1C, 0x7A, 0x61, 0x6D, 0x3F, 0x68, 0x03,
+ 0x00, 0x3F, 0x26, 0x02, 0x00, 0x09, 0x26, 0x02, 0x00, 0x0A, 0x68, 0x03,
+ 0x01, 0x51, 0x51, 0x02, 0x00, 0x02, 0x01, 0x18, 0x04, 0x1E, 0x5A, 0x1C,
+ 0x06, 0x18, 0x64, 0x03, 0x02, 0x51, 0x61, 0x1B, 0x03, 0x03, 0x1B, 0x3F,
+ 0x23, 0x0D, 0x06, 0x02, 0x33, 0x1D, 0x62, 0x02, 0x02, 0x02, 0x03, 0x17,
+ 0x04, 0x02, 0x39, 0x1D, 0x51, 0x01, 0x00, 0x3E, 0x25, 0x71, 0x01, 0x21,
+ 0x5B, 0x01, 0x22, 0x5B, 0x1B, 0x01, 0x23, 0x11, 0x06, 0x28, 0x1A, 0x4C,
+ 0x6B, 0x6D, 0x1B, 0x06, 0x1D, 0x6D, 0x60, 0x1A, 0x70, 0x1B, 0x01, 0x01,
+ 0x11, 0x06, 0x03, 0x63, 0x1A, 0x70, 0x01, 0x04, 0x50, 0x6B, 0x4A, 0x1C,
+ 0x06, 0x03, 0x5F, 0x04, 0x01, 0x7B, 0x51, 0x51, 0x04, 0x60, 0x51, 0x51,
+ 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, 0x38, 0x1D, 0x1A, 0x51, 0x6D,
+ 0x60, 0x06, 0x80, 0x63, 0x75, 0x1C, 0x06, 0x06, 0x01, 0x02, 0x3B, 0x04,
+ 0x80, 0x57, 0x76, 0x1C, 0x06, 0x06, 0x01, 0x03, 0x3B, 0x04, 0x80, 0x4D,
+ 0x77, 0x1C, 0x06, 0x06, 0x01, 0x04, 0x3B, 0x04, 0x80, 0x43, 0x78, 0x1C,
+ 0x06, 0x05, 0x01, 0x05, 0x3B, 0x04, 0x3A, 0x79, 0x1C, 0x06, 0x05, 0x01,
+ 0x06, 0x3B, 0x04, 0x31, 0x55, 0x1C, 0x06, 0x05, 0x01, 0x02, 0x3A, 0x04,
+ 0x28, 0x56, 0x1C, 0x06, 0x05, 0x01, 0x03, 0x3A, 0x04, 0x1F, 0x57, 0x1C,
+ 0x06, 0x05, 0x01, 0x04, 0x3A, 0x04, 0x16, 0x58, 0x1C, 0x06, 0x05, 0x01,
+ 0x05, 0x3A, 0x04, 0x0D, 0x59, 0x1C, 0x06, 0x05, 0x01, 0x06, 0x3A, 0x04,
+ 0x04, 0x01, 0x00, 0x01, 0x00, 0x04, 0x04, 0x01, 0x00, 0x01, 0x00, 0x46,
+ 0x25, 0x45, 0x25, 0x7A, 0x61, 0x7A, 0x51, 0x1A, 0x01, 0x01, 0x3D, 0x25,
+ 0x73, 0x30, 0x1D, 0x00, 0x00, 0x01, 0x81, 0x06, 0x00, 0x01, 0x54, 0x0D,
+ 0x06, 0x02, 0x32, 0x1D, 0x1B, 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00,
+ 0x6D, 0x71, 0x1B, 0x01, 0x01, 0x11, 0x06, 0x08, 0x63, 0x01, 0x01, 0x15,
+ 0x3E, 0x25, 0x04, 0x01, 0x2B, 0x7A, 0x00, 0x00, 0x70, 0x01, 0x06, 0x50,
+ 0x6F, 0x00, 0x00, 0x70, 0x01, 0x03, 0x50, 0x6B, 0x72, 0x06, 0x02, 0x37,
+ 0x1D, 0x00, 0x00, 0x26, 0x1B, 0x06, 0x07, 0x21, 0x1B, 0x06, 0x01, 0x16,
+ 0x04, 0x76, 0x2B, 0x00, 0x00, 0x01, 0x01, 0x50, 0x6A, 0x01, 0x01, 0x10,
+ 0x06, 0x02, 0x2C, 0x1D, 0x72, 0x27, 0x00, 0x00, 0x60, 0x05, 0x02, 0x39,
+ 0x1D, 0x47, 0x1C, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x48, 0x1C, 0x06,
+ 0x04, 0x01, 0x18, 0x04, 0x0A, 0x49, 0x1C, 0x06, 0x04, 0x01, 0x19, 0x04,
+ 0x02, 0x39, 0x1D, 0x00, 0x04, 0x70, 0x1B, 0x01, 0x17, 0x01, 0x18, 0x4B,
+ 0x05, 0x02, 0x2F, 0x1D, 0x01, 0x18, 0x11, 0x03, 0x00, 0x4D, 0x6B, 0x66,
+ 0x02, 0x00, 0x06, 0x0C, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01, 0x66, 0x02,
+ 0x01, 0x09, 0x04, 0x0E, 0x1B, 0x01, 0x32, 0x0D, 0x06, 0x04, 0x01, 0x80,
+ 0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, 0x03, 0x01, 0x02, 0x01, 0x01, 0x82,
+ 0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, 0x09, 0x01, 0x04, 0x0C, 0x09, 0x02,
+ 0x01, 0x01, 0x80, 0x63, 0x09, 0x01, 0x80, 0x64, 0x0C, 0x0A, 0x02, 0x01,
+ 0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, 0x10, 0x0C, 0x09, 0x03, 0x03, 0x01,
+ 0x01, 0x01, 0x0C, 0x67, 0x2A, 0x01, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04,
+ 0x07, 0x28, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07, 0x27, 0x02, 0x01, 0x01,
+ 0x83, 0x10, 0x07, 0x28, 0x1F, 0x15, 0x06, 0x03, 0x01, 0x18, 0x09, 0x5D,
+ 0x09, 0x52, 0x1B, 0x01, 0x05, 0x14, 0x02, 0x03, 0x09, 0x03, 0x03, 0x01,
+ 0x1F, 0x15, 0x01, 0x01, 0x26, 0x67, 0x02, 0x03, 0x09, 0x2A, 0x03, 0x03,
+ 0x01, 0x00, 0x01, 0x17, 0x67, 0x01, 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01,
+ 0x00, 0x01, 0x3B, 0x67, 0x01, 0x3C, 0x08, 0x02, 0x02, 0x09, 0x03, 0x02,
+ 0x01, 0x00, 0x01, 0x3C, 0x67, 0x02, 0x02, 0x09, 0x03, 0x02, 0x72, 0x1B,
+ 0x01, 0x2E, 0x11, 0x06, 0x0D, 0x1A, 0x72, 0x1B, 0x01, 0x30, 0x01, 0x39,
+ 0x4B, 0x06, 0x03, 0x1A, 0x04, 0x74, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02,
+ 0x2F, 0x1D, 0x51, 0x02, 0x03, 0x02, 0x02, 0x00, 0x01, 0x72, 0x53, 0x01,
+ 0x0A, 0x08, 0x03, 0x00, 0x72, 0x53, 0x02, 0x00, 0x09, 0x00, 0x02, 0x03,
+ 0x00, 0x03, 0x01, 0x66, 0x1B, 0x02, 0x01, 0x02, 0x00, 0x4B, 0x05, 0x02,
+ 0x2F, 0x1D, 0x00, 0x00, 0x23, 0x70, 0x01, 0x02, 0x50, 0x0B, 0x69, 0x00,
+ 0x03, 0x1B, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x6B, 0x72, 0x1B, 0x01,
+ 0x81, 0x00, 0x13, 0x06, 0x02, 0x36, 0x1D, 0x1B, 0x01, 0x00, 0x11, 0x06,
+ 0x0B, 0x1A, 0x1B, 0x05, 0x04, 0x1A, 0x01, 0x00, 0x00, 0x72, 0x04, 0x6F,
+ 0x02, 0x01, 0x1B, 0x05, 0x02, 0x33, 0x1D, 0x2A, 0x03, 0x01, 0x02, 0x02,
+ 0x25, 0x02, 0x02, 0x29, 0x03, 0x02, 0x1B, 0x06, 0x03, 0x72, 0x04, 0x68,
+ 0x1A, 0x02, 0x00, 0x02, 0x01, 0x0A, 0x00, 0x01, 0x72, 0x1B, 0x01, 0x81,
+ 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x0A, 0x1B, 0x05, 0x02,
+ 0x31, 0x1D, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x06,
+ 0x19, 0x02, 0x00, 0x2A, 0x03, 0x00, 0x1B, 0x01, 0x83, 0xFF, 0xFF, 0x7F,
+ 0x12, 0x06, 0x02, 0x32, 0x1D, 0x01, 0x08, 0x0E, 0x26, 0x72, 0x23, 0x09,
+ 0x04, 0x60, 0x00, 0x00, 0x6A, 0x5E, 0x00, 0x00, 0x6B, 0x7A, 0x00, 0x00,
+ 0x70, 0x4E, 0x6B, 0x00, 0x01, 0x6B, 0x1B, 0x05, 0x02, 0x36, 0x1D, 0x72,
+ 0x1B, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x36, 0x1D, 0x03, 0x00, 0x1B,
+ 0x06, 0x16, 0x72, 0x02, 0x00, 0x1B, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13,
+ 0x06, 0x02, 0x36, 0x1D, 0x01, 0x08, 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67,
+ 0x1A, 0x02, 0x00, 0x00, 0x00, 0x6B, 0x1B, 0x01, 0x81, 0x7F, 0x12, 0x06,
+ 0x08, 0x7A, 0x01, 0x00, 0x44, 0x25, 0x01, 0x00, 0x00, 0x1B, 0x44, 0x25,
+ 0x44, 0x29, 0x62, 0x01, 0x7F, 0x00, 0x01, 0x72, 0x03, 0x00, 0x02, 0x00,
+ 0x01, 0x05, 0x14, 0x01, 0x01, 0x15, 0x1E, 0x02, 0x00, 0x01, 0x06, 0x14,
+ 0x1B, 0x01, 0x01, 0x15, 0x06, 0x02, 0x2D, 0x1D, 0x01, 0x04, 0x0E, 0x02,
+ 0x00, 0x01, 0x1F, 0x15, 0x1B, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x2E, 0x1D,
+ 0x09, 0x00, 0x00, 0x1B, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x70,
+ 0x00, 0x00, 0x1B, 0x05, 0x02, 0x32, 0x1D, 0x2A, 0x73, 0x00, 0x00, 0x22,
+ 0x1B, 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x1A, 0x16, 0x04, 0x74, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00,
+ 0x01, 0x1F, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00,
+ 0x7B, 0x1A, 0x00, 0x00, 0x1B, 0x06, 0x07, 0x7C, 0x1B, 0x06, 0x01, 0x16,
+ 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x20, 0x21, 0x0B, 0x2B, 0x00
+};
+
+static const uint16_t t0_caddr[] = {
+ 0,
+ 5,
+ 10,
+ 15,
+ 20,
+ 24,
+ 28,
+ 32,
+ 36,
+ 40,
+ 44,
+ 48,
+ 52,
+ 56,
+ 60,
+ 64,
+ 68,
+ 72,
+ 76,
+ 80,
+ 84,
+ 88,
+ 93,
+ 98,
+ 103,
+ 111,
+ 116,
+ 121,
+ 126,
+ 131,
+ 136,
+ 141,
+ 146,
+ 151,
+ 156,
+ 161,
+ 166,
+ 181,
+ 187,
+ 193,
+ 198,
+ 206,
+ 214,
+ 220,
+ 231,
+ 246,
+ 250,
+ 255,
+ 260,
+ 265,
+ 270,
+ 275,
+ 279,
+ 289,
+ 620,
+ 625,
+ 639,
+ 659,
+ 666,
+ 678,
+ 692,
+ 707,
+ 740,
+ 960,
+ 974,
+ 991,
+ 1000,
+ 1067,
+ 1123,
+ 1127,
+ 1131,
+ 1136,
+ 1184,
+ 1210,
+ 1254,
+ 1265,
+ 1274,
+ 1287,
+ 1291,
+ 1295,
+ 1299,
+ 1303,
+ 1307,
+ 1311,
+ 1315,
+ 1327
+};
+
+#define T0_INTERPRETED 39
+
+#define T0_ENTER(ip, rp, slot) do { \
+ const unsigned char *t0_newip; \
+ uint32_t t0_lnum; \
+ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
+ t0_lnum = t0_parse7E_unsigned(&t0_newip); \
+ (rp) += t0_lnum; \
+ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
+ (ip) = t0_newip; \
+ } while (0)
+
+#define T0_DEFENTRY(name, slot) \
+void \
+name(void *ctx) \
+{ \
+ t0_context *t0ctx = ctx; \
+ t0ctx->ip = &t0_codeblock[0]; \
+ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
+}
+
+T0_DEFENTRY(br_x509_decoder_init_main, 92)
+
+#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
+
+void
+br_x509_decoder_run(void *t0ctx)
+{
+ uint32_t *dp, *rp;
+ const unsigned char *ip;
+
+#define T0_LOCAL(x) (*(rp - 2 - (x)))
+#define T0_POP() (*-- dp)
+#define T0_POPi() (*(int32_t *)(-- dp))
+#define T0_PEEK(x) (*(dp - 1 - (x)))
+#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
+#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
+#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
+#define T0_RPOP() (*-- rp)
+#define T0_RPOPi() (*(int32_t *)(-- rp))
+#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
+#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
+#define T0_ROLL(x) do { \
+ size_t t0len = (size_t)(x); \
+ uint32_t t0tmp = *(dp - 1 - t0len); \
+ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_SWAP() do { \
+ uint32_t t0tmp = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_ROT() do { \
+ uint32_t t0tmp = *(dp - 3); \
+ *(dp - 3) = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_NROT() do { \
+ uint32_t t0tmp = *(dp - 1); \
+ *(dp - 1) = *(dp - 2); \
+ *(dp - 2) = *(dp - 3); \
+ *(dp - 3) = t0tmp; \
+} while (0)
+#define T0_PICK(x) do { \
+ uint32_t t0depth = (x); \
+ T0_PUSH(T0_PEEK(t0depth)); \
+} while (0)
+#define T0_CO() do { \
+ goto t0_exit; \
+} while (0)
+#define T0_RET() goto t0_next
+
+ dp = ((t0_context *)t0ctx)->dp;
+ rp = ((t0_context *)t0ctx)->rp;
+ ip = ((t0_context *)t0ctx)->ip;
+ goto t0_next;
+ for (;;) {
+ uint32_t t0x;
+
+ t0_next:
+ t0x = T0_NEXT(&ip);
+ if (t0x < T0_INTERPRETED) {
+ switch (t0x) {
+ int32_t t0off;
+
+ case 0: /* ret */
+ t0x = T0_RPOP();
+ rp -= (t0x >> 16);
+ t0x &= 0xFFFF;
+ if (t0x == 0) {
+ ip = NULL;
+ goto t0_exit;
+ }
+ ip = &t0_codeblock[t0x];
+ break;
+ case 1: /* literal constant */
+ T0_PUSHi(t0_parse7E_signed(&ip));
+ break;
+ case 2: /* read local */
+ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
+ break;
+ case 3: /* write local */
+ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
+ break;
+ case 4: /* jump */
+ t0off = t0_parse7E_signed(&ip);
+ ip += t0off;
+ break;
+ case 5: /* jump if */
+ t0off = t0_parse7E_signed(&ip);
+ if (T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 6: /* jump if not */
+ t0off = t0_parse7E_signed(&ip);
+ if (!T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 7: {
+ /* %25 */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSHi(a % b);
+
+ }
+ break;
+ case 8: {
+ /* * */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a * b);
+
+ }
+ break;
+ case 9: {
+ /* + */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a + b);
+
+ }
+ break;
+ case 10: {
+ /* - */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a - b);
+
+ }
+ break;
+ case 11: {
+ /* -rot */
+ T0_NROT();
+ }
+ break;
+ case 12: {
+ /* / */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSHi(a / b);
+
+ }
+ break;
+ case 13: {
+ /* < */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a < b));
+
+ }
+ break;
+ case 14: {
+ /* << */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x << c);
+
+ }
+ break;
+ case 15: {
+ /* <= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a <= b));
+
+ }
+ break;
+ case 16: {
+ /* <> */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a != b));
+
+ }
+ break;
+ case 17: {
+ /* = */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a == b));
+
+ }
+ break;
+ case 18: {
+ /* > */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a > b));
+
+ }
+ break;
+ case 19: {
+ /* >= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a >= b));
+
+ }
+ break;
+ case 20: {
+ /* >> */
+
+ int c = (int)T0_POPi();
+ int32_t x = T0_POPi();
+ T0_PUSHi(x >> c);
+
+ }
+ break;
+ case 21: {
+ /* and */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a & b);
+
+ }
+ break;
+ case 22: {
+ /* co */
+ T0_CO();
+ }
+ break;
+ case 23: {
+ /* copy-ec-pkey */
+
+ size_t qlen = T0_POP();
+ uint32_t curve = T0_POP();
+ CTX->pkey.key_type = BR_KEYTYPE_EC;
+ CTX->pkey.key.ec.curve = curve;
+ CTX->pkey.key.ec.q = CTX->pkey_data;
+ CTX->pkey.key.ec.qlen = qlen;
+
+ }
+ break;
+ case 24: {
+ /* copy-rsa-pkey */
+
+ size_t elen = T0_POP();
+ size_t nlen = T0_POP();
+ CTX->pkey.key_type = BR_KEYTYPE_RSA;
+ CTX->pkey.key.rsa.n = CTX->pkey_data;
+ CTX->pkey.key.rsa.nlen = nlen;
+ CTX->pkey.key.rsa.e = CTX->pkey_data + nlen;
+ CTX->pkey.key.rsa.elen = elen;
+
+ }
+ break;
+ case 25: {
+ /* data-get8 */
+
+ size_t addr = T0_POP();
+ T0_PUSH(t0_datablock[addr]);
+
+ }
+ break;
+ case 26: {
+ /* drop */
+ (void)T0_POP();
+ }
+ break;
+ case 27: {
+ /* dup */
+ T0_PUSH(T0_PEEK(0));
+ }
+ break;
+ case 28: {
+ /* eqOID */
+
+ const unsigned char *a2 = &t0_datablock[T0_POP()];
+ const unsigned char *a1 = &CTX->pad[0];
+ size_t len = a1[0];
+ int x;
+ if (len == a2[0]) {
+ x = -(memcmp(a1 + 1, a2 + 1, len) == 0);
+ } else {
+ x = 0;
+ }
+ T0_PUSH((uint32_t)x);
+
+ }
+ break;
+ case 29: {
+ /* fail */
+
+ CTX->err = T0_POPi();
+ T0_CO();
+
+ }
+ break;
+ case 30: {
+ /* neg */
+
+ uint32_t a = T0_POP();
+ T0_PUSH(-a);
+
+ }
+ break;
+ case 31: {
+ /* or */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a | b);
+
+ }
+ break;
+ case 32: {
+ /* over */
+ T0_PUSH(T0_PEEK(1));
+ }
+ break;
+ case 33: {
+ /* read-blob-inner */
+
+ uint32_t len = T0_POP();
+ uint32_t addr = T0_POP();
+ size_t clen = CTX->hlen;
+ if (clen > len) {
+ clen = (size_t)len;
+ }
+ if (addr != 0) {
+ memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
+ }
+ if (CTX->copy_dn && CTX->append_dn) {
+ CTX->append_dn(CTX->append_dn_ctx, CTX->hbuf, clen);
+ }
+ CTX->hbuf += clen;
+ CTX->hlen -= clen;
+ T0_PUSH(addr + clen);
+ T0_PUSH(len - clen);
+
+ }
+ break;
+ case 34: {
+ /* read8-low */
+
+ if (CTX->hlen == 0) {
+ T0_PUSHi(-1);
+ } else {
+ unsigned char x = *CTX->hbuf ++;
+ if (CTX->copy_dn && CTX->append_dn) {
+ CTX->append_dn(CTX->append_dn_ctx, &x, 1);
+ }
+ CTX->hlen --;
+ T0_PUSH(x);
+ }
+
+ }
+ break;
+ case 35: {
+ /* rot */
+ T0_ROT();
+ }
+ break;
+ case 36: {
+ /* set32 */
+
+ uint32_t addr = T0_POP();
+ *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP();
+
+ }
+ break;
+ case 37: {
+ /* set8 */
+
+ uint32_t addr = T0_POP();
+ *((unsigned char *)CTX + addr) = (unsigned char)T0_POP();
+
+ }
+ break;
+ case 38: {
+ /* swap */
+ T0_SWAP();
+ }
+ break;
+ }
+
+ } else {
+ T0_ENTER(ip, rp, t0x);
+ }
+ }
+t0_exit:
+ ((t0_context *)t0ctx)->dp = dp;
+ ((t0_context *)t0ctx)->rp = rp;
+ ((t0_context *)t0ctx)->ip = ip;
+}
Property changes on: stable/12/contrib/bearssl/src/x509/x509_decoder.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/x509_decoder.t0
===================================================================
--- stable/12/contrib/bearssl/src/x509/x509_decoder.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/x509_decoder.t0 (revision 346145)
@@ -0,0 +1,321 @@
+\ 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.
+
+preamble {
+
+#include "inner.h"
+
+#define CTX ((br_x509_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_decoder_context, cpu)))
+#define CONTEXT_NAME br_x509_decoder_context
+
+/* see bearssl_x509.h */
+void
+br_x509_decoder_init(br_x509_decoder_context *ctx,
+ void (*append_dn)(void *ctx, const void *buf, size_t len),
+ void *append_dn_ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ /* obsolete
+ ctx->err = 0;
+ ctx->hbuf = NULL;
+ ctx->hlen = 0;
+ */
+ ctx->append_dn = append_dn;
+ ctx->append_dn_ctx = append_dn_ctx;
+ ctx->cpu.dp = &ctx->dp_stack[0];
+ ctx->cpu.rp = &ctx->rp_stack[0];
+ br_x509_decoder_init_main(&ctx->cpu);
+ br_x509_decoder_run(&ctx->cpu);
+}
+
+/* see bearssl_x509.h */
+void
+br_x509_decoder_push(br_x509_decoder_context *ctx,
+ const void *data, size_t len)
+{
+ ctx->hbuf = data;
+ ctx->hlen = len;
+ br_x509_decoder_run(&ctx->cpu);
+}
+
+}
+
+addr: decoded
+addr: notbefore_days
+addr: notbefore_seconds
+addr: notafter_days
+addr: notafter_seconds
+addr: isCA
+addr: copy_dn
+addr: signer_key_type
+addr: signer_hash_id
+
+cc: read8-low ( -- x ) {
+ if (CTX->hlen == 0) {
+ T0_PUSHi(-1);
+ } else {
+ unsigned char x = *CTX->hbuf ++;
+ if (CTX->copy_dn && CTX->append_dn) {
+ CTX->append_dn(CTX->append_dn_ctx, &x, 1);
+ }
+ CTX->hlen --;
+ T0_PUSH(x);
+ }
+}
+
+cc: read-blob-inner ( addr len -- addr len ) {
+ uint32_t len = T0_POP();
+ uint32_t addr = T0_POP();
+ size_t clen = CTX->hlen;
+ if (clen > len) {
+ clen = (size_t)len;
+ }
+ if (addr != 0) {
+ memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
+ }
+ if (CTX->copy_dn && CTX->append_dn) {
+ CTX->append_dn(CTX->append_dn_ctx, CTX->hbuf, clen);
+ }
+ CTX->hbuf += clen;
+ CTX->hlen -= clen;
+ T0_PUSH(addr + clen);
+ T0_PUSH(len - clen);
+}
+
+\ Get the address and length for the pkey_data buffer.
+: addr-len-pkey_data ( -- addr len )
+ CX 0 8191 { offsetof(br_x509_decoder_context, pkey_data) }
+ CX 0 8191 { BR_X509_BUFSIZE_KEY } ;
+
+\ Copy the public key (RSA) to the permanent buffer.
+cc: copy-rsa-pkey ( nlen elen -- ) {
+ size_t elen = T0_POP();
+ size_t nlen = T0_POP();
+ CTX->pkey.key_type = BR_KEYTYPE_RSA;
+ CTX->pkey.key.rsa.n = CTX->pkey_data;
+ CTX->pkey.key.rsa.nlen = nlen;
+ CTX->pkey.key.rsa.e = CTX->pkey_data + nlen;
+ CTX->pkey.key.rsa.elen = elen;
+}
+
+\ Copy the public key (EC) to the permanent buffer.
+cc: copy-ec-pkey ( curve qlen -- ) {
+ size_t qlen = T0_POP();
+ uint32_t curve = T0_POP();
+ CTX->pkey.key_type = BR_KEYTYPE_EC;
+ CTX->pkey.key.ec.curve = curve;
+ CTX->pkey.key.ec.q = CTX->pkey_data;
+ CTX->pkey.key.ec.qlen = qlen;
+}
+
+\ Extensions with specific processing.
+OID: basicConstraints 2.5.29.19
+
+\ Process a Basic Constraints extension. We want the "CA" flag only.
+: process-basicConstraints ( lim -- lim )
+ read-sequence-open
+ read-tag-or-end dup 0x01 = if
+ read-boolean 1 and addr-isCA set8
+ else
+ 2drop
+ then
+ skip-close-elt
+ ;
+
+\ Decode a certificate.
+: main ( -- ! )
+
+ \ Initialise state flags.
+ 0 addr-decoded set8
+ 0 addr-copy_dn set8
+
+ \ An arbitrary limit for the total certificate size.
+ 0xFFFFFF
+
+ \ Open the outer SEQUENCE.
+ read-sequence-open
+
+ \ TBS
+ read-sequence-open
+
+ \ First element may be an explicit version. We accept only
+ \ versions 0 to 2 (certificates v1 to v3).
+ read-tag dup 0x20 = if
+ drop check-constructed read-length-open-elt
+ read-tag
+ 0x02 check-tag-primitive
+ read-small-int-value
+ 2 > if ERR_X509_UNSUPPORTED fail then
+ close-elt
+ read-tag
+ then
+
+ \ Serial number. We just check that the tag is correct.
+ 0x02 check-tag-primitive read-length-skip
+
+ \ Signature algorithm.
+ read-sequence-open skip-close-elt
+
+ \ Issuer name.
+ read-sequence-open skip-close-elt
+
+ \ Validity dates.
+ read-sequence-open
+ read-date addr-notbefore_seconds set32 addr-notbefore_days set32
+ read-date addr-notafter_seconds set32 addr-notafter_days set32
+ close-elt
+
+ \ Subject name.
+ 1 addr-copy_dn set8
+ read-sequence-open skip-close-elt
+ 0 addr-copy_dn set8
+
+ \ Public Key.
+ read-sequence-open
+ \ Algorithm Identifier. Right now we are only interested in the
+ \ OID, since we only support RSA keys.
+ \ TODO: support EC keys
+ read-sequence-open
+ read-OID ifnot ERR_X509_UNSUPPORTED fail then
+ choice
+ \ RSA public key.
+ rsaEncryption eqOID uf
+ skip-close-elt
+ \ Public key itself: the BIT STRING contains bytes
+ \ (no partial byte) and these bytes encode the
+ \ actual value.
+ read-bits-open
+ \ RSA public key is a SEQUENCE of two
+ \ INTEGER. We get both INTEGER values into
+ \ the pkey_data[] buffer, if they fit.
+ read-sequence-open
+ addr-len-pkey_data
+ read-integer { nlen }
+ addr-len-pkey_data swap nlen + swap nlen -
+ read-integer { elen }
+ close-elt
+ close-elt
+ nlen elen copy-rsa-pkey
+ enduf
+
+ \ EC public key.
+ id-ecPublicKey eqOID uf
+ \ We support only named curves, for which the
+ \ "parameters" field in the AlgorithmIdentifier
+ \ field should be an OID.
+ read-curve-ID { curve }
+ close-elt
+ read-bits-open
+ dup { qlen }
+ dup addr-len-pkey_data rot < if
+ ERR_X509_LIMIT_EXCEEDED fail
+ then
+ read-blob
+ curve qlen copy-ec-pkey
+ enduf
+ ERR_X509_UNSUPPORTED fail
+ endchoice
+ close-elt
+
+ \ This flag will be set to true if the Basic Constraints extension
+ \ is encountered.
+ 0 addr-isCA set8
+
+ \ Skip issuerUniqueID and subjectUniqueID, and process extensions
+ \ if present. Extensions are an explicit context tag of value 3
+ \ around a SEQUENCE OF extensions. Each extension is a SEQUENCE
+ \ with an OID, an optional boolean, and a value; the value is
+ \ an OCTET STRING.
+ read-tag-or-end
+ 0x21 iftag-skip
+ 0x22 iftag-skip
+ dup 0x23 = if
+ drop
+ check-constructed read-length-open-elt
+ read-sequence-open
+ begin dup while
+ read-sequence-open
+ read-OID drop
+ read-tag dup 0x01 = if
+ read-boolean drop
+ read-tag
+ then
+ 0x04 check-tag-primitive read-length-open-elt
+ choice
+ \ Extensions with specific processing.
+ basicConstraints eqOID uf
+ process-basicConstraints
+ enduf
+ skip-remaining
+ endchoice
+ close-elt
+ close-elt
+ repeat
+ close-elt
+ close-elt
+ else
+ -1 = ifnot ERR_X509_UNEXPECTED fail then
+ drop
+ then
+
+ close-elt
+
+ \ signature algorithm
+ read-sequence-open
+ read-OID if
+ choice
+ sha1WithRSAEncryption eqOID uf 2 KEYTYPE_RSA enduf
+ sha224WithRSAEncryption eqOID uf 3 KEYTYPE_RSA enduf
+ sha256WithRSAEncryption eqOID uf 4 KEYTYPE_RSA enduf
+ sha384WithRSAEncryption eqOID uf 5 KEYTYPE_RSA enduf
+ sha512WithRSAEncryption eqOID uf 6 KEYTYPE_RSA enduf
+
+ ecdsa-with-SHA1 eqOID uf 2 KEYTYPE_EC enduf
+ ecdsa-with-SHA224 eqOID uf 3 KEYTYPE_EC enduf
+ ecdsa-with-SHA256 eqOID uf 4 KEYTYPE_EC enduf
+ ecdsa-with-SHA384 eqOID uf 5 KEYTYPE_EC enduf
+ ecdsa-with-SHA512 eqOID uf 6 KEYTYPE_EC enduf
+
+ 0 0
+ endchoice
+ else
+ 0 0
+ then
+ addr-signer_key_type set8
+ addr-signer_hash_id set8
+ skip-close-elt
+ \ read-sequence-open skip-close-elt
+
+ \ signature value
+ read-bits-open skip-close-elt
+
+ \ Close the outer SEQUENCE.
+ close-elt
+ drop
+
+ \ Mark the decoding as successful.
+ 1 addr-decoded set8
+
+ \ Read one byte, then fail: if the read succeeds, then there is
+ \ some trailing byte.
+ read8-nc ERR_X509_EXTRA_ELEMENT fail
+ ;
Index: stable/12/contrib/bearssl/src/x509/x509_knownkey.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/x509_knownkey.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/x509_knownkey.c (revision 346145)
@@ -0,0 +1,105 @@
+/*
+ * 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 bearssl_x509.h */
+void
+br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
+ const br_rsa_public_key *pk, unsigned usages)
+{
+ ctx->vtable = &br_x509_knownkey_vtable;
+ ctx->pkey.key_type = BR_KEYTYPE_RSA;
+ ctx->pkey.key.rsa = *pk;
+ ctx->usages = usages;
+}
+
+/* see bearssl_x509.h */
+void
+br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
+ const br_ec_public_key *pk, unsigned usages)
+{
+ ctx->vtable = &br_x509_knownkey_vtable;
+ ctx->pkey.key_type = BR_KEYTYPE_EC;
+ ctx->pkey.key.ec = *pk;
+ ctx->usages = usages;
+}
+
+static void
+kk_start_chain(const br_x509_class **ctx, const char *server_name)
+{
+ (void)ctx;
+ (void)server_name;
+}
+
+static void
+kk_start_cert(const br_x509_class **ctx, uint32_t length)
+{
+ (void)ctx;
+ (void)length;
+}
+
+static void
+kk_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)
+{
+ (void)ctx;
+ (void)buf;
+ (void)len;
+}
+
+static void
+kk_end_cert(const br_x509_class **ctx)
+{
+ (void)ctx;
+}
+
+static unsigned
+kk_end_chain(const br_x509_class **ctx)
+{
+ (void)ctx;
+ return 0;
+}
+
+static const br_x509_pkey *
+kk_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
+{
+ const br_x509_knownkey_context *xc;
+
+ xc = (const br_x509_knownkey_context *)ctx;
+ if (usages != NULL) {
+ *usages = xc->usages;
+ }
+ return &xc->pkey;
+}
+
+/* see bearssl_x509.h */
+const br_x509_class br_x509_knownkey_vtable = {
+ sizeof(br_x509_knownkey_context),
+ kk_start_chain,
+ kk_start_cert,
+ kk_append,
+ kk_end_cert,
+ kk_end_chain,
+ kk_get_pkey
+};
Property changes on: stable/12/contrib/bearssl/src/x509/x509_knownkey.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/x509_minimal.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/x509_minimal.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/x509_minimal.c (revision 346145)
@@ -0,0 +1,1713 @@
+/* Automatically generated code; do not modify directly. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint32_t *dp;
+ uint32_t *rp;
+ const unsigned char *ip;
+} t0_context;
+
+static uint32_t
+t0_parse7E_unsigned(const unsigned char **p)
+{
+ uint32_t x;
+
+ x = 0;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ return x;
+ }
+ }
+}
+
+static int32_t
+t0_parse7E_signed(const unsigned char **p)
+{
+ int neg;
+ uint32_t x;
+
+ neg = ((**p) >> 6) & 1;
+ x = (uint32_t)-neg;
+ for (;;) {
+ unsigned y;
+
+ y = *(*p) ++;
+ x = (x << 7) | (uint32_t)(y & 0x7F);
+ if (y < 0x80) {
+ if (neg) {
+ return -(int32_t)~x - 1;
+ } else {
+ return (int32_t)x;
+ }
+ }
+ }
+}
+
+#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
+#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
+#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
+#define T0_INT1(x) T0_FBYTE(x, 0)
+#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
+
+/* static const unsigned char t0_datablock[]; */
+
+
+void br_x509_minimal_init_main(void *t0ctx);
+
+void br_x509_minimal_run(void *t0ctx);
+
+
+
+#include "inner.h"
+
+
+
+
+
+#include "inner.h"
+
+/*
+ * Implementation Notes
+ * --------------------
+ *
+ * The C code pushes the data by chunks; all decoding is done in the
+ * T0 code. The cert_length value is set to the certificate length when
+ * a new certificate is started; the T0 code picks it up as outer limit,
+ * and decoding functions use it to ensure that no attempt is made at
+ * reading past it. The T0 code also checks that once the certificate is
+ * decoded, there are no trailing bytes.
+ *
+ * The T0 code sets cert_length to 0 when the certificate is fully
+ * decoded.
+ *
+ * The C code must still perform two checks:
+ *
+ * -- If the certificate length is 0, then the T0 code will not be
+ * invoked at all. This invalid condition must thus be reported by the
+ * C code.
+ *
+ * -- When reaching the end of certificate, the C code must verify that
+ * the certificate length has been set to 0, thereby signaling that
+ * the T0 code properly decoded a certificate.
+ *
+ * Processing of a chain works in the following way:
+ *
+ * -- The error flag is set to a non-zero value when validation is
+ * finished. The value is either BR_ERR_X509_OK (validation is
+ * successful) or another non-zero error code. When a non-zero error
+ * code is obtained, the remaining bytes in the current certificate and
+ * the subsequent certificates (if any) are completely ignored.
+ *
+ * -- Each certificate is decoded in due course, with the following
+ * "interesting points":
+ *
+ * -- Start of the TBS: the multihash engine is reset and activated.
+ *
+ * -- Start of the issuer DN: the secondary hash engine is started,
+ * to process the encoded issuer DN.
+ *
+ * -- End of the issuer DN: the secondary hash engine is stopped. The
+ * resulting hash value is computed and then copied into the
+ * next_dn_hash[] buffer.
+ *
+ * -- Start of the subject DN: the secondary hash engine is started,
+ * to process the encoded subject DN.
+ *
+ * -- For the EE certificate only: the Common Name, if any, is matched
+ * against the expected server name.
+ *
+ * -- End of the subject DN: the secondary hash engine is stopped. The
+ * resulting hash value is computed into the pad. It is then processed:
+ *
+ * -- If this is the EE certificate, then the hash is ignored
+ * (except for direct trust processing, see later; the hash is
+ * simply left in current_dn_hash[]).
+ *
+ * -- Otherwise, the hashed subject DN is compared with the saved
+ * hash value (in saved_dn_hash[]). They must match.
+ *
+ * Either way, the next_dn_hash[] value is then copied into the
+ * saved_dn_hash[] value. Thus, at that point, saved_dn_hash[]
+ * contains the hash of the issuer DN for the current certificate,
+ * and current_dn_hash[] contains the hash of the subject DN for the
+ * current certificate.
+ *
+ * -- Public key: it is decoded into the cert_pkey[] buffer. Unknown
+ * key types are reported at that point.
+ *
+ * -- If this is the EE certificate, then the key type is compared
+ * with the expected key type (initialization parameter). The public
+ * key data is copied to ee_pkey_data[]. The key and hashed subject
+ * DN are also compared with the "direct trust" keys; if the key
+ * and DN are matched, then validation ends with a success.
+ *
+ * -- Otherwise, the saved signature (cert_sig[]) is verified
+ * against the saved TBS hash (tbs_hash[]) and that freshly
+ * decoded public key. Failure here ends validation with an error.
+ *
+ * -- Extensions: extension values are processed in due order.
+ *
+ * -- Basic Constraints: for all certificates except EE, must be
+ * present, indicate a CA, and have a path legnth compatible with
+ * the chain length so far.
+ *
+ * -- Key Usage: for the EE, if present, must allow signatures
+ * or encryption/key exchange, as required for the cipher suite.
+ * For non-EE, if present, must have the "certificate sign" bit.
+ *
+ * -- Subject Alt Name: for the EE, dNSName names are matched
+ * against the server name. Ignored for non-EE.
+ *
+ * -- Authority Key Identifier, Subject Key Identifier, Issuer
+ * Alt Name, Subject Directory Attributes, CRL Distribution Points
+ * Freshest CRL, Authority Info Access and Subject Info Access
+ * extensions are always ignored: they either contain only
+ * informative data, or they relate to revocation processing, which
+ * we explicitly do not support.
+ *
+ * -- All other extensions are ignored if non-critical. If a
+ * critical extension other than the ones above is encountered,
+ * then a failure is reported.
+ *
+ * -- End of the TBS: the multihash engine is stopped.
+ *
+ * -- Signature algorithm: the signature algorithm on the
+ * certificate is decoded. A failure is reported if that algorithm
+ * is unknown. The hashed TBS corresponding to the signature hash
+ * function is computed and stored in tbs_hash[] (if not supported,
+ * then a failure is reported). The hash OID and length are stored
+ * in cert_sig_hash_oid and cert_sig_hash_len.
+ *
+ * -- Signature value: the signature value is copied into the
+ * cert_sig[] array.
+ *
+ * -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is
+ * looked up in the trust store (CA trust anchors only); for all
+ * that match, the signature (cert_sig[]) is verified against the
+ * anchor public key (hashed TBS is in tbs_hash[]). If one of these
+ * signatures is valid, then validation ends with a success.
+ *
+ * -- If the chain end is reached without obtaining a validation success,
+ * then validation is reported as failed.
+ */
+
+#if BR_USE_UNIX_TIME
+#include <time.h>
+#endif
+
+#if BR_USE_WIN32_TIME
+#include <windows.h>
+#endif
+
+/*
+ * The T0 compiler will produce these prototypes declarations in the
+ * header.
+ *
+void br_x509_minimal_init_main(void *ctx);
+void br_x509_minimal_run(void *ctx);
+ */
+
+/* see bearssl_x509.h */
+void
+br_x509_minimal_init(br_x509_minimal_context *ctx,
+ const br_hash_class *dn_hash_impl,
+ const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->vtable = &br_x509_minimal_vtable;
+ ctx->dn_hash_impl = dn_hash_impl;
+ ctx->trust_anchors = trust_anchors;
+ ctx->trust_anchors_num = trust_anchors_num;
+}
+
+static void
+xm_start_chain(const br_x509_class **ctx, const char *server_name)
+{
+ br_x509_minimal_context *cc;
+ size_t u;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ for (u = 0; u < cc->num_name_elts; u ++) {
+ cc->name_elts[u].status = 0;
+ cc->name_elts[u].buf[0] = 0;
+ }
+ memset(&cc->pkey, 0, sizeof cc->pkey);
+ cc->num_certs = 0;
+ cc->err = 0;
+ cc->cpu.dp = cc->dp_stack;
+ cc->cpu.rp = cc->rp_stack;
+ br_x509_minimal_init_main(&cc->cpu);
+ if (server_name == NULL || *server_name == 0) {
+ cc->server_name = NULL;
+ } else {
+ cc->server_name = server_name;
+ }
+}
+
+static void
+xm_start_cert(const br_x509_class **ctx, uint32_t length)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err != 0) {
+ return;
+ }
+ if (length == 0) {
+ cc->err = BR_ERR_X509_TRUNCATED;
+ return;
+ }
+ cc->cert_length = length;
+}
+
+static void
+xm_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err != 0) {
+ return;
+ }
+ cc->hbuf = buf;
+ cc->hlen = len;
+ br_x509_minimal_run(&cc->cpu);
+}
+
+static void
+xm_end_cert(const br_x509_class **ctx)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err == 0 && cc->cert_length != 0) {
+ cc->err = BR_ERR_X509_TRUNCATED;
+ }
+ cc->num_certs ++;
+}
+
+static unsigned
+xm_end_chain(const br_x509_class **ctx)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err == 0) {
+ if (cc->num_certs == 0) {
+ cc->err = BR_ERR_X509_EMPTY_CHAIN;
+ } else {
+ cc->err = BR_ERR_X509_NOT_TRUSTED;
+ }
+ } else if (cc->err == BR_ERR_X509_OK) {
+ return 0;
+ }
+ return (unsigned)cc->err;
+}
+
+static const br_x509_pkey *
+xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err == BR_ERR_X509_OK
+ || cc->err == BR_ERR_X509_NOT_TRUSTED)
+ {
+ if (usages != NULL) {
+ *usages = cc->key_usages;
+ }
+ return &((br_x509_minimal_context *)(void *)ctx)->pkey;
+ } else {
+ return NULL;
+ }
+}
+
+/* see bearssl_x509.h */
+const br_x509_class br_x509_minimal_vtable = {
+ sizeof(br_x509_minimal_context),
+ xm_start_chain,
+ xm_start_cert,
+ xm_append,
+ xm_end_cert,
+ xm_end_chain,
+ xm_get_pkey
+};
+
+#define CTX ((br_x509_minimal_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_minimal_context, cpu)))
+#define CONTEXT_NAME br_x509_minimal_context
+
+#define DNHASH_LEN ((CTX->dn_hash_impl->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK)
+
+/*
+ * Hash a DN (from a trust anchor) into the provided buffer. This uses the
+ * DN hash implementation and context structure from the X.509 engine
+ * context.
+ */
+static void
+hash_dn(br_x509_minimal_context *ctx, const void *dn, size_t len,
+ unsigned char *out)
+{
+ ctx->dn_hash_impl->init(&ctx->dn_hash.vtable);
+ ctx->dn_hash_impl->update(&ctx->dn_hash.vtable, dn, len);
+ ctx->dn_hash_impl->out(&ctx->dn_hash.vtable, out);
+}
+
+/*
+ * Compare two big integers for equality. The integers use unsigned big-endian
+ * encoding; extra leading bytes (of value 0) are allowed.
+ */
+static int
+eqbigint(const unsigned char *b1, size_t len1,
+ const unsigned char *b2, size_t len2)
+{
+ while (len1 > 0 && *b1 == 0) {
+ b1 ++;
+ len1 --;
+ }
+ while (len2 > 0 && *b2 == 0) {
+ b2 ++;
+ len2 --;
+ }
+ if (len1 != len2) {
+ return 0;
+ }
+ return memcmp(b1, b2, len1) == 0;
+}
+
+/*
+ * Compare two strings for equality, in a case-insensitive way. This
+ * function handles casing only for ASCII letters.
+ */
+static int
+eqnocase(const void *s1, const void *s2, size_t len)
+{
+ const unsigned char *buf1, *buf2;
+
+ buf1 = s1;
+ buf2 = s2;
+ while (len -- > 0) {
+ int x1, x2;
+
+ x1 = *buf1 ++;
+ x2 = *buf2 ++;
+ if (x1 >= 'A' && x1 <= 'Z') {
+ x1 += 'a' - 'A';
+ }
+ if (x2 >= 'A' && x2 <= 'Z') {
+ x2 += 'a' - 'A';
+ }
+ if (x1 != x2) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int verify_signature(br_x509_minimal_context *ctx,
+ const br_x509_pkey *pk);
+
+
+
+static const unsigned char t0_datablock[] = {
+ 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x09, 0x2A, 0x86,
+ 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+ 0x01, 0x01, 0x0C, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
+ 0x0D, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x09, 0x60, 0x86, 0x48, 0x01,
+ 0x65, 0x03, 0x04, 0x02, 0x04, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x01, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
+ 0x02, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x07,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x05, 0x2B,
+ 0x81, 0x04, 0x00, 0x23, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01,
+ 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x08, 0x2A, 0x86,
+ 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x04, 0x03, 0x03, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04,
+ 0x03, 0x55, 0x04, 0x03, 0x00, 0x1F, 0x03, 0xFC, 0x07, 0x7F, 0x0B, 0x5E,
+ 0x0F, 0x1F, 0x12, 0xFE, 0x16, 0xBF, 0x1A, 0x9F, 0x1E, 0x7E, 0x22, 0x3F,
+ 0x26, 0x1E, 0x29, 0xDF, 0x00, 0x1F, 0x03, 0xFD, 0x07, 0x9F, 0x0B, 0x7E,
+ 0x0F, 0x3F, 0x13, 0x1E, 0x16, 0xDF, 0x1A, 0xBF, 0x1E, 0x9E, 0x22, 0x5F,
+ 0x26, 0x3E, 0x29, 0xFF, 0x03, 0x55, 0x1D, 0x13, 0x03, 0x55, 0x1D, 0x0F,
+ 0x03, 0x55, 0x1D, 0x11, 0x03, 0x55, 0x1D, 0x20, 0x08, 0x2B, 0x06, 0x01,
+ 0x05, 0x05, 0x07, 0x02, 0x01, 0x03, 0x55, 0x1D, 0x23, 0x03, 0x55, 0x1D,
+ 0x0E, 0x03, 0x55, 0x1D, 0x12, 0x03, 0x55, 0x1D, 0x09, 0x03, 0x55, 0x1D,
+ 0x1F, 0x03, 0x55, 0x1D, 0x2E, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0B
+};
+
+static const unsigned char t0_codeblock[] = {
+ 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01,
+ 0x00, 0x11, 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x01, 0x0A,
+ 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_BOOLEAN), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_DN), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_SERVER_NAME), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_BAD_TIME), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_CRITICAL_EXTENSION), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_DN_MISMATCH), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_EXPIRED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_FORBIDDEN_KEY_USAGE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_NOT_CA), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_PARTIAL_BYTE), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01,
+ T0_INT1(BR_ERR_X509_WEAK_PUBLIC_KEY), 0x00, 0x00, 0x01,
+ T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA),
+ 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_length)), 0x00,
+ 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_len)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_oid)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_len)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, cert_signer_key_type)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(CONTEXT_NAME, current_dn_hash)), 0x00, 0x00,
+ 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_usages)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(br_x509_minimal_context, pkey_data)), 0x01,
+ T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, min_rsa_size)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, next_dn_hash)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, num_certs)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01,
+ T0_INT2(offsetof(CONTEXT_NAME, saved_dn_hash)), 0x00, 0x00, 0xC9, 0x71,
+ 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00, 0x00,
+ 0x01, 0x81, 0x02, 0x00, 0x00, 0x92, 0x05, 0x05, 0x34, 0x42, 0x01, 0x00,
+ 0x00, 0x34, 0x01, 0x0A, 0x0E, 0x09, 0x01, 0x9A, 0xFF, 0xB8, 0x00, 0x0A,
+ 0x00, 0x00, 0x01, 0x82, 0x19, 0x00, 0x00, 0x01, 0x82, 0x01, 0x00, 0x00,
+ 0x01, 0x81, 0x68, 0x00, 0x04, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x03,
+ 0x03, 0x02, 0x03, 0x02, 0x01, 0x11, 0x06, 0x07, 0x02, 0x02, 0x02, 0x00,
+ 0x0D, 0x04, 0x05, 0x02, 0x03, 0x02, 0x01, 0x0D, 0x00, 0x02, 0x03, 0x00,
+ 0x03, 0x01, 0x25, 0x02, 0x01, 0x13, 0x3B, 0x02, 0x00, 0x0F, 0x15, 0x00,
+ 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x05, 0x02, 0x52, 0x28, 0x00, 0x00,
+ 0x06, 0x02, 0x53, 0x28, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, 0x00, 0x11,
+ 0x05, 0x02, 0x56, 0x28, 0x74, 0x00, 0x00, 0x11, 0x05, 0x02, 0x56, 0x28,
+ 0x75, 0x00, 0x00, 0x06, 0x02, 0x4C, 0x28, 0x00, 0x00, 0x01, 0x82, 0x11,
+ 0x00, 0x00, 0x25, 0x20, 0x01, 0x08, 0x0E, 0x3B, 0x40, 0x20, 0x09, 0x00,
+ 0x09, 0x03, 0x00, 0x5B, 0x2B, 0xAF, 0x39, 0xAF, 0xB3, 0x25, 0x01, 0x20,
+ 0x11, 0x06, 0x11, 0x24, 0x74, 0xAD, 0xB3, 0x01, 0x02, 0x78, 0xB0, 0x01,
+ 0x02, 0x12, 0x06, 0x02, 0x57, 0x28, 0x79, 0xB3, 0x01, 0x02, 0x78, 0xAE,
+ 0xAF, 0xC2, 0x9C, 0x65, 0x61, 0x21, 0x16, 0xAF, 0xA7, 0x29, 0x69, 0x06,
+ 0x02, 0x4B, 0x28, 0xA7, 0x29, 0x71, 0x06, 0x02, 0x4B, 0x28, 0x79, 0x02,
+ 0x00, 0x06, 0x05, 0x9D, 0x03, 0x01, 0x04, 0x09, 0x9C, 0x61, 0x68, 0x21,
+ 0x27, 0x05, 0x02, 0x4A, 0x28, 0x68, 0x65, 0x21, 0x16, 0xAF, 0xAF, 0x9E,
+ 0x05, 0x02, 0x57, 0x28, 0xBC, 0x26, 0x06, 0x27, 0xC2, 0xA4, 0xAF, 0x63,
+ 0xAA, 0x03, 0x03, 0x63, 0x3B, 0x02, 0x03, 0x09, 0x3B, 0x02, 0x03, 0x0A,
+ 0xAA, 0x03, 0x04, 0x79, 0x64, 0x2A, 0x01, 0x81, 0x00, 0x09, 0x02, 0x03,
+ 0x12, 0x06, 0x02, 0x58, 0x28, 0x79, 0x5A, 0x03, 0x02, 0x04, 0x3A, 0x88,
+ 0x26, 0x06, 0x34, 0x9E, 0x05, 0x02, 0x57, 0x28, 0x6A, 0x26, 0x06, 0x04,
+ 0x01, 0x17, 0x04, 0x12, 0x6B, 0x26, 0x06, 0x04, 0x01, 0x18, 0x04, 0x0A,
+ 0x6C, 0x26, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x57, 0x28, 0x03, 0x05,
+ 0x79, 0xA4, 0x25, 0x03, 0x06, 0x25, 0x63, 0x34, 0x0D, 0x06, 0x02, 0x50,
+ 0x28, 0xA5, 0x59, 0x03, 0x02, 0x04, 0x02, 0x57, 0x28, 0x79, 0x02, 0x00,
+ 0x06, 0x21, 0x02, 0x02, 0x5A, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x03,
+ 0x02, 0x04, 0x1D, 0x04, 0x10, 0x59, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02,
+ 0x05, 0x02, 0x06, 0x1C, 0x04, 0x03, 0x57, 0x28, 0x24, 0x04, 0x24, 0x02,
+ 0x02, 0x5A, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x03, 0x02, 0x04, 0x23,
+ 0x04, 0x10, 0x59, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x05, 0x02, 0x06,
+ 0x22, 0x04, 0x03, 0x57, 0x28, 0x24, 0x25, 0x06, 0x01, 0x28, 0x24, 0x01,
+ 0x00, 0x03, 0x07, 0xB4, 0x01, 0x21, 0x8F, 0x01, 0x22, 0x8F, 0x25, 0x01,
+ 0x23, 0x11, 0x06, 0x81, 0x26, 0x24, 0x74, 0xAD, 0xAF, 0x25, 0x06, 0x81,
+ 0x1A, 0x01, 0x00, 0x03, 0x08, 0xAF, 0x9E, 0x24, 0xB3, 0x25, 0x01, 0x01,
+ 0x11, 0x06, 0x04, 0xA6, 0x03, 0x08, 0xB3, 0x01, 0x04, 0x78, 0xAD, 0x70,
+ 0x26, 0x06, 0x0F, 0x02, 0x00, 0x06, 0x03, 0xC3, 0x04, 0x05, 0x99, 0x01,
+ 0x7F, 0x03, 0x07, 0x04, 0x80, 0x6C, 0x91, 0x26, 0x06, 0x06, 0x02, 0x00,
+ 0x9B, 0x04, 0x80, 0x62, 0xC5, 0x26, 0x06, 0x11, 0x02, 0x00, 0x06, 0x09,
+ 0x01, 0x00, 0x03, 0x01, 0x98, 0x03, 0x01, 0x04, 0x01, 0xC3, 0x04, 0x80,
+ 0x4D, 0x73, 0x26, 0x06, 0x0A, 0x02, 0x08, 0x06, 0x03, 0x9A, 0x04, 0x01,
+ 0xC3, 0x04, 0x3F, 0x6F, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x38, 0xC8, 0x26,
+ 0x06, 0x03, 0xC3, 0x04, 0x31, 0x90, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x2A,
+ 0xC6, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x23, 0x7A, 0x26, 0x06, 0x03, 0xC3,
+ 0x04, 0x1C, 0x85, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x15, 0x6E, 0x26, 0x06,
+ 0x03, 0xC3, 0x04, 0x0E, 0xC7, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x07, 0x02,
+ 0x08, 0x06, 0x02, 0x49, 0x28, 0xC3, 0x79, 0x79, 0x04, 0xFE, 0x62, 0x79,
+ 0x79, 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, 0x56, 0x28, 0x24, 0x79,
+ 0x3A, 0x02, 0x00, 0x06, 0x08, 0x02, 0x01, 0x3C, 0x2F, 0x05, 0x02, 0x45,
+ 0x28, 0x02, 0x00, 0x06, 0x01, 0x17, 0x02, 0x00, 0x02, 0x07, 0x2F, 0x05,
+ 0x02, 0x51, 0x28, 0xB3, 0x76, 0xAD, 0x9E, 0x06, 0x80, 0x77, 0xBD, 0x26,
+ 0x06, 0x07, 0x01, 0x02, 0x5A, 0x8A, 0x04, 0x80, 0x5E, 0xBE, 0x26, 0x06,
+ 0x07, 0x01, 0x03, 0x5A, 0x8B, 0x04, 0x80, 0x53, 0xBF, 0x26, 0x06, 0x07,
+ 0x01, 0x04, 0x5A, 0x8C, 0x04, 0x80, 0x48, 0xC0, 0x26, 0x06, 0x06, 0x01,
+ 0x05, 0x5A, 0x8D, 0x04, 0x3E, 0xC1, 0x26, 0x06, 0x06, 0x01, 0x06, 0x5A,
+ 0x8E, 0x04, 0x34, 0x7F, 0x26, 0x06, 0x06, 0x01, 0x02, 0x59, 0x8A, 0x04,
+ 0x2A, 0x80, 0x26, 0x06, 0x06, 0x01, 0x03, 0x59, 0x8B, 0x04, 0x20, 0x81,
+ 0x26, 0x06, 0x06, 0x01, 0x04, 0x59, 0x8C, 0x04, 0x16, 0x82, 0x26, 0x06,
+ 0x06, 0x01, 0x05, 0x59, 0x8D, 0x04, 0x0C, 0x83, 0x26, 0x06, 0x06, 0x01,
+ 0x06, 0x59, 0x8E, 0x04, 0x02, 0x57, 0x28, 0x5E, 0x35, 0x60, 0x37, 0x1B,
+ 0x25, 0x05, 0x02, 0x57, 0x28, 0x5D, 0x37, 0x04, 0x02, 0x57, 0x28, 0xC2,
+ 0xA4, 0x25, 0x01, T0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02, 0x50,
+ 0x28, 0x25, 0x5F, 0x35, 0x5C, 0xA5, 0x79, 0x79, 0x01, 0x00, 0x5B, 0x36,
+ 0x18, 0x00, 0x00, 0x01, 0x30, 0x0A, 0x25, 0x01, 0x00, 0x01, 0x09, 0x72,
+ 0x05, 0x02, 0x48, 0x28, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x01, 0x81,
+ 0x08, 0x00, 0x00, 0x01, 0x81, 0x10, 0x00, 0x00, 0x01, 0x81, 0x19, 0x00,
+ 0x00, 0x01, 0x81, 0x22, 0x00, 0x00, 0x01, 0x81, 0x2B, 0x00, 0x01, 0x7E,
+ 0x01, 0x01, 0x11, 0x3B, 0x01, 0x83, 0xFD, 0x7F, 0x11, 0x15, 0x06, 0x03,
+ 0x3B, 0x24, 0x00, 0x3B, 0x25, 0x03, 0x00, 0x25, 0xCA, 0x05, 0x04, 0x42,
+ 0x01, 0x00, 0x00, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x96, 0x04,
+ 0x80, 0x49, 0x25, 0x01, 0x90, 0x00, 0x0D, 0x06, 0x0F, 0x01, 0x06, 0x14,
+ 0x01, 0x81, 0x40, 0x2F, 0x96, 0x02, 0x00, 0x01, 0x00, 0x97, 0x04, 0x33,
+ 0x25, 0x01, 0x83, 0xFF, 0x7F, 0x0D, 0x06, 0x14, 0x01, 0x0C, 0x14, 0x01,
+ 0x81, 0x60, 0x2F, 0x96, 0x02, 0x00, 0x01, 0x06, 0x97, 0x02, 0x00, 0x01,
+ 0x00, 0x97, 0x04, 0x17, 0x01, 0x12, 0x14, 0x01, 0x81, 0x70, 0x2F, 0x96,
+ 0x02, 0x00, 0x01, 0x0C, 0x97, 0x02, 0x00, 0x01, 0x06, 0x97, 0x02, 0x00,
+ 0x01, 0x00, 0x97, 0x00, 0x00, 0x01, 0x82, 0x15, 0x00, 0x00, 0x25, 0x01,
+ 0x83, 0xB0, 0x00, 0x01, 0x83, 0xB7, 0x7F, 0x72, 0x00, 0x00, 0x01, 0x81,
+ 0x34, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x81, 0x78, 0x00,
+ 0x00, 0x01, 0x3D, 0x00, 0x00, 0x01, 0x80, 0x43, 0x00, 0x00, 0x01, 0x80,
+ 0x4D, 0x00, 0x00, 0x01, 0x80, 0x57, 0x00, 0x00, 0x01, 0x80, 0x61, 0x00,
+ 0x00, 0x30, 0x11, 0x06, 0x04, 0x42, 0xAD, 0xC2, 0xB4, 0x00, 0x00, 0x01,
+ 0x82, 0x09, 0x00, 0x00, 0x01, 0x81, 0x6C, 0x00, 0x00, 0x25, 0x01, 0x83,
+ 0xB8, 0x00, 0x01, 0x83, 0xBF, 0x7F, 0x72, 0x00, 0x00, 0x01, 0x30, 0x62,
+ 0x37, 0x01, 0x7F, 0x7C, 0x19, 0x01, 0x00, 0x7C, 0x19, 0x04, 0x7A, 0x00,
+ 0x01, 0x81, 0x38, 0x00, 0x01, 0x7E, 0x0D, 0x06, 0x02, 0x4F, 0x28, 0x25,
+ 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, 0x30, 0x25, 0x3F, 0x3B, 0x01,
+ 0x82, 0x00, 0x13, 0x2F, 0x06, 0x04, 0x42, 0x01, 0x00, 0x00, 0x30, 0x67,
+ 0x09, 0x37, 0x40, 0x00, 0x00, 0x14, 0x01, 0x3F, 0x15, 0x01, 0x81, 0x00,
+ 0x2F, 0x96, 0x00, 0x02, 0x01, 0x00, 0x03, 0x00, 0xAF, 0x25, 0x06, 0x80,
+ 0x59, 0xB3, 0x01, 0x20, 0x30, 0x11, 0x06, 0x17, 0x24, 0x74, 0xAD, 0x9E,
+ 0x24, 0x01, 0x7F, 0x2E, 0x03, 0x01, 0xB3, 0x01, 0x20, 0x77, 0xAD, 0xB2,
+ 0x02, 0x01, 0x1F, 0x79, 0x79, 0x04, 0x38, 0x01, 0x21, 0x30, 0x11, 0x06,
+ 0x08, 0x24, 0x75, 0xB6, 0x01, 0x01, 0x1E, 0x04, 0x2A, 0x01, 0x22, 0x30,
+ 0x11, 0x06, 0x11, 0x24, 0x75, 0xB6, 0x25, 0x06, 0x06, 0x2C, 0x02, 0x00,
+ 0x2F, 0x03, 0x00, 0x01, 0x02, 0x1E, 0x04, 0x13, 0x01, 0x26, 0x30, 0x11,
+ 0x06, 0x08, 0x24, 0x75, 0xB6, 0x01, 0x06, 0x1E, 0x04, 0x05, 0x42, 0xAE,
+ 0x01, 0x00, 0x24, 0x04, 0xFF, 0x23, 0x79, 0x02, 0x00, 0x00, 0x00, 0xAF,
+ 0xB4, 0x25, 0x01, 0x01, 0x11, 0x06, 0x08, 0xA6, 0x05, 0x02, 0x51, 0x28,
+ 0xB4, 0x04, 0x02, 0x51, 0x28, 0x25, 0x01, 0x02, 0x11, 0x06, 0x0C, 0x24,
+ 0x75, 0xB0, 0x66, 0x2B, 0x41, 0x0D, 0x06, 0x02, 0x51, 0x28, 0xB4, 0x01,
+ 0x7F, 0x10, 0x06, 0x02, 0x56, 0x28, 0x24, 0x79, 0x00, 0x00, 0xAF, 0x25,
+ 0x06, 0x1A, 0xAF, 0x9E, 0x24, 0x25, 0x06, 0x11, 0xAF, 0x25, 0x06, 0x0C,
+ 0xAF, 0x9E, 0x24, 0x89, 0x26, 0x05, 0x02, 0x49, 0x28, 0xC2, 0x04, 0x71,
+ 0x79, 0x79, 0x04, 0x63, 0x79, 0x00, 0x02, 0x03, 0x00, 0xB3, 0x01, 0x03,
+ 0x78, 0xAD, 0xBA, 0x03, 0x01, 0x02, 0x01, 0x01, 0x07, 0x12, 0x06, 0x02,
+ 0x56, 0x28, 0x25, 0x01, 0x00, 0x30, 0x11, 0x06, 0x05, 0x24, 0x4D, 0x28,
+ 0x04, 0x15, 0x01, 0x01, 0x30, 0x11, 0x06, 0x0A, 0x24, 0xBA, 0x02, 0x01,
+ 0x14, 0x02, 0x01, 0x0E, 0x04, 0x05, 0x24, 0xBA, 0x01, 0x00, 0x24, 0x02,
+ 0x00, 0x06, 0x19, 0x01, 0x00, 0x30, 0x01, 0x38, 0x15, 0x06, 0x03, 0x01,
+ 0x10, 0x2F, 0x3B, 0x01, 0x81, 0x40, 0x15, 0x06, 0x03, 0x01, 0x20, 0x2F,
+ 0x62, 0x37, 0x04, 0x07, 0x01, 0x04, 0x15, 0x05, 0x02, 0x4D, 0x28, 0xC2,
+ 0x00, 0x00, 0x38, 0xAF, 0xC2, 0x1A, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00,
+ 0x38, 0xAF, 0x25, 0x06, 0x30, 0xB3, 0x01, 0x11, 0x77, 0xAD, 0x25, 0x05,
+ 0x02, 0x44, 0x28, 0x25, 0x06, 0x20, 0xAF, 0x9E, 0x24, 0x87, 0x26, 0x03,
+ 0x01, 0x01, 0x00, 0x2E, 0x03, 0x02, 0xB2, 0x25, 0x02, 0x01, 0x15, 0x06,
+ 0x07, 0x2C, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x02, 0x02, 0x1F, 0x79,
+ 0x04, 0x5D, 0x79, 0x04, 0x4D, 0x79, 0x1A, 0x02, 0x00, 0x00, 0x00, 0xB3,
+ 0x01, 0x06, 0x78, 0xB1, 0x00, 0x00, 0xB8, 0x86, 0x06, 0x0E, 0x3B, 0x25,
+ 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x00, 0x00, 0xB8, 0x6D, 0x04, 0x08,
+ 0x92, 0x06, 0x05, 0x24, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB9, 0x86,
+ 0x06, 0x0E, 0x3B, 0x25, 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x00, 0x00,
+ 0xB9, 0x6D, 0x04, 0x08, 0x92, 0x06, 0x05, 0x24, 0x01, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x00, 0x04,
+ 0x80, 0x55, 0x25, 0x01, 0x81, 0x40, 0x0D, 0x06, 0x07, 0x24, 0x01, 0x00,
+ 0x00, 0x04, 0x80, 0x47, 0x25, 0x01, 0x81, 0x60, 0x0D, 0x06, 0x0E, 0x01,
+ 0x1F, 0x15, 0x01, 0x01, 0xA3, 0x01, 0x81, 0x00, 0x01, 0x8F, 0x7F, 0x04,
+ 0x32, 0x25, 0x01, 0x81, 0x70, 0x0D, 0x06, 0x0F, 0x01, 0x0F, 0x15, 0x01,
+ 0x02, 0xA3, 0x01, 0x90, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x04, 0x1C, 0x25,
+ 0x01, 0x81, 0x78, 0x0D, 0x06, 0x11, 0x01, 0x07, 0x15, 0x01, 0x03, 0xA3,
+ 0x01, 0x84, 0x80, 0x00, 0x01, 0x80, 0xC3, 0xFF, 0x7F, 0x04, 0x04, 0x24,
+ 0x01, 0x00, 0x00, 0x72, 0x05, 0x03, 0x24, 0x01, 0x00, 0x00, 0x00, 0x3B,
+ 0x25, 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xBA, 0x34, 0x25,
+ 0x3D, 0x06, 0x03, 0x3B, 0x24, 0x00, 0x01, 0x06, 0x0E, 0x3B, 0x25, 0x01,
+ 0x06, 0x14, 0x01, 0x02, 0x10, 0x06, 0x04, 0x42, 0x01, 0x7F, 0x00, 0x01,
+ 0x3F, 0x15, 0x09, 0x00, 0x00, 0x25, 0x06, 0x06, 0x0B, 0xA2, 0x34, 0x41,
+ 0x04, 0x77, 0x24, 0x25, 0x00, 0x00, 0xB3, 0x01, 0x03, 0x78, 0xAD, 0xBA,
+ 0x06, 0x02, 0x55, 0x28, 0x00, 0x00, 0x3B, 0x25, 0x06, 0x07, 0x31, 0x25,
+ 0x06, 0x01, 0x19, 0x04, 0x76, 0x42, 0x00, 0x00, 0x01, 0x01, 0x78, 0xAC,
+ 0x01, 0x01, 0x10, 0x06, 0x02, 0x43, 0x28, 0xBA, 0x3E, 0x00, 0x04, 0xB3,
+ 0x25, 0x01, 0x17, 0x01, 0x18, 0x72, 0x05, 0x02, 0x48, 0x28, 0x01, 0x18,
+ 0x11, 0x03, 0x00, 0x75, 0xAD, 0xA8, 0x02, 0x00, 0x06, 0x0C, 0x01, 0x80,
+ 0x64, 0x08, 0x03, 0x01, 0xA8, 0x02, 0x01, 0x09, 0x04, 0x0E, 0x25, 0x01,
+ 0x32, 0x0D, 0x06, 0x04, 0x01, 0x80, 0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09,
+ 0x03, 0x01, 0x02, 0x01, 0x01, 0x82, 0x6D, 0x08, 0x02, 0x01, 0x01, 0x03,
+ 0x09, 0x01, 0x04, 0x0C, 0x09, 0x02, 0x01, 0x01, 0x80, 0x63, 0x09, 0x01,
+ 0x80, 0x64, 0x0C, 0x0A, 0x02, 0x01, 0x01, 0x83, 0x0F, 0x09, 0x01, 0x83,
+ 0x10, 0x0C, 0x09, 0x03, 0x03, 0x01, 0x01, 0x01, 0x0C, 0xA9, 0x41, 0x01,
+ 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04, 0x07, 0x3F, 0x02, 0x01, 0x01, 0x80,
+ 0x64, 0x07, 0x3E, 0x02, 0x01, 0x01, 0x83, 0x10, 0x07, 0x3F, 0x2F, 0x15,
+ 0x06, 0x03, 0x01, 0x18, 0x09, 0x94, 0x09, 0x7B, 0x25, 0x01, 0x05, 0x14,
+ 0x02, 0x03, 0x09, 0x03, 0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x3B, 0xA9,
+ 0x02, 0x03, 0x09, 0x41, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0xA9, 0x01,
+ 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0xA9, 0x01, 0x3C,
+ 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C, 0xA9, 0x02,
+ 0x02, 0x09, 0x03, 0x02, 0xBA, 0x25, 0x01, 0x2E, 0x11, 0x06, 0x0D, 0x24,
+ 0xBA, 0x25, 0x01, 0x30, 0x01, 0x39, 0x72, 0x06, 0x03, 0x24, 0x04, 0x74,
+ 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x48, 0x28, 0x79, 0x02, 0x03, 0x02,
+ 0x02, 0x00, 0x01, 0xBA, 0x7D, 0x01, 0x0A, 0x08, 0x03, 0x00, 0xBA, 0x7D,
+ 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0xA8, 0x25, 0x02,
+ 0x01, 0x02, 0x00, 0x72, 0x05, 0x02, 0x48, 0x28, 0x00, 0x00, 0x34, 0xB3,
+ 0x01, 0x02, 0x78, 0x0B, 0xAB, 0x00, 0x03, 0x25, 0x03, 0x00, 0x03, 0x01,
+ 0x03, 0x02, 0xAD, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x54,
+ 0x28, 0x25, 0x01, 0x00, 0x11, 0x06, 0x0B, 0x24, 0x25, 0x05, 0x04, 0x24,
+ 0x01, 0x00, 0x00, 0xBA, 0x04, 0x6F, 0x02, 0x01, 0x25, 0x05, 0x02, 0x50,
+ 0x28, 0x41, 0x03, 0x01, 0x02, 0x02, 0x37, 0x02, 0x02, 0x40, 0x03, 0x02,
+ 0x25, 0x06, 0x03, 0xBA, 0x04, 0x68, 0x24, 0x02, 0x00, 0x02, 0x01, 0x0A,
+ 0x00, 0x01, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01,
+ 0x81, 0x00, 0x0A, 0x25, 0x05, 0x02, 0x4E, 0x28, 0x03, 0x00, 0x01, 0x00,
+ 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x19, 0x02, 0x00, 0x41, 0x03, 0x00,
+ 0x25, 0x01, 0x83, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02, 0x4F, 0x28, 0x01,
+ 0x08, 0x0E, 0x3B, 0xBA, 0x34, 0x09, 0x04, 0x60, 0x00, 0x00, 0xAC, 0x95,
+ 0x00, 0x00, 0xAD, 0xC2, 0x00, 0x00, 0xB3, 0x76, 0xAD, 0x00, 0x01, 0xAD,
+ 0x25, 0x05, 0x02, 0x54, 0x28, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x13, 0x06,
+ 0x02, 0x54, 0x28, 0x03, 0x00, 0x25, 0x06, 0x16, 0xBA, 0x02, 0x00, 0x25,
+ 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x54, 0x28, 0x01, 0x08,
+ 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67, 0x24, 0x02, 0x00, 0x00, 0x00, 0xAD,
+ 0x25, 0x01, 0x81, 0x7F, 0x12, 0x06, 0x08, 0xC2, 0x01, 0x00, 0x67, 0x37,
+ 0x01, 0x00, 0x00, 0x25, 0x67, 0x37, 0x67, 0x40, 0xA5, 0x01, 0x7F, 0x00,
+ 0x00, 0xB3, 0x01, 0x0C, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB6, 0x04,
+ 0x3E, 0x01, 0x12, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x33,
+ 0x01, 0x13, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x28, 0x01,
+ 0x14, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x1D, 0x01, 0x16,
+ 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x12, 0x01, 0x1E, 0x30,
+ 0x11, 0x06, 0x05, 0x24, 0x75, 0xB5, 0x04, 0x07, 0x42, 0xAE, 0x01, 0x00,
+ 0x01, 0x00, 0x24, 0x00, 0x01, 0xBA, 0x03, 0x00, 0x02, 0x00, 0x01, 0x05,
+ 0x14, 0x01, 0x01, 0x15, 0x2D, 0x02, 0x00, 0x01, 0x06, 0x14, 0x25, 0x01,
+ 0x01, 0x15, 0x06, 0x02, 0x46, 0x28, 0x01, 0x04, 0x0E, 0x02, 0x00, 0x01,
+ 0x1F, 0x15, 0x25, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x47, 0x28, 0x09, 0x00,
+ 0x00, 0x25, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xB3, 0x00, 0x01,
+ 0xAD, 0x25, 0x05, 0x05, 0x67, 0x37, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x03,
+ 0x00, 0x9F, 0x25, 0x01, 0x83, 0xFF, 0x7E, 0x11, 0x06, 0x16, 0x24, 0x25,
+ 0x06, 0x10, 0xA0, 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02,
+ 0x00, 0x84, 0x03, 0x00, 0x04, 0x6D, 0x04, 0x1B, 0x25, 0x05, 0x05, 0x24,
+ 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, 0x00, 0x25, 0x06, 0x0B,
+ 0x9F, 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x6D, 0x24,
+ 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, 0x37, 0x01, 0x7F, 0x00,
+ 0x01, 0xAD, 0x01, 0x01, 0x03, 0x00, 0x25, 0x06, 0x10, 0xA1, 0x25, 0x05,
+ 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, 0x00, 0x04,
+ 0x6D, 0x24, 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, 0x37, 0x01,
+ 0x7F, 0x00, 0x01, 0xAD, 0x01, 0x01, 0x03, 0x00, 0x25, 0x06, 0x10, 0xBA,
+ 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03,
+ 0x00, 0x04, 0x6D, 0x24, 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67,
+ 0x37, 0x01, 0x7F, 0x00, 0x00, 0xBA, 0x01, 0x08, 0x0E, 0x3B, 0xBA, 0x34,
+ 0x09, 0x00, 0x00, 0xBA, 0x3B, 0xBA, 0x01, 0x08, 0x0E, 0x34, 0x09, 0x00,
+ 0x00, 0x25, 0x05, 0x02, 0x4F, 0x28, 0x41, 0xBB, 0x00, 0x00, 0x32, 0x25,
+ 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x24, 0x19, 0x04, 0x74, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01,
+ 0x1F, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0xC3,
+ 0x24, 0x00, 0x00, 0x25, 0x06, 0x07, 0xC4, 0x25, 0x06, 0x01, 0x19, 0x04,
+ 0x76, 0x00, 0x00, 0x01, 0x00, 0x30, 0x31, 0x0B, 0x42, 0x00, 0x00, 0x01,
+ 0x81, 0x70, 0x00, 0x00, 0x01, 0x82, 0x0D, 0x00, 0x00, 0x01, 0x82, 0x22,
+ 0x00, 0x00, 0x01, 0x82, 0x05, 0x00, 0x00, 0x01, 0x03, 0x33, 0x01, 0x03,
+ 0x33, 0x00, 0x00, 0x25, 0x01, 0x83, 0xFB, 0x50, 0x01, 0x83, 0xFD, 0x5F,
+ 0x72, 0x06, 0x04, 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x83, 0xB0, 0x00,
+ 0x01, 0x83, 0xBF, 0x7F, 0x72, 0x06, 0x04, 0x24, 0x01, 0x00, 0x00, 0x01,
+ 0x83, 0xFF, 0x7F, 0x15, 0x01, 0x83, 0xFF, 0x7E, 0x0D, 0x00
+};
+
+static const uint16_t t0_caddr[] = {
+ 0,
+ 5,
+ 10,
+ 15,
+ 20,
+ 25,
+ 29,
+ 33,
+ 37,
+ 41,
+ 45,
+ 49,
+ 53,
+ 57,
+ 61,
+ 65,
+ 69,
+ 73,
+ 77,
+ 81,
+ 85,
+ 89,
+ 93,
+ 97,
+ 101,
+ 105,
+ 109,
+ 113,
+ 117,
+ 121,
+ 125,
+ 130,
+ 135,
+ 140,
+ 145,
+ 150,
+ 155,
+ 160,
+ 165,
+ 173,
+ 178,
+ 183,
+ 188,
+ 193,
+ 198,
+ 202,
+ 207,
+ 212,
+ 217,
+ 238,
+ 243,
+ 248,
+ 253,
+ 282,
+ 297,
+ 302,
+ 308,
+ 314,
+ 319,
+ 327,
+ 335,
+ 341,
+ 346,
+ 357,
+ 992,
+ 1007,
+ 1011,
+ 1016,
+ 1021,
+ 1026,
+ 1031,
+ 1036,
+ 1150,
+ 1155,
+ 1167,
+ 1172,
+ 1177,
+ 1182,
+ 1186,
+ 1191,
+ 1196,
+ 1201,
+ 1206,
+ 1216,
+ 1221,
+ 1226,
+ 1238,
+ 1253,
+ 1258,
+ 1272,
+ 1294,
+ 1305,
+ 1408,
+ 1455,
+ 1488,
+ 1579,
+ 1585,
+ 1648,
+ 1655,
+ 1683,
+ 1711,
+ 1816,
+ 1858,
+ 1871,
+ 1883,
+ 1897,
+ 1912,
+ 2132,
+ 2146,
+ 2163,
+ 2172,
+ 2239,
+ 2295,
+ 2299,
+ 2303,
+ 2308,
+ 2356,
+ 2382,
+ 2458,
+ 2502,
+ 2513,
+ 2598,
+ 2636,
+ 2674,
+ 2684,
+ 2694,
+ 2703,
+ 2716,
+ 2720,
+ 2724,
+ 2728,
+ 2732,
+ 2736,
+ 2740,
+ 2744,
+ 2756,
+ 2764,
+ 2769,
+ 2774,
+ 2779,
+ 2784,
+ 2792
+};
+
+#define T0_INTERPRETED 61
+
+#define T0_ENTER(ip, rp, slot) do { \
+ const unsigned char *t0_newip; \
+ uint32_t t0_lnum; \
+ t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
+ t0_lnum = t0_parse7E_unsigned(&t0_newip); \
+ (rp) += t0_lnum; \
+ *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
+ (ip) = t0_newip; \
+ } while (0)
+
+#define T0_DEFENTRY(name, slot) \
+void \
+name(void *ctx) \
+{ \
+ t0_context *t0ctx = ctx; \
+ t0ctx->ip = &t0_codeblock[0]; \
+ T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
+}
+
+T0_DEFENTRY(br_x509_minimal_init_main, 147)
+
+#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
+
+void
+br_x509_minimal_run(void *t0ctx)
+{
+ uint32_t *dp, *rp;
+ const unsigned char *ip;
+
+#define T0_LOCAL(x) (*(rp - 2 - (x)))
+#define T0_POP() (*-- dp)
+#define T0_POPi() (*(int32_t *)(-- dp))
+#define T0_PEEK(x) (*(dp - 1 - (x)))
+#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
+#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
+#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
+#define T0_RPOP() (*-- rp)
+#define T0_RPOPi() (*(int32_t *)(-- rp))
+#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
+#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
+#define T0_ROLL(x) do { \
+ size_t t0len = (size_t)(x); \
+ uint32_t t0tmp = *(dp - 1 - t0len); \
+ memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_SWAP() do { \
+ uint32_t t0tmp = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_ROT() do { \
+ uint32_t t0tmp = *(dp - 3); \
+ *(dp - 3) = *(dp - 2); \
+ *(dp - 2) = *(dp - 1); \
+ *(dp - 1) = t0tmp; \
+} while (0)
+#define T0_NROT() do { \
+ uint32_t t0tmp = *(dp - 1); \
+ *(dp - 1) = *(dp - 2); \
+ *(dp - 2) = *(dp - 3); \
+ *(dp - 3) = t0tmp; \
+} while (0)
+#define T0_PICK(x) do { \
+ uint32_t t0depth = (x); \
+ T0_PUSH(T0_PEEK(t0depth)); \
+} while (0)
+#define T0_CO() do { \
+ goto t0_exit; \
+} while (0)
+#define T0_RET() goto t0_next
+
+ dp = ((t0_context *)t0ctx)->dp;
+ rp = ((t0_context *)t0ctx)->rp;
+ ip = ((t0_context *)t0ctx)->ip;
+ goto t0_next;
+ for (;;) {
+ uint32_t t0x;
+
+ t0_next:
+ t0x = T0_NEXT(&ip);
+ if (t0x < T0_INTERPRETED) {
+ switch (t0x) {
+ int32_t t0off;
+
+ case 0: /* ret */
+ t0x = T0_RPOP();
+ rp -= (t0x >> 16);
+ t0x &= 0xFFFF;
+ if (t0x == 0) {
+ ip = NULL;
+ goto t0_exit;
+ }
+ ip = &t0_codeblock[t0x];
+ break;
+ case 1: /* literal constant */
+ T0_PUSHi(t0_parse7E_signed(&ip));
+ break;
+ case 2: /* read local */
+ T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
+ break;
+ case 3: /* write local */
+ T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
+ break;
+ case 4: /* jump */
+ t0off = t0_parse7E_signed(&ip);
+ ip += t0off;
+ break;
+ case 5: /* jump if */
+ t0off = t0_parse7E_signed(&ip);
+ if (T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 6: /* jump if not */
+ t0off = t0_parse7E_signed(&ip);
+ if (!T0_POP()) {
+ ip += t0off;
+ }
+ break;
+ case 7: {
+ /* %25 */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSHi(a % b);
+
+ }
+ break;
+ case 8: {
+ /* * */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a * b);
+
+ }
+ break;
+ case 9: {
+ /* + */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a + b);
+
+ }
+ break;
+ case 10: {
+ /* - */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a - b);
+
+ }
+ break;
+ case 11: {
+ /* -rot */
+ T0_NROT();
+ }
+ break;
+ case 12: {
+ /* / */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSHi(a / b);
+
+ }
+ break;
+ case 13: {
+ /* < */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a < b));
+
+ }
+ break;
+ case 14: {
+ /* << */
+
+ int c = (int)T0_POPi();
+ uint32_t x = T0_POP();
+ T0_PUSH(x << c);
+
+ }
+ break;
+ case 15: {
+ /* <= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a <= b));
+
+ }
+ break;
+ case 16: {
+ /* <> */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a != b));
+
+ }
+ break;
+ case 17: {
+ /* = */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(-(uint32_t)(a == b));
+
+ }
+ break;
+ case 18: {
+ /* > */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a > b));
+
+ }
+ break;
+ case 19: {
+ /* >= */
+
+ int32_t b = T0_POPi();
+ int32_t a = T0_POPi();
+ T0_PUSH(-(uint32_t)(a >= b));
+
+ }
+ break;
+ case 20: {
+ /* >> */
+
+ int c = (int)T0_POPi();
+ int32_t x = T0_POPi();
+ T0_PUSHi(x >> c);
+
+ }
+ break;
+ case 21: {
+ /* and */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a & b);
+
+ }
+ break;
+ case 22: {
+ /* blobcopy */
+
+ size_t len = T0_POP();
+ unsigned char *src = (unsigned char *)CTX + T0_POP();
+ unsigned char *dst = (unsigned char *)CTX + T0_POP();
+ memcpy(dst, src, len);
+
+ }
+ break;
+ case 23: {
+ /* check-direct-trust */
+
+ size_t u;
+
+ for (u = 0; u < CTX->trust_anchors_num; u ++) {
+ const br_x509_trust_anchor *ta;
+ unsigned char hashed_DN[64];
+ int kt;
+
+ ta = &CTX->trust_anchors[u];
+ if (ta->flags & BR_X509_TA_CA) {
+ continue;
+ }
+ hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
+ if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) {
+ continue;
+ }
+ kt = CTX->pkey.key_type;
+ if ((ta->pkey.key_type & 0x0F) != kt) {
+ continue;
+ }
+ switch (kt) {
+
+ case BR_KEYTYPE_RSA:
+ if (!eqbigint(CTX->pkey.key.rsa.n,
+ CTX->pkey.key.rsa.nlen,
+ ta->pkey.key.rsa.n,
+ ta->pkey.key.rsa.nlen)
+ || !eqbigint(CTX->pkey.key.rsa.e,
+ CTX->pkey.key.rsa.elen,
+ ta->pkey.key.rsa.e,
+ ta->pkey.key.rsa.elen))
+ {
+ continue;
+ }
+ break;
+
+ case BR_KEYTYPE_EC:
+ if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve
+ || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen
+ || memcmp(CTX->pkey.key.ec.q,
+ ta->pkey.key.ec.q,
+ ta->pkey.key.ec.qlen) != 0)
+ {
+ continue;
+ }
+ break;
+
+ default:
+ continue;
+ }
+
+ /*
+ * Direct trust match!
+ */
+ CTX->err = BR_ERR_X509_OK;
+ T0_CO();
+ }
+
+ }
+ break;
+ case 24: {
+ /* check-trust-anchor-CA */
+
+ size_t u;
+
+ for (u = 0; u < CTX->trust_anchors_num; u ++) {
+ const br_x509_trust_anchor *ta;
+ unsigned char hashed_DN[64];
+
+ ta = &CTX->trust_anchors[u];
+ if (!(ta->flags & BR_X509_TA_CA)) {
+ continue;
+ }
+ hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
+ if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) {
+ continue;
+ }
+ if (verify_signature(CTX, &ta->pkey) == 0) {
+ CTX->err = BR_ERR_X509_OK;
+ T0_CO();
+ }
+ }
+
+ }
+ break;
+ case 25: {
+ /* co */
+ T0_CO();
+ }
+ break;
+ case 26: {
+ /* compute-dn-hash */
+
+ CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash);
+ CTX->do_dn_hash = 0;
+
+ }
+ break;
+ case 27: {
+ /* compute-tbs-hash */
+
+ int id = T0_POPi();
+ size_t len;
+ len = br_multihash_out(&CTX->mhash, id, CTX->tbs_hash);
+ T0_PUSH(len);
+
+ }
+ break;
+ case 28: {
+ /* copy-ee-ec-pkey */
+
+ size_t qlen = T0_POP();
+ uint32_t curve = T0_POP();
+ memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen);
+ CTX->pkey.key_type = BR_KEYTYPE_EC;
+ CTX->pkey.key.ec.curve = curve;
+ CTX->pkey.key.ec.q = CTX->ee_pkey_data;
+ CTX->pkey.key.ec.qlen = qlen;
+
+ }
+ break;
+ case 29: {
+ /* copy-ee-rsa-pkey */
+
+ size_t elen = T0_POP();
+ size_t nlen = T0_POP();
+ memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen);
+ CTX->pkey.key_type = BR_KEYTYPE_RSA;
+ CTX->pkey.key.rsa.n = CTX->ee_pkey_data;
+ CTX->pkey.key.rsa.nlen = nlen;
+ CTX->pkey.key.rsa.e = CTX->ee_pkey_data + nlen;
+ CTX->pkey.key.rsa.elen = elen;
+
+ }
+ break;
+ case 30: {
+ /* copy-name-SAN */
+
+ unsigned tag = T0_POP();
+ unsigned ok = T0_POP();
+ size_t u, len;
+
+ len = CTX->pad[0];
+ for (u = 0; u < CTX->num_name_elts; u ++) {
+ br_name_element *ne;
+
+ ne = &CTX->name_elts[u];
+ if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) {
+ if (ok && ne->len > len) {
+ memcpy(ne->buf, CTX->pad + 1, len);
+ ne->buf[len] = 0;
+ ne->status = 1;
+ } else {
+ ne->status = -1;
+ }
+ break;
+ }
+ }
+
+ }
+ break;
+ case 31: {
+ /* copy-name-element */
+
+ size_t len;
+ int32_t off = T0_POPi();
+ int ok = T0_POPi();
+
+ if (off >= 0) {
+ br_name_element *ne = &CTX->name_elts[off];
+
+ if (ok) {
+ len = CTX->pad[0];
+ if (len < ne->len) {
+ memcpy(ne->buf, CTX->pad + 1, len);
+ ne->buf[len] = 0;
+ ne->status = 1;
+ } else {
+ ne->status = -1;
+ }
+ } else {
+ ne->status = -1;
+ }
+ }
+
+ }
+ break;
+ case 32: {
+ /* data-get8 */
+
+ size_t addr = T0_POP();
+ T0_PUSH(t0_datablock[addr]);
+
+ }
+ break;
+ case 33: {
+ /* dn-hash-length */
+
+ T0_PUSH(DNHASH_LEN);
+
+ }
+ break;
+ case 34: {
+ /* do-ecdsa-vrfy */
+
+ size_t qlen = T0_POP();
+ int curve = T0_POP();
+ br_x509_pkey pk;
+
+ pk.key_type = BR_KEYTYPE_EC;
+ pk.key.ec.curve = curve;
+ pk.key.ec.q = CTX->pkey_data;
+ pk.key.ec.qlen = qlen;
+ T0_PUSH(verify_signature(CTX, &pk));
+
+ }
+ break;
+ case 35: {
+ /* do-rsa-vrfy */
+
+ size_t elen = T0_POP();
+ size_t nlen = T0_POP();
+ br_x509_pkey pk;
+
+ pk.key_type = BR_KEYTYPE_RSA;
+ pk.key.rsa.n = CTX->pkey_data;
+ pk.key.rsa.nlen = nlen;
+ pk.key.rsa.e = CTX->pkey_data + nlen;
+ pk.key.rsa.elen = elen;
+ T0_PUSH(verify_signature(CTX, &pk));
+
+ }
+ break;
+ case 36: {
+ /* drop */
+ (void)T0_POP();
+ }
+ break;
+ case 37: {
+ /* dup */
+ T0_PUSH(T0_PEEK(0));
+ }
+ break;
+ case 38: {
+ /* eqOID */
+
+ const unsigned char *a2 = &t0_datablock[T0_POP()];
+ const unsigned char *a1 = &CTX->pad[0];
+ size_t len = a1[0];
+ int x;
+ if (len == a2[0]) {
+ x = -(memcmp(a1 + 1, a2 + 1, len) == 0);
+ } else {
+ x = 0;
+ }
+ T0_PUSH((uint32_t)x);
+
+ }
+ break;
+ case 39: {
+ /* eqblob */
+
+ size_t len = T0_POP();
+ const unsigned char *a2 = (const unsigned char *)CTX + T0_POP();
+ const unsigned char *a1 = (const unsigned char *)CTX + T0_POP();
+ T0_PUSHi(-(memcmp(a1, a2, len) == 0));
+
+ }
+ break;
+ case 40: {
+ /* fail */
+
+ CTX->err = T0_POPi();
+ T0_CO();
+
+ }
+ break;
+ case 41: {
+ /* get-system-date */
+
+ if (CTX->days == 0 && CTX->seconds == 0) {
+#if BR_USE_UNIX_TIME
+ time_t x = time(NULL);
+
+ T0_PUSH((uint32_t)(x / 86400) + 719528);
+ T0_PUSH((uint32_t)(x % 86400));
+#elif BR_USE_WIN32_TIME
+ FILETIME ft;
+ uint64_t x;
+
+ GetSystemTimeAsFileTime(&ft);
+ x = ((uint64_t)ft.dwHighDateTime << 32)
+ + (uint64_t)ft.dwLowDateTime;
+ x = (x / 10000000);
+ T0_PUSH((uint32_t)(x / 86400) + 584754);
+ T0_PUSH((uint32_t)(x % 86400));
+#else
+ CTX->err = BR_ERR_X509_TIME_UNKNOWN;
+ T0_CO();
+#endif
+ } else {
+ T0_PUSH(CTX->days);
+ T0_PUSH(CTX->seconds);
+ }
+
+ }
+ break;
+ case 42: {
+ /* get16 */
+
+ uint32_t addr = T0_POP();
+ T0_PUSH(*(uint16_t *)(void *)((unsigned char *)CTX + addr));
+
+ }
+ break;
+ case 43: {
+ /* get32 */
+
+ uint32_t addr = T0_POP();
+ T0_PUSH(*(uint32_t *)(void *)((unsigned char *)CTX + addr));
+
+ }
+ break;
+ case 44: {
+ /* match-server-name */
+
+ size_t n1, n2;
+
+ if (CTX->server_name == NULL) {
+ T0_PUSH(0);
+ T0_RET();
+ }
+ n1 = strlen(CTX->server_name);
+ n2 = CTX->pad[0];
+ if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) {
+ T0_PUSHi(-1);
+ T0_RET();
+ }
+ if (n2 >= 2 && CTX->pad[1] == '*' && CTX->pad[2] == '.') {
+ size_t u;
+
+ u = 0;
+ while (u < n1 && CTX->server_name[u] != '.') {
+ u ++;
+ }
+ u ++;
+ n1 -= u;
+ if ((n2 - 2) == n1
+ && eqnocase(&CTX->pad[3], CTX->server_name + u, n1))
+ {
+ T0_PUSHi(-1);
+ T0_RET();
+ }
+ }
+ T0_PUSH(0);
+
+ }
+ break;
+ case 45: {
+ /* neg */
+
+ uint32_t a = T0_POP();
+ T0_PUSH(-a);
+
+ }
+ break;
+ case 46: {
+ /* offset-name-element */
+
+ unsigned san = T0_POP();
+ size_t u;
+
+ for (u = 0; u < CTX->num_name_elts; u ++) {
+ if (CTX->name_elts[u].status == 0) {
+ const unsigned char *oid;
+ size_t len, off;
+
+ oid = CTX->name_elts[u].oid;
+ if (san) {
+ if (oid[0] != 0 || oid[1] != 0) {
+ continue;
+ }
+ off = 2;
+ } else {
+ off = 0;
+ }
+ len = oid[off];
+ if (len != 0 && len == CTX->pad[0]
+ && memcmp(oid + off + 1,
+ CTX->pad + 1, len) == 0)
+ {
+ T0_PUSH(u);
+ T0_RET();
+ }
+ }
+ }
+ T0_PUSHi(-1);
+
+ }
+ break;
+ case 47: {
+ /* or */
+
+ uint32_t b = T0_POP();
+ uint32_t a = T0_POP();
+ T0_PUSH(a | b);
+
+ }
+ break;
+ case 48: {
+ /* over */
+ T0_PUSH(T0_PEEK(1));
+ }
+ break;
+ case 49: {
+ /* read-blob-inner */
+
+ uint32_t len = T0_POP();
+ uint32_t addr = T0_POP();
+ size_t clen = CTX->hlen;
+ if (clen > len) {
+ clen = (size_t)len;
+ }
+ if (addr != 0) {
+ memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
+ }
+ if (CTX->do_mhash) {
+ br_multihash_update(&CTX->mhash, CTX->hbuf, clen);
+ }
+ if (CTX->do_dn_hash) {
+ CTX->dn_hash_impl->update(
+ &CTX->dn_hash.vtable, CTX->hbuf, clen);
+ }
+ CTX->hbuf += clen;
+ CTX->hlen -= clen;
+ T0_PUSH(addr + clen);
+ T0_PUSH(len - clen);
+
+ }
+ break;
+ case 50: {
+ /* read8-low */
+
+ if (CTX->hlen == 0) {
+ T0_PUSHi(-1);
+ } else {
+ unsigned char x = *CTX->hbuf ++;
+ if (CTX->do_mhash) {
+ br_multihash_update(&CTX->mhash, &x, 1);
+ }
+ if (CTX->do_dn_hash) {
+ CTX->dn_hash_impl->update(&CTX->dn_hash.vtable, &x, 1);
+ }
+ CTX->hlen --;
+ T0_PUSH(x);
+ }
+
+ }
+ break;
+ case 51: {
+ /* roll */
+ T0_ROLL(T0_POP());
+ }
+ break;
+ case 52: {
+ /* rot */
+ T0_ROT();
+ }
+ break;
+ case 53: {
+ /* set16 */
+
+ uint32_t addr = T0_POP();
+ *(uint16_t *)(void *)((unsigned char *)CTX + addr) = T0_POP();
+
+ }
+ break;
+ case 54: {
+ /* set32 */
+
+ uint32_t addr = T0_POP();
+ *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP();
+
+ }
+ break;
+ case 55: {
+ /* set8 */
+
+ uint32_t addr = T0_POP();
+ *((unsigned char *)CTX + addr) = (unsigned char)T0_POP();
+
+ }
+ break;
+ case 56: {
+ /* start-dn-hash */
+
+ CTX->dn_hash_impl->init(&CTX->dn_hash.vtable);
+ CTX->do_dn_hash = 1;
+
+ }
+ break;
+ case 57: {
+ /* start-tbs-hash */
+
+ br_multihash_init(&CTX->mhash);
+ CTX->do_mhash = 1;
+
+ }
+ break;
+ case 58: {
+ /* stop-tbs-hash */
+
+ CTX->do_mhash = 0;
+
+ }
+ break;
+ case 59: {
+ /* swap */
+ T0_SWAP();
+ }
+ break;
+ case 60: {
+ /* zero-server-name */
+
+ T0_PUSHi(-(CTX->server_name == NULL));
+
+ }
+ break;
+ }
+
+ } else {
+ T0_ENTER(ip, rp, t0x);
+ }
+ }
+t0_exit:
+ ((t0_context *)t0ctx)->dp = dp;
+ ((t0_context *)t0ctx)->rp = rp;
+ ((t0_context *)t0ctx)->ip = ip;
+}
+
+
+
+/*
+ * Verify the signature on the certificate with the provided public key.
+ * This function checks the public key type with regards to the expected
+ * type. Returned value is either 0 on success, or a non-zero error code.
+ */
+static int
+verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk)
+{
+ int kt;
+
+ kt = ctx->cert_signer_key_type;
+ if ((pk->key_type & 0x0F) != kt) {
+ return BR_ERR_X509_WRONG_KEY_TYPE;
+ }
+ switch (kt) {
+ unsigned char tmp[64];
+
+ case BR_KEYTYPE_RSA:
+ if (ctx->irsa == 0) {
+ return BR_ERR_X509_UNSUPPORTED;
+ }
+ if (!ctx->irsa(ctx->cert_sig, ctx->cert_sig_len,
+ &t0_datablock[ctx->cert_sig_hash_oid],
+ ctx->cert_sig_hash_len, &pk->key.rsa, tmp))
+ {
+ return BR_ERR_X509_BAD_SIGNATURE;
+ }
+ if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) {
+ return BR_ERR_X509_BAD_SIGNATURE;
+ }
+ return 0;
+
+ case BR_KEYTYPE_EC:
+ if (ctx->iecdsa == 0) {
+ return BR_ERR_X509_UNSUPPORTED;
+ }
+ if (!ctx->iecdsa(ctx->iec, ctx->tbs_hash,
+ ctx->cert_sig_hash_len, &pk->key.ec,
+ ctx->cert_sig, ctx->cert_sig_len))
+ {
+ return BR_ERR_X509_BAD_SIGNATURE;
+ }
+ return 0;
+
+ default:
+ return BR_ERR_X509_UNSUPPORTED;
+ }
+}
+
+
Property changes on: stable/12/contrib/bearssl/src/x509/x509_minimal.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/src/x509/x509_minimal.t0
===================================================================
--- stable/12/contrib/bearssl/src/x509/x509_minimal.t0 (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/x509_minimal.t0 (revision 346145)
@@ -0,0 +1,1508 @@
+\ 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.
+
+preamble {
+
+#include "inner.h"
+
+/*
+ * Implementation Notes
+ * --------------------
+ *
+ * The C code pushes the data by chunks; all decoding is done in the
+ * T0 code. The cert_length value is set to the certificate length when
+ * a new certificate is started; the T0 code picks it up as outer limit,
+ * and decoding functions use it to ensure that no attempt is made at
+ * reading past it. The T0 code also checks that once the certificate is
+ * decoded, there are no trailing bytes.
+ *
+ * The T0 code sets cert_length to 0 when the certificate is fully
+ * decoded.
+ *
+ * The C code must still perform two checks:
+ *
+ * -- If the certificate length is 0, then the T0 code will not be
+ * invoked at all. This invalid condition must thus be reported by the
+ * C code.
+ *
+ * -- When reaching the end of certificate, the C code must verify that
+ * the certificate length has been set to 0, thereby signaling that
+ * the T0 code properly decoded a certificate.
+ *
+ * Processing of a chain works in the following way:
+ *
+ * -- The error flag is set to a non-zero value when validation is
+ * finished. The value is either BR_ERR_X509_OK (validation is
+ * successful) or another non-zero error code. When a non-zero error
+ * code is obtained, the remaining bytes in the current certificate and
+ * the subsequent certificates (if any) are completely ignored.
+ *
+ * -- Each certificate is decoded in due course, with the following
+ * "interesting points":
+ *
+ * -- Start of the TBS: the multihash engine is reset and activated.
+ *
+ * -- Start of the issuer DN: the secondary hash engine is started,
+ * to process the encoded issuer DN.
+ *
+ * -- End of the issuer DN: the secondary hash engine is stopped. The
+ * resulting hash value is computed and then copied into the
+ * next_dn_hash[] buffer.
+ *
+ * -- Start of the subject DN: the secondary hash engine is started,
+ * to process the encoded subject DN.
+ *
+ * -- For the EE certificate only: the Common Name, if any, is matched
+ * against the expected server name.
+ *
+ * -- End of the subject DN: the secondary hash engine is stopped. The
+ * resulting hash value is computed into the pad. It is then processed:
+ *
+ * -- If this is the EE certificate, then the hash is ignored
+ * (except for direct trust processing, see later; the hash is
+ * simply left in current_dn_hash[]).
+ *
+ * -- Otherwise, the hashed subject DN is compared with the saved
+ * hash value (in saved_dn_hash[]). They must match.
+ *
+ * Either way, the next_dn_hash[] value is then copied into the
+ * saved_dn_hash[] value. Thus, at that point, saved_dn_hash[]
+ * contains the hash of the issuer DN for the current certificate,
+ * and current_dn_hash[] contains the hash of the subject DN for the
+ * current certificate.
+ *
+ * -- Public key: it is decoded into the cert_pkey[] buffer. Unknown
+ * key types are reported at that point.
+ *
+ * -- If this is the EE certificate, then the key type is compared
+ * with the expected key type (initialization parameter). The public
+ * key data is copied to ee_pkey_data[]. The key and hashed subject
+ * DN are also compared with the "direct trust" keys; if the key
+ * and DN are matched, then validation ends with a success.
+ *
+ * -- Otherwise, the saved signature (cert_sig[]) is verified
+ * against the saved TBS hash (tbs_hash[]) and that freshly
+ * decoded public key. Failure here ends validation with an error.
+ *
+ * -- Extensions: extension values are processed in due order.
+ *
+ * -- Basic Constraints: for all certificates except EE, must be
+ * present, indicate a CA, and have a path legnth compatible with
+ * the chain length so far.
+ *
+ * -- Key Usage: for the EE, if present, must allow signatures
+ * or encryption/key exchange, as required for the cipher suite.
+ * For non-EE, if present, must have the "certificate sign" bit.
+ *
+ * -- Subject Alt Name: for the EE, dNSName names are matched
+ * against the server name. Ignored for non-EE.
+ *
+ * -- Authority Key Identifier, Subject Key Identifier, Issuer
+ * Alt Name, Subject Directory Attributes, CRL Distribution Points
+ * Freshest CRL, Authority Info Access and Subject Info Access
+ * extensions are always ignored: they either contain only
+ * informative data, or they relate to revocation processing, which
+ * we explicitly do not support.
+ *
+ * -- All other extensions are ignored if non-critical. If a
+ * critical extension other than the ones above is encountered,
+ * then a failure is reported.
+ *
+ * -- End of the TBS: the multihash engine is stopped.
+ *
+ * -- Signature algorithm: the signature algorithm on the
+ * certificate is decoded. A failure is reported if that algorithm
+ * is unknown. The hashed TBS corresponding to the signature hash
+ * function is computed and stored in tbs_hash[] (if not supported,
+ * then a failure is reported). The hash OID and length are stored
+ * in cert_sig_hash_oid and cert_sig_hash_len.
+ *
+ * -- Signature value: the signature value is copied into the
+ * cert_sig[] array.
+ *
+ * -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is
+ * looked up in the trust store (CA trust anchors only); for all
+ * that match, the signature (cert_sig[]) is verified against the
+ * anchor public key (hashed TBS is in tbs_hash[]). If one of these
+ * signatures is valid, then validation ends with a success.
+ *
+ * -- If the chain end is reached without obtaining a validation success,
+ * then validation is reported as failed.
+ */
+
+#if BR_USE_UNIX_TIME
+#include <time.h>
+#endif
+
+#if BR_USE_WIN32_TIME
+#include <windows.h>
+#endif
+
+/*
+ * The T0 compiler will produce these prototypes declarations in the
+ * header.
+ *
+void br_x509_minimal_init_main(void *ctx);
+void br_x509_minimal_run(void *ctx);
+ */
+
+/* see bearssl_x509.h */
+void
+br_x509_minimal_init(br_x509_minimal_context *ctx,
+ const br_hash_class *dn_hash_impl,
+ const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->vtable = &br_x509_minimal_vtable;
+ ctx->dn_hash_impl = dn_hash_impl;
+ ctx->trust_anchors = trust_anchors;
+ ctx->trust_anchors_num = trust_anchors_num;
+}
+
+static void
+xm_start_chain(const br_x509_class **ctx, const char *server_name)
+{
+ br_x509_minimal_context *cc;
+ size_t u;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ for (u = 0; u < cc->num_name_elts; u ++) {
+ cc->name_elts[u].status = 0;
+ cc->name_elts[u].buf[0] = 0;
+ }
+ memset(&cc->pkey, 0, sizeof cc->pkey);
+ cc->num_certs = 0;
+ cc->err = 0;
+ cc->cpu.dp = cc->dp_stack;
+ cc->cpu.rp = cc->rp_stack;
+ br_x509_minimal_init_main(&cc->cpu);
+ if (server_name == NULL || *server_name == 0) {
+ cc->server_name = NULL;
+ } else {
+ cc->server_name = server_name;
+ }
+}
+
+static void
+xm_start_cert(const br_x509_class **ctx, uint32_t length)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err != 0) {
+ return;
+ }
+ if (length == 0) {
+ cc->err = BR_ERR_X509_TRUNCATED;
+ return;
+ }
+ cc->cert_length = length;
+}
+
+static void
+xm_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err != 0) {
+ return;
+ }
+ cc->hbuf = buf;
+ cc->hlen = len;
+ br_x509_minimal_run(&cc->cpu);
+}
+
+static void
+xm_end_cert(const br_x509_class **ctx)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err == 0 && cc->cert_length != 0) {
+ cc->err = BR_ERR_X509_TRUNCATED;
+ }
+ cc->num_certs ++;
+}
+
+static unsigned
+xm_end_chain(const br_x509_class **ctx)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err == 0) {
+ if (cc->num_certs == 0) {
+ cc->err = BR_ERR_X509_EMPTY_CHAIN;
+ } else {
+ cc->err = BR_ERR_X509_NOT_TRUSTED;
+ }
+ } else if (cc->err == BR_ERR_X509_OK) {
+ return 0;
+ }
+ return (unsigned)cc->err;
+}
+
+static const br_x509_pkey *
+xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
+{
+ br_x509_minimal_context *cc;
+
+ cc = (br_x509_minimal_context *)(void *)ctx;
+ if (cc->err == BR_ERR_X509_OK
+ || cc->err == BR_ERR_X509_NOT_TRUSTED)
+ {
+ if (usages != NULL) {
+ *usages = cc->key_usages;
+ }
+ return &((br_x509_minimal_context *)(void *)ctx)->pkey;
+ } else {
+ return NULL;
+ }
+}
+
+/* see bearssl_x509.h */
+const br_x509_class br_x509_minimal_vtable = {
+ sizeof(br_x509_minimal_context),
+ xm_start_chain,
+ xm_start_cert,
+ xm_append,
+ xm_end_cert,
+ xm_end_chain,
+ xm_get_pkey
+};
+
+#define CTX ((br_x509_minimal_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_minimal_context, cpu)))
+#define CONTEXT_NAME br_x509_minimal_context
+
+#define DNHASH_LEN ((CTX->dn_hash_impl->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK)
+
+/*
+ * Hash a DN (from a trust anchor) into the provided buffer. This uses the
+ * DN hash implementation and context structure from the X.509 engine
+ * context.
+ */
+static void
+hash_dn(br_x509_minimal_context *ctx, const void *dn, size_t len,
+ unsigned char *out)
+{
+ ctx->dn_hash_impl->init(&ctx->dn_hash.vtable);
+ ctx->dn_hash_impl->update(&ctx->dn_hash.vtable, dn, len);
+ ctx->dn_hash_impl->out(&ctx->dn_hash.vtable, out);
+}
+
+/*
+ * Compare two big integers for equality. The integers use unsigned big-endian
+ * encoding; extra leading bytes (of value 0) are allowed.
+ */
+static int
+eqbigint(const unsigned char *b1, size_t len1,
+ const unsigned char *b2, size_t len2)
+{
+ while (len1 > 0 && *b1 == 0) {
+ b1 ++;
+ len1 --;
+ }
+ while (len2 > 0 && *b2 == 0) {
+ b2 ++;
+ len2 --;
+ }
+ if (len1 != len2) {
+ return 0;
+ }
+ return memcmp(b1, b2, len1) == 0;
+}
+
+/*
+ * Compare two strings for equality, in a case-insensitive way. This
+ * function handles casing only for ASCII letters.
+ */
+static int
+eqnocase(const void *s1, const void *s2, size_t len)
+{
+ const unsigned char *buf1, *buf2;
+
+ buf1 = s1;
+ buf2 = s2;
+ while (len -- > 0) {
+ int x1, x2;
+
+ x1 = *buf1 ++;
+ x2 = *buf2 ++;
+ if (x1 >= 'A' && x1 <= 'Z') {
+ x1 += 'a' - 'A';
+ }
+ if (x2 >= 'A' && x2 <= 'Z') {
+ x2 += 'a' - 'A';
+ }
+ if (x1 != x2) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int verify_signature(br_x509_minimal_context *ctx,
+ const br_x509_pkey *pk);
+
+}
+
+postamble {
+
+/*
+ * Verify the signature on the certificate with the provided public key.
+ * This function checks the public key type with regards to the expected
+ * type. Returned value is either 0 on success, or a non-zero error code.
+ */
+static int
+verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk)
+{
+ int kt;
+
+ kt = ctx->cert_signer_key_type;
+ if ((pk->key_type & 0x0F) != kt) {
+ return BR_ERR_X509_WRONG_KEY_TYPE;
+ }
+ switch (kt) {
+ unsigned char tmp[64];
+
+ case BR_KEYTYPE_RSA:
+ if (ctx->irsa == 0) {
+ return BR_ERR_X509_UNSUPPORTED;
+ }
+ if (!ctx->irsa(ctx->cert_sig, ctx->cert_sig_len,
+ &t0_datablock[ctx->cert_sig_hash_oid],
+ ctx->cert_sig_hash_len, &pk->key.rsa, tmp))
+ {
+ return BR_ERR_X509_BAD_SIGNATURE;
+ }
+ if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) {
+ return BR_ERR_X509_BAD_SIGNATURE;
+ }
+ return 0;
+
+ case BR_KEYTYPE_EC:
+ if (ctx->iecdsa == 0) {
+ return BR_ERR_X509_UNSUPPORTED;
+ }
+ if (!ctx->iecdsa(ctx->iec, ctx->tbs_hash,
+ ctx->cert_sig_hash_len, &pk->key.ec,
+ ctx->cert_sig, ctx->cert_sig_len))
+ {
+ return BR_ERR_X509_BAD_SIGNATURE;
+ }
+ return 0;
+
+ default:
+ return BR_ERR_X509_UNSUPPORTED;
+ }
+}
+
+}
+
+cc: read8-low ( -- x ) {
+ if (CTX->hlen == 0) {
+ T0_PUSHi(-1);
+ } else {
+ unsigned char x = *CTX->hbuf ++;
+ if (CTX->do_mhash) {
+ br_multihash_update(&CTX->mhash, &x, 1);
+ }
+ if (CTX->do_dn_hash) {
+ CTX->dn_hash_impl->update(&CTX->dn_hash.vtable, &x, 1);
+ }
+ CTX->hlen --;
+ T0_PUSH(x);
+ }
+}
+
+addr: cert_length
+addr: num_certs
+
+cc: read-blob-inner ( addr len -- addr len ) {
+ uint32_t len = T0_POP();
+ uint32_t addr = T0_POP();
+ size_t clen = CTX->hlen;
+ if (clen > len) {
+ clen = (size_t)len;
+ }
+ if (addr != 0) {
+ memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen);
+ }
+ if (CTX->do_mhash) {
+ br_multihash_update(&CTX->mhash, CTX->hbuf, clen);
+ }
+ if (CTX->do_dn_hash) {
+ CTX->dn_hash_impl->update(
+ &CTX->dn_hash.vtable, CTX->hbuf, clen);
+ }
+ CTX->hbuf += clen;
+ CTX->hlen -= clen;
+ T0_PUSH(addr + clen);
+ T0_PUSH(len - clen);
+}
+
+\ Compute the TBS hash, using the provided hash ID. The hash value is
+\ written in the tbs_hash[] array, and the hash length is returned. If
+\ the requested hash function is not supported, then 0 is returned.
+cc: compute-tbs-hash ( id -- hashlen ) {
+ int id = T0_POPi();
+ size_t len;
+ len = br_multihash_out(&CTX->mhash, id, CTX->tbs_hash);
+ T0_PUSH(len);
+}
+
+\ Push true (-1) if no server name is expected in the EE certificate.
+cc: zero-server-name ( -- bool ) {
+ T0_PUSHi(-(CTX->server_name == NULL));
+}
+
+addr: key_usages
+addr: cert_sig
+addr: cert_sig_len
+addr: cert_signer_key_type
+addr: cert_sig_hash_oid
+addr: cert_sig_hash_len
+addr: tbs_hash
+addr: min_rsa_size
+
+\ Start TBS hash computation. The hash functions are reinitialised.
+cc: start-tbs-hash ( -- ) {
+ br_multihash_init(&CTX->mhash);
+ CTX->do_mhash = 1;
+}
+
+\ Stop TBS hash computation.
+cc: stop-tbs-hash ( -- ) {
+ CTX->do_mhash = 0;
+}
+
+\ Start DN hash computation.
+cc: start-dn-hash ( -- ) {
+ CTX->dn_hash_impl->init(&CTX->dn_hash.vtable);
+ CTX->do_dn_hash = 1;
+}
+
+\ Terminate DN hash computation and write the DN hash into the
+\ current_dn_hash buffer.
+cc: compute-dn-hash ( -- ) {
+ CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash);
+ CTX->do_dn_hash = 0;
+}
+
+\ Get the length of hash values obtained with the DN hasher.
+cc: dn-hash-length ( -- len ) {
+ T0_PUSH(DNHASH_LEN);
+}
+
+\ Copy data between two areas in the context.
+cc: blobcopy ( addr-dst addr-src len -- ) {
+ size_t len = T0_POP();
+ unsigned char *src = (unsigned char *)CTX + T0_POP();
+ unsigned char *dst = (unsigned char *)CTX + T0_POP();
+ memcpy(dst, src, len);
+}
+
+addr: current_dn_hash
+addr: next_dn_hash
+addr: saved_dn_hash
+
+\ Read a DN, hashing it into current_dn_hash. The DN contents are not
+\ inspected (only the outer tag, for SEQUENCE, is checked).
+: read-DN ( lim -- lim )
+ start-dn-hash
+ read-sequence-open skip-close-elt
+ compute-dn-hash ;
+
+cc: offset-name-element ( san -- n ) {
+ unsigned san = T0_POP();
+ size_t u;
+
+ for (u = 0; u < CTX->num_name_elts; u ++) {
+ if (CTX->name_elts[u].status == 0) {
+ const unsigned char *oid;
+ size_t len, off;
+
+ oid = CTX->name_elts[u].oid;
+ if (san) {
+ if (oid[0] != 0 || oid[1] != 0) {
+ continue;
+ }
+ off = 2;
+ } else {
+ off = 0;
+ }
+ len = oid[off];
+ if (len != 0 && len == CTX->pad[0]
+ && memcmp(oid + off + 1,
+ CTX->pad + 1, len) == 0)
+ {
+ T0_PUSH(u);
+ T0_RET();
+ }
+ }
+ }
+ T0_PUSHi(-1);
+}
+
+cc: copy-name-element ( bool offbuf -- ) {
+ size_t len;
+ int32_t off = T0_POPi();
+ int ok = T0_POPi();
+
+ if (off >= 0) {
+ br_name_element *ne = &CTX->name_elts[off];
+
+ if (ok) {
+ len = CTX->pad[0];
+ if (len < ne->len) {
+ memcpy(ne->buf, CTX->pad + 1, len);
+ ne->buf[len] = 0;
+ ne->status = 1;
+ } else {
+ ne->status = -1;
+ }
+ } else {
+ ne->status = -1;
+ }
+ }
+}
+
+cc: copy-name-SAN ( bool tag -- ) {
+ unsigned tag = T0_POP();
+ unsigned ok = T0_POP();
+ size_t u, len;
+
+ len = CTX->pad[0];
+ for (u = 0; u < CTX->num_name_elts; u ++) {
+ br_name_element *ne;
+
+ ne = &CTX->name_elts[u];
+ if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) {
+ if (ok && ne->len > len) {
+ memcpy(ne->buf, CTX->pad + 1, len);
+ ne->buf[len] = 0;
+ ne->status = 1;
+ } else {
+ ne->status = -1;
+ }
+ break;
+ }
+ }
+}
+
+\ Read a value, decoding string types. If the string type is recognised
+\ and the value could be converted to UTF-8 into the pad, then true (-1)
+\ is returned; in all other cases, false (0) is returned. Either way, the
+\ object is consumed.
+: read-string ( lim -- lim bool )
+ read-tag case
+ \ UTF8String
+ 12 of check-primitive read-value-UTF8 endof
+ \ NumericString
+ 18 of check-primitive read-value-latin1 endof
+ \ PrintableString
+ 19 of check-primitive read-value-latin1 endof
+ \ TeletexString
+ 20 of check-primitive read-value-latin1 endof
+ \ IA5String
+ 22 of check-primitive read-value-latin1 endof
+ \ BMPString
+ 30 of check-primitive read-value-UTF16 endof
+ 2drop read-length-skip 0 0
+ endcase ;
+
+\ Read a DN for the EE. The normalized DN hash is computed and stored in the
+\ current_dn_hash.
+\ Name elements are gathered. Also, the Common Name is matched against the
+\ intended server name.
+\ Returned value is true (-1) if the CN matches the intended server name,
+\ false (0) otherwise.
+: read-DN-EE ( lim -- lim bool )
+ \ Flag will be set to true if there is a CN and it matches the
+ \ intended server name.
+ 0 { eename-matches }
+
+ \ Activate DN hashing.
+ start-dn-hash
+
+ \ Parse the DN structure: it is a SEQUENCE of SET of
+ \ AttributeTypeAndValue. Each AttributeTypeAndValue is a
+ \ SEQUENCE { OBJECT IDENTIFIER, ANY }.
+ read-sequence-open
+ begin
+ dup while
+
+ read-tag 0x11 check-tag-constructed read-length-open-elt
+ dup ifnot ERR_X509_BAD_DN fail then
+ begin
+ dup while
+
+ read-sequence-open
+
+ \ Read the OID. If the OID could not be read (too
+ \ long) then the first pad byte will be 0.
+ read-OID drop
+
+ \ If it is the Common Name then we'll need to
+ \ match it against the intended server name (if
+ \ applicable).
+ id-at-commonName eqOID { isCN }
+
+ \ Get offset for reception buffer for that element
+ \ (or -1).
+ 0 offset-name-element { offbuf }
+
+ \ Try to read the value as a string.
+ read-string
+
+ \ If the value could be decoded as a string,
+ \ copy it and/or match it, as appropriate.
+ dup isCN and if
+ match-server-name if
+ -1 >eename-matches
+ then
+ then
+ offbuf copy-name-element
+
+ \ Close the SEQUENCE
+ close-elt
+
+ repeat
+ close-elt
+ repeat
+ close-elt
+
+ \ Compute DN hash and deactivate DN hashing.
+ compute-dn-hash
+
+ \ Return the CN match flag.
+ eename-matches ;
+
+\ Get the validation date and time from the context or system.
+cc: get-system-date ( -- days seconds ) {
+ if (CTX->days == 0 && CTX->seconds == 0) {
+#if BR_USE_UNIX_TIME
+ time_t x = time(NULL);
+
+ T0_PUSH((uint32_t)(x / 86400) + 719528);
+ T0_PUSH((uint32_t)(x % 86400));
+#elif BR_USE_WIN32_TIME
+ FILETIME ft;
+ uint64_t x;
+
+ GetSystemTimeAsFileTime(&ft);
+ x = ((uint64_t)ft.dwHighDateTime << 32)
+ + (uint64_t)ft.dwLowDateTime;
+ x = (x / 10000000);
+ T0_PUSH((uint32_t)(x / 86400) + 584754);
+ T0_PUSH((uint32_t)(x % 86400));
+#else
+ CTX->err = BR_ERR_X509_TIME_UNKNOWN;
+ T0_CO();
+#endif
+ } else {
+ T0_PUSH(CTX->days);
+ T0_PUSH(CTX->seconds);
+ }
+}
+
+\ Compare two dates (days+seconds) together.
+: before ( days1 seconds1 days2 seconds2 -- bool )
+ { d1 s1 d2 s2 }
+ d1 d2 = if s1 s2 < else d1 d2 < then ;
+
+: after ( days1 seconds1 days2 seconds2 -- bool )
+ swap2 before ;
+
+\ Swap the top two elements with the two elements immediately below.
+: swap2 ( a b c d -- c d a b )
+ 3 roll 3 roll ;
+
+\ Match the name in the pad with the expected server name. Returned value
+\ is true (-1) on match, false (0) otherwise. If there is no expected
+\ server name, then 0 is returned.
+\ Match conditions: either an exact match (case insensitive), or a
+\ wildcard match, if the found name starts with "*.". We only match a
+\ starting wildcard, and only against a complete DN name component.
+cc: match-server-name ( -- bool ) {
+ size_t n1, n2;
+
+ if (CTX->server_name == NULL) {
+ T0_PUSH(0);
+ T0_RET();
+ }
+ n1 = strlen(CTX->server_name);
+ n2 = CTX->pad[0];
+ if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) {
+ T0_PUSHi(-1);
+ T0_RET();
+ }
+ if (n2 >= 2 && CTX->pad[1] == '*' && CTX->pad[2] == '.') {
+ size_t u;
+
+ u = 0;
+ while (u < n1 && CTX->server_name[u] != '.') {
+ u ++;
+ }
+ u ++;
+ n1 -= u;
+ if ((n2 - 2) == n1
+ && eqnocase(&CTX->pad[3], CTX->server_name + u, n1))
+ {
+ T0_PUSHi(-1);
+ T0_RET();
+ }
+ }
+ T0_PUSH(0);
+}
+
+\ Get the address and length for the pkey_data buffer.
+: addr-len-pkey_data ( -- addr len )
+ CX 0 8191 { offsetof(br_x509_minimal_context, pkey_data) }
+ CX 0 8191 { BR_X509_BUFSIZE_KEY } ;
+
+\ Copy the EE public key to the permanent buffer (RSA).
+cc: copy-ee-rsa-pkey ( nlen elen -- ) {
+ size_t elen = T0_POP();
+ size_t nlen = T0_POP();
+ memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen);
+ CTX->pkey.key_type = BR_KEYTYPE_RSA;
+ CTX->pkey.key.rsa.n = CTX->ee_pkey_data;
+ CTX->pkey.key.rsa.nlen = nlen;
+ CTX->pkey.key.rsa.e = CTX->ee_pkey_data + nlen;
+ CTX->pkey.key.rsa.elen = elen;
+}
+
+\ Copy the EE public key to the permanent buffer (EC).
+cc: copy-ee-ec-pkey ( curve qlen -- ) {
+ size_t qlen = T0_POP();
+ uint32_t curve = T0_POP();
+ memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen);
+ CTX->pkey.key_type = BR_KEYTYPE_EC;
+ CTX->pkey.key.ec.curve = curve;
+ CTX->pkey.key.ec.q = CTX->ee_pkey_data;
+ CTX->pkey.key.ec.qlen = qlen;
+}
+
+\ Check whether the current certificate (EE) is directly trusted.
+cc: check-direct-trust ( -- ) {
+ size_t u;
+
+ for (u = 0; u < CTX->trust_anchors_num; u ++) {
+ const br_x509_trust_anchor *ta;
+ unsigned char hashed_DN[64];
+ int kt;
+
+ ta = &CTX->trust_anchors[u];
+ if (ta->flags & BR_X509_TA_CA) {
+ continue;
+ }
+ hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
+ if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) {
+ continue;
+ }
+ kt = CTX->pkey.key_type;
+ if ((ta->pkey.key_type & 0x0F) != kt) {
+ continue;
+ }
+ switch (kt) {
+
+ case BR_KEYTYPE_RSA:
+ if (!eqbigint(CTX->pkey.key.rsa.n,
+ CTX->pkey.key.rsa.nlen,
+ ta->pkey.key.rsa.n,
+ ta->pkey.key.rsa.nlen)
+ || !eqbigint(CTX->pkey.key.rsa.e,
+ CTX->pkey.key.rsa.elen,
+ ta->pkey.key.rsa.e,
+ ta->pkey.key.rsa.elen))
+ {
+ continue;
+ }
+ break;
+
+ case BR_KEYTYPE_EC:
+ if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve
+ || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen
+ || memcmp(CTX->pkey.key.ec.q,
+ ta->pkey.key.ec.q,
+ ta->pkey.key.ec.qlen) != 0)
+ {
+ continue;
+ }
+ break;
+
+ default:
+ continue;
+ }
+
+ /*
+ * Direct trust match!
+ */
+ CTX->err = BR_ERR_X509_OK;
+ T0_CO();
+ }
+}
+
+\ Check the signature on the certificate with regards to all trusted CA.
+\ We use the issuer hash (in saved_dn_hash[]) as CA identifier.
+cc: check-trust-anchor-CA ( -- ) {
+ size_t u;
+
+ for (u = 0; u < CTX->trust_anchors_num; u ++) {
+ const br_x509_trust_anchor *ta;
+ unsigned char hashed_DN[64];
+
+ ta = &CTX->trust_anchors[u];
+ if (!(ta->flags & BR_X509_TA_CA)) {
+ continue;
+ }
+ hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN);
+ if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) {
+ continue;
+ }
+ if (verify_signature(CTX, &ta->pkey) == 0) {
+ CTX->err = BR_ERR_X509_OK;
+ T0_CO();
+ }
+ }
+}
+
+\ Verify RSA signature. This uses the public key that was just decoded
+\ into CTX->pkey_data; the modulus and exponent length are provided as
+\ parameters. The resulting hash value is compared with the one in
+\ tbs_hash. Returned value is 0 on success, or a non-zero error code.
+cc: do-rsa-vrfy ( nlen elen -- err ) {
+ size_t elen = T0_POP();
+ size_t nlen = T0_POP();
+ br_x509_pkey pk;
+
+ pk.key_type = BR_KEYTYPE_RSA;
+ pk.key.rsa.n = CTX->pkey_data;
+ pk.key.rsa.nlen = nlen;
+ pk.key.rsa.e = CTX->pkey_data + nlen;
+ pk.key.rsa.elen = elen;
+ T0_PUSH(verify_signature(CTX, &pk));
+}
+
+\ Verify ECDSA signature. This uses the public key that was just decoded
+\ into CTX->pkey_dayta; the curve ID and public point length are provided
+\ as parameters. The hash value in tbs_hash is used. Returned value is 0
+\ on success, or non-zero error code.
+cc: do-ecdsa-vrfy ( curve qlen -- err ) {
+ size_t qlen = T0_POP();
+ int curve = T0_POP();
+ br_x509_pkey pk;
+
+ pk.key_type = BR_KEYTYPE_EC;
+ pk.key.ec.curve = curve;
+ pk.key.ec.q = CTX->pkey_data;
+ pk.key.ec.qlen = qlen;
+ T0_PUSH(verify_signature(CTX, &pk));
+}
+
+cc: print-bytes ( addr len -- ) {
+ extern int printf(const char *fmt, ...);
+ size_t len = T0_POP();
+ unsigned char *buf = (unsigned char *)CTX + T0_POP();
+ size_t u;
+
+ for (u = 0; u < len; u ++) {
+ printf("%02X", buf[u]);
+ }
+}
+
+cc: printOID ( -- ) {
+ extern int printf(const char *fmt, ...);
+ size_t u, len;
+
+ len = CTX->pad[0];
+ if (len == 0) {
+ printf("*");
+ T0_RET();
+ }
+ printf("%u.%u", CTX->pad[1] / 40, CTX->pad[1] % 40);
+ u = 2;
+ while (u <= len) {
+ unsigned long ul;
+
+ ul = 0;
+ for (;;) {
+ int x;
+
+ if (u > len) {
+ printf("BAD");
+ T0_RET();
+ }
+ x = CTX->pad[u ++];
+ ul = (ul << 7) + (x & 0x7F);
+ if (!(x & 0x80)) {
+ break;
+ }
+ }
+ printf(".%lu", ul);
+ }
+}
+
+\ Extensions with specific processing.
+OID: basicConstraints 2.5.29.19
+OID: keyUsage 2.5.29.15
+OID: subjectAltName 2.5.29.17
+OID: certificatePolicies 2.5.29.32
+
+\ Policy qualifier "pointer to CPS"
+OID: id-qt-cps 1.3.6.1.5.5.7.2.1
+
+\ Extensions which are ignored when encountered, even if critical.
+OID: authorityKeyIdentifier 2.5.29.35
+OID: subjectKeyIdentifier 2.5.29.14
+OID: issuerAltName 2.5.29.18
+OID: subjectDirectoryAttributes 2.5.29.9
+OID: crlDistributionPoints 2.5.29.31
+OID: freshestCRL 2.5.29.46
+OID: authorityInfoAccess 1.3.6.1.5.5.7.1.1
+OID: subjectInfoAccess 1.3.6.1.5.5.7.1.11
+
+\ Process a Basic Constraints extension. This should be called only if
+\ the certificate is not the EE. We check that the extension contains
+\ the "CA" flag, and that the path length, if specified, is compatible
+\ with the current chain length.
+: process-basicConstraints ( lim -- lim )
+ read-sequence-open
+ read-tag-or-end
+ dup 0x01 = if
+ read-boolean ifnot ERR_X509_NOT_CA fail then
+ read-tag-or-end
+ else
+ ERR_X509_NOT_CA fail
+ then
+ dup 0x02 = if
+ drop check-primitive read-small-int-value
+ addr-num_certs get32 1- < if ERR_X509_NOT_CA fail then
+ read-tag-or-end
+ then
+ -1 <> if ERR_X509_UNEXPECTED fail then
+ drop
+ close-elt
+ ;
+
+\ Process a Key Usage extension.
+\ For the EE certificate:
+\ -- if the key usage contains keyEncipherment (2), dataEncipherment (3)
+\ or keyAgreement (4), then the "key exchange" usage is allowed;
+\ -- if the key usage contains digitalSignature (0) or nonRepudiation (1),
+\ then the "signature" usage is allowed.
+\ For CA certificates, the extension must contain keyCertSign (5).
+: process-keyUsage ( lim ee -- lim )
+ { ee }
+
+ \ Read tag for the BIT STRING and open it.
+ read-tag 0x03 check-tag-primitive
+ read-length-open-elt
+ \ First byte indicates number of ignored bits in the last byte. It
+ \ must be between 0 and 7.
+ read8 { ign }
+ ign 7 > if ERR_X509_UNEXPECTED fail then
+ \ Depending on length, we have either 0, 1 or more bytes to read.
+ dup case
+ 0 of ERR_X509_FORBIDDEN_KEY_USAGE fail endof
+ 1 of read8 ign >> ign << endof
+ drop read8 0
+ endcase
+
+ \ Check bits.
+ ee if
+ \ EE: get usages.
+ 0
+ over 0x38 and if 0x10 or then
+ swap 0xC0 and if 0x20 or then
+ addr-key_usages set8
+ else
+ \ Not EE: keyCertSign must be set.
+ 0x04 and ifnot ERR_X509_FORBIDDEN_KEY_USAGE fail then
+ then
+
+ \ We don't care about subsequent bytes.
+ skip-close-elt ;
+
+\ Process a Certificate Policies extension.
+\
+\ Since we don't actually support full policies processing, this function
+\ only checks that the extension contents can be safely ignored. Indeed,
+\ we don't validate against a specific set of policies (in RFC 5280
+\ terminology, user-initial-policy-set only contains the special value
+\ any-policy). Moreover, we don't support policy constraints (if a
+\ critical Policy Constraints extension is encountered, the validation
+\ will fail). Therefore, we can safely ignore the contents of this
+\ extension, except if it is critical AND one of the policy OID has a
+\ qualifier which is distinct from id-qt-cps (because id-qt-cps is
+\ specially designated by RFC 5280 has having no mandated action).
+\
+\ This function is called only if the extension is critical.
+: process-certPolicies ( lim -- lim )
+ \ Extension value is a SEQUENCE OF PolicyInformation.
+ read-sequence-open
+ begin dup while
+ \ PolicyInformation ::= SEQUENCE {
+ \ policyIdentifier OBJECT IDENTIFIER,
+ \ policyQualifiers SEQUENCE OF PolicyQualifierInfo OPTIONAL
+ \ }
+ read-sequence-open
+ read-OID drop
+ dup if
+ read-sequence-open
+ begin dup while
+ \ PolicyQualifierInfo ::= SEQUENCE {
+ \ policyQualifierId OBJECT IDENTIFIER,
+ \ qualifier ANY
+ \ }
+ read-sequence-open
+ read-OID drop id-qt-cps eqOID ifnot
+ ERR_X509_CRITICAL_EXTENSION fail
+ then
+ skip-close-elt
+ repeat
+ close-elt
+ then
+ close-elt
+ repeat
+ close-elt ;
+
+\ Process a Subject Alt Name extension. Returned value is a boolean set
+\ to true if the expected server name was matched against a dNSName in
+\ the extension.
+: process-SAN ( lim -- lim bool )
+ 0 { m }
+ read-sequence-open
+ begin dup while
+ \ Read the tag. If the tag is context-0, then parse an
+ \ 'otherName'. If the tag is context-2, then parse a
+ \ dNSName. If the tag is context-1 or context-6,
+ \ parse
+ read-tag case
+ \ OtherName
+ 0x20 of
+ \ OtherName ::= SEQUENCE {
+ \ type-id OBJECT IDENTIFIER,
+ \ value [0] EXPLICIT ANY
+ \ }
+ check-constructed read-length-open-elt
+ read-OID drop
+ -1 offset-name-element { offbuf }
+ read-tag 0x20 check-tag-constructed
+ read-length-open-elt
+ read-string offbuf copy-name-element
+ close-elt
+ close-elt
+ endof
+ \ rfc822Name (IA5String)
+ 0x21 of
+ check-primitive
+ read-value-UTF8 1 copy-name-SAN
+ endof
+ \ dNSName (IA5String)
+ 0x22 of
+ check-primitive
+ read-value-UTF8
+ dup if match-server-name m or >m then
+ 2 copy-name-SAN
+ endof
+ \ uniformResourceIdentifier (IA5String)
+ 0x26 of
+ check-primitive
+ read-value-UTF8 6 copy-name-SAN
+ endof
+ 2drop read-length-skip 0
+ endcase
+
+ \ We check only names of type dNSName; they use IA5String,
+ \ which is basically ASCII.
+ \ read-tag 0x22 = if
+ \ check-primitive
+ \ read-small-value drop
+ \ match-server-name m or >m
+ \ else
+ \ drop read-length-skip
+ \ then
+ repeat
+ close-elt
+ m ;
+
+\ Decode a certificate. The "ee" boolean must be true for the EE.
+: decode-certificate ( ee -- )
+ { ee }
+
+ \ Obtain the total certificate length.
+ addr-cert_length get32
+
+ \ Open the outer SEQUENCE.
+ read-sequence-open
+
+ \ TBS
+ \ Activate hashing.
+ start-tbs-hash
+ read-sequence-open
+
+ \ First element may be an explicit version. We accept only
+ \ versions 0 to 2 (certificates v1 to v3).
+ read-tag dup 0x20 = if
+ drop check-constructed read-length-open-elt
+ read-tag
+ 0x02 check-tag-primitive
+ read-small-int-value
+ 2 > if ERR_X509_UNSUPPORTED fail then
+ close-elt
+ read-tag
+ then
+
+ \ Serial number. We just check that the tag is correct.
+ 0x02 check-tag-primitive
+ read-length-skip
+
+ \ Signature algorithm. This structure is redundant with the one
+ \ on the outside; we just skip it.
+ read-sequence-open skip-close-elt
+
+ \ Issuer name: hashed, then copied into next_dn_hash[].
+ read-DN
+ addr-next_dn_hash addr-current_dn_hash dn-hash-length blobcopy
+
+ \ Validity dates.
+ read-sequence-open
+ read-date get-system-date after if ERR_X509_EXPIRED fail then
+ read-date get-system-date before if ERR_X509_EXPIRED fail then
+ close-elt
+
+ \ Subject name.
+ ee if
+ \ For the EE, we must check whether the Common Name, if
+ \ any, matches the expected server name.
+ read-DN-EE { eename }
+ else
+ \ For a non-EE certificate, the hashed subject DN must match
+ \ the saved hashed issuer DN from the previous certificate.
+ read-DN
+ addr-current_dn_hash addr-saved_dn_hash dn-hash-length eqblob
+ ifnot ERR_X509_DN_MISMATCH fail then
+ then
+ \ Move the hashed issuer DN for this certificate into the
+ \ saved_dn_hash[] array.
+ addr-saved_dn_hash addr-next_dn_hash dn-hash-length blobcopy
+
+ \ Public Key.
+ read-sequence-open
+ \ Algorithm Identifier. Right now we are only interested in the
+ \ OID, since we only support RSA keys.
+ read-sequence-open
+ read-OID ifnot ERR_X509_UNSUPPORTED fail then
+ { ; pkey-type }
+ choice
+ \ RSA public key.
+ rsaEncryption eqOID uf
+ skip-close-elt
+ \ Public key itself: the BIT STRING contains bytes
+ \ (no partial byte) and these bytes encode the
+ \ actual value.
+ read-bits-open
+ \ RSA public key is a SEQUENCE of two
+ \ INTEGER. We get both INTEGER values into
+ \ the pkey_data[] buffer, if they fit.
+ read-sequence-open
+ addr-len-pkey_data
+ read-integer { nlen }
+ addr-len-pkey_data swap nlen + swap nlen -
+ read-integer { elen }
+ close-elt
+
+ \ Check that the public key fits our minimal
+ \ size requirements. Note that the integer
+ \ decoder already skipped the leading bytes
+ \ of value 0, so we are working on the true
+ \ modulus length here.
+ addr-min_rsa_size get16 128 + nlen > if
+ ERR_X509_WEAK_PUBLIC_KEY fail
+ then
+ close-elt
+ KEYTYPE_RSA >pkey-type
+ enduf
+
+ \ EC public key.
+ id-ecPublicKey eqOID uf
+ \ We support only named curves, for which the
+ \ "parameters" field in the AlgorithmIdentifier
+ \ field should be an OID.
+ read-OID ifnot ERR_X509_UNSUPPORTED fail then
+ choice
+ ansix9p256r1 eqOID uf 23 enduf
+ ansix9p384r1 eqOID uf 24 enduf
+ ansix9p521r1 eqOID uf 25 enduf
+ ERR_X509_UNSUPPORTED fail
+ endchoice
+ { curve }
+ close-elt
+ read-bits-open
+ dup { qlen }
+ dup addr-len-pkey_data rot < if
+ ERR_X509_LIMIT_EXCEEDED fail
+ then
+ read-blob
+ KEYTYPE_EC >pkey-type
+ enduf
+
+ \ Not a recognised public key type.
+ ERR_X509_UNSUPPORTED fail
+ endchoice
+ close-elt
+
+ \ Process public key.
+ ee if
+ \ For the EE certificate, copy the key data to the
+ \ relevant buffer.
+ pkey-type case
+ KEYTYPE_RSA of nlen elen copy-ee-rsa-pkey endof
+ KEYTYPE_EC of curve qlen copy-ee-ec-pkey endof
+ ERR_X509_UNSUPPORTED fail
+ endcase
+ else
+ \ Verify signature on previous certificate. We invoke
+ \ the RSA implementation.
+ pkey-type case
+ KEYTYPE_RSA of nlen elen do-rsa-vrfy endof
+ KEYTYPE_EC of curve qlen do-ecdsa-vrfy endof
+ ERR_X509_UNSUPPORTED fail
+ endcase
+ dup if fail then
+ drop
+ then
+
+ \ This flag will be set to true if the Basic Constraints extension
+ \ is encountered.
+ 0 { seenBC }
+
+ \ Skip issuerUniqueID and subjectUniqueID, and process extensions
+ \ if present. Extensions are an explicit context tag of value 3
+ \ around a SEQUENCE OF extensions. Each extension is a SEQUENCE
+ \ with an OID, an optional boolean, and a value; the value is
+ \ an OCTET STRING.
+ read-tag-or-end
+ 0x21 iftag-skip
+ 0x22 iftag-skip
+ dup 0x23 = if
+ drop
+ check-constructed read-length-open-elt
+ read-sequence-open
+ begin dup while
+ 0 { critical }
+ read-sequence-open
+ read-OID drop
+ read-tag dup 0x01 = if
+ read-boolean >critical
+ read-tag
+ then
+ 0x04 check-tag-primitive read-length-open-elt
+ choice
+ \ Extensions with specific processing.
+ basicConstraints eqOID uf
+ ee if
+ skip-remaining
+ else
+ process-basicConstraints
+ -1 >seenBC
+ then
+ enduf
+ keyUsage eqOID uf
+ ee process-keyUsage
+ enduf
+ subjectAltName eqOID uf
+ ee if
+ 0 >eename
+ process-SAN >eename
+ else
+ skip-remaining
+ then
+ enduf
+
+ \ We don't implement full processing of
+ \ policies. The call below mostly checks
+ \ that the contents of the Certificate
+ \ Policies extension can be safely ignored.
+ certificatePolicies eqOID uf
+ critical if
+ process-certPolicies
+ else
+ skip-remaining
+ then
+ enduf
+
+ \ Extensions which are always ignored,
+ \ even if critical.
+ authorityKeyIdentifier eqOID uf
+ skip-remaining
+ enduf
+ subjectKeyIdentifier eqOID uf
+ skip-remaining
+ enduf
+ issuerAltName eqOID uf
+ skip-remaining
+ enduf
+ subjectDirectoryAttributes eqOID uf
+ skip-remaining
+ enduf
+ crlDistributionPoints eqOID uf
+ skip-remaining
+ enduf
+ freshestCRL eqOID uf
+ skip-remaining
+ enduf
+ authorityInfoAccess eqOID uf
+ skip-remaining
+ enduf
+ subjectInfoAccess eqOID uf
+ skip-remaining
+ enduf
+
+ \ Unrecognized extensions trigger a failure
+ \ if critical; otherwise, they are just
+ \ ignored.
+ critical if
+ ERR_X509_CRITICAL_EXTENSION fail
+ then
+ skip-remaining
+ endchoice
+ close-elt
+ close-elt
+ repeat
+ close-elt
+ close-elt
+ else
+ -1 = ifnot ERR_X509_UNEXPECTED fail then
+ drop
+ then
+
+ close-elt
+ \ Terminate hashing.
+ stop-tbs-hash
+
+ \ For the EE certificate, verify that the intended server name
+ \ was matched.
+ ee if
+ eename zero-server-name or ifnot
+ ERR_X509_BAD_SERVER_NAME fail
+ then
+ then
+
+ \ If this is the EE certificate, then direct trust may apply.
+ \ Note: we do this at this point, not immediately after decoding
+ \ the public key, because even in case of direct trust we still
+ \ want to check the server name with regards to the SAN extension.
+ \ However, we want to check direct trust before trying to decode
+ \ the signature algorithm, because it should work even if that
+ \ algorithm is not supported.
+ ee if check-direct-trust then
+
+ \ Non-EE certificates MUST have a Basic Constraints extension
+ \ (that marks them as being CA).
+ ee seenBC or ifnot ERR_X509_NOT_CA fail then
+
+ \ signature algorithm
+ read-tag check-sequence read-length-open-elt
+ \ Read and understand the OID. Right now, we support only
+ \ RSA with PKCS#1 v1.5 padding, and hash functions SHA-1,
+ \ SHA-224, SHA-256, SHA-384 and SHA-512. We purposely do NOT
+ \ support MD5 here.
+ \ TODO: add support for RSA/PSS
+ read-OID if
+ \ Based on the signature OID, we get:
+ \ -- the signing key type
+ \ -- the hash function numeric identifier
+ \ -- the hash function OID
+ choice
+ sha1WithRSAEncryption eqOID
+ uf 2 KEYTYPE_RSA id-sha1 enduf
+ sha224WithRSAEncryption eqOID
+ uf 3 KEYTYPE_RSA id-sha224 enduf
+ sha256WithRSAEncryption eqOID
+ uf 4 KEYTYPE_RSA id-sha256 enduf
+ sha384WithRSAEncryption eqOID
+ uf 5 KEYTYPE_RSA id-sha384 enduf
+ sha512WithRSAEncryption eqOID
+ uf 6 KEYTYPE_RSA id-sha512 enduf
+
+ ecdsa-with-SHA1 eqOID
+ uf 2 KEYTYPE_EC id-sha1 enduf
+ ecdsa-with-SHA224 eqOID
+ uf 3 KEYTYPE_EC id-sha224 enduf
+ ecdsa-with-SHA256 eqOID
+ uf 4 KEYTYPE_EC id-sha256 enduf
+ ecdsa-with-SHA384 eqOID
+ uf 5 KEYTYPE_EC id-sha384 enduf
+ ecdsa-with-SHA512 eqOID
+ uf 6 KEYTYPE_EC id-sha512 enduf
+ ERR_X509_UNSUPPORTED fail
+ endchoice
+ addr-cert_sig_hash_oid set16
+ addr-cert_signer_key_type set8
+
+ \ Compute the TBS hash into tbs_hash.
+ compute-tbs-hash
+ dup ifnot ERR_X509_UNSUPPORTED fail then
+ addr-cert_sig_hash_len set8
+ else
+ ERR_X509_UNSUPPORTED fail
+ then
+ \ We ignore the parameters, whether they are present or not,
+ \ because we got all the information from the OID.
+ skip-close-elt
+
+ \ signature value
+ read-bits-open
+ dup CX 0 8191 { BR_X509_BUFSIZE_SIG } > if
+ ERR_X509_LIMIT_EXCEEDED fail
+ then
+ dup addr-cert_sig_len set16
+ addr-cert_sig read-blob
+
+ \ Close the outer SEQUENCE.
+ close-elt
+
+ \ Close the advertised total certificate length. This checks that
+ \ there is no trailing garbage after the certificate.
+ close-elt
+
+ \ Flag the certificate as fully processed.
+ 0 addr-cert_length set32
+
+ \ Check whether the issuer for the current certificate is known
+ \ as a trusted CA; in which case, verify the signature.
+ check-trust-anchor-CA ;
+
+: main
+ \ Unless restricted by a Key Usage extension, all usages are
+ \ deemed allowed.
+ 0x30 addr-key_usages set8
+ -1 decode-certificate
+ co
+ begin
+ 0 decode-certificate co
+ again
+ ;
Index: stable/12/contrib/bearssl/src/x509/x509_minimal_full.c
===================================================================
--- stable/12/contrib/bearssl/src/x509/x509_minimal_full.c (nonexistent)
+++ stable/12/contrib/bearssl/src/x509/x509_minimal_full.c (revision 346145)
@@ -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.
+ */
+
+#include "inner.h"
+
+/* see bearssl_x509.h */
+void
+br_x509_minimal_init_full(br_x509_minimal_context *xc,
+ const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num)
+{
+ /*
+ * All hash functions are activated.
+ * Note: the X.509 validation engine will nonetheless refuse to
+ * validate signatures that use MD5 as hash function.
+ */
+ static const br_hash_class *hashes[] = {
+ &br_md5_vtable,
+ &br_sha1_vtable,
+ &br_sha224_vtable,
+ &br_sha256_vtable,
+ &br_sha384_vtable,
+ &br_sha512_vtable
+ };
+
+ int id;
+
+ br_x509_minimal_init(xc, &br_sha256_vtable,
+ trust_anchors, trust_anchors_num);
+ 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);
+ for (id = br_md5_ID; id <= br_sha512_ID; id ++) {
+ const br_hash_class *hc;
+
+ hc = hashes[id - 1];
+ br_x509_minimal_set_hash(xc, id, hc);
+ }
+}
Property changes on: stable/12/contrib/bearssl/src/x509/x509_minimal_full.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/test_crypto.c
===================================================================
--- stable/12/contrib/bearssl/test/test_crypto.c (nonexistent)
+++ stable/12/contrib/bearssl/test/test_crypto.c (revision 346145)
@@ -0,0 +1,9475 @@
+/*
+ * 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 "bearssl.h"
+#include "inner.h"
+
+/*
+ * Decode an hexadecimal string. Returned value is the number of decoded
+ * bytes.
+ */
+static size_t
+hextobin(unsigned char *dst, const char *src)
+{
+ size_t num;
+ unsigned acc;
+ int z;
+
+ num = 0;
+ z = 0;
+ acc = 0;
+ while (*src != 0) {
+ int c = *src ++;
+ if (c >= '0' && c <= '9') {
+ c -= '0';
+ } else if (c >= 'A' && c <= 'F') {
+ c -= ('A' - 10);
+ } else if (c >= 'a' && c <= 'f') {
+ c -= ('a' - 10);
+ } else {
+ continue;
+ }
+ if (z) {
+ *dst ++ = (acc << 4) + c;
+ num ++;
+ } else {
+ acc = c;
+ }
+ z = !z;
+ }
+ return num;
+}
+
+static void
+check_equals(const char *banner, const void *v1, const void *v2, size_t len)
+{
+ size_t u;
+ const unsigned char *b;
+
+ if (memcmp(v1, v2, len) == 0) {
+ return;
+ }
+ fprintf(stderr, "\n%s failed\n", banner);
+ fprintf(stderr, "v1: ");
+ for (u = 0, b = v1; u < len; u ++) {
+ fprintf(stderr, "%02X", b[u]);
+ }
+ fprintf(stderr, "\nv2: ");
+ for (u = 0, b = v2; u < len; u ++) {
+ fprintf(stderr, "%02X", b[u]);
+ }
+ fprintf(stderr, "\n");
+ exit(EXIT_FAILURE);
+}
+
+#define HASH_SIZE(cname) br_ ## cname ## _SIZE
+
+#define TEST_HASH(Name, cname) \
+static void \
+test_ ## cname ## _internal(char *data, char *refres) \
+{ \
+ br_ ## cname ## _context mc; \
+ unsigned char res[HASH_SIZE(cname)], ref[HASH_SIZE(cname)]; \
+ size_t u, n; \
+ \
+ hextobin(ref, refres); \
+ n = strlen(data); \
+ br_ ## cname ## _init(&mc); \
+ br_ ## cname ## _update(&mc, data, n); \
+ br_ ## cname ## _out(&mc, res); \
+ check_equals("KAT " #Name " 1", res, ref, HASH_SIZE(cname)); \
+ br_ ## cname ## _init(&mc); \
+ for (u = 0; u < n; u ++) { \
+ br_ ## cname ## _update(&mc, data + u, 1); \
+ } \
+ br_ ## cname ## _out(&mc, res); \
+ check_equals("KAT " #Name " 2", res, ref, HASH_SIZE(cname)); \
+ for (u = 0; u < n; u ++) { \
+ br_ ## cname ## _context mc2; \
+ br_ ## cname ## _init(&mc); \
+ br_ ## cname ## _update(&mc, data, u); \
+ mc2 = mc; \
+ br_ ## cname ## _update(&mc, data + u, n - u); \
+ br_ ## cname ## _out(&mc, res); \
+ check_equals("KAT " #Name " 3", res, ref, HASH_SIZE(cname)); \
+ br_ ## cname ## _update(&mc2, data + u, n - u); \
+ br_ ## cname ## _out(&mc2, res); \
+ check_equals("KAT " #Name " 4", res, ref, HASH_SIZE(cname)); \
+ } \
+ memset(&mc, 0, sizeof mc); \
+ memset(res, 0, sizeof res); \
+ br_ ## cname ## _vtable.init(&mc.vtable); \
+ mc.vtable->update(&mc.vtable, data, n); \
+ mc.vtable->out(&mc.vtable, res); \
+ check_equals("KAT " #Name " 5", res, ref, HASH_SIZE(cname)); \
+ memset(res, 0, sizeof res); \
+ mc.vtable->init(&mc.vtable); \
+ mc.vtable->update(&mc.vtable, data, n); \
+ mc.vtable->out(&mc.vtable, res); \
+ check_equals("KAT " #Name " 6", res, ref, HASH_SIZE(cname)); \
+}
+
+#define KAT_MILLION_A(Name, cname, refres) do { \
+ br_ ## cname ## _context mc; \
+ unsigned char buf[1000]; \
+ unsigned char res[HASH_SIZE(cname)], ref[HASH_SIZE(cname)]; \
+ int i; \
+ \
+ hextobin(ref, refres); \
+ memset(buf, 'a', sizeof buf); \
+ br_ ## cname ## _init(&mc); \
+ for (i = 0; i < 1000; i ++) { \
+ br_ ## cname ## _update(&mc, buf, sizeof buf); \
+ } \
+ br_ ## cname ## _out(&mc, res); \
+ check_equals("KAT " #Name " 5", res, ref, HASH_SIZE(cname)); \
+ } while (0)
+
+TEST_HASH(MD5, md5)
+TEST_HASH(SHA-1, sha1)
+TEST_HASH(SHA-224, sha224)
+TEST_HASH(SHA-256, sha256)
+TEST_HASH(SHA-384, sha384)
+TEST_HASH(SHA-512, sha512)
+
+static void
+test_MD5(void)
+{
+ printf("Test MD5: ");
+ fflush(stdout);
+ test_md5_internal("", "d41d8cd98f00b204e9800998ecf8427e");
+ test_md5_internal("a", "0cc175b9c0f1b6a831c399e269772661");
+ test_md5_internal("abc", "900150983cd24fb0d6963f7d28e17f72");
+ test_md5_internal("message digest", "f96b697d7cb7938d525a2f31aaf161d0");
+ test_md5_internal("abcdefghijklmnopqrstuvwxyz",
+ "c3fcd3d76192e4007dfb496cca67e13b");
+ test_md5_internal("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu"
+ "vwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f");
+ test_md5_internal("1234567890123456789012345678901234567890123456789"
+ "0123456789012345678901234567890",
+ "57edf4a22be3c955ac49da2e2107b67a");
+ KAT_MILLION_A(MD5, md5,
+ "7707d6ae4e027c70eea2a935c2296f21");
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_SHA1(void)
+{
+ printf("Test SHA-1: ");
+ fflush(stdout);
+ test_sha1_internal("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
+ test_sha1_internal("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm"
+ "nomnopnopq", "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
+
+ KAT_MILLION_A(SHA-1, sha1,
+ "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_SHA224(void)
+{
+ printf("Test SHA-224: ");
+ fflush(stdout);
+ test_sha224_internal("abc",
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7");
+ test_sha224_internal("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm"
+ "nomnopnopq",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525");
+
+ KAT_MILLION_A(SHA-224, sha224,
+ "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67");
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_SHA256(void)
+{
+ printf("Test SHA-256: ");
+ fflush(stdout);
+ test_sha256_internal("abc",
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
+ test_sha256_internal("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm"
+ "nomnopnopq",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
+
+ KAT_MILLION_A(SHA-256, sha256,
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_SHA384(void)
+{
+ printf("Test SHA-384: ");
+ fflush(stdout);
+ test_sha384_internal("abc",
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded163"
+ "1a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7");
+ test_sha384_internal(
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d2"
+ "2fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039");
+
+ KAT_MILLION_A(SHA-384, sha384,
+ "9d0e1809716474cb086e834e310a4a1ced149e9c00f24852"
+ "7972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985");
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_SHA512(void)
+{
+ printf("Test SHA-512: ");
+ fflush(stdout);
+ test_sha512_internal("abc",
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
+ test_sha512_internal(
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909");
+
+ KAT_MILLION_A(SHA-512, sha512,
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b");
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_MD5_SHA1(void)
+{
+ unsigned char buf[500], out[36], outM[16], outS[20];
+ unsigned char seed[1];
+ br_hmac_drbg_context rc;
+ br_md5_context mc;
+ br_sha1_context sc;
+ br_md5sha1_context cc;
+ size_t u;
+
+ printf("Test MD5+SHA-1: ");
+ fflush(stdout);
+
+ seed[0] = 0;
+ br_hmac_drbg_init(&rc, &br_sha256_vtable, seed, sizeof seed);
+ for (u = 0; u < sizeof buf; u ++) {
+ size_t v;
+
+ br_hmac_drbg_generate(&rc, buf, u);
+ br_md5_init(&mc);
+ br_md5_update(&mc, buf, u);
+ br_md5_out(&mc, outM);
+ br_sha1_init(&sc);
+ br_sha1_update(&sc, buf, u);
+ br_sha1_out(&sc, outS);
+ br_md5sha1_init(&cc);
+ br_md5sha1_update(&cc, buf, u);
+ br_md5sha1_out(&cc, out);
+ check_equals("MD5+SHA-1 [1]", out, outM, 16);
+ check_equals("MD5+SHA-1 [2]", out + 16, outS, 20);
+ br_md5sha1_init(&cc);
+ for (v = 0; v < u; v ++) {
+ br_md5sha1_update(&cc, buf + v, 1);
+ }
+ br_md5sha1_out(&cc, out);
+ check_equals("MD5+SHA-1 [3]", out, outM, 16);
+ check_equals("MD5+SHA-1 [4]", out + 16, outS, 20);
+ }
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+/*
+ * Compute a hash function, on some data, by ID. Returned value is
+ * hash output length.
+ */
+static size_t
+do_hash(int id, const void *data, size_t len, void *out)
+{
+ br_md5_context cmd5;
+ br_sha1_context csha1;
+ br_sha224_context csha224;
+ br_sha256_context csha256;
+ br_sha384_context csha384;
+ br_sha512_context csha512;
+
+ switch (id) {
+ case br_md5_ID:
+ br_md5_init(&cmd5);
+ br_md5_update(&cmd5, data, len);
+ br_md5_out(&cmd5, out);
+ return 16;
+ case br_sha1_ID:
+ br_sha1_init(&csha1);
+ br_sha1_update(&csha1, data, len);
+ br_sha1_out(&csha1, out);
+ return 20;
+ case br_sha224_ID:
+ br_sha224_init(&csha224);
+ br_sha224_update(&csha224, data, len);
+ br_sha224_out(&csha224, out);
+ return 28;
+ case br_sha256_ID:
+ br_sha256_init(&csha256);
+ br_sha256_update(&csha256, data, len);
+ br_sha256_out(&csha256, out);
+ return 32;
+ case br_sha384_ID:
+ br_sha384_init(&csha384);
+ br_sha384_update(&csha384, data, len);
+ br_sha384_out(&csha384, out);
+ return 48;
+ case br_sha512_ID:
+ br_sha512_init(&csha512);
+ br_sha512_update(&csha512, data, len);
+ br_sha512_out(&csha512, out);
+ return 64;
+ default:
+ fprintf(stderr, "Uknown hash function: %d\n", id);
+ exit(EXIT_FAILURE);
+ return 0;
+ }
+}
+
+/*
+ * Tests for a multihash. Returned value should be 258 multiplied by the
+ * number of hash functions implemented by the context.
+ */
+static int
+test_multihash_inner(br_multihash_context *mc)
+{
+ /*
+ * Try hashing messages for all lengths from 0 to 257 bytes
+ * (inclusive). Each attempt is done twice, with data input
+ * either in one go, or byte by byte. In the byte by byte
+ * test, intermediate result are obtained and checked.
+ */
+ size_t len;
+ unsigned char buf[258];
+ int i;
+ int tcount;
+
+ tcount = 0;
+ for (len = 0; len < sizeof buf; len ++) {
+ br_sha1_context sc;
+ unsigned char tmp[20];
+
+ br_sha1_init(&sc);
+ br_sha1_update(&sc, buf, len);
+ br_sha1_out(&sc, tmp);
+ buf[len] = tmp[0];
+ }
+ for (len = 0; len <= 257; len ++) {
+ size_t u;
+
+ br_multihash_init(mc);
+ br_multihash_update(mc, buf, len);
+ for (i = 1; i <= 6; i ++) {
+ unsigned char tmp[64], tmp2[64];
+ size_t olen, olen2;
+
+ olen = br_multihash_out(mc, i, tmp);
+ if (olen == 0) {
+ continue;
+ }
+ olen2 = do_hash(i, buf, len, tmp2);
+ if (olen != olen2) {
+ fprintf(stderr,
+ "Bad hash output length: %u / %u\n",
+ (unsigned)olen, (unsigned)olen2);
+ exit(EXIT_FAILURE);
+ }
+ check_equals("Hash output", tmp, tmp2, olen);
+ tcount ++;
+ }
+
+ br_multihash_init(mc);
+ for (u = 0; u < len; u ++) {
+ br_multihash_update(mc, buf + u, 1);
+ for (i = 1; i <= 6; i ++) {
+ unsigned char tmp[64], tmp2[64];
+ size_t olen, olen2;
+
+ olen = br_multihash_out(mc, i, tmp);
+ if (olen == 0) {
+ continue;
+ }
+ olen2 = do_hash(i, buf, u + 1, tmp2);
+ if (olen != olen2) {
+ fprintf(stderr, "Bad hash output"
+ " length: %u / %u\n",
+ (unsigned)olen,
+ (unsigned)olen2);
+ exit(EXIT_FAILURE);
+ }
+ check_equals("Hash output", tmp, tmp2, olen);
+ }
+ }
+ }
+ return tcount;
+}
+
+static void
+test_multihash(void)
+{
+ br_multihash_context mc;
+
+ printf("Test MultiHash: ");
+ fflush(stdout);
+
+ br_multihash_zero(&mc);
+ br_multihash_setimpl(&mc, br_md5_ID, &br_md5_vtable);
+ if (test_multihash_inner(&mc) != 258) {
+ fprintf(stderr, "Failed test count\n");
+ }
+ printf(".");
+ fflush(stdout);
+
+ br_multihash_zero(&mc);
+ br_multihash_setimpl(&mc, br_sha1_ID, &br_sha1_vtable);
+ if (test_multihash_inner(&mc) != 258) {
+ fprintf(stderr, "Failed test count\n");
+ }
+ printf(".");
+ fflush(stdout);
+
+ br_multihash_zero(&mc);
+ br_multihash_setimpl(&mc, br_sha224_ID, &br_sha224_vtable);
+ if (test_multihash_inner(&mc) != 258) {
+ fprintf(stderr, "Failed test count\n");
+ }
+ printf(".");
+ fflush(stdout);
+
+ br_multihash_zero(&mc);
+ br_multihash_setimpl(&mc, br_sha256_ID, &br_sha256_vtable);
+ if (test_multihash_inner(&mc) != 258) {
+ fprintf(stderr, "Failed test count\n");
+ }
+ printf(".");
+ fflush(stdout);
+
+ br_multihash_zero(&mc);
+ br_multihash_setimpl(&mc, br_sha384_ID, &br_sha384_vtable);
+ if (test_multihash_inner(&mc) != 258) {
+ fprintf(stderr, "Failed test count\n");
+ }
+ printf(".");
+ fflush(stdout);
+
+ br_multihash_zero(&mc);
+ br_multihash_setimpl(&mc, br_sha512_ID, &br_sha512_vtable);
+ if (test_multihash_inner(&mc) != 258) {
+ fprintf(stderr, "Failed test count\n");
+ }
+ printf(".");
+ fflush(stdout);
+
+ br_multihash_zero(&mc);
+ br_multihash_setimpl(&mc, br_md5_ID, &br_md5_vtable);
+ br_multihash_setimpl(&mc, br_sha1_ID, &br_sha1_vtable);
+ br_multihash_setimpl(&mc, br_sha224_ID, &br_sha224_vtable);
+ br_multihash_setimpl(&mc, br_sha256_ID, &br_sha256_vtable);
+ br_multihash_setimpl(&mc, br_sha384_ID, &br_sha384_vtable);
+ br_multihash_setimpl(&mc, br_sha512_ID, &br_sha512_vtable);
+ if (test_multihash_inner(&mc) != 258 * 6) {
+ fprintf(stderr, "Failed test count\n");
+ }
+ printf(".");
+ fflush(stdout);
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+do_KAT_HMAC_bin_bin(const br_hash_class *digest_class,
+ const void *key, size_t key_len,
+ const void *data, size_t data_len, const char *href)
+{
+ br_hmac_key_context kc;
+ br_hmac_context ctx;
+ unsigned char tmp[64], ref[64];
+ size_t u, len;
+
+ len = hextobin(ref, href);
+ br_hmac_key_init(&kc, digest_class, key, key_len);
+ br_hmac_init(&ctx, &kc, 0);
+ br_hmac_update(&ctx, data, data_len);
+ br_hmac_out(&ctx, tmp);
+ check_equals("KAT HMAC 1", tmp, ref, len);
+
+ br_hmac_init(&ctx, &kc, 0);
+ for (u = 0; u < data_len; u ++) {
+ br_hmac_update(&ctx, (const unsigned char *)data + u, 1);
+ }
+ br_hmac_out(&ctx, tmp);
+ check_equals("KAT HMAC 2", tmp, ref, len);
+
+ for (u = 0; u < data_len; u ++) {
+ br_hmac_init(&ctx, &kc, 0);
+ br_hmac_update(&ctx, data, u);
+ br_hmac_out(&ctx, tmp);
+ br_hmac_update(&ctx,
+ (const unsigned char *)data + u, data_len - u);
+ br_hmac_out(&ctx, tmp);
+ check_equals("KAT HMAC 3", tmp, ref, len);
+ }
+}
+
+static void
+do_KAT_HMAC_str_str(const br_hash_class *digest_class, const char *key,
+ const char *data, const char *href)
+{
+ do_KAT_HMAC_bin_bin(digest_class, key, strlen(key),
+ data, strlen(data), href);
+}
+
+static void
+do_KAT_HMAC_hex_hex(const br_hash_class *digest_class, const char *skey,
+ const char *sdata, const char *href)
+{
+ unsigned char key[1024];
+ unsigned char data[1024];
+
+ do_KAT_HMAC_bin_bin(digest_class, key, hextobin(key, skey),
+ data, hextobin(data, sdata), href);
+}
+
+static void
+do_KAT_HMAC_hex_str(const br_hash_class *digest_class,
+ const char *skey, const char *data, const char *href)
+{
+ unsigned char key[1024];
+
+ do_KAT_HMAC_bin_bin(digest_class, key, hextobin(key, skey),
+ data, strlen(data), href);
+}
+
+static void
+test_HMAC_CT(const br_hash_class *digest_class,
+ const void *key, size_t key_len, const void *data)
+{
+ br_hmac_key_context kc;
+ br_hmac_context hc1, hc2;
+ unsigned char buf1[64], buf2[64];
+ size_t u, v;
+
+ br_hmac_key_init(&kc, digest_class, key, key_len);
+
+ for (u = 0; u < 2; u ++) {
+ for (v = 0; v < 130; v ++) {
+ size_t min_len, max_len;
+ size_t w;
+
+ min_len = v;
+ max_len = v + 256;
+ for (w = min_len; w <= max_len; w ++) {
+ char tmp[30];
+ size_t hlen1, hlen2;
+
+ br_hmac_init(&hc1, &kc, 0);
+ br_hmac_update(&hc1, data, u + w);
+ hlen1 = br_hmac_out(&hc1, buf1);
+ br_hmac_init(&hc2, &kc, 0);
+ br_hmac_update(&hc2, data, u);
+ hlen2 = br_hmac_outCT(&hc2,
+ (const unsigned char *)data + u, w,
+ min_len, max_len, buf2);
+ if (hlen1 != hlen2) {
+ fprintf(stderr, "HMAC length mismatch:"
+ " %u / %u\n", (unsigned)hlen1,
+ (unsigned)hlen2);
+ exit(EXIT_FAILURE);
+ }
+ sprintf(tmp, "HMAC CT %u,%u,%u",
+ (unsigned)u, (unsigned)v, (unsigned)w);
+ check_equals(tmp, buf1, buf2, hlen1);
+ }
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ printf(" ");
+ fflush(stdout);
+}
+
+static void
+test_HMAC(void)
+{
+ unsigned char data[1000];
+ unsigned x;
+ size_t u;
+ const char key[] = "test HMAC key";
+
+ printf("Test HMAC: ");
+ fflush(stdout);
+ do_KAT_HMAC_hex_str(&br_md5_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "Hi There",
+ "9294727a3638bb1c13f48ef8158bfc9d");
+ do_KAT_HMAC_str_str(&br_md5_vtable,
+ "Jefe",
+ "what do ya want for nothing?",
+ "750c783e6ab0b503eaa86e310a5db738");
+ do_KAT_HMAC_hex_hex(&br_md5_vtable,
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "56be34521d144c88dbb8c733f0e8b3f6");
+ do_KAT_HMAC_hex_hex(&br_md5_vtable,
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "697eaf0aca3a3aea3a75164746ffaa79");
+ do_KAT_HMAC_hex_str(&br_md5_vtable,
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "Test With Truncation",
+ "56461ef2342edc00f9bab995690efd4c");
+ do_KAT_HMAC_hex_str(&br_md5_vtable,
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd");
+ do_KAT_HMAC_hex_str(&br_md5_vtable,
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+ "6f630fad67cda0ee1fb1f562db3aa53e");
+
+ do_KAT_HMAC_hex_str(&br_sha1_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "Hi There",
+ "b617318655057264e28bc0b6fb378c8ef146be00");
+ do_KAT_HMAC_str_str(&br_sha1_vtable,
+ "Jefe",
+ "what do ya want for nothing?",
+ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79");
+ do_KAT_HMAC_hex_hex(&br_sha1_vtable,
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "125d7342b9ac11cd91a39af48aa17b4f63f175d3");
+ do_KAT_HMAC_hex_hex(&br_sha1_vtable,
+ "0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "4c9007f4026250c6bc8414f9bf50c86c2d7235da");
+ do_KAT_HMAC_hex_str(&br_sha1_vtable,
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ "Test With Truncation",
+ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04");
+ do_KAT_HMAC_hex_str(&br_sha1_vtable,
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112");
+ do_KAT_HMAC_hex_str(&br_sha1_vtable,
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91");
+
+ /* From RFC 4231 */
+
+ do_KAT_HMAC_hex_hex(&br_sha224_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "896fb1128abbdf196832107cd49df33f"
+ "47b4b1169912ba4f53684b22");
+
+ do_KAT_HMAC_hex_hex(&br_sha256_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "b0344c61d8db38535ca8afceaf0bf12b"
+ "881dc200c9833da726e9376c2e32cff7");
+
+ do_KAT_HMAC_hex_hex(&br_sha384_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "afd03944d84895626b0825f4ab46907f"
+ "15f9dadbe4101ec682aa034c7cebc59c"
+ "faea9ea9076ede7f4af152e8b2fa9cb6");
+
+ do_KAT_HMAC_hex_hex(&br_sha512_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "87aa7cdea5ef619d4ff0b4241a1d6cb0"
+ "2379f4e2ce4ec2787ad0b30545e17cde"
+ "daa833b7d6b8a702038b274eaea3f4e4"
+ "be9d914eeb61f1702e696c203a126854");
+
+ do_KAT_HMAC_hex_hex(&br_sha224_vtable,
+ "4a656665",
+ "7768617420646f2079612077616e7420"
+ "666f72206e6f7468696e673f",
+ "a30e01098bc6dbbf45690f3a7e9e6d0f"
+ "8bbea2a39e6148008fd05e44");
+
+ do_KAT_HMAC_hex_hex(&br_sha256_vtable,
+ "4a656665",
+ "7768617420646f2079612077616e7420"
+ "666f72206e6f7468696e673f",
+ "5bdcc146bf60754e6a042426089575c7"
+ "5a003f089d2739839dec58b964ec3843");
+
+ do_KAT_HMAC_hex_hex(&br_sha384_vtable,
+ "4a656665",
+ "7768617420646f2079612077616e7420"
+ "666f72206e6f7468696e673f",
+ "af45d2e376484031617f78d2b58a6b1b"
+ "9c7ef464f5a01b47e42ec3736322445e"
+ "8e2240ca5e69e2c78b3239ecfab21649");
+
+ do_KAT_HMAC_hex_hex(&br_sha512_vtable,
+ "4a656665",
+ "7768617420646f2079612077616e7420"
+ "666f72206e6f7468696e673f",
+ "164b7a7bfcf819e2e395fbe73b56e0a3"
+ "87bd64222e831fd610270cd7ea250554"
+ "9758bf75c05a994a6d034f65f8f0e6fd"
+ "caeab1a34d4a6b4b636e070a38bce737");
+
+ do_KAT_HMAC_hex_hex(&br_sha224_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddd",
+ "7fb3cb3588c6c1f6ffa9694d7d6ad264"
+ "9365b0c1f65d69d1ec8333ea");
+
+ do_KAT_HMAC_hex_hex(&br_sha256_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddd",
+ "773ea91e36800e46854db8ebd09181a7"
+ "2959098b3ef8c122d9635514ced565fe");
+
+ do_KAT_HMAC_hex_hex(&br_sha384_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddd",
+ "88062608d3e6ad8a0aa2ace014c8a86f"
+ "0aa635d947ac9febe83ef4e55966144b"
+ "2a5ab39dc13814b94e3ab6e101a34f27");
+
+ do_KAT_HMAC_hex_hex(&br_sha512_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddd"
+ "dddd",
+ "fa73b0089d56a284efb0f0756c890be9"
+ "b1b5dbdd8ee81a3655f83e33b2279d39"
+ "bf3e848279a722c806b485a47e67c807"
+ "b946a337bee8942674278859e13292fb");
+
+ do_KAT_HMAC_hex_hex(&br_sha224_vtable,
+ "0102030405060708090a0b0c0d0e0f10"
+ "111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcd",
+ "6c11506874013cac6a2abc1bb382627c"
+ "ec6a90d86efc012de7afec5a");
+
+ do_KAT_HMAC_hex_hex(&br_sha256_vtable,
+ "0102030405060708090a0b0c0d0e0f10"
+ "111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcd",
+ "82558a389a443c0ea4cc819899f2083a"
+ "85f0faa3e578f8077a2e3ff46729665b");
+
+ do_KAT_HMAC_hex_hex(&br_sha384_vtable,
+ "0102030405060708090a0b0c0d0e0f10"
+ "111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcd",
+ "3e8a69b7783c25851933ab6290af6ca7"
+ "7a9981480850009cc5577c6e1f573b4e"
+ "6801dd23c4a7d679ccf8a386c674cffb");
+
+ do_KAT_HMAC_hex_hex(&br_sha512_vtable,
+ "0102030405060708090a0b0c0d0e0f10"
+ "111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcd",
+ "b0ba465637458c6990e5a8c5f61d4af7"
+ "e576d97ff94b872de76f8050361ee3db"
+ "a91ca5c11aa25eb4d679275cc5788063"
+ "a5f19741120c4f2de2adebeb10a298dd");
+
+ do_KAT_HMAC_hex_hex(&br_sha224_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c61726765"
+ "72205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579"
+ "204669727374",
+ "95e9a0db962095adaebe9b2d6f0dbce2"
+ "d499f112f2d2b7273fa6870e");
+
+ do_KAT_HMAC_hex_hex(&br_sha256_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c61726765"
+ "72205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579"
+ "204669727374",
+ "60e431591ee0b67f0d8a26aacbf5b77f"
+ "8e0bc6213728c5140546040f0ee37f54");
+
+ do_KAT_HMAC_hex_hex(&br_sha384_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c61726765"
+ "72205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579"
+ "204669727374",
+ "4ece084485813e9088d2c63a041bc5b4"
+ "4f9ef1012a2b588f3cd11f05033ac4c6"
+ "0c2ef6ab4030fe8296248df163f44952");
+
+ do_KAT_HMAC_hex_hex(&br_sha512_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c61726765"
+ "72205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579"
+ "204669727374",
+ "80b24263c7c1a3ebb71493c1dd7be8b4"
+ "9b46d1f41b4aeec1121b013783f8f352"
+ "6b56d037e05f2598bd0fd2215d6a1e52"
+ "95e64f73f63f0aec8b915a985d786598");
+
+ do_KAT_HMAC_hex_hex(&br_sha224_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54686973206973206120746573742075"
+ "73696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b65"
+ "7920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a652064"
+ "6174612e20546865206b6579206e6565"
+ "647320746f2062652068617368656420"
+ "6265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c"
+ "676f726974686d2e",
+ "3a854166ac5d9f023f54d517d0b39dbd"
+ "946770db9c2b95c9f6f565d1");
+
+ do_KAT_HMAC_hex_hex(&br_sha256_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54686973206973206120746573742075"
+ "73696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b65"
+ "7920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a652064"
+ "6174612e20546865206b6579206e6565"
+ "647320746f2062652068617368656420"
+ "6265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c"
+ "676f726974686d2e",
+ "9b09ffa71b942fcb27635fbcd5b0e944"
+ "bfdc63644f0713938a7f51535c3a35e2");
+
+ do_KAT_HMAC_hex_hex(&br_sha384_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54686973206973206120746573742075"
+ "73696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b65"
+ "7920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a652064"
+ "6174612e20546865206b6579206e6565"
+ "647320746f2062652068617368656420"
+ "6265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c"
+ "676f726974686d2e",
+ "6617178e941f020d351e2f254e8fd32c"
+ "602420feb0b8fb9adccebb82461e99c5"
+ "a678cc31e799176d3860e6110c46523e");
+
+ do_KAT_HMAC_hex_hex(&br_sha512_vtable,
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54686973206973206120746573742075"
+ "73696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b65"
+ "7920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a652064"
+ "6174612e20546865206b6579206e6565"
+ "647320746f2062652068617368656420"
+ "6265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c"
+ "676f726974686d2e",
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffd"
+ "debd71f8867289865df5a32d20cdc944"
+ "b6022cac3c4982b10d5eeb55c3e4de15"
+ "134676fb6de0446065c97440fa8c6a58");
+
+ for (x = 1, u = 0; u < sizeof data; u ++) {
+ data[u] = x;
+ x = (x * 45) % 257;
+ }
+ printf("(MD5) ");
+ test_HMAC_CT(&br_md5_vtable, key, sizeof key, data);
+ printf("(SHA-1) ");
+ test_HMAC_CT(&br_sha1_vtable, key, sizeof key, data);
+ printf("(SHA-224) ");
+ test_HMAC_CT(&br_sha224_vtable, key, sizeof key, data);
+ printf("(SHA-256) ");
+ test_HMAC_CT(&br_sha256_vtable, key, sizeof key, data);
+ printf("(SHA-384) ");
+ test_HMAC_CT(&br_sha384_vtable, key, sizeof key, data);
+ printf("(SHA-512) ");
+ test_HMAC_CT(&br_sha512_vtable, key, sizeof key, data);
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_HKDF_inner(const br_hash_class *dig, const char *ikmhex,
+ const char *salthex, const char *infohex, const char *okmhex)
+{
+ unsigned char ikm[100], saltbuf[100], info[100], okm[100], tmp[107];
+ const unsigned char *salt;
+ size_t ikm_len, salt_len, info_len, okm_len;
+ br_hkdf_context hc;
+ size_t u;
+
+ ikm_len = hextobin(ikm, ikmhex);
+ if (salthex == NULL) {
+ salt = BR_HKDF_NO_SALT;
+ salt_len = 0;
+ } else {
+ salt = saltbuf;
+ salt_len = hextobin(saltbuf, salthex);
+ }
+ info_len = hextobin(info, infohex);
+ okm_len = hextobin(okm, okmhex);
+
+ br_hkdf_init(&hc, dig, salt, salt_len);
+ br_hkdf_inject(&hc, ikm, ikm_len);
+ br_hkdf_flip(&hc);
+ br_hkdf_produce(&hc, info, info_len, tmp, okm_len);
+ check_equals("KAT HKDF 1", tmp, okm, okm_len);
+
+ br_hkdf_init(&hc, dig, salt, salt_len);
+ for (u = 0; u < ikm_len; u ++) {
+ br_hkdf_inject(&hc, &ikm[u], 1);
+ }
+ br_hkdf_flip(&hc);
+ for (u = 0; u < okm_len; u ++) {
+ br_hkdf_produce(&hc, info, info_len, &tmp[u], 1);
+ }
+ check_equals("KAT HKDF 2", tmp, okm, okm_len);
+
+ br_hkdf_init(&hc, dig, salt, salt_len);
+ br_hkdf_inject(&hc, ikm, ikm_len);
+ br_hkdf_flip(&hc);
+ for (u = 0; u < okm_len; u += 7) {
+ br_hkdf_produce(&hc, info, info_len, &tmp[u], 7);
+ }
+ check_equals("KAT HKDF 3", tmp, okm, okm_len);
+
+ printf(".");
+ fflush(stdout);
+}
+
+static void
+test_HKDF(void)
+{
+ printf("Test HKDF: ");
+ fflush(stdout);
+
+ test_HKDF_inner(&br_sha256_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "000102030405060708090a0b0c",
+ "f0f1f2f3f4f5f6f7f8f9",
+ "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865");
+
+ test_HKDF_inner(&br_sha256_vtable,
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f",
+ "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87");
+
+ test_HKDF_inner(&br_sha256_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "",
+ "",
+ "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8");
+
+ test_HKDF_inner(&br_sha1_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b",
+ "000102030405060708090a0b0c",
+ "f0f1f2f3f4f5f6f7f8f9",
+ "085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896");
+
+ test_HKDF_inner(&br_sha1_vtable,
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f",
+ "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ "0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4");
+
+ test_HKDF_inner(&br_sha1_vtable,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "",
+ "",
+ "0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918");
+
+ test_HKDF_inner(&br_sha1_vtable,
+ "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+ NULL,
+ "",
+ "2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48");
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+/*
+ * Known-answer test vectors for SHAKE128, from the NIST validation test
+ * suite. Each vector is a pair (input,output).
+ */
+static const char *const KAT_SHAKE128[] = {
+
+ "e4e932fc9907620ebebffd32b10fda7890a5bc20e5f41d5589882a18c2960e7aafd8730ee697469e5b0abb1d84de92ddba169802e31570374ef9939fde2b960e6b34ac7a65d36bacba4cd33bfa028cbbba486f32367548cb3a36dacf422924d0e0a7e3285ee158a2a42e4b765da3507b56e54998263b2c7b14e7078e35b74127d5d7220018e995e6e1572db5f3e8678357922f1cfd90a5afa6b420c600fd737b136c70e9dd14",
+ "459ce4fa824ee1910a678abc77c1f769",
+
+ "18636f702f216b1b9302e59d82192f4e002f82d526c3f04cbd4f9b9f0bcd2535ed7a67d326da66bdf7fc821ef0fff1a905d56c81e4472856863908d104301133ad111e39552cd542ef78d9b35f20419b893f4a93aee848e9f86ae3fd53d27fea7fb1fc69631fa0f3a5ff51267785086ab4f682d42baf394b3b6992e9a0bb58a38ce0692df9bbaf183e18523ee1352c5fad817e0c04a3e1c476be7f5e92f482a6fb29cd4bbf09ea",
+ "b7b9db481898f888e5ee4ed629859844",
+
+ "5d9ff9fe63c328ddbe0c865ac6ba605c52a14ee8e4870ba320ce849283532f2551959e74cf1a54c8b30ed75dd92e076637e4ad5213b3574e73d6640bd6245bc121378174dccdaa769e6e4f2dc650e1166c775d0a982021c0b160fe9438098e86b6cdc786f2a6d1ef68751551f7e99773daa28598d9961002c0b47ab511c8707df69f9b32796b723bf7685251d2c0d08567ad4e8540ddcc1b8a1a01f6c92aaaadcaf42301d9e53463",
+ "f50af2684408915871948779a14c147c",
+
+ "38c0be76e7b60f262f1499e328e0519f864bbb9d134d00345d8942d0ab762c3936c0cd1896eca6b77b3c01089dd285e9f61708a62e5ea4bf57c50decda5c215fb18ac149d7ace09ffdfed91e7fbf068d96908e42cf1e7ee7bc001c7ee9e378a311e44311923de4681f24c92eb5f0fb13d07ef679ded3b733f402168dc050568dbf97fb79afe8db994874783e27ad8d040ba8e75343c6762c6793a42247eee5a6216b908817f5edbbdf",
+ "e4786ad8f2ea9c8e420a6f50b5feec9a",
+
+ "ec586d52ad2ced1f96bd9458a5a1f64bc1b4cce1fa52517513c9ebe63d0d0eeb26ae5da73208137e08baa22651599a01bc65cbaa467baeceb8cd013d71d0b2406534fe2e6619da3aa380928f6effb09f42ba1fb7048e90d7898f1dc259b52c51b2d2970cd0c70afb6cf8acba83fd01cc589b0f31bcf2bf3b8df7879d7d2546c514706f6cf97b6a6b6d0a37d018ba553108f0e240f70f03a0ccee86f76589c64594f6cf74679bc330ad9f",
+ "191a3710c72d11da7a2410bc73ba9d9f",
+
+ "c201dfe59e03574476e3c220c971c1685ea96ea137daed2ac10845c54d8e6e53c307acdf956f1bdef3868ab53e758c7cbeb4cd02972ba311f998e5f3983000345c8947aa59b78bb301b6ecbe9808ee0de99ed0b938fc19f677997398bd84bcd6f34d5b4ed123d04a093a8f42c1700fa2472f1ecc00957761a2d296bda3d2cbc0f21d8ed4e4fb122b71db1d49a0f516c3402f6046d93de6dae20df7683462557abfbf88437c8678dfa2613b",
+ "464121895e5c9d85190bcee0437453dd",
+
+ "bd34acd613e0e0da6bebc45ba73fefa0bd8aa8ebba34040a07944f29eb63adea527101b8cd960e58d9ecddc0643b5e2d8db55170ace4678892e0a57612c50a4dc0647189f839b9a1229e22e0353dfa707acb7ab893f4ebe8bb910cd14f21b8fb8e77c4f19db027e0cd685d60212e0d920b34e96b774bd54f0a0f4ce2ac5f001b4411c19ac2e3a03b63b454eb30f4ddbac959673260d370e708c32d5030682ad56a99322972ba6eda6be9d027",
+ "8e167ceae101ea0b3b98175f66e46b0e",
+
+ "166b4fec6967c2a25f80c0075379978124833b84894c3cb3a538f649dcee08b8e41707901f6273a128cce964ac1e9b977bb7fe28de8bc2542c6c07109889cea84d34ada6bde8c8f5358afc46b5ef5db3009fe3a2efd860ed0ad6b540595246c27849abf7eafea9e5af42607519f3c51ddbc353bc633afec56aff69a0c953584d8ede684b4faefeb8be7d7db97e32bc1c35abb73ce3ba8425726d89f98e93ed93b67b4c6993ffafb789c1bbda8d",
+ "eb2fa0e8e04e698ca511d6abf7de84fb",
+
+ "62c625d31a400c5ff092d6fd638f1ea911ad912f2aabffea2377b1d2af4efeb6eb2519c5d8482d530f41acdab0fbe43f9c27d357e4df3caa8189fa7745ff95f811ed13e6497a1040852a1149890216d078ee6eb34461cfa6693ba631dbefacf83ce5ba3f531ddeadba16ae50d6eedce20cca0b4b3278e16644535e0859676c3fd5d6b7d7df7bbe2316cc2bfa7f055fffc2835225976d9a737b9ac905a7affc544288b1b7d6dad92901162f4c6d90",
+ "bb0acc4423c1d8cfc788e748ade8d5fd",
+
+ "8af63bbe701b84ff9b0c9d2fd830e28b7d557af3fcf4874bb7b69f2116388090d70bff64a600427eeea22f7bee0324900fbce9b8752fe312d40f8a8485231da5d94694daadb3d6bf3e7f2cc83f67f52829cc9cf1d3fcc87d42b3d20ec2e27cb135aee068acbca68734ac7a5ff3e3bd1a738e7be63de39e56aaaa6104f6fd077c964ccc55cba41ca1783003883100e52f94096fdfdc6dcd63b3fd1db148fc24cda22640eb34f19ed4b113ad8a2144d3",
+ "4a824cae0f236eab147bd6ebf66eafc2",
+
+ "a8c0f0e4afcda47e02afaaa2357c589e6b94168a6f6f142b019938186efa5b1b645bb4da032694b7376d54f4462e8c1ba5d6869d1003f3b9d98edc9f81c9dbd685058adb7a583c0b5c9debc224bb72c5982bfcdd67b4bdc57579e0467436c0a1b4c75a2d3cea034119455654f6ab7163ed9b61949d09da187d612b556fca724599a80c1970645023156f7df2e584f0bf4c2e9b08d98bb27a984fa7149c0b598adbb089e73f4f8d77f92248e419d0599f",
+ "4800f8f5e598a26ee05a0ea141f849d0",
+
+ "a035c12af3fb705602540bd0f4a00395e1625edf2d44af4a145b463585aba46b34ee3203eb9132842000f54dcd234e347c28486ea18414af2d3445916049403adfa3ed3906fdb3b27f2aa4bb149df405c12fb0bf0e1dacb79c50bec3fde2295fc8dd5c97ed46dd28475a80e27017dc50d9feff9b1a1861ac86371791037e49221923e6e44874962d9f18f1898a98ee5dec1e9eca6d7c1ad4166fbac41b2587caf7fef3e7be90c80aafed5f7a0928127321",
+ "2d124d81a4a45ad9c0b91cca23cc2991",
+
+ "d41739834414a0792470d53dee0f3f6c5a197314d3a14d75278440048294eab69df6eb7a33c9f807b5082bd93eb29d76c92837f6a2d6c5c21a154c9c7f509ee04b662b099c501a76e404996fe2997163d1abdd73df019c35e06d45b144f4dbb0462fa13767f12f4e1b2bc605c20ce1b9d96c0c94726af953e154d14cb9c8c8aff719f40c7cf45f15c1445ba6c65215024b316d60435905a686929874c6148e64c4eccd90c3a1d1553d18ff57d6b536c58ec3",
+ "551fc7eceeee151523be716538258e2e",
+
+ "5bbb333460ffac345e4d2bc2dba303ef75b85c57233590fabd22d547bf9e1d7a4ad43a286b2a4618a0bb42559808fd813bea376ceacc07e608167ad1b9ec7d7ae919fd2991464cf63570c7dfb299b61836bd73a29007cf1faa45b1e5539a00514272c35d58bb877526530187afbcf55a6f1757209c50af4eab96c2ab160e6ea75dc8d6ef4bf2bf3e7a4b3a7619db84efede22a0f960e701b14f0f44c89b18f2640017c05ef51bcf93942b8d3775d2980b80435",
+ "2c98dce5b1ec5f1f23554a755fac7700",
+
+ "8040a7296d7553886e5b25c7cf1f64a6a0a143185a83abf5c5813bef18008ec762e9bcc12ab7235552cf67274210b73942ac525f26364af431fc88cc34961169f6bf8872d864f360b9fbc27b18160d0578381db509e72e678402731157555bf9026b1325c1a34c136b863eab9a58ec720cedaa0049bfddb4863d03a6ca65f3dd4f9465c32b9db4d52f19e39f10ffdfe8c475032a2fe5e145ff524073d5ed617fa5e387325f7ab50fcf5cba40c2326bcf6a753019",
+ "c0bb8427ef0ca4e457d2887878d91310",
+
+ "cbaceb762e6c2f5f96052d4a681b899b84de459d198b3624bd35b471bdc59655b1405e9a5448b09e93e60941e486ad01d943e164f5655b97be28f75413c0ab08c099bd3650e33316234e8c83c012ad146b331e88fb037667e6e814e69e5f100b20417113c946a1116cc71ed7a3c87119623564d0d26c70dd5cfc75ef03acaea6f8c0e3f96877e0d599d8270635aee25be6d21b0522a82f4149ec8037edaf6b21709c7aafd580daaad00a0fd91fcfe6211d90abef95",
+ "626bd9eb0982b6db884d38e8c234854e",
+
+ "1bbee570394bc18d0f8713c7149cabb84e0567dd184510e922d97f5fb96b045f494808c02014f06074bd45b8a8ad12b4cb448ec16285fb27670fce99914f100ad6f504c32fa40ab39beec306667f76f9ab98b3ec18c036b8f1b60d4457a9fe53cbab23a0ee64d72d8a03d6d8d67a9f2ff6eb1d85c25d8746c8b4858794e094e12f54ab80e5ba1f774be5c456810755ffb52415b5e8c6b776f5f37b8bcf5c9b5d0ad7e58a9d0fa938e67ad5aaee8c5f11ef2be3a41362",
+ "a489ab3eb43f65ffbd4d4c34169ee762",
+
+ "aeacffca0e87bfdb2e6e74bfb67c9c90a8b6fb918b9be164cafcab7d570d8cd693bd8ee47243d3cbdaf921ce4d6e9e09c8b6d762eb0507bd597d976f6243e1f5e0d839e75ea72e2780da0d5e9f72a7a9b397548f762c3837c6a7c5d74b2081705ba70ab91adb5758e6b94058f2b141d830ff7b007538fb3ad8233f9e5bcbf6adcdd20843ee08d6c7d53cc3a58f53f3fe0997539e2f51d92e56990daad76dc816fd013b6d225634db140e9d2bbe7f45830406e44fee9d59",
+ "4eaa27b085d08fc6a7473e672ea2ca1b",
+
+ "a22314d2173ca4d53897924c4b395f0ae52c7fff4880525cee9055f866879af35f22759903b779898676a216feefd4ed75d484f83c00b58383b9279e2732cbc2cb5479b72abee5b4ab0bd0c937537b7a47f461ad419225c6045cca10c191225f0e4389f3355cd3a0d2de822c9d6f3cf984147de3fd3d8a6c9a02a617ddac87114f770b16cc96289321782108d94a00b153bd40651809cabe6c32237a2389e321b67769e89676cdd6c060162592ecadebdd7512fa3bfece04",
+ "eea88229becc3608df892998b80cf57b",
+
+ "f99bba3e3b14c8de38c8edecd9c983aa641320a251130f45596a00d2cfeefe7933f1a2c105c78627d782fd07a60001c06a286d14ec706dcdd8a232a613e1ea684ee7ef54dc903ec1c09c2c060bb0549a659fd47ae9e8b9cb3680b7c1c2d11ebf720209c06879d8f51d9ee1afafe263807c01bb9def83db879a89f7eb85c681c6c6cc58cc52893d0b131186cc3b9e16bad7d48c46a74abb492d475beb04c9fdc573cc454242c8534bcc7c822356ea558f9fa3ae3bb844415916",
+ "5109746cb7a61482e6e28de02db1a4a5",
+
+ "564da8460dc0c3d20b1fda3628349a399ba52446b5d3626fd0039ab282bc437b166f186b3c5e6c58ffb6bd95f8fe8b73c1b56a07ad37572eb6e148cfb7750760dcc03fac567ad7d3536d80922dda8ac4e118fc29c47ee3677183ea4e06242b6090864591c3ddaf4bef8c4cb52f8e3f35e4140034616faf21e831a9b8d68f5a841a0a52a2eb4f9ac9bb5b488766e251cdb0f29faeeed463640333ad948e7f3ad362948c68379740539f219d8f3ba069952efa0021d273a738aad0",
+ "f43552da8b2623a130196e70a770230d",
+
+ "8a54e8bf30eeb2e098955f2eef10af3c0a32391656fdff82120e4785bb35a629c8635e7e98c9eadfa93ed6760ae1d40313000dd85339b528cadfe28258a09e9976643a462477e6d022eb7f6a6338a8fdbf261c28e8ed43869f9a032f28b4d881fb202720bc42cf3b6d650211e35d53b4766a0f0dfd60d121fa05519211bb7d69bf5fcb124870cda8f17406747097fcb0a1968e907adb888341ea75b6fcfbb4d92ae8ce27b04a07a016df3399f330cb77a67040b847a68f33de0f16",
+ "c51c6e34cef091a05dfcf30d45b21536",
+
+ "2a64753a74d768b82c5638a0b24ef0da181bc7d6e2c4ffdb0ae50d9c48ecfa0d90880974db5f9ac32a004e25c8186cd7d0e88439f0f652256c03e47f663eff0d5cb7c089f2167ff5f28df82f910badc5f4b3860af28cbb6a1c7af3fafa6dae5398d8e0a14165def78be77ee6948f7a4d8a64167271ed0352203082368de1cd874bd3b2e351b28170fdf42871590d9d179ce27c99f481f287820fd95ba60124517e907e78a9662e09519e3ef868ebdcca311700a603b04fae4afe4090",
+ "2d2ee67938422ae12f8cfa8b2e744577",
+
+ "a7d645b70f27f01617e76abc2ae514164f18d6fd4f3464e71a7fc05a67e101a79b3b52d4ecfa3ddac6ec2a116d5222e8e536d9d90fffec9c1442679b06db8aa7c53dcde92006211b3dd779f83b6289f015c4cd21ca16ce83bb3ea162540bb012ee82bddef4722341454f5f59da3cd098a96abbbdc9a19202d61c7697979afa50deb22a9bb067ccb4a6fce51c930a7f4767cfaa9454c9c1832f83ee2318b0f0c95d761c079c0ca2dc28871229aef11f64199ca290b2b5e26d8c1c12ec1f",
+ "ec989e0290fc737952de37dd1ebc01c6",
+
+ "3436fe321f2a41478164b8b408a7a8f54ff2a79cb2020bf36118a2e3b3fca414bd42e55624cc4f402f909016209b10f0c55626194a098bb6519d0fa844a68ab3eaa116df39797b1e6c51eb30557df0c4f3d1a2e0471f1d8264fb3288c6c15dcde4daf795083aad2b5f2d31c84c542fb702ea83b7524ca9a1c1b9754ade5604abd375f23f3916cdad31aecaa7b028b7121a2a316713991759925f3fb8366c6795defa6ea77416c4ed095c1f9527026f1d621815b8310d4ff3fc76f798760b",
+ "bb5e48212442ad7ae83697092024c22b",
+
+ "01bdb4f89f84b728a9d6b3a03f60709900571c1a2a0f912702cad73677ceeae202babde3d0197e3e23381cb9f6350792e05937703aa76f9a84b5c36705bb58f6b2ea6b1e51ff94a8de174cbc2ec5ae9ad2627a8b3ea45f162b727a7639f71a4cd9f6c6926a5d81d0a21c4c923037ed199f1aef517e2eea03bea9044c5baab84e3f85d625635bcb1c37ef232144b44c770f2b9dab416b96c906016acfb3fbba62ab40a4c08323fcf66437d953b164541cea3a8c81d186eed0cb23b3e98813a9",
+ "8bb7ffa4572616f3bc7c33bd70bbcd59",
+
+ "9ae51ed483306c9a5a6db027f03cd4472cf3a71df5f1e11852306123d01ab81c259eeb88128275858efb8cff207ba5278dca3a21b358cbfdb5d223e958f3dca5ad9d2537f128c3dfb1fa564d3157de120f7b7d5524e67fc7abf897d9a5bd6b2c7c0a5348e6c95e920c919778ec7a86effb2ff91f0f44045c7dca46597e216e98d80efe25ba0d4f84e7e9d5e81689a5a6990d34e83e1a62a67371b7d2adc7ecd30ad1ad35359e9d9f8a299b057a2f441e313eb819770fa18cd41572adf856edc4",
+ "e7f66f49f70d506a9b5508cc50f65cf2",
+
+ "899c81ea1162514ea7a2d3487d0efcc4648a3067f891131918d59cc19a266b4f3c955c00ddd95cddedf27b86220c432d6ca548e52cf2011da17fd667a2177a7f93e37b8892d51898f1485277e9e046a48cb8b999fcbcf550db53d40602421a3f76cd070a971e2d869beb80a53b54ac30ac0aab0cd1b696bbaf99bb25216ff199cd9a280f567c44b0d4252c98812e1ddab4e445c414aa8d650598b64d6768a7948093051e36b7051c823c7ed6213743a98d8eaf4b2b5e8157c699ea053cf4e53877",
+ "52173b139c76a744b7a4d2221d4178c4",
+
+ "e50422869373abac1c26e738fb3ccb577b65975a7998ba096b04ef3aa148ada2cbe6beeabcf52d056d1766c245ab999d97445fdb6d59a0d6843eb4959752c89fe07b8411ddcfebef509482b8896bb43de7c875b29da52606b278b8704c62154b2da9bb237e68aa10cb85814250e4e4de73da200991e51241fd9a45f446de5a4bb959ad4727283510e9d2ac8a207ef0284163aa05d27f2d316e8ca1480f30604a8d74a0a661775398af644bb584a1a2c55c4959d0e7dd3f7c0c3614962fbeefeeafe0",
+ "f4c517a82c850c3c4c96d23a8f3106b8",
+
+ "066febbe205ea342cde69fd4c72889442e14a5977d886252bdbc2ff5f8dd8fc5f1f870ce121ab929a6b6227b484648be9b3501443cfdecf8f58d4de834ed1800bb244c18985a8232583ac6fc789aa59d1c5e87ad03994085bbf6e1ba1157d4e4ccbb28a49b6529e54b3b34613d6cc9671855e2dcbba6838176c093737962eaf88c85ab780184d4cae78013b28103dca7f7e3b8d94a6ae0728db30a1c535783c4644a7e9eb4ffac6a95d30cf52ba805e220d0b2aa9a2e7de26a97efbd877ec6d1bad148",
+ "bac7162dc8328911fa639f26ba952ab0",
+
+ "ccf92b17b9cf0d8577c1f3db9c19d3c86f16bab4058611f6aa97204783ebd07671eab55e375c4b16e03780675bb5738369aa7cf3b9156cd250f516392f5e0efa30cbb09132b66457756621f947093029e10233938c846513086023252d1bac9dd3442598f004e0b200f7dd79aa3a9122a0c6e77bc7fc8521988050f3c64b32c620fc1b5bba6f458e4791bdcfca731fd66e9da093b1a45264c8ffa48b3f1628dfe19c9ac1d71f1d5214ddc7e4f0da60ae122f67c394a55645628228d5e3a3174fdccbaab4",
+ "19a9eadf9c7c000fe340603f27bd830b",
+
+ "a37dcfab50a317e6a7cc51524b5d611a53652b59fc7df0229af3dac4d527d54c1134a14b2ed325d9727d07d9c3d0797f1a34561034be6de98b551dc384132235eaedae7a9b97bb7581a2a0f2c4e8e32f3e294f9b30f646dd33ce58187188146e14f01dc3ffb581c3bc834726b66c4732a98c3f8256ed22077ba8b34c024d53fe798517abc2f61eca0c6722fc02254c9141a54d4e106aaa6d4b2957e6a12c88ed00f4c4bc4c223b92579859fc0edb9b53f0bba286c53786198c9b6c6eb5eb5b4490844b7d06",
+ "b9e1455d06233d14b8d3020441351a76",
+
+ "0248b909e1f31ee855a03b6c81366757aa3732d2eca0b06a2b1015584c2d8205a4431fcdb02f6a03077ccf368ecb78b3eb78664b3c7ac157088b6cf9758adda4bc1d2cdedb9a69448a2833cf6f21865795bbd5551be859ed297aa82c288b898e331c07c3c8fcc4b2c4ec90bf8e003a499248a677f1b020357625f079cdf92fcbef89d904e11d23569e0f0e8c52303c93c867023a269bc036d8d36d69ca9c7664daacc92a8dc42c3600dbd4c02278333d216011252271def835ce4783883c0760dbcc00bc33bb",
+ "ea4606777e21f27d4ae860b3c25283b7",
+
+ "ce283768aa91488c75c71ee80a4df9495377b6a9ae3351a5962aa8317f08818a0117cf6c391331866d3abc2beea2fa4a43cf32a08385ea2c03dbabe3319104a6c0a3d171061ebed5a23306a8618a81fb63d9dd4c79b42bfdd2a79e05d78290e653f4c6dfd75bf5625ddb85c82bad9444faba3e1558691c004bb50afe37822e320131361d7572e015e559c0f313b53e0d529dde64e74bc41eb52e77361a3ae5721483a795a80a87d684d63f92e347843eb1a8439fef032b3d5a396b154751bd8ed211a3ae37cbf0",
+ "dca4d5f9f9b7f8011f4c2f547ce42847",
+
+ "19265f48c1ea240990847dc15d8198785d55ea6243ef7012ac903beabbdc2bd60032fb3a9f397d28aebb27d7deb7cf505eb1b36bfc4dbcfa8e1c044490b695b50e0974d3c5f0de748508d12ed9bfce10eaadde8fa128d3c30c12d0d403f60baf0b53d2fd7a38cc55dc1182b096c11d1ec9f171b879a73bd6ef1aa7825bc5162cbeba1d9f0739d1337c8142445ce645e4c32477cdcdf37e99fedb9236e24a3d94f0e45ea0b41a74762efe19d27555cdc89feef5b6e533237603fe98d8deae084f69799deac9043e86",
+ "688e532e15bde53b0b652291edfb7681",
+
+ "1080391fa810c50c7437ec058459d3a8cd23c33071c187474151151c809871b6eaf4cf88f592f84557e1eef5c847d3490912072b25b1919af724c0b5ecb111150bd95460328a0b1ba29613c0bd6486110fe6dfab8cca5fde18f5b0bc4d2dc970781511d2e45fc7385c3da18eeb18b3a9e68593d82c75bbbcadab2e5a29745f6f3a924e039579f4418dbee186d9cc24b896d96bd990186bdcbd3082b70aee9bb95a36531ecc405ae13d011bd10fe69fe728c8aed73d1d38e5506bf4fa770347f7e0eb6749121cc0be75",
+ "cbf8ee5d477630dac9457a9a0659497d",
+
+ "0a13ad2c7a239b4ba73ea6592ae84ea9",
+ "5feaf99c15f48851943ff9baa6e5055d8377f0dd347aa4dbece51ad3a6d9ce0c01aee9fe2260b80a4673a909b532adcdd1e421c32d6460535b5fe392a58d2634979a5a104d6c470aa3306c400b061db91c463b2848297bca2bc26d1864ba49d7ff949ebca50fbf79a5e63716dc82b600bd52ca7437ed774d169f6bf02e46487956fba2230f34cd2a0485484d",
+
+ NULL
+};
+
+/*
+ * Known-answer test vectors for SHAKE256, from the NIST validation test
+ * suite. Each vector is a pair (input,output).
+ */
+static const char *const KAT_SHAKE256[] = {
+ "389fe2a4eecdab928818c1aa6f14fabd41b8ff1a246247b05b1b4672171ce1008f922683529f3ad8dca192f268b66679068063b7ed25a1b5129ad4a1fa22c673cc1105d1aad6d82f4138783a9fe07d77451897277ed27e6fefec2cb56eb2494d18a5e7559d7b6fdddf66db4cbc9926fe270901327e70c8241798b4761dd652d49ad434d8d4",
+ "50717d9da0d528c3da799a3307ec74fc086a7d45acfb157774ac28e01ecc74f7",
+
+ "719effd45ed3a8394bf6c49b43f35879176a598601bd6f598867f966a38f512d21dc51b1488c162cbdc00301a41a09f2078a26937c652cfe02b8c4c92ddbb23583495ba825ae845eb2425c5b6856bda48c2cafae0c0c2e1764942d94be50da2b5d8b24a23b647a37f124d691d8cefbf76ef8fbc0fbdafb0a74a53aaf9f165075784ab485d4d4",
+ "6881babbb48e9eea72eeb3524db56e4efc323f3350b6be3cdb1f9c6826e359da",
+
+ "362f1eb00b37a9613b1ae82b90452579d42f8b1f9ede95f86badc6cdf04c9b79af08be4bc94d7cac136979026b92a2d44d2b642ea1431b47d75fce61367919f171486a007cc271d19de0d1c4c6a11c7a2251fe3aee0bb8938a7dd043d0eb0758a4768c95cc9f6f1703075839487879b47c29c10b2c3e5326ac8f363c65aa4ef76f1b8bd363eb60",
+ "c6ce60c1852ea780ed845aac4ca6a30e09f5c0064c9675865178717cfeb1dc97",
+
+ "d8f12b97f81d47aebbfb7314ff04172cf2be71c3778e238bcccdeecb691fbd542b00e5b7b1a0abb507f107f781fea700ea7e375fdea9e029754a0ea62216774bda3c59e8783d022360fe9625621c0d93e27f7bc03632942150716f019d048a752ccc0f93139c55df0f4aaa066a0550cf22e8c54e47d0475ba56b9842a392ffbc6bd98f1e4b64abd1",
+ "e2e1c432dd07c2ee89a78f31211c92eeb5306c4fa4db93c4e5cd43080d6079e4",
+
+ "a10d05d7e51e75dc150f640ec4722837220b86df2a3580ca1c826ec22ea250977e8663634cc4f212663e6f22e3ffc2a81465e194b885a1356fcbcc0072e1738d80d285e21c70a1f4f5f3296ba6e298a69f3715ff63be4850f5be6cb68cdba5948e3b94dbbce82989aa75b97073e55139aac849a894a71c2294a2776ce6588fb59007b8d796f434da6e",
+ "02f17bf86dc7b7f9c3fb96e4b3a10ca574cd0f8dedda50f3dda8008ce9e8fec9",
+
+ "152009657b680243c03af091d05cce6d1e0c3220a1f178ae1c521daba386694f5bab51cd819b9be1ae1c43a859571eb59d8cbd613c039462e5465ba0b28db544f57a10113406ccf772bc9fe5b02538e0b483225209c1eca447ab870e955befae6bf30dd89d92ddae9580ccf0dfac6415ec592a9a0f14c79acce9679f52d65fb8468012cbc225152d9ed2",
+ "b341f4114eee547eddeb2e7363b11d1e31d5e1eb5c18ea702b9d96b404938bad",
+
+ "eaf4249b5347c2395104a96d39fbf5322c9af2f8ec6a8c45efdc06a2b246efb5502952ab53b52ed9ca8f25a29cd1789b1b5333eddc29a5fbc76c13456a3eae8c9208c1381d062ff60a061da5d26cec73fb7a6a43eace4953f92cd01bc97ed078da19da095842afd938f1f83f84d53703f397fec2bd635f94ada5a3eb78103ebf4de503e8ad7295cb7dd91e",
+ "d14c7422c0832687786f1722f69c81fbe25b5889886bf85c7c7271bf7575517b",
+
+ "a03e55ee76150a6498634099ae418184228320bc838dbfe8276913761516ec9021226f4b597ba622a0823ca499618169c79eb44af2f182d1cc53caefd458a3ed7bbea0a5854653f2b3c20f659f70f23ae786238a8d0e59c29ef49d53125e50abf43b6f65c31f16bc174e43468717dddfcb63f5e21e8d4ba0e674140a97cffab1d5c165f1d9aef968154c60ad",
+ "fa889888d3b984c1577fe7c38ca86f0df859291502fe0b2f6e82c778babff377",
+
+ "2fb4178a0af42b155a739e2910b004e0781c1bca697ca479bf8e71430aefc043883cc7a151779013d2ad07a47cd652b5bdfd604130a1c565115ac51ff3c0ae56b5886c1ab2f0572e385e4fc33c430b874b46aedec49f9b6f45c08be3633bdde99ee02d7e9325276b74cc9d0fb6bfd85e093f2c2a8d3dcfa24308ec18c229f2072b8b32545ee0a9d46e3f1a0f53",
+ "254a115343d0ebd865e5d3ff6c61c3f9b65fe96ea92865a5681b1f1f0d1b00e9",
+
+ "dd344dd531f415a590a9c1838f242af8605bc0c29c1a71283ff5cd8af581683c94c48095e9e9e042b73804e0fd467ecb78699930696f3b6a9890108b99a0e4384e8a51bbadf99b53c358d8cef9fd545a97a13399861458f35a2e86309009c546136d086f058c0c7fbdf083750cb17250c5ebd8247c6f906c8db978a26123d30dec58ecdb7a0afd6face84efcbdca",
+ "2d56bef53fde76ef9849f97be2ed22d3c3d10f23b049eca2a8aba0d1fec33119",
+
+ "353111e447fee6f0bd05d562f30626ab9fb06384a620c49034a5eb3c0bc6d1eb1b86015053e6041ab8ac1cd7b4633512b0a318bfe592e2da6eabb44aa2bead0ba238158c2ea5db56bd7342efccf9d7fe76b8a6af45e0ad594816915f65749054f1d1b7627e4355ecf4e3af72e4d0f5b51877751c6f110f57e86ce942fcef640c31d94e98ecc959238683cb28a3f178",
+ "11b27034db724b46882a3086815a835947d19322885e08595be271c511ef783d",
+
+ "c4e5a5afa1c7d2edd5a21db8b4891ed53c926131f82c69d323b3f410114281fecbc9102bfa5f298e06d91fbd7e9b9661bbae43e7c013f3796557cf2db568de7c94a7cbf5a53ee9326ab4740cadbf1a0b1f59b92040156b977eb4c047a1f34a0c66a85f776a0d1ac34a5ca30b099cb0bbb2ba4c453edbd815b7f14fc69e8cce968bf453171374c428eef8342459db6359",
+ "f1ebe75725c26b82ffb59c5a577edaa2f24e49c9070cb9ca007e65938f33dae4",
+
+ "3b79da982ac5f2a0646374472826361c9d2d2e481414db678e67e0967e5cf3cdd0c1f570293362207191ecd78fb063347350d8135a4f02614d1de12feb70a0046939c078d7d673fea589460265290334d217d6231274ae0d3891e6f50da725f710c983d9bb16ede20833caef34f9dec3c36a6f9fc4eaa71256ac3a136b6a494dcc5985ba5e5c9773a377c0c78387bc8a4d",
+ "1fc7c4802141e2db7a9199c747d885a72d8f068262863843c9f4cbb19db38994",
+
+ "cf9552db2edd8947fd7fbbb2f7189a578343e742891ae6fb85fa0f64da8706e468f0cdc5607539db5726a2679aeddf3ac2ce711e886eff71dad203132e6ac283164e814414c7f686b011fd02c95f8c262920e9725c811a22c1339e0de16e5acd0036d620f2dda98e30c9324c2b778961e0c0b507ad5b205463a448199c9bb60b4f303420a1be3b3cfed5ab0d693cbe331036",
+ "b51adb0c2375c9d302ba61859040fa4bfa0091275eec1053fc13950aae706c25",
+
+ "4ebc9225da5f168c07ef62f621d742cd7c71bbd063269f5e51d65ef164791fe90e070f8b0e96f9499ec21843ee52290fd219c3b5b719ebfedcefe4efbf6b4490d57e4df27d59796f37d35734110b96fd634f5f20bc3de9cd1c28479464be84270ae7f16211f0be8839e8c8d0734ab22097dd371859d9be527a4b2fe83bba0637170ba6e3b1a2ef1c0cca121ffa57a4ffd78af2",
+ "54a3fd90ae00dfc77644ca16b4964c3b32a4641c5305704ee25d9f8fdbfb5c7f",
+
+ "a83f74dcbb48d679db402433020e33dacfa2c37f1e39b2d9dcdc70e81a2ab3d75f586c274376f90a39f49c0dad642cfa4f810afdae7157050847646d60cc6adcd27f7c6a24dab9049dd7c6111ab37c555ef2dd16aaa34d7e8de5ff41feaaad80a8bb8cec85fd7f2eaef28a8772828ab3a5fc24143a58fc0c15bf27ab1a4de28a8a1584f68f65b151154cd1b6dc5ac0dccba7c73d",
+ "5d084841c35b1cd9c43082746960ff5bb2d3de78f9bfdd80dc9ca4f5eae2a66d",
+
+ "734f872c431ab145706b7517e496a3be98bca885fca0105a99b54980f47caa84b60cb3720bf29748483cf7abd0d1f1d9380459dfa968460c86e5d1a54f0b19dac6a78bf9509460e29dd466bb8bdf04e5483b782eb74d6448166f897add43d295e946942ad9a814fab95b4aaede6ae4c8108c8edaeff971f58f7cf96566c9dc9b6812586b70d5bc78e2f829ec8e179a6cd81d224b16",
+ "14ec5a3c2ad919aa0f0492f206710347e742e7a58d6fdfd4b2c93dc2183b7b6f",
+
+ "10112498600da6e925d54d3e8cb0cdc90d0488b243d404b9fb879d1c8beb77bb6579b77aebdbf3e785abe61df17e69e8db219f29ae226f7ca9923719350abef876ec6b3920ebb5c28ccedb2a0b70d5d67a0c8a6116b74341922e60a867d24aa96cf1a89ca647d6c361c5922e7f91f9db114db322249c6a50dde28093c94c01166e11d66c26f73c322d1875f0f8e6bd41c86d803480d8",
+ "c9a88a3f221a857cc994a858f7cb4567979ada7834a265278e55de04c1fe496a",
+
+ "6969a27ad5d0aae6479b2b044bb4b043642375ff503ccb538e17be2f1e41f6aa88b1db991ffefd6087cfb20875920192b671be8b7381f7e1b33d8ff5213429f110fe475cbc74b3ecd2211f9b33f308fcf536e0d0abc36bd5e7756adefddd7728093730ec339c97313179b9e40e3f8e2a2a5c21f5836bf0d632a7961239a6a7f77b44dc700cdd70d8abbfc90c8dde5bc45dcaca2380df4e",
+ "bcdec7a8776380df27a4613cb50b7221995d3f752fa55691798ac2dfa0b15599",
+
+ "163cf8e89b260a81a3d6e4787587a304b35eab8b84faebcef14c626290a9e15f601d135cf503bc9ad5d23e7f213a6146787053f618c6ee90467e3a8df1e03387928acc375608339f7fa45788077fa82f87e11d3c58ce7cf3f8dad6aeaf3e508b722a2a62075df9fa6af4377c707ffe27aa5a11468c3b1c5fce073dae13eac2d1c9a635c5502b96115e69e741a262ee96a78336fcfc34573c",
+ "181d10fa5a58ca57077be52eda53910135087312ca7711084e4a5213c81cb4a2",
+
+ "3a023141ab4db8b08c5cb6792ad97abdf0116d512ea8f4141a8b987f1527657d2fd98f7deca55cc6492a3d0bfad53e40f656a1ac3550c63eb8554f24cb11819a87c5ec009af84e304b69b50eb847e46162a4f8e1ec284b902002994e332461a84ab08ef23cad57959aff64a9ed9632c73ee5b818dc964bb2597cbf25d6c9cf508081be7a5b2e3f9e3fd69305202af11a92002a7b8b038d4c6b",
+ "b75b698857675f8aff2b482ac437925af3ea86198484cbc87b60e6dacb13e7e8",
+
+ "2fd7ed70c6946b11c819775fd45bc0924c02e131ab6d4a3618f67e6d3b77801d4f0d87ea781bf9fa57929757dc70f5945c872eb4e480d547cc1f2fd68fc99f81da4361e7e2bc7b46fb0ef1e3674139ad6b50ee1da830c960a90fccb8b9dac020f701e22fac7eda3edb14eccd1ad47223a1e68a35a1860cc9d74dbfdb60b2cc40cfd072897d6afc2a202cf0dc9f338a3f25d068c4758987ca7d61",
+ "85c9275ec610ffbcd7f785c0ad24b7700b32ee352e6720f1ea2305bdb7f45277",
+
+ "cecb838187223873bab25205a54dadb1ab5a633958cbef3aa04f930467c8f7a947ff12548d964ddc843fe699f72c9377f1c76948c7a2fb5f58b1c65a94b7cd3f3bfe80cbe74be2064d11eb1bc0e52b67f732b1d00f2e2b58d30c4ff13c7479943430958d9f283f199c9029320860bdaa450404773955c74e99c9f47367e642cfb9fd1843bd14ac3cfa246887d885916763a62ae54c011668304e7e",
+ "3a5dd05e009e7f985a2668885dd0ea30c5502a1b5c575db6a4c1149c2e6229c1",
+
+ "283dfdb2e1dc081e3c2b377ba5bc6491cc4af08c40fbfa5e3fe2d45fcdc8b736032cb5fdaa88f0a008d60a86fa53dc7443836bae2475175f2d48163a52ee216241306d87f3f2dd5281b976043a6a135af2555ab39c71ee741ce9e6ac56d87ff48b510d9ae5a338fe50db643b8c8a710a80c8a5e4d278e667b4ce2dfb010f37b588987e7ca822676a1d44bd7419395e4e96e43489eb1167ff9efed170",
+ "5643c4252210fd45a2a67cd0a97d37e80d1b4a3c2fc86b0c3a3b4d3c1723b9ec",
+
+ "f32d2e50e8d5df7ce59a9d60255a19f48bffe790e3b1e0ba6b4bc53d920b257bff8d8003d5faac66367d784706f690b2f1f3a0afafdcbc16866d00a41169734f418d31d7a1c3ca9ede99e5b986f1294710fa5d011d5fcd13fdbef02b755b49cfbf168bf3d39a00cbe5d82bde2fb4ad5cf0fd65b1b5a3db5ad724dff745486da2830ed480f3e61795542094dd88a5e3989ae501e5ff10ae921c89133309",
+ "1ead94e30440b647d4cb4d7b3ed6b87ac07e8d72b3e5f28352bf14a78232ff1d",
+
+ "8bbc18eab6bcd9a3d6b90ec56d3be949e02a8866d69c7808e1ec787e600c7f72a41c001f513b6cbe079df94142dda2447f956e41a12df60392f0215d2d65331b5cdc06397d4796530b4bc45d7a975394627537b4e09e0f6c3a53f00fc1a9648cfc25b2a00288604a28ecf780dc100620d1f169295d9acb2b1f3c6afce4811aadcb1e8dbca8a8d18ba7a81a1132f1c2d014318e07dec7332889d4198c5e95",
+ "429f15c653f92734bfe4d1749e84da8c28861b70c5158bf59809ece810221774",
+
+ "a3d0eecfeff88df1cdd1e86df7bd2ec3ba60bcedfc9c42ef7dc021b05dfc1808df19201a6c6694e4dbf69514ef08ad1d21c7b28ba034ee9397607cefaedef5e9d3784db53a21f703a22b50d5dbba3a8e8579074c1a8b9a782fc5c89cf61a047408563c476110fe77acd9df58c2ba1d3e6dde83da718b8dc6cd57cd5e3e988dd2051cb679ea1af16881690b44acf09e54615eeedaad1b11a4f97e53de8d40d8",
+ "afccfd3b18f6d292d2e125884b721b3e3099c4dac8aef05ab0fba26799043d02",
+
+ "2ecb657808b29574b020545fb7f94071406047ef4de20c003cf08cbd91930187f55b079d7f99fded33cdae2bc8623021af990d4650c4a19197b4c38faf74a8b40d3803efb1907180a8e1150ed6167ff4f293d3ddd26a2790e9d22c0d0ed511d87e48a4952500bbd51943d230687df5941334e1dc5a3e66a43a320f5c351c059c517531b76352a1938ddb2db806ff5aa619667e6c71a7257693bcb4a7acb34ca8",
+ "c994acd17e08e8efd3ba83915245781e3727bac445672c44e6335e4f7deaf90b",
+
+ "e649888592d192c5fb59f10560f5f5a7b0ac21739c35dd80f1fe6b5825731c572f7cc4549c476b84e049459aea7fe533fbfaad72b79a89e77d1addb6f44cbbf5e6a65a5552fec305bc92ced3c84b4d95074387c71184e875d413f65c2b2d874cb3d031d0da7d0311383d72f823e296937d8f97bad17a62f29ef1a091f39be8233c01330d5c4c9170fc501b5022ca29f605e6c59220055f2585bcc29e742046432c",
+ "88a9aa4b4ffac981d1ef0e8b233cb309695f89211cd4e94d50760909e3cb919c",
+
+ "816b0bffd99b0f7821e6093ef152723a9cb45f7a082ef8d6bdf72cd33b5aa3c79102f43e2b74199decdd20057d0e227ae4c57945582e2e9653a9b16eeacecdbc5aaedac7e35c35cbd9adede7f83bbf36f8b0453d61416a85a17821885b3757d203fa2560a85c4b4c10dddaac0ae230b700fd2929cc6f94e9ccebe4e9399d284eb46b3ed2227b4366baf54d1b5c0a5d4225358fd240c0940bff8b62592a092a7b978b",
+ "c593f3d663c48426ce892f22584d49a3335cce3456194b7b5ee4814fab477fcb",
+
+ "a10918880cf31a8551af80bcb0d1a6ed71ca42c71e533967ef0fb71c866b7e6ddcca7e5d7cdfa6edef59fbe377c6e7ca00b1d33a530ef8598dd971a2cff995e5386a858f109b012c4615802a1d5e7fe0221d19cf617ed827d8d8cb8d2c8ed81b9b3354a832f1d14a402b371a0a611737c0543b0eb06b82d8ba56eb6304f1ef16ef6b143049a7bf50c4e2493aa69756d8c39f627fa89d9d741a99f9afbfeb81de1a5bec",
+ "d557aed03eb7c4c4c8091efdee992c9ad7f8d2e79e9296b40a08acae37868d48",
+
+ "de7ba70e45c879ad6c90ada6fda071c2b692840f7893eeca9b69ef8285b4357b7b735151b6cb6cddba04365ce3d520ce41e1cb9da681c07ffcc4619ddcb420f55ddbeefd2a06f689d8498cee7643606865a3f8b96aeb5d1301751438f4b34fe02dba655bc80280776d6795a4dd749a56cae1f3abec5a2d4e5183ee9bf5382c0492199eb3b946707022673bc641f0346119a3a4bb555698f895f6d90e06cc1e2835ff814d",
+ "06cfdd9cd7ce04abcdbf3121a9ba379505dbbb52f148c9d28ad9b50facf573ab",
+
+ "6e9a5752ff8ae7c385b088e651ef2543daae1624562052f787c9e0f5d83e8f01a82ce7d3e69b5f55de74d14d52412a3dcd356687346cbcd59e7315b8650bc3907e2a70ab054354b11cc7ac3ff6ec67d22fad22e75f125660eeb1d02a2a75621d969ed92385092e9de8b20102657742c9a91f328afe9a8a60208af9914c03d4719b8f0a838e7656e2ea3cb8dfc66a25ece2927eb93a8dbf9cdb077936f63e82543306ea1347",
+ "cb1e8082bb94629f162f20d815bcf3b212007bc049951a29ddb18a1f556bf3d1",
+
+ "b05007119789d382fa750d2087dde79b37a5459c24522b649ac976b07059cbdf99fcce56f6da94246e0f5ae241ae77dd99068f7863240acb5c99c4906f7d06403eb3b679ff6fcaa389f602d3aea5d7efcc35af149f3d523459f8a104f5498615c8fc2740594f5f4872b16ebb77c9ef19f7ba0b3881a6ede7b97175d2aac731a65e608975ac82395b52c805624423a7a3431e0daeb066c12ca389a9c338fef03a296644dea211",
+ "9021fefc1a020cd0c579e3dd67a66dacfabedde9cd36ddfc7d5c5c7c47be2721",
+
+ "a19909e14ddf9b3c470df6bb604604ad767c38c83b2b747937472b791173c3a10a733dffcae417295f2a71d183ab709a1d3be02a0bd61d811f95338967db44eeb2cf2a2f4f105ef618a418a5b031b831086f653328ddf43c2cb30b698c188638a196199a65cb374a7b61335c6f40a6193e01100a19a6c2536689fb4308935128e0ae5268937d6ccd8e4a0a21484000fbc7da29d8669b4e6dd5004a3c61b36c6676011dc0628ec3",
+ "7dcbf4dd9c27fd8340f51c553898502cec53d3bc83198352fc58465625c076a2",
+
+ "b0dffe4a5f64f612359397e4e070a8fa01296c1d8cee25177104d76a7c154e4279cb62a99d9d7afa21e84f983041f3df030a115b4b437638cfa3d0fa56e7b66fc76be9e18ff7da8f43db6c5f863efacd2eb39c27a20da6fc867572d29bb96017e0e71a5afe1b1dbbe29575a0ac0ec7aac84c95e85af5be4ae0a14458133252230d687e7cb1b04b65483df2c5685a62601aff85053ba2c509234fcff585fb967c96169bb0725f6d75",
+ "8e7023d18902a9184a0191f1c7a2b79030e833800baeeb33e2d0673500245dfa",
+
+ "dda3625c78f733c7df0b5f4987cd30d7207afa40ca07f3b686c0458aea2f62371a3f98a2f3a1e5a0896f0cb9d40fe82ca65b0132e0fe5d87e621992750483855e3763ae2bf98f0acd9201065acf105962c7b88e3fc277490e0f5d6447563440d209271a544a4fef4b86892d578392c1d9a23b8da8448e1d85d82276ac14a3166b9d96472ea8cb47e0c8dba929eb007cad89bb99fe22a4c674312b21f9cc4a56996943cd1191abc54bf",
+ "ad83957a387225aad811b0737f582dbe7eb616187a8ba8e09b00db5d0bee4a7b",
+
+ "5cd623be5b6bf6d1bcb414c826d0f4ce60793791b6d82dae9f9e9b699e50bba266e2850541882d80b2c9edfa59d504421818ff45740f37853e5b9bc67214af0a5f5fd5c00843cc39cbb8765b4001de99643c7923f738ac5922868f865dd3f1cb90759c597843d9e34daa3754a2fd89bd8c0d2e9106fa95149448ff11273587cb414a603759315f6881c6b94b46700d94d8b2a5f86bfdf99ddcc974cf98e47bf4ba09acc273b463afaf35",
+ "f754a71e3439760aec2d763751e160d05d3de0809dd4fd6aeef588da8b86a517",
+
+ "42c0a452e83840ae858c094c044961d5f2195ddb34a21cd1f5ab575be3803ac99b9872dd617688d515cd6da562e756853947c9ab7e8ef85a019b4f1baff6494b0a6f87d5d602234115fe42ee3667e89b8a98112cf72cfdabf01fcb8ea4314938768b0bc2aea5bafa6e67aface78fc021cc525ae60746d1ceac7ff33a2bf8e398c935252a5127f5090650dd69dd28861ee9becf6017a21ccb1b03f0a9aa15bf74eab5fd9727507b75c701f3",
+ "d5980482d666dde4f2c3a99b45e523fd6410be999a96ba8c5df397c950605e70",
+
+ "fece673103322483b85340e991e478c2c15e2d795a98adb5b697b4cf17a733898aaa4ffd11b1add300c9edb7a818740a33286fd8cf82140b0f7f2bde8d5bce94d58b6d697e5015c99a8df1c051d611b2c8c96a4c48a11eba9c08fe1aba2d4d31a617c75d9439e2cb4d4654ead346d52048ea26bb0c1c522a26db346de54639cac6f668c299919f43e09c1f1f78914abd7b32ac0f641c39c3749fd5be55cd1ac6fed1557ed683d1981c395946",
+ "17f4b2f60cb364da5e8a62db58e07eb1c44b888c433adc1e62461879cd271463",
+
+ "a542b2bdf8e04ec2a004cccd2f89e7bfd17ace1ad285c91360ac20e9913e3976a806000494c28b61b9d7ff36f342ad94d8d281d03e949d91fe8f4127f7b2ee1e550bcb13133a47c7be2400727cece45a4e1f95a3922e1269cc22950ca58bb7cb34b9da957d2fc81b3755982ad36dd238b9c8d33dd53a72c452cbe341a5afdca5ce79f730da8b5886add18f06feafbf57a33700430fa003c919f3f56dff08a5d3aab1e88c33353d30a700adad07",
+ "50cf700b5b6c802e20da4c1f9b75bd0a6632678212bd0e2418201f3a10389994",
+
+ "8fa67f49db80f22bc267a70e5636dfbc8a21c83d9691fe4b9c3051068b3fc9e94430e7fdfb712e4ce086e299ff5a104e65d7ceb685b4c46cda8eeb14cd3b9548d85baed5ec2f412810af3d034cd67a75c541f70829f8663c4d8cea3415621fb0954e5b3b756333a69a0a41b402522517f087ca9b4a06eba23f4fd5d02c5c6e07c132769660b50dadc5c07515ec751a1d2fd2cfd8b0855b85f602344fdbd28a37a52e874e73ccd627dbf9628cd1e8",
+ "3379265620eb781d6b59e331cc525e60e8c063e19f96cfabb2fda9aa83cdeba5",
+
+ "23ae9cd31da25c0187c0247be19e089872742d772f73d0efde5889c97b40d12ddbbec35b8f2b1f9c0b3d947708db3f2726306f4dd6ffabe37736f671bfc551835db0825adc6314e2cb479fe41b92497dc8638dcfbc0e3bf6f0b4c03dd418a892f1ad6138ccf442bc0e04cb2ae36a2f80a0340f63a849891190fc719781e0de44dedde95d2783b1121e9fa3b1280cf81af5cc7e7363579c1da03390e68fc5fc806e67a132b5bb6acd413eace2b120ac",
+ "a17a00ac106c0af50c4f449d3cdcc2cdbb9848d2d85a36ff434099162e25606c",
+
+ "3bfa57a5f9f60203059defd501977628908ee42116e4674dc0a52a32c5bac02aeb60c6714cd9c47c5a61558c21648884ccee85f76b637486f3709a698641c54bf5f5eb5b844f0ea0edae628ca73fb2d567710080e8a96c3fe83857fc738ac7b6639f0d8c28bfa617c56a60fd1b8fbdc36afe9ce3151e161fa5e3a71411fb8e123d48762bc093558aea7f950706bb72f8dc7ca3497a2b3ccf345ad3d9eafde10889d76c61d432e3a165d34ad0ee2d9619",
+ "1a2cfebf3483c33a5eba84121737d892cf8bd6c3ba324fd4ae4c2db42872e54f",
+
+ "e9b9525afd5634cf8d16df4ae7e12e8ae206c6ed6e7d4dd96f6fd75accf7a10cc22b023c7f569e4aec88dd51ca519c0a00c922ee33d3559b98a32d79067e6a9d50c182eed125de864841455be751991ea635c163ddbde6031223e2be0fd9f5253885bab81c4b5a4b4a4a00ae66698d8c7c538c9493c068d786f7dc710f90ac6c257f93e1884e7c609aaaf5927021e01d292a6bc87e6643e09b2505da2d2cf639bdb6f3b33cb8ab8fdf690b512d02fa9956",
+ "3ff47b4bf4f908aace95b0468a54b7e6644fe07df69ae327c0ff2e45325b97b9",
+
+ "13ec10c6b27a6ce6fdd5e2314e8626a28a69f313ec62f29b044cde1aff32e61228c252b9affe6a4ca93593a55932bc10aeb3f85b0c1d6c2c506d6c970e72e1f01c3aeede55cad3b1971111f60e1fcf48b5937c691952b691617f6a058ba73decf83b2b5e2b446ebfce52a24bf5b526f1a7f0c5659b6b96713f68208cfe38c2adc3af5361b9d5051c56de8fcc975d8bb48db41c7818cfd574f312d652f08f38dc857dac0e88e55e70379f20a37b7dc4396ec6",
+ "9703a69f279ef15b843b355f86b3f7098a46eafcad625920d93e0e3fb136fc5f",
+
+ "3d8263a177af8c5beabc76a4388e0816ab1bf1f5856e985791f15688feebe4ac6d480fa64999b339575be66d8e7c7435281b8c4ef990b86a00ac128e3c41b6b9c0e573c60af4c69391d408639d7de6815b38122731a6389d4f0534a587af82175ee3f5c963c8acb1bfaf434e0e9946436df9eb46d4bb0038a7842295873c300f6ecaff76fb1e4fdb0a75fef588d87cc486e67f738bd4f8832fb24526e5f0a8e91920f8967bfd96599aada321b4437049cc8836",
+ "e82d636a61c7657029699374a2da3dfabfae366e7708c7e4ba2dacd8b786a36f",
+
+ "01f793fa05548645f644a64ee1b5ff7fd38eaa233f874cd59f3ddf385e86b5e9f601b9b256f2f901864d61988d11c98593d7335543ab4d85731a3e39078c9e3012d5c6f83f064b5e7089c529a46dd5081efe66c8c49932cac5be88b57e674d689f98423389388446fb1f5969ee7029eebd29cbe489f8038edc5148148cbdca77e375b3cafc2fada07038a5c133c3cf21b881eb125c71c6b801fa03bdf9371b472792a3276094ce5417fb32973a0dcf87572d4db8",
+ "98bf0fd777137c94300ab5b1bff7b3f487a03a788e6bb96c715ba6f10ba1922b",
+
+ "71a986d2f662bf36dcbadbba0657f4e2797b569610e2d82271ee6d813f01f6db922a5a4ca405d9e7cddc9dfbb1129294b8c27845bea337250c2f721887045e50288ad513acd6a6be8dce300a308e2f8e600bd585fbf61dd2ebe45c4158ab18101c0f1eae789ecfc205d8bb6fed9371d65a9e94dd2fa5322ff75452851abfcc2357025ea56e24fbfb1d4266b34ee900768fc3dfd6c2761f4716c97d6a36092192c0abbc81f832d372be535b5dbd578576e6c2dbf61d",
+ "27255d504a38296857b8d382dc8ad4f1ca03ef3a8d1983e54bc01ef97b04e581",
+
+ "69ee06f5f53f74c76674751f8fa80efb42f43e71132ae0fc5ec6d2148c21570191e8baf0b9cd3547a57c103690d10d8ed84804d7b9b5cb9d5b35580a0f642abad5d0e5ca23ae3c32e1cc1355b8c7e5d78c7e64af47c6607dd960ea1d7d28b97c3d8ecdaab84a5131234cc6a68ef25e7d687ea62146c76845e02fd0745cd4cdf0d00bbab9020a3eec72e4714e9abb4029743012573d1fac9c798a513937d22ebd962df61f8854ca0ad67c5b7864885282b77df076b436",
+ "600b41954a9398ee66ea0e603c8c80d936fbc8be98c74f44ae13b0aa4b50b8d5",
+
+ "2a74e9800ce49aac07af3df2e451f245d4ffa5304c318574135eb7f39a064bcc8bf66fc8a4c8e2f5c6a9ac90495f0d28938ab301e9292fb78461aa23e87ad482712b1ed42f172983f4977e45aaba7f43ea8a9e7bcb91cc63f89c34cf06bf2a1404995e6e53d9569fb8011bd9af6b32de0289cd669b7043c19698bebd9bdd33ca6bca985cb81751913a70eb14ff790c41030eaa8a00cf7c1987dcaeb650ddd9eccf46326707d902a1a36c56be43ecf7b414a29caea3b55f",
+ "4e549f206099a8b3183fa3b86af220b1b6554ac3d8d52c54d093e68f60597256",
+
+ "5b2e2f2fd3ecc733a6198d34e5d143c176b60c3cc3dac6deafdf99fbce5cd088d583e8da4f01e7b09226f074f24613be345f691a46fb610b2d5855503ec761659152744db3a1a78f9b1fce7fdf584dbe28a52e04e40c701d3a62a13243b2af4a77e3fb106594afd7a84b52db16cf99ca3ad2808305d39a1dc043a52b45e7623e6f7da4accfa2a690a0f3a112fd739ee9522d891e111a8812a6448bc2ac2c234a616997a8579335c36d5fe6acfe0b052358fd715d70a7e104",
+ "24a3de94be98126ce95cfd3140754230b6880c71cfe4ec215c3f451bdc8bb690",
+
+ "013944b7958b6b3686b14bdb042f2f5b42768edc20fdd6a90894692b15f6e5157b9da9de23da95749524102f1bb150032343d6fbe64537e247162243fea59f95f53e95aff2a38f82775fbf06e7574475e9a2a8b8119aad1ebe3349543e8cef9239c410124c0fe2c6f409604aae4a92185c3a0efbeb26bfc63394e5451ed45d740dd823ef774615aad3caf9e2b9b1c25344b40facba11f5406fe1fefee6a571a33a22d42ebc6fb094de4c94b650b55c9068b7b3b3c783d7f53a",
+ "009661924d01ad811d4c598580eb954362b8554c5e9cd13686acbe41ac8c3940",
+
+ "72c2880163482bbe822cf72ff0e02be7081d271b366fd94c0cf37926925f76a9de44b086e590e7cc915773c314d336187ba9d03b866d1106b769b49fa99a4a9fa3fc74746d085504627a4792c757cde65b2fcaa82f9ff00eb81b7ab723ea1ed6e8723d92a2b65ead1e1dda64b275d897d0377c2ada0d5cab38913435a958da94d62f74a92da4e810ecc994017c344074014a50892fbe3e265f5448e2e2eb662295ba7f81b5dadc76f504dd31ce9debc517efad8cd5ba7fc754eb",
+ "77cf32d62a3d0622cd90f7c858ce1ae3bda60f9edc9cf50f7ecc9d7253d8d18d",
+
+ "c6dad2ff2cba3ed8873955178068b5704cbccf1e8c62eed472d275f726a7670a68ae2d6a763d943b30c616a27aab5a34e254feaf838093e828d8e905b5ca8decc39491fc8b9f8bfa050fe04e5198436f5593789ca8515ecdaeaf2ce905eafb3920b5851d32892cfd4e3d3e83ccd67707eea0c74bc47e56694c7ec609deb0b8d7c739913535a37e2c5377b5a9b40efee6f5a472269eae83a54a6d3dcf08c4ccb000473dac5a9489705be6cf28d1e7e1f2b2c60293008aee6aefa61b",
+ "8708b77ac39005607b179857c037f64860540e80ed7c7a4240e09ae62c88f87e",
+
+ "02553a2117e654ac28d948a6f67a83daf2089a95ff6631ff78131baa755cc36c4ad0ca6a51f5f176ea393a9bbf2b4af54deb12c6a0dfaec75da88dbc0655d34b7ad6fb0ebbb3c1e7f4fe3f94bb865683934d4fe7b53cc20b1016b7e68eab0cf1994e1735de888ba8500ea0b970f16e2acc159a1ec6e435739743e15194c53603af1f640640dd19600653a53368d55c92012b3b935c3fcfa6fc195325a00d192cc5332baa6b1831b81cb3952a2b9be6643a777a70feb5584d477f5489",
+ "376b551c1e8f908d7e1979efa436ab69013d2e85c34430dc826179b4f94480ae",
+
+ "9945c4f0e067b943986b6841b8fd21109e91d2f2549c711a11039abf03d37a6e4b34eba44a98e09c1b38046660c19e39424ab80ab38a805df648ee5c6212a72663322269c1de093325afe205d955ee2acf885146e5417432672ba807d5540c79e729b067cfa1faafbeb84947a91fd98a4d32e7cf712a15406b940feae5026f10e100dec5fb497cbaee3b83545a892701c530c0cddfac2a300a6b6c2a19829992589ff4accd3e57f9be20d65374f99f393e6a2467b82e7da94c9807f2fa",
+ "a4ab2e8f96b69097d84596b628e7bb76f460c001043ce5fa6e379fd29d1eabba",
+
+ "a4d7897eaf5c49979b361c39a67f47e26c2f75e5ffe0645539d4de245138eb8cadaa45aef7fa0c7a732dbbce90c85be2bd4bf6e37dfb4fdebee4d0e0671fc45c3051c6ccb674799bcfda7a431a6e93b3db3e32f30636190a9a2e5620302876e0d4d2f6201353fac4554341df6efb591c6f100f5dc21a2aa176ba592bd7db69e14237bbf2371df6bbb072f9ecb1f714e621c97768d82eea6bf98ebf4a82c005262188ff894a5dd549866f88b00ee82bd99872515d71fac230ccb472c55a60",
+ "9510ff5231813a865918badd0011f05915364165492ef17b85929a63e4951589",
+
+ "22813ee9edc5c2a90d8b3f07b48d9534e60f08312dc296d68fe78719bdb7478d8d037129aa182c4b8ae5bafca1604e76d5251ee43160ba68ddee9c624ebf00f0ba7ff6b1cf75b5cfa4ab323cf04ff13b7a591b23d06ed25f3c04c1baf4c8f7da913cf509c2a5053c4224ce4d0723268cbdf2277672b285c493731ea81799d353fa8497baed70c59a4c99b7b950a39470863a69667ff67c9ec981ddb41ffb3d63dd9d034bb79d9df1a95214083199e4efbd770a7a5f005ef5c877236674b6dd",
+ "44f8a8b05fc643566f1f53a93a122f7902d2cab68bb02267c0479339371a7304",
+
+ "eebfa2629596f61a926c4cd472ecb03eb2ecaf7f7650b12f7d2b8aa755284b7ccb295e46a62dd2a69577f38765ed1ea377bed34972470c5e3538cda310f2fd353334745a66f7557afb969e6c0132fdf4bb55e68951d5e25bc4fc2a9427e574de0d290d263ebc28a0ae11760caf85f63765fa0fc47ac2dc2c14c0c70404c9597f415050339443f2209430a2eed5acb1765df5768457d6a1db0ccbcc7a0e66531eb6f16608d1555c00973b4a9add70d5b88b8e44504fd9da709367627fad840bc5",
+ "9949d3ac3c05b4a08b85fa371811fd3f0b50c71950fef50acbb59c450ab1c587",
+
+ "ddf38f51b732aea3fdf1fe4c756d17961262163d737f407fad17e9724a19959a92425cbb099193ec38fca8edb0614eba4dbfda60b8a6ed102fec547289a22c3b74464a02023ada50647545f6f57959a37a85a4b5a70b2050e66416ad55c33cb50d6820cfaa16caf608c69d0e4a9d7f78211c3ae44b97216659e8f6cdb6640b30e50ea8c90a0bad06ac5678deb9b50962caec6494a930377b11debd77b46de2d382a2a8992902c9aad88d9e0d49a93f88fe5dec6dcbbfacb794b0335558c609c66e",
+ "954473b4965a57c4cbb20e199b8730487eb621f5fd694a1eb1667940da0d6728",
+
+ "184e1b9ccec71f837dca25838db073d51cacc26246fda091a468135d12e67faab69ac9d93e05bd9a687dad01c8db5bddc6751a45e64c2f734c867dd67f1e62626ddadc2baf7df0320f3e4c7e477a2b6f0ca679504b87372bb3a522e173fd8f7945f69ab9ab967ff378f6482293f3a936f82728abff188060e1ae48a778ebd09846d64cacb9b83487ad8bea1433b09ed791e06f7f8a65d2bbdf8a384f1550eb677962392b624bd593b6e77a7daf17d1fddfb995f472d8f5e4b41f3a02d394a98de583",
+ "0a7506e1b6cc43acdb4f2ec456e069e6e4b7608deb70dbe7ccb88578658be9da",
+
+ "c436d19f05550b6979bdc69bfd27ea4cd80c1a60f00a8b093e89178c7f9e8d492c304cf6ad59102bca0e0b23620338c15fc9ecd1e939ae91da16486f72ee1e154d41bfa391e6ba3b6ca9b3c3be39b5e61242ca5cd3d6c96cbd1170af91fdb2160db3522e1bc3b1a349d6e50479920ac5d9bedd8a16a787a3cdc2b6d24392f25555cc2f20b2ba9e6b47ddc96cfbd6df669d874ce21a758d3cf4704362ef7786d90ed67b01bd91299950058885accddbcf44e340ed4807864218653ee7ff7215aa1e1761",
+ "206be726fc681367387ff0a15303533058070f9655438ad8142cf39a0523b2ce",
+
+ "daf7c7526cdb85127df59220fbcb67dc5069ef58dc069a18a2e4ad164178dc0927cb1ae70120b0a975d78c4e1491dc228a95dc401873ec5645e7e6a8d0ffae58e8800be49f87b5f09d6caf4611ebd61bee86bb945325ae884a001b88b6be1a1c87de41503057bc6f5b7ba00fdb217d4de203335a746506371bf8f4bcddfd45df6bad65339bd9efaf18ce0ab1587bf842cfd6ec9c637b1cea1f96184e2b045a28fcb51e96c85574373d2b9335724170821ec58f6108af1929bea430458a1a7f80a2be1580",
+ "742389244ad26d7a16d1f2b01e9c83e987a283bbf3aa2907a556746fe8c98c38",
+
+ "597dadb776945e01c564f17eed4b5c1bbb34eebb13bce37d2d93363efe24b660f3785cc9e557dc2e4ab17a91a83d1f085060acc148508e43897993f66a20fbe65d46d3c4d9cf7e2e97e3952f0195f10ae8c20533753c719f6228d53d69a5e3c5fdafb9b039426d8716c2e961e09af9a8eb24a21b82c9b6192069a51ce3fc96843d7ab696edf9d0c42d151f2e2d95606ac14c2a80563c82392b02ab9abe6e3bab8471747ddc3cd06a46a6de9fd0ce4dd8d202466bdbe00088ebbb8ebfe341fbc2395a986df0",
+ "892985bdf2379f8ae138aac016894ee23408955d627cfa699fa5fa1439340a91",
+
+ "0efc14917a94f5320eb734c2b9e45f659d06c9f5c454deff0e76b30f6ee9e22e56a494a870fcdf138fc5538ce5bacf44761f993ccca4ae4ced8d576a8a10fd2979fe3e8066a641cdc5f746190ae4819e1d0d2886089bcbf6f36be44b5370afa45e523ba0c25bc169969436f1912b1c7b7a189d5edf00da050a5a813b31d09da5ede8b390ede30aeeece64a9ae05749e4758a2149b99d868219a056c18cf972370e07cdd95006c264ae33ab9e6130afdff6a9dbd1fe38747408868c65ccb4d45fa9f9b102528c",
+ "73088e0551c89477bcb675245c5c6347b4230390285832c7d723bf668c8061fb",
+
+ "9ac34ec974d28b18b7bcf6982eac60ebc670b0674e2acd697b49bfeb2fb81159fa5579a1e2a5bb8a5fc6ca46aaa5304a3771b15d804f2bef054fc1ad919e3852befea1c0bb74394f4d408d651412e247107bd32e64a23c9e593857f3a5ae253deea5104d8aa6ce108913881cf55d3c89587860027f8cc81b7eeec9e5f44e9fc190320c71d4a3427519250394d4ed07b9174f9e005b7696117c575fad05e76d86ae8cde5423d25d25076046f4392a0a7e56e8d6517fc66f265c5d617060e258354f9dce1dfe9de6",
+ "17cba68f47a0615b3513d28a44feda6ad36b6e6eb1ead7232f4e2a4e1a64bf50",
+
+ "d00df64c4bb9e2fd16fb6f9ca746d6cf162015ec7326e41a5d51e9b3d0792fed3f17d5bae34f03ec522e229d53304dcef105024ece941edeba410892846b2c7a1039ab82aa9750979a7bc70bf96d093bc3461b6f2d38f801380eccc286b562996cfce06d4a98b245176bc4ae4006f45eb36cc71636185acdfe429c0a7d5fbb927be7dc43685a0f40f185824ed102f57eeafe6d0d943e2d883564e233126f1eac648207ccafe651ce4f5169b35369f3e48f84771aedb2577b04fd0506ecef72305055cacfc4435e38",
+ "67302648e0082254d8d342b4eb8070ef9a44e0fc55c3d9a3f20613e4824aff21",
+
+ "fff5deb2bc7f43bd2db44ceff874e9c3b7c1a2f54cc6889f74186ca2a03d5047006b1b26e0919147379c81887df3403ebe43571fed8279607a2eb81a26d6f8f217dca3f927799ed182017c127069f2eb6f068b0d85979dc4d4867c676f6bedf36cd2def33b3e54a3366ea45478dee612f391a785bd0ede15aba921512103199228d434dbc1e899047a6861183e5b04fb716c11503dee2399261d10a0e5a76317736b0d7b6480573e76791b246ae734ee12203336ac3f539a6e6cb01c625eb3c9741dd199ca0d759753",
+ "bf64c9ab7042245fb2d8054edd699086dbe27a1ce904174d28bc0831ed9acf97",
+
+ "8d8001e2c096f1b88e7c9224a086efd4797fbf74a8033a2d422a2b6b8f6747e4",
+ "2e975f6a8a14f0704d51b13667d8195c219f71e6345696c49fa4b9d08e9225d3d39393425152c97e71dd24601c11abcfa0f12f53c680bd3ae757b8134a9c10d429615869217fdd5885c4db174985703a6d6de94a667eac3023443a8337ae1bc601b76d7d38ec3c34463105f0d3949d78e562a039e4469548b609395de5a4fd43c46ca9fd6ee29ada5efc07d84d553249450dab4a49c483ded250c9338f85cd937ae66bb436f3b4026e859fda1ca571432f3bfc09e7c03ca4d183b741111ca0483d0edabc03feb23b17ee48e844ba2408d9dcfd0139d2e8c7310125aee801c61ab7900d1efc47c078281766f361c5e6111346235e1dc38325666c",
+
+ NULL
+};
+
+static void
+test_SHAKE_KAT(int security_level, const char *const *kat)
+{
+ size_t u;
+
+ for (u = 0; kat[u] != NULL; u += 2) {
+ unsigned char msg[250], out[250], ref[250];
+ size_t msg_len, out_len, v;
+ br_shake_context sc;
+
+ msg_len = hextobin(msg, kat[u]);
+ out_len = hextobin(ref, kat[u + 1]);
+ br_shake_init(&sc, security_level);
+ br_shake_inject(&sc, msg, msg_len);
+ br_shake_flip(&sc);
+ br_shake_produce(&sc, out, out_len);
+ check_equals("KAT 1", out, ref, out_len);
+
+ br_shake_init(&sc, security_level);
+ for (v = 0; v < msg_len; v ++) {
+ br_shake_inject(&sc, msg + v, 1);
+ }
+ br_shake_flip(&sc);
+ br_shake_produce(&sc, out, out_len);
+ check_equals("KAT 2", out, ref, out_len);
+
+ br_shake_init(&sc, security_level);
+ br_shake_inject(&sc, msg, msg_len);
+ br_shake_flip(&sc);
+ for (v = 0; v < out_len; v ++) {
+ unsigned char x;
+
+ br_shake_produce(&sc, &x, 1);
+ if (x != ref[v]) {
+ fprintf(stderr, "KAT 3 (byte %u)\n",
+ (unsigned)v);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+}
+
+static void
+test_SHAKE_MonteCarlo(int security_level,
+ size_t minoutlen, size_t maxoutlen, const char *smsg, const char *sref)
+{
+ unsigned char out[250], ref[250];
+ size_t len, rlen, outlen, range;
+ int i, j;
+
+ hextobin(out, smsg);
+ outlen = maxoutlen;
+ range = maxoutlen - minoutlen + 1;
+ for (j = 0; j < 100; j ++) {
+ for (i = 1; i < 1001; i ++) {
+ br_shake_context sc;
+
+ len = outlen;
+ br_shake_init(&sc, security_level);
+ br_shake_inject(&sc, out, 16);
+ br_shake_flip(&sc);
+ br_shake_produce(&sc, out, len);
+ if (len < 16) {
+ memset(out + len, 0, 16 - len);
+ }
+ outlen = minoutlen
+ + (br_dec16be(out + len - 2) % range);
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ rlen = hextobin(ref, sref);
+ if (rlen != len) {
+ fprintf(stderr, "MC: bad length (%u vs %u)\n",
+ (unsigned)len, (unsigned)rlen);
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT MC", out, ref, len);
+}
+
+static void
+test_SHAKE(void)
+{
+ printf("Test SHAKE: ");
+ fflush(stdout);
+
+ test_SHAKE_KAT(128, KAT_SHAKE128);
+
+ printf(" ");
+ fflush(stdout);
+
+ test_SHAKE_MonteCarlo(128, 16, 140,
+ "c8b310cb97efa3855434998fa81c7674",
+ "4aa371f0099b04a909f9b1680e8b52a21c6510ea2640137d501ffa114bf84717b1f725d64bae4ae5d87a");
+
+ printf(" ");
+ fflush(stdout);
+
+ test_SHAKE_KAT(256, KAT_SHAKE256);
+
+ printf(" ");
+ fflush(stdout);
+
+ test_SHAKE_MonteCarlo(256, 2, 250,
+ "48a0321b3653e4e86446d00f6a036efd",
+ "d4c8c26ded38cca426d8d1c8f8aedb5c543541333839deca8713cfd8684480fe923f57c3a5c89cb61427c220c7");
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_HMAC_DRBG(void)
+{
+ br_hmac_drbg_context ctx;
+ unsigned char seed[42], tmp[30];
+ unsigned char ref1[30], ref2[30], ref3[30];
+ size_t seed_len;
+
+ printf("Test HMAC_DRBG: ");
+ fflush(stdout);
+
+ seed_len = hextobin(seed,
+ "009A4D6792295A7F730FC3F2B49CBC0F62E862272F"
+ "01795EDF0D54DB760F156D0DAC04C0322B3A204224");
+ hextobin(ref1,
+ "9305A46DE7FF8EB107194DEBD3FD48AA"
+ "20D5E7656CBE0EA69D2A8D4E7C67");
+ hextobin(ref2,
+ "C70C78608A3B5BE9289BE90EF6E81A9E"
+ "2C1516D5751D2F75F50033E45F73");
+ hextobin(ref3,
+ "475E80E992140567FCC3A50DAB90FE84"
+ "BCD7BB03638E9C4656A06F37F650");
+ br_hmac_drbg_init(&ctx, &br_sha256_vtable, seed, seed_len);
+ br_hmac_drbg_generate(&ctx, tmp, sizeof tmp);
+ check_equals("KAT HMAC_DRBG 1", tmp, ref1, sizeof tmp);
+ br_hmac_drbg_generate(&ctx, tmp, sizeof tmp);
+ check_equals("KAT HMAC_DRBG 2", tmp, ref2, sizeof tmp);
+ br_hmac_drbg_generate(&ctx, tmp, sizeof tmp);
+ check_equals("KAT HMAC_DRBG 3", tmp, ref3, sizeof tmp);
+
+ memset(&ctx, 0, sizeof ctx);
+ br_hmac_drbg_vtable.init(&ctx.vtable,
+ &br_sha256_vtable, seed, seed_len);
+ ctx.vtable->generate(&ctx.vtable, tmp, sizeof tmp);
+ check_equals("KAT HMAC_DRBG 4", tmp, ref1, sizeof tmp);
+ ctx.vtable->generate(&ctx.vtable, tmp, sizeof tmp);
+ check_equals("KAT HMAC_DRBG 5", tmp, ref2, sizeof tmp);
+ ctx.vtable->generate(&ctx.vtable, tmp, sizeof tmp);
+ check_equals("KAT HMAC_DRBG 6", tmp, ref3, sizeof tmp);
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_AESCTR_DRBG(void)
+{
+ br_aesctr_drbg_context ctx;
+ const br_block_ctr_class *ictr;
+ unsigned char tmp1[64], tmp2[64];
+
+ printf("Test AESCTR_DRBG: ");
+ fflush(stdout);
+
+ ictr = br_aes_x86ni_ctr_get_vtable();
+ if (ictr == NULL) {
+ ictr = br_aes_pwr8_ctr_get_vtable();
+ if (ictr == NULL) {
+#if BR_64
+ ictr = &br_aes_ct64_ctr_vtable;
+#else
+ ictr = &br_aes_ct_ctr_vtable;
+#endif
+ }
+ }
+ br_aesctr_drbg_init(&ctx, ictr, NULL, 0);
+ ctx.vtable->generate(&ctx.vtable, tmp1, sizeof tmp1);
+ ctx.vtable->update(&ctx.vtable, "new seed", 8);
+ ctx.vtable->generate(&ctx.vtable, tmp2, sizeof tmp2);
+
+ if (memcmp(tmp1, tmp2, sizeof tmp1) == 0) {
+ fprintf(stderr, "AESCTR_DRBG failure\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+do_KAT_PRF(br_tls_prf_impl prf,
+ const char *ssecret, const char *label, const char *sseed,
+ const char *sref)
+{
+ unsigned char secret[100], seed[100], ref[500], out[500];
+ size_t secret_len, seed_len, ref_len;
+ br_tls_prf_seed_chunk chunks[2];
+
+ secret_len = hextobin(secret, ssecret);
+ seed_len = hextobin(seed, sseed);
+ ref_len = hextobin(ref, sref);
+
+ chunks[0].data = seed;
+ chunks[0].len = seed_len;
+ prf(out, ref_len, secret, secret_len, label, 1, chunks);
+ check_equals("TLS PRF KAT 1", out, ref, ref_len);
+
+ chunks[0].data = seed;
+ chunks[0].len = seed_len;
+ chunks[1].data = NULL;
+ chunks[1].len = 0;
+ prf(out, ref_len, secret, secret_len, label, 2, chunks);
+ check_equals("TLS PRF KAT 2", out, ref, ref_len);
+
+ chunks[0].data = NULL;
+ chunks[0].len = 0;
+ chunks[1].data = seed;
+ chunks[1].len = seed_len;
+ prf(out, ref_len, secret, secret_len, label, 2, chunks);
+ check_equals("TLS PRF KAT 3", out, ref, ref_len);
+
+ chunks[0].data = seed;
+ chunks[0].len = seed_len >> 1;
+ chunks[1].data = seed + chunks[0].len;
+ chunks[1].len = seed_len - chunks[0].len;
+ prf(out, ref_len, secret, secret_len, label, 2, chunks);
+ check_equals("TLS PRF KAT 4", out, ref, ref_len);
+}
+
+static void
+test_PRF(void)
+{
+ printf("Test TLS PRF: ");
+ fflush(stdout);
+
+ /*
+ * Test vector taken from an email that was on:
+ * http://www.imc.org/ietf-tls/mail-archive/msg01589.html
+ * but no longer exists there; a version archived in 2008
+ * can be found on http://www.archive.org/
+ */
+ do_KAT_PRF(&br_tls10_prf,
+ "abababababababababababababababababababababababababababababababababababababababababababababababab",
+ "PRF Testvector",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "d3d4d1e349b5d515044666d51de32bab258cb521b6b053463e354832fd976754443bcf9a296519bc289abcbc1187e4ebd31e602353776c408aafb74cbc85eff69255f9788faa184cbb957a9819d84a5d7eb006eb459d3ae8de9810454b8b2d8f1afbc655a8c9a013");
+
+ /*
+ * Test vectors are taken from:
+ * https://www.ietf.org/mail-archive/web/tls/current/msg03416.html
+ */
+ do_KAT_PRF(&br_tls12_sha256_prf,
+ "9bbe436ba940f017b17652849a71db35",
+ "test label",
+ "a0ba9f936cda311827a6f796ffd5198c",
+ "e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa022f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b66");
+ do_KAT_PRF(&br_tls12_sha384_prf,
+ "b80b733d6ceefcdc71566ea48e5567df",
+ "test label",
+ "cd665cf6a8447dd6ff8b27555edb7465",
+ "7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792eca722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e56f");
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+/*
+ * AES known-answer tests. Order: key, plaintext, ciphertext.
+ */
+static const char *const KAT_AES[] = {
+ /*
+ * From FIPS-197.
+ */
+ "000102030405060708090a0b0c0d0e0f",
+ "00112233445566778899aabbccddeeff",
+ "69c4e0d86a7b0430d8cdb78070b4c55a",
+
+ "000102030405060708090a0b0c0d0e0f1011121314151617",
+ "00112233445566778899aabbccddeeff",
+ "dda97ca4864cdfe06eaf70a0ec0d7191",
+
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
+ "00112233445566778899aabbccddeeff",
+ "8ea2b7ca516745bfeafc49904b496089",
+
+ /*
+ * From NIST validation suite (ECBVarTxt128.rsp).
+ */
+ "00000000000000000000000000000000",
+ "80000000000000000000000000000000",
+ "3ad78e726c1ec02b7ebfe92b23d9ec34",
+
+ "00000000000000000000000000000000",
+ "c0000000000000000000000000000000",
+ "aae5939c8efdf2f04e60b9fe7117b2c2",
+
+ "00000000000000000000000000000000",
+ "e0000000000000000000000000000000",
+ "f031d4d74f5dcbf39daaf8ca3af6e527",
+
+ "00000000000000000000000000000000",
+ "f0000000000000000000000000000000",
+ "96d9fd5cc4f07441727df0f33e401a36",
+
+ "00000000000000000000000000000000",
+ "f8000000000000000000000000000000",
+ "30ccdb044646d7e1f3ccea3dca08b8c0",
+
+ "00000000000000000000000000000000",
+ "fc000000000000000000000000000000",
+ "16ae4ce5042a67ee8e177b7c587ecc82",
+
+ "00000000000000000000000000000000",
+ "fe000000000000000000000000000000",
+ "b6da0bb11a23855d9c5cb1b4c6412e0a",
+
+ "00000000000000000000000000000000",
+ "ff000000000000000000000000000000",
+ "db4f1aa530967d6732ce4715eb0ee24b",
+
+ "00000000000000000000000000000000",
+ "ff800000000000000000000000000000",
+ "a81738252621dd180a34f3455b4baa2f",
+
+ "00000000000000000000000000000000",
+ "ffc00000000000000000000000000000",
+ "77e2b508db7fd89234caf7939ee5621a",
+
+ "00000000000000000000000000000000",
+ "ffe00000000000000000000000000000",
+ "b8499c251f8442ee13f0933b688fcd19",
+
+ "00000000000000000000000000000000",
+ "fff00000000000000000000000000000",
+ "965135f8a81f25c9d630b17502f68e53",
+
+ "00000000000000000000000000000000",
+ "fff80000000000000000000000000000",
+ "8b87145a01ad1c6cede995ea3670454f",
+
+ "00000000000000000000000000000000",
+ "fffc0000000000000000000000000000",
+ "8eae3b10a0c8ca6d1d3b0fa61e56b0b2",
+
+ "00000000000000000000000000000000",
+ "fffe0000000000000000000000000000",
+ "64b4d629810fda6bafdf08f3b0d8d2c5",
+
+ "00000000000000000000000000000000",
+ "ffff0000000000000000000000000000",
+ "d7e5dbd3324595f8fdc7d7c571da6c2a",
+
+ "00000000000000000000000000000000",
+ "ffff8000000000000000000000000000",
+ "f3f72375264e167fca9de2c1527d9606",
+
+ "00000000000000000000000000000000",
+ "ffffc000000000000000000000000000",
+ "8ee79dd4f401ff9b7ea945d86666c13b",
+
+ "00000000000000000000000000000000",
+ "ffffe000000000000000000000000000",
+ "dd35cea2799940b40db3f819cb94c08b",
+
+ "00000000000000000000000000000000",
+ "fffff000000000000000000000000000",
+ "6941cb6b3e08c2b7afa581ebdd607b87",
+
+ "00000000000000000000000000000000",
+ "fffff800000000000000000000000000",
+ "2c20f439f6bb097b29b8bd6d99aad799",
+
+ "00000000000000000000000000000000",
+ "fffffc00000000000000000000000000",
+ "625d01f058e565f77ae86378bd2c49b3",
+
+ "00000000000000000000000000000000",
+ "fffffe00000000000000000000000000",
+ "c0b5fd98190ef45fbb4301438d095950",
+
+ "00000000000000000000000000000000",
+ "ffffff00000000000000000000000000",
+ "13001ff5d99806efd25da34f56be854b",
+
+ "00000000000000000000000000000000",
+ "ffffff80000000000000000000000000",
+ "3b594c60f5c8277a5113677f94208d82",
+
+ "00000000000000000000000000000000",
+ "ffffffc0000000000000000000000000",
+ "e9c0fc1818e4aa46bd2e39d638f89e05",
+
+ "00000000000000000000000000000000",
+ "ffffffe0000000000000000000000000",
+ "f8023ee9c3fdc45a019b4e985c7e1a54",
+
+ "00000000000000000000000000000000",
+ "fffffff0000000000000000000000000",
+ "35f40182ab4662f3023baec1ee796b57",
+
+ "00000000000000000000000000000000",
+ "fffffff8000000000000000000000000",
+ "3aebbad7303649b4194a6945c6cc3694",
+
+ "00000000000000000000000000000000",
+ "fffffffc000000000000000000000000",
+ "a2124bea53ec2834279bed7f7eb0f938",
+
+ "00000000000000000000000000000000",
+ "fffffffe000000000000000000000000",
+ "b9fb4399fa4facc7309e14ec98360b0a",
+
+ "00000000000000000000000000000000",
+ "ffffffff000000000000000000000000",
+ "c26277437420c5d634f715aea81a9132",
+
+ "00000000000000000000000000000000",
+ "ffffffff800000000000000000000000",
+ "171a0e1b2dd424f0e089af2c4c10f32f",
+
+ "00000000000000000000000000000000",
+ "ffffffffc00000000000000000000000",
+ "7cadbe402d1b208fe735edce00aee7ce",
+
+ "00000000000000000000000000000000",
+ "ffffffffe00000000000000000000000",
+ "43b02ff929a1485af6f5c6d6558baa0f",
+
+ "00000000000000000000000000000000",
+ "fffffffff00000000000000000000000",
+ "092faacc9bf43508bf8fa8613ca75dea",
+
+ "00000000000000000000000000000000",
+ "fffffffff80000000000000000000000",
+ "cb2bf8280f3f9742c7ed513fe802629c",
+
+ "00000000000000000000000000000000",
+ "fffffffffc0000000000000000000000",
+ "215a41ee442fa992a6e323986ded3f68",
+
+ "00000000000000000000000000000000",
+ "fffffffffe0000000000000000000000",
+ "f21e99cf4f0f77cea836e11a2fe75fb1",
+
+ "00000000000000000000000000000000",
+ "ffffffffff0000000000000000000000",
+ "95e3a0ca9079e646331df8b4e70d2cd6",
+
+ "00000000000000000000000000000000",
+ "ffffffffff8000000000000000000000",
+ "4afe7f120ce7613f74fc12a01a828073",
+
+ "00000000000000000000000000000000",
+ "ffffffffffc000000000000000000000",
+ "827f000e75e2c8b9d479beed913fe678",
+
+ "00000000000000000000000000000000",
+ "ffffffffffe000000000000000000000",
+ "35830c8e7aaefe2d30310ef381cbf691",
+
+ "00000000000000000000000000000000",
+ "fffffffffff000000000000000000000",
+ "191aa0f2c8570144f38657ea4085ebe5",
+
+ "00000000000000000000000000000000",
+ "fffffffffff800000000000000000000",
+ "85062c2c909f15d9269b6c18ce99c4f0",
+
+ "00000000000000000000000000000000",
+ "fffffffffffc00000000000000000000",
+ "678034dc9e41b5a560ed239eeab1bc78",
+
+ "00000000000000000000000000000000",
+ "fffffffffffe00000000000000000000",
+ "c2f93a4ce5ab6d5d56f1b93cf19911c1",
+
+ "00000000000000000000000000000000",
+ "ffffffffffff00000000000000000000",
+ "1c3112bcb0c1dcc749d799743691bf82",
+
+ "00000000000000000000000000000000",
+ "ffffffffffff80000000000000000000",
+ "00c55bd75c7f9c881989d3ec1911c0d4",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffc0000000000000000000",
+ "ea2e6b5ef182b7dff3629abd6a12045f",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffe0000000000000000000",
+ "22322327e01780b17397f24087f8cc6f",
+
+ "00000000000000000000000000000000",
+ "fffffffffffff0000000000000000000",
+ "c9cacb5cd11692c373b2411768149ee7",
+
+ "00000000000000000000000000000000",
+ "fffffffffffff8000000000000000000",
+ "a18e3dbbca577860dab6b80da3139256",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffc000000000000000000",
+ "79b61c37bf328ecca8d743265a3d425c",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffe000000000000000000",
+ "d2d99c6bcc1f06fda8e27e8ae3f1ccc7",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffff000000000000000000",
+ "1bfd4b91c701fd6b61b7f997829d663b",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffff800000000000000000",
+ "11005d52f25f16bdc9545a876a63490a",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffc00000000000000000",
+ "3a4d354f02bb5a5e47d39666867f246a",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffe00000000000000000",
+ "d451b8d6e1e1a0ebb155fbbf6e7b7dc3",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffff00000000000000000",
+ "6898d4f42fa7ba6a10ac05e87b9f2080",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffff80000000000000000",
+ "b611295e739ca7d9b50f8e4c0e754a3f",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffc0000000000000000",
+ "7d33fc7d8abe3ca1936759f8f5deaf20",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffe0000000000000000",
+ "3b5e0f566dc96c298f0c12637539b25c",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffff0000000000000000",
+ "f807c3e7985fe0f5a50e2cdb25c5109e",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffff8000000000000000",
+ "41f992a856fb278b389a62f5d274d7e9",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffc000000000000000",
+ "10d3ed7a6fe15ab4d91acbc7d0767ab1",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffe000000000000000",
+ "21feecd45b2e675973ac33bf0c5424fc",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffff000000000000000",
+ "1480cb3955ba62d09eea668f7c708817",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffff800000000000000",
+ "66404033d6b72b609354d5496e7eb511",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffc00000000000000",
+ "1c317a220a7d700da2b1e075b00266e1",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffe00000000000000",
+ "ab3b89542233f1271bf8fd0c0f403545",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffff00000000000000",
+ "d93eae966fac46dca927d6b114fa3f9e",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffff80000000000000",
+ "1bdec521316503d9d5ee65df3ea94ddf",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffc0000000000000",
+ "eef456431dea8b4acf83bdae3717f75f",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffe0000000000000",
+ "06f2519a2fafaa596bfef5cfa15c21b9",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffff0000000000000",
+ "251a7eac7e2fe809e4aa8d0d7012531a",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffff8000000000000",
+ "3bffc16e4c49b268a20f8d96a60b4058",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffc000000000000",
+ "e886f9281999c5bb3b3e8862e2f7c988",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffe000000000000",
+ "563bf90d61beef39f48dd625fcef1361",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffff000000000000",
+ "4d37c850644563c69fd0acd9a049325b",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffff800000000000",
+ "b87c921b91829ef3b13ca541ee1130a6",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffc00000000000",
+ "2e65eb6b6ea383e109accce8326b0393",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffe00000000000",
+ "9ca547f7439edc3e255c0f4d49aa8990",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffff00000000000",
+ "a5e652614c9300f37816b1f9fd0c87f9",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffff80000000000",
+ "14954f0b4697776f44494fe458d814ed",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffc0000000000",
+ "7c8d9ab6c2761723fe42f8bb506cbcf7",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffe0000000000",
+ "db7e1932679fdd99742aab04aa0d5a80",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffff0000000000",
+ "4c6a1c83e568cd10f27c2d73ded19c28",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffff8000000000",
+ "90ecbe6177e674c98de412413f7ac915",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffc000000000",
+ "90684a2ac55fe1ec2b8ebd5622520b73",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffe000000000",
+ "7472f9a7988607ca79707795991035e6",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffff000000000",
+ "56aff089878bf3352f8df172a3ae47d8",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffff800000000",
+ "65c0526cbe40161b8019a2a3171abd23",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffc00000000",
+ "377be0be33b4e3e310b4aabda173f84f",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffe00000000",
+ "9402e9aa6f69de6504da8d20c4fcaa2f",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffff00000000",
+ "123c1f4af313ad8c2ce648b2e71fb6e1",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffff80000000",
+ "1ffc626d30203dcdb0019fb80f726cf4",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffc0000000",
+ "76da1fbe3a50728c50fd2e621b5ad885",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffe0000000",
+ "082eb8be35f442fb52668e16a591d1d6",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffff0000000",
+ "e656f9ecf5fe27ec3e4a73d00c282fb3",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffff8000000",
+ "2ca8209d63274cd9a29bb74bcd77683a",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffc000000",
+ "79bf5dce14bb7dd73a8e3611de7ce026",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffe000000",
+ "3c849939a5d29399f344c4a0eca8a576",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffff000000",
+ "ed3c0a94d59bece98835da7aa4f07ca2",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffff800000",
+ "63919ed4ce10196438b6ad09d99cd795",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffc00000",
+ "7678f3a833f19fea95f3c6029e2bc610",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffe00000",
+ "3aa426831067d36b92be7c5f81c13c56",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffff00000",
+ "9272e2d2cdd11050998c845077a30ea0",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffff80000",
+ "088c4b53f5ec0ff814c19adae7f6246c",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffc0000",
+ "4010a5e401fdf0a0354ddbcc0d012b17",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffe0000",
+ "a87a385736c0a6189bd6589bd8445a93",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffff0000",
+ "545f2b83d9616dccf60fa9830e9cd287",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffff8000",
+ "4b706f7f92406352394037a6d4f4688d",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffc000",
+ "b7972b3941c44b90afa7b264bfba7387",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffe000",
+ "6f45732cf10881546f0fd23896d2bb60",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffff000",
+ "2e3579ca15af27f64b3c955a5bfc30ba",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffff800",
+ "34a2c5a91ae2aec99b7d1b5fa6780447",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffc00",
+ "a4d6616bd04f87335b0e53351227a9ee",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffe00",
+ "7f692b03945867d16179a8cefc83ea3f",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffff00",
+ "3bd141ee84a0e6414a26e7a4f281f8a2",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffff80",
+ "d1788f572d98b2b16ec5d5f3922b99bc",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffc0",
+ "0833ff6f61d98a57b288e8c3586b85a6",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffe0",
+ "8568261797de176bf0b43becc6285afb",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffff0",
+ "f9b0fda0c4a898f5b9e6f661c4ce4d07",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffff8",
+ "8ade895913685c67c5269f8aae42983e",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffffc",
+ "39bde67d5c8ed8a8b1c37eb8fa9f5ac0",
+
+ "00000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffffe",
+ "5c005e72c1418c44f569f2ea33ba54f3",
+
+ "00000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffff",
+ "3f5b8cc9ea855a0afa7347d23e8d664e",
+
+ /*
+ * From NIST validation suite (ECBVarTxt192.rsp).
+ */
+ "000000000000000000000000000000000000000000000000",
+ "80000000000000000000000000000000",
+ "6cd02513e8d4dc986b4afe087a60bd0c",
+
+ "000000000000000000000000000000000000000000000000",
+ "c0000000000000000000000000000000",
+ "2ce1f8b7e30627c1c4519eada44bc436",
+
+ "000000000000000000000000000000000000000000000000",
+ "e0000000000000000000000000000000",
+ "9946b5f87af446f5796c1fee63a2da24",
+
+ "000000000000000000000000000000000000000000000000",
+ "f0000000000000000000000000000000",
+ "2a560364ce529efc21788779568d5555",
+
+ "000000000000000000000000000000000000000000000000",
+ "f8000000000000000000000000000000",
+ "35c1471837af446153bce55d5ba72a0a",
+
+ "000000000000000000000000000000000000000000000000",
+ "fc000000000000000000000000000000",
+ "ce60bc52386234f158f84341e534cd9e",
+
+ "000000000000000000000000000000000000000000000000",
+ "fe000000000000000000000000000000",
+ "8c7c27ff32bcf8dc2dc57c90c2903961",
+
+ "000000000000000000000000000000000000000000000000",
+ "ff000000000000000000000000000000",
+ "32bb6a7ec84499e166f936003d55a5bb",
+
+ "000000000000000000000000000000000000000000000000",
+ "ff800000000000000000000000000000",
+ "a5c772e5c62631ef660ee1d5877f6d1b",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffc00000000000000000000000000000",
+ "030d7e5b64f380a7e4ea5387b5cd7f49",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffe00000000000000000000000000000",
+ "0dc9a2610037009b698f11bb7e86c83e",
+
+ "000000000000000000000000000000000000000000000000",
+ "fff00000000000000000000000000000",
+ "0046612c766d1840c226364f1fa7ed72",
+
+ "000000000000000000000000000000000000000000000000",
+ "fff80000000000000000000000000000",
+ "4880c7e08f27befe78590743c05e698b",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffc0000000000000000000000000000",
+ "2520ce829a26577f0f4822c4ecc87401",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffe0000000000000000000000000000",
+ "8765e8acc169758319cb46dc7bcf3dca",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffff0000000000000000000000000000",
+ "e98f4ba4f073df4baa116d011dc24a28",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffff8000000000000000000000000000",
+ "f378f68c5dbf59e211b3a659a7317d94",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffc000000000000000000000000000",
+ "283d3b069d8eb9fb432d74b96ca762b4",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffe000000000000000000000000000",
+ "a7e1842e8a87861c221a500883245c51",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffff000000000000000000000000000",
+ "77aa270471881be070fb52c7067ce732",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffff800000000000000000000000000",
+ "01b0f476d484f43f1aeb6efa9361a8ac",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffc00000000000000000000000000",
+ "1c3a94f1c052c55c2d8359aff2163b4f",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffe00000000000000000000000000",
+ "e8a067b604d5373d8b0f2e05a03b341b",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffff00000000000000000000000000",
+ "a7876ec87f5a09bfea42c77da30fd50e",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffff80000000000000000000000000",
+ "0cf3e9d3a42be5b854ca65b13f35f48d",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffc0000000000000000000000000",
+ "6c62f6bbcab7c3e821c9290f08892dda",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffe0000000000000000000000000",
+ "7f5e05bd2068738196fee79ace7e3aec",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffff0000000000000000000000000",
+ "440e0d733255cda92fb46e842fe58054",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffff8000000000000000000000000",
+ "aa5d5b1c4ea1b7a22e5583ac2e9ed8a7",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffc000000000000000000000000",
+ "77e537e89e8491e8662aae3bc809421d",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffe000000000000000000000000",
+ "997dd3e9f1598bfa73f75973f7e93b76",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffff000000000000000000000000",
+ "1b38d4f7452afefcb7fc721244e4b72e",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffff800000000000000000000000",
+ "0be2b18252e774dda30cdda02c6906e3",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffc00000000000000000000000",
+ "d2695e59c20361d82652d7d58b6f11b2",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffe00000000000000000000000",
+ "902d88d13eae52089abd6143cfe394e9",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffff00000000000000000000000",
+ "d49bceb3b823fedd602c305345734bd2",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffff80000000000000000000000",
+ "707b1dbb0ffa40ef7d95def421233fae",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffc0000000000000000000000",
+ "7ca0c1d93356d9eb8aa952084d75f913",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffe0000000000000000000000",
+ "f2cbf9cb186e270dd7bdb0c28febc57d",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffff0000000000000000000000",
+ "c94337c37c4e790ab45780bd9c3674a0",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffff8000000000000000000000",
+ "8e3558c135252fb9c9f367ed609467a1",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffc000000000000000000000",
+ "1b72eeaee4899b443914e5b3a57fba92",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffe000000000000000000000",
+ "011865f91bc56868d051e52c9efd59b7",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffff000000000000000000000",
+ "e4771318ad7a63dd680f6e583b7747ea",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffff800000000000000000000",
+ "61e3d194088dc8d97e9e6db37457eac5",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffc00000000000000000000",
+ "36ff1ec9ccfbc349e5d356d063693ad6",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffe00000000000000000000",
+ "3cc9e9a9be8cc3f6fb2ea24088e9bb19",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffff00000000000000000000",
+ "1ee5ab003dc8722e74905d9a8fe3d350",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffff80000000000000000000",
+ "245339319584b0a412412869d6c2eada",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffc0000000000000000000",
+ "7bd496918115d14ed5380852716c8814",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffe0000000000000000000",
+ "273ab2f2b4a366a57d582a339313c8b1",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffff0000000000000000000",
+ "113365a9ffbe3b0ca61e98507554168b",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffff8000000000000000000",
+ "afa99c997ac478a0dea4119c9e45f8b1",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffc000000000000000000",
+ "9216309a7842430b83ffb98638011512",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffe000000000000000000",
+ "62abc792288258492a7cb45145f4b759",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffff000000000000000000",
+ "534923c169d504d7519c15d30e756c50",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffff800000000000000000",
+ "fa75e05bcdc7e00c273fa33f6ee441d2",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffc00000000000000000",
+ "7d350fa6057080f1086a56b17ec240db",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffe00000000000000000",
+ "f34e4a6324ea4a5c39a661c8fe5ada8f",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffff00000000000000000",
+ "0882a16f44088d42447a29ac090ec17e",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffff80000000000000000",
+ "3a3c15bfc11a9537c130687004e136ee",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffc0000000000000000",
+ "22c0a7678dc6d8cf5c8a6d5a9960767c",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffe0000000000000000",
+ "b46b09809d68b9a456432a79bdc2e38c",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffff0000000000000000",
+ "93baaffb35fbe739c17c6ac22eecf18f",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffff8000000000000000",
+ "c8aa80a7850675bc007c46df06b49868",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffc000000000000000",
+ "12c6f3877af421a918a84b775858021d",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffe000000000000000",
+ "33f123282c5d633924f7d5ba3f3cab11",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffff000000000000000",
+ "a8f161002733e93ca4527d22c1a0c5bb",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffff800000000000000",
+ "b72f70ebf3e3fda23f508eec76b42c02",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffc00000000000000",
+ "6a9d965e6274143f25afdcfc88ffd77c",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffe00000000000000",
+ "a0c74fd0b9361764ce91c5200b095357",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffff00000000000000",
+ "091d1fdc2bd2c346cd5046a8c6209146",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffff80000000000000",
+ "e2a37580116cfb71856254496ab0aca8",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffc0000000000000",
+ "e0b3a00785917c7efc9adba322813571",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffe0000000000000",
+ "733d41f4727b5ef0df4af4cf3cffa0cb",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffff0000000000000",
+ "a99ebb030260826f981ad3e64490aa4f",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffff8000000000000",
+ "73f34c7d3eae5e80082c1647524308ee",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffc000000000000",
+ "40ebd5ad082345b7a2097ccd3464da02",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffe000000000000",
+ "7cc4ae9a424b2cec90c97153c2457ec5",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffff000000000000",
+ "54d632d03aba0bd0f91877ebdd4d09cb",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffff800000000000",
+ "d3427be7e4d27cd54f5fe37b03cf0897",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffc00000000000",
+ "b2099795e88cc158fd75ea133d7e7fbe",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffe00000000000",
+ "a6cae46fb6fadfe7a2c302a34242817b",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffff00000000000",
+ "026a7024d6a902e0b3ffccbaa910cc3f",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffff80000000000",
+ "156f07767a85a4312321f63968338a01",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffc0000000000",
+ "15eec9ebf42b9ca76897d2cd6c5a12e2",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffe0000000000",
+ "db0d3a6fdcc13f915e2b302ceeb70fd8",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffff0000000000",
+ "71dbf37e87a2e34d15b20e8f10e48924",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffff8000000000",
+ "c745c451e96ff3c045e4367c833e3b54",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffc000000000",
+ "340da09c2dd11c3b679d08ccd27dd595",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffe000000000",
+ "8279f7c0c2a03ee660c6d392db025d18",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffff000000000",
+ "a4b2c7d8eba531ff47c5041a55fbd1ec",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffff800000000",
+ "74569a2ca5a7bd5131ce8dc7cbfbf72f",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffc00000000",
+ "3713da0c0219b63454035613b5a403dd",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffe00000000",
+ "8827551ddcc9df23fa72a3de4e9f0b07",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffff00000000",
+ "2e3febfd625bfcd0a2c06eb460da1732",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffff80000000",
+ "ee82e6ba488156f76496311da6941deb",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffc0000000",
+ "4770446f01d1f391256e85a1b30d89d3",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffe0000000",
+ "af04b68f104f21ef2afb4767cf74143c",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffff0000000",
+ "cf3579a9ba38c8e43653173e14f3a4c6",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffff8000000",
+ "b3bba904f4953e09b54800af2f62e7d4",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffc000000",
+ "fc4249656e14b29eb9c44829b4c59a46",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffe000000",
+ "9b31568febe81cfc2e65af1c86d1a308",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffff000000",
+ "9ca09c25f273a766db98a480ce8dfedc",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffff800000",
+ "b909925786f34c3c92d971883c9fbedf",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffc00000",
+ "82647f1332fe570a9d4d92b2ee771d3b",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffe00000",
+ "3604a7e80832b3a99954bca6f5b9f501",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffff00000",
+ "884607b128c5de3ab39a529a1ef51bef",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffff80000",
+ "670cfa093d1dbdb2317041404102435e",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffc0000",
+ "7a867195f3ce8769cbd336502fbb5130",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffe0000",
+ "52efcf64c72b2f7ca5b3c836b1078c15",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffff0000",
+ "4019250f6eefb2ac5ccbcae044e75c7e",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffff8000",
+ "022c4f6f5a017d292785627667ddef24",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffc000",
+ "e9c21078a2eb7e03250f71000fa9e3ed",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffe000",
+ "a13eaeeb9cd391da4e2b09490b3e7fad",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffff000",
+ "c958a171dca1d4ed53e1af1d380803a9",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffff800",
+ "21442e07a110667f2583eaeeee44dc8c",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffc00",
+ "59bbb353cf1dd867a6e33737af655e99",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffe00",
+ "43cd3b25375d0ce41087ff9fe2829639",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffff00",
+ "6b98b17e80d1118e3516bd768b285a84",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffff80",
+ "ae47ed3676ca0c08deea02d95b81db58",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffc0",
+ "34ec40dc20413795ed53628ea748720b",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffe0",
+ "4dc68163f8e9835473253542c8a65d46",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffff0",
+ "2aabb999f43693175af65c6c612c46fb",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffff8",
+ "e01f94499dac3547515c5b1d756f0f58",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffffc",
+ "9d12435a46480ce00ea349f71799df9a",
+
+ "000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffffe",
+ "cef41d16d266bdfe46938ad7884cc0cf",
+
+ "000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffff",
+ "b13db4da1f718bc6904797c82bcf2d32",
+
+ /*
+ * From NIST validation suite (ECBVarTxt256.rsp).
+ */
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "80000000000000000000000000000000",
+ "ddc6bf790c15760d8d9aeb6f9a75fd4e",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "c0000000000000000000000000000000",
+ "0a6bdc6d4c1e6280301fd8e97ddbe601",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "e0000000000000000000000000000000",
+ "9b80eefb7ebe2d2b16247aa0efc72f5d",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "f0000000000000000000000000000000",
+ "7f2c5ece07a98d8bee13c51177395ff7",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "f8000000000000000000000000000000",
+ "7818d800dcf6f4be1e0e94f403d1e4c2",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fc000000000000000000000000000000",
+ "e74cd1c92f0919c35a0324123d6177d3",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fe000000000000000000000000000000",
+ "8092a4dcf2da7e77e93bdd371dfed82e",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ff000000000000000000000000000000",
+ "49af6b372135acef10132e548f217b17",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ff800000000000000000000000000000",
+ "8bcd40f94ebb63b9f7909676e667f1e7",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffc00000000000000000000000000000",
+ "fe1cffb83f45dcfb38b29be438dbd3ab",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffe00000000000000000000000000000",
+ "0dc58a8d886623705aec15cb1e70dc0e",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fff00000000000000000000000000000",
+ "c218faa16056bd0774c3e8d79c35a5e4",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fff80000000000000000000000000000",
+ "047bba83f7aa841731504e012208fc9e",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffc0000000000000000000000000000",
+ "dc8f0e4915fd81ba70a331310882f6da",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffe0000000000000000000000000000",
+ "1569859ea6b7206c30bf4fd0cbfac33c",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffff0000000000000000000000000000",
+ "300ade92f88f48fa2df730ec16ef44cd",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffff8000000000000000000000000000",
+ "1fe6cc3c05965dc08eb0590c95ac71d0",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffc000000000000000000000000000",
+ "59e858eaaa97fec38111275b6cf5abc0",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffe000000000000000000000000000",
+ "2239455e7afe3b0616100288cc5a723b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffff000000000000000000000000000",
+ "3ee500c5c8d63479717163e55c5c4522",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffff800000000000000000000000000",
+ "d5e38bf15f16d90e3e214041d774daa8",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffc00000000000000000000000000",
+ "b1f4066e6f4f187dfe5f2ad1b17819d0",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffe00000000000000000000000000",
+ "6ef4cc4de49b11065d7af2909854794a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffff00000000000000000000000000",
+ "ac86bc606b6640c309e782f232bf367f",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffff80000000000000000000000000",
+ "36aff0ef7bf3280772cf4cac80a0d2b2",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffc0000000000000000000000000",
+ "1f8eedea0f62a1406d58cfc3ecea72cf",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffe0000000000000000000000000",
+ "abf4154a3375a1d3e6b1d454438f95a6",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffff0000000000000000000000000",
+ "96f96e9d607f6615fc192061ee648b07",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffff8000000000000000000000000",
+ "cf37cdaaa0d2d536c71857634c792064",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffc000000000000000000000000",
+ "fbd6640c80245c2b805373f130703127",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffe000000000000000000000000",
+ "8d6a8afe55a6e481badae0d146f436db",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffff000000000000000000000000",
+ "6a4981f2915e3e68af6c22385dd06756",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffff800000000000000000000000",
+ "42a1136e5f8d8d21d3101998642d573b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffc00000000000000000000000",
+ "9b471596dc69ae1586cee6158b0b0181",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffe00000000000000000000000",
+ "753665c4af1eff33aa8b628bf8741cfd",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffff00000000000000000000000",
+ "9a682acf40be01f5b2a4193c9a82404d",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffff80000000000000000000000",
+ "54fafe26e4287f17d1935f87eb9ade01",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffc0000000000000000000000",
+ "49d541b2e74cfe73e6a8e8225f7bd449",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffe0000000000000000000000",
+ "11a45530f624ff6f76a1b3826626ff7b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffff0000000000000000000000",
+ "f96b0c4a8bc6c86130289f60b43b8fba",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffff8000000000000000000000",
+ "48c7d0e80834ebdc35b6735f76b46c8b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffc000000000000000000000",
+ "2463531ab54d66955e73edc4cb8eaa45",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffe000000000000000000000",
+ "ac9bd8e2530469134b9d5b065d4f565b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffff000000000000000000000",
+ "3f5f9106d0e52f973d4890e6f37e8a00",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffff800000000000000000000",
+ "20ebc86f1304d272e2e207e59db639f0",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffc00000000000000000000",
+ "e67ae6426bf9526c972cff072b52252c",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffe00000000000000000000",
+ "1a518dddaf9efa0d002cc58d107edfc8",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffff00000000000000000000",
+ "ead731af4d3a2fe3b34bed047942a49f",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffff80000000000000000000",
+ "b1d4efe40242f83e93b6c8d7efb5eae9",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffc0000000000000000000",
+ "cd2b1fec11fd906c5c7630099443610a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffe0000000000000000000",
+ "a1853fe47fe29289d153161d06387d21",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffff0000000000000000000",
+ "4632154179a555c17ea604d0889fab14",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffff8000000000000000000",
+ "dd27cac6401a022e8f38f9f93e774417",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffc000000000000000000",
+ "c090313eb98674f35f3123385fb95d4d",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffe000000000000000000",
+ "cc3526262b92f02edce548f716b9f45c",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffff000000000000000000",
+ "c0838d1a2b16a7c7f0dfcc433c399c33",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffff800000000000000000",
+ "0d9ac756eb297695eed4d382eb126d26",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffc00000000000000000",
+ "56ede9dda3f6f141bff1757fa689c3e1",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffe00000000000000000",
+ "768f520efe0f23e61d3ec8ad9ce91774",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffff00000000000000000",
+ "b1144ddfa75755213390e7c596660490",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffff80000000000000000",
+ "1d7c0c4040b355b9d107a99325e3b050",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffc0000000000000000",
+ "d8e2bb1ae8ee3dcf5bf7d6c38da82a1a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffe0000000000000000",
+ "faf82d178af25a9886a47e7f789b98d7",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffff0000000000000000",
+ "9b58dbfd77fe5aca9cfc190cd1b82d19",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffff8000000000000000",
+ "77f392089042e478ac16c0c86a0b5db5",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffc000000000000000",
+ "19f08e3420ee69b477ca1420281c4782",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffe000000000000000",
+ "a1b19beee4e117139f74b3c53fdcb875",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffff000000000000000",
+ "a37a5869b218a9f3a0868d19aea0ad6a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffff800000000000000",
+ "bc3594e865bcd0261b13202731f33580",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffc00000000000000",
+ "811441ce1d309eee7185e8c752c07557",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffe00000000000000",
+ "959971ce4134190563518e700b9874d1",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffff00000000000000",
+ "76b5614a042707c98e2132e2e805fe63",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffff80000000000000",
+ "7d9fa6a57530d0f036fec31c230b0cc6",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffc0000000000000",
+ "964153a83bf6989a4ba80daa91c3e081",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffe0000000000000",
+ "a013014d4ce8054cf2591d06f6f2f176",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffff0000000000000",
+ "d1c5f6399bf382502e385eee1474a869",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffff8000000000000",
+ "0007e20b8298ec354f0f5fe7470f36bd",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffc000000000000",
+ "b95ba05b332da61ef63a2b31fcad9879",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffe000000000000",
+ "4620a49bd967491561669ab25dce45f4",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffff000000000000",
+ "12e71214ae8e04f0bb63d7425c6f14d5",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffff800000000000",
+ "4cc42fc1407b008fe350907c092e80ac",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffc00000000000",
+ "08b244ce7cbc8ee97fbba808cb146fda",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffe00000000000",
+ "39b333e8694f21546ad1edd9d87ed95b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffff00000000000",
+ "3b271f8ab2e6e4a20ba8090f43ba78f3",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffff80000000000",
+ "9ad983f3bf651cd0393f0a73cccdea50",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffc0000000000",
+ "8f476cbff75c1f725ce18e4bbcd19b32",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffe0000000000",
+ "905b6267f1d6ab5320835a133f096f2a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffff0000000000",
+ "145b60d6d0193c23f4221848a892d61a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffff8000000000",
+ "55cfb3fb6d75cad0445bbc8dafa25b0f",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffc000000000",
+ "7b8e7098e357ef71237d46d8b075b0f5",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffe000000000",
+ "2bf27229901eb40f2df9d8398d1505ae",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffff000000000",
+ "83a63402a77f9ad5c1e931a931ecd706",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffff800000000",
+ "6f8ba6521152d31f2bada1843e26b973",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffc00000000",
+ "e5c3b8e30fd2d8e6239b17b44bd23bbd",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffe00000000",
+ "1ac1f7102c59933e8b2ddc3f14e94baa",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffff00000000",
+ "21d9ba49f276b45f11af8fc71a088e3d",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffff80000000",
+ "649f1cddc3792b4638635a392bc9bade",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffc0000000",
+ "e2775e4b59c1bc2e31a2078c11b5a08c",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffe0000000",
+ "2be1fae5048a25582a679ca10905eb80",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffff0000000",
+ "da86f292c6f41ea34fb2068df75ecc29",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffff8000000",
+ "220df19f85d69b1b562fa69a3c5beca5",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffc000000",
+ "1f11d5d0355e0b556ccdb6c7f5083b4d",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffe000000",
+ "62526b78be79cb384633c91f83b4151b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffff000000",
+ "90ddbcb950843592dd47bbef00fdc876",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffff800000",
+ "2fd0e41c5b8402277354a7391d2618e2",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffc00000",
+ "3cdf13e72dee4c581bafec70b85f9660",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffe00000",
+ "afa2ffc137577092e2b654fa199d2c43",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffff00000",
+ "8d683ee63e60d208e343ce48dbc44cac",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffff80000",
+ "705a4ef8ba2133729c20185c3d3a4763",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffc0000",
+ "0861a861c3db4e94194211b77ed761b9",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffe0000",
+ "4b00c27e8b26da7eab9d3a88dec8b031",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffff0000",
+ "5f397bf03084820cc8810d52e5b666e9",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffff8000",
+ "63fafabb72c07bfbd3ddc9b1203104b8",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffc000",
+ "683e2140585b18452dd4ffbb93c95df9",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffe000",
+ "286894e48e537f8763b56707d7d155c8",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffff000",
+ "a423deabc173dcf7e2c4c53e77d37cd1",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffff800",
+ "eb8168313e1cfdfdb5e986d5429cf172",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffc00",
+ "27127daafc9accd2fb334ec3eba52323",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffe00",
+ "ee0715b96f72e3f7a22a5064fc592f4c",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffff00",
+ "29ee526770f2a11dcfa989d1ce88830f",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffff80",
+ "0493370e054b09871130fe49af730a5a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffc0",
+ "9b7b940f6c509f9e44a4ee140448ee46",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffe0",
+ "2915be4a1ecfdcbe3e023811a12bb6c7",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffff0",
+ "7240e524bc51d8c4d440b1be55d1062c",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffff8",
+ "da63039d38cb4612b2dc36ba26684b93",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffffc",
+ "0f59cb5a4b522e2ac56c1a64f558ad9a",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "fffffffffffffffffffffffffffffffe",
+ "7bfe9d876c6d63c1d035da8fe21c409d",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "ffffffffffffffffffffffffffffffff",
+ "acdace8078a32b1a182bfa4987ca1347",
+
+ /*
+ * Table end marker.
+ */
+ NULL
+};
+
+/*
+ * AES known-answer tests for CBC. Order: key, IV, plaintext, ciphertext.
+ */
+static const char *const KAT_AES_CBC[] = {
+ /*
+ * From NIST validation suite "Multiblock Message Test"
+ * (cbcmmt128.rsp).
+ */
+ "1f8e4973953f3fb0bd6b16662e9a3c17",
+ "2fe2b333ceda8f98f4a99b40d2cd34a8",
+ "45cf12964fc824ab76616ae2f4bf0822",
+ "0f61c4d44c5147c03c195ad7e2cc12b2",
+
+ "0700d603a1c514e46b6191ba430a3a0c",
+ "aad1583cd91365e3bb2f0c3430d065bb",
+ "068b25c7bfb1f8bdd4cfc908f69dffc5ddc726a197f0e5f720f730393279be91",
+ "c4dc61d9725967a3020104a9738f23868527ce839aab1752fd8bdb95a82c4d00",
+
+ "3348aa51e9a45c2dbe33ccc47f96e8de",
+ "19153c673160df2b1d38c28060e59b96",
+ "9b7cee827a26575afdbb7c7a329f887238052e3601a7917456ba61251c214763d5e1847a6ad5d54127a399ab07ee3599",
+ "d5aed6c9622ec451a15db12819952b6752501cf05cdbf8cda34a457726ded97818e1f127a28d72db5652749f0c6afee5",
+
+ "b7f3c9576e12dd0db63e8f8fac2b9a39",
+ "c80f095d8bb1a060699f7c19974a1aa0",
+ "9ac19954ce1319b354d3220460f71c1e373f1cd336240881160cfde46ebfed2e791e8d5a1a136ebd1dc469dec00c4187722b841cdabcb22c1be8a14657da200e",
+ "19b9609772c63f338608bf6eb52ca10be65097f89c1e0905c42401fd47791ae2c5440b2d473116ca78bd9ff2fb6015cfd316524eae7dcb95ae738ebeae84a467",
+
+ "b6f9afbfe5a1562bba1368fc72ac9d9c",
+ "3f9d5ebe250ee7ce384b0d00ee849322",
+ "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1",
+ "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9",
+
+ "bbe7b7ba07124ff1ae7c3416fe8b465e",
+ "7f65b5ee3630bed6b84202d97fb97a1e",
+ "2aad0c2c4306568bad7447460fd3dac054346d26feddbc9abd9110914011b4794be2a9a00a519a51a5b5124014f4ed2735480db21b434e99a911bb0b60fe0253763725b628d5739a5117b7ee3aefafc5b4c1bf446467e7bf5f78f31ff7caf187",
+ "3b8611bfc4973c5cd8e982b073b33184cd26110159172e44988eb5ff5661a1e16fad67258fcbfee55469267a12dc374893b4e3533d36f5634c3095583596f135aa8cd1138dc898bc5651ee35a92ebf89ab6aeb5366653bc60a70e0074fc11efe",
+
+ "89a553730433f7e6d67d16d373bd5360",
+ "f724558db3433a523f4e51a5bea70497",
+ "807bc4ea684eedcfdcca30180680b0f1ae2814f35f36d053c5aea6595a386c1442770f4d7297d8b91825ee7237241da8925dd594ccf676aecd46ca2068e8d37a3a0ec8a7d5185a201e663b5ff36ae197110188a23503763b8218826d23ced74b31e9f6e2d7fbfa6cb43420c7807a8625",
+ "406af1429a478c3d07e555c5287a60500d37fc39b68e5bbb9bafd6ddb223828561d6171a308d5b1a4551e8a5e7d572918d25c968d3871848d2f16635caa9847f38590b1df58ab5efb985f2c66cfaf86f61b3f9c0afad6c963c49cee9b8bc81a2ddb06c967f325515a4849eec37ce721a",
+
+ "c491ca31f91708458e29a925ec558d78",
+ "9ef934946e5cd0ae97bd58532cb49381",
+ "cb6a787e0dec56f9a165957f81af336ca6b40785d9e94093c6190e5152649f882e874d79ac5e167bd2a74ce5ae088d2ee854f6539e0a94796b1e1bd4c9fcdbc79acbef4d01eeb89776d18af71ae2a4fc47dd66df6c4dbe1d1850e466549a47b636bcc7c2b3a62495b56bb67b6d455f1eebd9bfefecbca6c7f335cfce9b45cb9d",
+ "7b2931f5855f717145e00f152a9f4794359b1ffcb3e55f594e33098b51c23a6c74a06c1d94fded7fd2ae42c7db7acaef5844cb33aeddc6852585ed0020a6699d2cb53809cefd169148ce42292afab063443978306c582c18b9ce0da3d084ce4d3c482cfd8fcf1a85084e89fb88b40a084d5e972466d07666126fb761f84078f2",
+
+ "f6e87d71b0104d6eb06a68dc6a71f498",
+ "1c245f26195b76ebebc2edcac412a2f8",
+ "f82bef3c73a6f7f80db285726d691db6bf55eec25a859d3ba0e0445f26b9bb3b16a3161ed1866e4dd8f2e5f8ecb4e46d74a7a78c20cdfc7bcc9e479ba7a0caba9438238ad0c01651d5d98de37f03ddce6e6b4bd4ab03cf9e8ed818aedfa1cf963b932067b97d776dce1087196e7e913f7448e38244509f0caf36bd8217e15336d35c149fd4e41707893fdb84014f8729",
+ "b09512f3eff9ed0d85890983a73dadbb7c3678d52581be64a8a8fc586f490f2521297a478a0598040ebd0f5509fafb0969f9d9e600eaef33b1b93eed99687b167f89a5065aac439ce46f3b8d22d30865e64e45ef8cd30b6984353a844a11c8cd60dba0e8866b3ee30d24b3fa8a643b328353e06010fa8273c8fd54ef0a2b6930e5520aae5cd5902f9b86a33592ca4365",
+
+ "2c14413751c31e2730570ba3361c786b",
+ "1dbbeb2f19abb448af849796244a19d7",
+ "40d930f9a05334d9816fe204999c3f82a03f6a0457a8c475c94553d1d116693adc618049f0a769a2eed6a6cb14c0143ec5cccdbc8dec4ce560cfd206225709326d4de7948e54d603d01b12d7fed752fb23f1aa4494fbb00130e9ded4e77e37c079042d828040c325b1a5efd15fc842e44014ca4374bf38f3c3fc3ee327733b0c8aee1abcd055772f18dc04603f7b2c1ea69ff662361f2be0a171bbdcea1e5d3f",
+ "6be8a12800455a320538853e0cba31bd2d80ea0c85164a4c5c261ae485417d93effe2ebc0d0a0b51d6ea18633d210cf63c0c4ddbc27607f2e81ed9113191ef86d56f3b99be6c415a4150299fb846ce7160b40b63baf1179d19275a2e83698376d28b92548c68e06e6d994e2c1501ed297014e702cdefee2f656447706009614d801de1caaf73f8b7fa56cf1ba94b631933bbe577624380850f117435a0355b2b",
+
+ /*
+ * From NIST validation suite "Multiblock Message Test"
+ * (cbcmmt192.rsp).
+ */
+ "ba75f4d1d9d7cf7f551445d56cc1a8ab2a078e15e049dc2c",
+ "531ce78176401666aa30db94ec4a30eb",
+ "c51fc276774dad94bcdc1d2891ec8668",
+ "70dd95a14ee975e239df36ff4aee1d5d",
+
+ "eab3b19c581aa873e1981c83ab8d83bbf8025111fb2e6b21",
+ "f3d6667e8d4d791e60f7505ba383eb05",
+ "9d4e4cccd1682321856df069e3f1c6fa391a083a9fb02d59db74c14081b3acc4",
+ "51d44779f90d40a80048276c035cb49ca2a47bcb9b9cf7270b9144793787d53f",
+
+ "16c93bb398f1fc0cf6d68fc7a5673cdf431fa147852b4a2d",
+ "eaaeca2e07ddedf562f94df63f0a650f",
+ "c5ce958613bf741718c17444484ebaf1050ddcacb59b9590178cbe69d7ad7919608cb03af13bbe04f3506b718a301ea0",
+ "ed6a50e0c6921d52d6647f75d67b4fd56ace1fedb8b5a6a997b4d131640547d22c5d884a75e6752b5846b5b33a5181f4",
+
+ "067bb17b4df785697eaccf961f98e212cb75e6797ce935cb",
+ "8b59c9209c529ca8391c9fc0ce033c38",
+ "db3785a889b4bd387754da222f0e4c2d2bfe0d79e05bc910fba941beea30f1239eacf0068f4619ec01c368e986fca6b7c58e490579d29611bd10087986eff54f",
+ "d5f5589760bf9c762228fde236de1fa2dd2dad448db3fa9be0c4196efd46a35c84dd1ac77d9db58c95918cb317a6430a08d2fb6a8e8b0f1c9b72c7a344dc349f",
+
+ "0fd39de83e0be77a79c8a4a612e3dd9c8aae2ce35e7a2bf8",
+ "7e1d629b84f93b079be51f9a5f5cb23c",
+ "38fbda37e28fa86d9d83a4345e419dea95d28c7818ff25925db6ac3aedaf0a86154e20a4dfcc5b1b4192895393e5eb5846c88bdbd41ecf7af3104f410eaee470f5d9017ed460475f626953035a13db1f",
+ "edadae2f9a45ff3473e02d904c94d94a30a4d92da4deb6bcb4b0774472694571842039f21c496ef93fd658842c735f8a81fcd0aa578442ab893b18f606aed1bab11f81452dd45e9b56adf2eccf4ea095",
+
+ "e3fecc75f0075a09b383dfd389a3d33cc9b854b3b254c0f4",
+ "36eab883afef936cc38f63284619cd19",
+ "931b2f5f3a5820d53a6beaaa6431083a3488f4eb03b0f5b57ef838e1579623103bd6e6800377538b2e51ef708f3c4956432e8a8ee6a34e190642b26ad8bdae6c2af9a6c7996f3b6004d2671e41f1c9f40ee03d1c4a52b0a0654a331f15f34dce",
+ "75395974bd32b3665654a6c8e396b88ae34b123575872a7ab687d8e76b46df911a8a590cd01d2f5c330be3a6626e9dd3aa5e10ed14e8ff829811b6fed50f3f533ca4385a1cbca78f5c4744e50f2f8359165c2485d1324e76c3eae76a0ccac629",
+
+ "f9c27565eb07947c8cb51b79248430f7b1066c3d2fdc3d13",
+ "2bd67cc89ab7948d644a49672843cbd9",
+ "6abcc270173cf114d44847e911a050db57ba7a2e2c161c6f37ccb6aaa4677bddcaf50cad0b5f8758fcf7c0ebc650ceb5cd52cafb8f8dd3edcece55d9f1f08b9fa8f54365cf56e28b9596a7e1dd1d3418e4444a7724add4cf79d527b183ec88de4be4eeff29c80a97e54f85351cb189ee",
+ "ca282924a61187feb40520979106e5cc861957f23828dcb7285e0eaac8a0ca2a6b60503d63d6039f4693dba32fa1f73ae2e709ca94911f28a5edd1f30eaddd54680c43acc9c74cd90d8bb648b4e544275f47e514daa20697f66c738eb30337f017fca1a26da4d1a0cc0a0e98e2463070",
+
+ "fb09cf9e00dbf883689d079c920077c0073c31890b55bab5",
+ "e3c89bd097c3abddf64f4881db6dbfe2",
+ "c1a37683fb289467dd1b2c89efba16bbd2ee24cf18d19d44596ded2682c79a2f711c7a32bf6a24badd32a4ee637c73b7a41da6258635650f91fb9ffa45bdfc3cb122136241b3deced8996aa51ea8d3e81c9d70e006a44bc0571ed48623a0d622a93fa9da290baaedf5d9e876c94620945ff8ecc83f27379ed55cf490c5790f27",
+ "8158e21420f25b59d6ae943fa1cbf21f02e979f419dab0126a721b7eef55bee9ad97f5ccff7d239057bbc19a8c378142f7672f1d5e7e17d7bebcb0070e8355cace6660171a53b61816ae824a6ef69ce470b6ffd3b5bb4b438874d91d27854d3b6f25860d3868958de3307d62b1339bdddb8a318c0ce0f33c17caf0e9f6040820",
+
+ "bca6fa3c67fd294e958f66fe8bd64f45f428f5bc8e9733a7",
+ "92a47f2833f1450d1da41717bdc6e83c",
+ "5becbc31d8bead6d36ae014a5863d14a431e6b55d29ea6baaa417271716db3a33b2e506b452086dfe690834ac2de30bc41254ec5401ec47d064237c7792fdcd7914d8af20eb114756642d519021a8c75a92f6bc53d326ae9a5b7e1b10a9756574692934d9939fc399e0c203f7edf8e7e6482eadd31a0400770e897b48c6bca2b404593045080e93377358c42a0f4dede",
+ "926db248cc1ba20f0c57631a7c8aef094f791937b905949e3460240e8bfa6fa483115a1b310b6e4369caebc5262888377b1ddaa5800ea496a2bdff0f9a1031e7129c9a20e35621e7f0b8baca0d87030f2ae7ca8593c8599677a06fd4b26009ead08fecac24caa9cf2cad3b470c8227415a7b1e0f2eab3fad96d70a209c8bb26c627677e2531b9435ca6e3c444d195b5f",
+
+ "162ad50ee64a0702aa551f571dedc16b2c1b6a1e4d4b5eee",
+ "24408038161a2ccae07b029bb66355c1",
+ "be8abf00901363987a82cc77d0ec91697ba3857f9e4f84bd79406c138d02698f003276d0449120bef4578d78fecabe8e070e11710b3f0a2744bd52434ec70015884c181ebdfd51c604a71c52e4c0e110bc408cd462b248a80b8a8ac06bb952ac1d7faed144807f1a731b7febcaf7835762defe92eccfc7a9944e1c702cffe6bc86733ed321423121085ac02df8962bcbc1937092eebf0e90a8b20e3dd8c244ae",
+ "c82cf2c476dea8cb6a6e607a40d2f0391be82ea9ec84a537a6820f9afb997b76397d005424faa6a74dc4e8c7aa4a8900690f894b6d1dca80675393d2243adac762f159301e357e98b724762310cd5a7bafe1c2a030dba46fd93a9fdb89cc132ca9c17dc72031ec6822ee5a9d99dbca66c784c01b0885cbb62e29d97801927ec415a5d215158d325f9ee689437ad1b7684ad33c0d92739451ac87f39ff8c31b84",
+
+ /*
+ * From NIST validation suite "Multiblock Message Test"
+ * (cbcmmt256.rsp).
+ */
+ "6ed76d2d97c69fd1339589523931f2a6cff554b15f738f21ec72dd97a7330907",
+ "851e8764776e6796aab722dbb644ace8",
+ "6282b8c05c5c1530b97d4816ca434762",
+ "6acc04142e100a65f51b97adf5172c41",
+
+ "dce26c6b4cfb286510da4eecd2cffe6cdf430f33db9b5f77b460679bd49d13ae",
+ "fdeaa134c8d7379d457175fd1a57d3fc",
+ "50e9eee1ac528009e8cbcd356975881f957254b13f91d7c6662d10312052eb00",
+ "2fa0df722a9fd3b64cb18fb2b3db55ff2267422757289413f8f657507412a64c",
+
+ "fe8901fecd3ccd2ec5fdc7c7a0b50519c245b42d611a5ef9e90268d59f3edf33",
+ "bd416cb3b9892228d8f1df575692e4d0",
+ "8d3aa196ec3d7c9b5bb122e7fe77fb1295a6da75abe5d3a510194d3a8a4157d5c89d40619716619859da3ec9b247ced9",
+ "608e82c7ab04007adb22e389a44797fed7de090c8c03ca8a2c5acd9e84df37fbc58ce8edb293e98f02b640d6d1d72464",
+
+ "0493ff637108af6a5b8e90ac1fdf035a3d4bafd1afb573be7ade9e8682e663e5",
+ "c0cd2bebccbb6c49920bd5482ac756e8",
+ "8b37f9148df4bb25956be6310c73c8dc58ea9714ff49b643107b34c9bff096a94fedd6823526abc27a8e0b16616eee254ab4567dd68e8ccd4c38ac563b13639c",
+ "05d5c77729421b08b737e41119fa4438d1f570cc772a4d6c3df7ffeda0384ef84288ce37fc4c4c7d1125a499b051364c389fd639bdda647daa3bdadab2eb5594",
+
+ "9adc8fbd506e032af7fa20cf5343719de6d1288c158c63d6878aaf64ce26ca85",
+ "11958dc6ab81e1c7f01631e9944e620f",
+ "c7917f84f747cd8c4b4fedc2219bdbc5f4d07588389d8248854cf2c2f89667a2d7bcf53e73d32684535f42318e24cd45793950b3825e5d5c5c8fcd3e5dda4ce9246d18337ef3052d8b21c5561c8b660e",
+ "9c99e68236bb2e929db1089c7750f1b356d39ab9d0c40c3e2f05108ae9d0c30b04832ccdbdc08ebfa426b7f5efde986ed05784ce368193bb3699bc691065ac62e258b9aa4cc557e2b45b49ce05511e65",
+
+ "73b8faf00b3302ac99855cf6f9e9e48518690a5906a4869d4dcf48d282faae2a",
+ "b3cb97a80a539912b8c21f450d3b9395",
+ "3adea6e06e42c4f041021491f2775ef6378cb08824165edc4f6448e232175b60d0345b9f9c78df6596ec9d22b7b9e76e8f3c76b32d5d67273f1d83fe7a6fc3dd3c49139170fa5701b3beac61b490f0a9e13f844640c4500f9ad3087adfb0ae10",
+ "ac3d6dbafe2e0f740632fd9e820bf6044cd5b1551cbb9cc03c0b25c39ccb7f33b83aacfca40a3265f2bbff879153448acacb88fcfb3bb7b10fe463a68c0109f028382e3e557b1adf02ed648ab6bb895df0205d26ebbfa9a5fd8cebd8e4bee3dc",
+
+ "9ddf3745896504ff360a51a3eb49c01b79fccebc71c3abcb94a949408b05b2c9",
+ "e79026639d4aa230b5ccffb0b29d79bc",
+ "cf52e5c3954c51b94c9e38acb8c9a7c76aebdaa9943eae0a1ce155a2efdb4d46985d935511471452d9ee64d2461cb2991d59fc0060697f9a671672163230f367fed1422316e52d29eceacb8768f56d9b80f6d278093c9a8acd3cfd7edd8ebd5c293859f64d2f8486ae1bd593c65bc014",
+ "34df561bd2cfebbcb7af3b4b8d21ca5258312e7e2e4e538e35ad2490b6112f0d7f148f6aa8d522a7f3c61d785bd667db0e1dc4606c318ea4f26af4fe7d11d4dcff0456511b4aed1a0d91ba4a1fd6cd9029187bc5881a5a07fe02049d39368e83139b12825bae2c7be81e6f12c61bb5c5",
+
+ "458b67bf212d20f3a57fce392065582dcefbf381aa22949f8338ab9052260e1d",
+ "4c12effc5963d40459602675153e9649",
+ "256fd73ce35ae3ea9c25dd2a9454493e96d8633fe633b56176dce8785ce5dbbb84dbf2c8a2eeb1e96b51899605e4f13bbc11b93bf6f39b3469be14858b5b720d4a522d36feed7a329c9b1e852c9280c47db8039c17c4921571a07d1864128330e09c308ddea1694e95c84500f1a61e614197e86a30ecc28df64ccb3ccf5437aa",
+ "90b7b9630a2378f53f501ab7beff039155008071bc8438e789932cfd3eb1299195465e6633849463fdb44375278e2fdb1310821e6492cf80ff15cb772509fb426f3aeee27bd4938882fd2ae6b5bd9d91fa4a43b17bb439ebbe59c042310163a82a5fe5388796eee35a181a1271f00be29b852d8fa759bad01ff4678f010594cd",
+
+ "d2412db0845d84e5732b8bbd642957473b81fb99ca8bff70e7920d16c1dbec89",
+ "51c619fcf0b23f0c7925f400a6cacb6d",
+ "026006c4a71a180c9929824d9d095b8faaa86fc4fa25ecac61d85ff6de92dfa8702688c02a282c1b8af4449707f22d75e91991015db22374c95f8f195d5bb0afeb03040ff8965e0e1339dba5653e174f8aa5a1b39fe3ac839ce307a4e44b4f8f1b0063f738ec18acdbff2ebfe07383e734558723e741f0a1836dafdf9de82210a9248bc113b3c1bc8b4e252ca01bd803",
+ "0254b23463bcabec5a395eb74c8fb0eb137a07bc6f5e9f61ec0b057de305714f8fa294221c91a159c315939b81e300ee902192ec5f15254428d8772f79324ec43298ca21c00b370273ee5e5ed90e43efa1e05a5d171209fe34f9f29237dba2a6726650fd3b1321747d1208863c6c3c6b3e2d879ab5f25782f08ba8f2abbe63e0bedb4a227e81afb36bb6645508356d34",
+
+ "48be597e632c16772324c8d3fa1d9c5a9ecd010f14ec5d110d3bfec376c5532b",
+ "d6d581b8cf04ebd3b6eaa1b53f047ee1",
+ "0c63d413d3864570e70bb6618bf8a4b9585586688c32bba0a5ecc1362fada74ada32c52acfd1aa7444ba567b4e7daaecf7cc1cb29182af164ae5232b002868695635599807a9a7f07a1f137e97b1e1c9dabc89b6a5e4afa9db5855edaa575056a8f4f8242216242bb0c256310d9d329826ac353d715fa39f80cec144d6424558f9f70b98c920096e0f2c855d594885a00625880e9dfb734163cecef72cf030b8",
+ "fc5873e50de8faf4c6b84ba707b0854e9db9ab2e9f7d707fbba338c6843a18fc6facebaf663d26296fb329b4d26f18494c79e09e779647f9bafa87489630d79f4301610c2300c19dbf3148b7cac8c4f4944102754f332e92b6f7c5e75bc6179eb877a078d4719009021744c14f13fd2a55a2b9c44d18000685a845a4f632c7c56a77306efa66a24d05d088dcd7c13fe24fc447275965db9e4d37fbc9304448cd",
+
+ /*
+ * End-of-table marker.
+ */
+ NULL
+};
+
+/*
+ * AES known-answer tests for CTR. Order: key, IV, plaintext, ciphertext.
+ */
+static const char *const KAT_AES_CTR[] = {
+ /*
+ * From RFC 3686.
+ */
+ "ae6852f8121067cc4bf7a5765577f39e",
+ "000000300000000000000000",
+ "53696e676c6520626c6f636b206d7367",
+ "e4095d4fb7a7b3792d6175a3261311b8",
+
+ "7e24067817fae0d743d6ce1f32539163",
+ "006cb6dbc0543b59da48d90b",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
+ "5104a106168a72d9790d41ee8edad388eb2e1efc46da57c8fce630df9141be28",
+
+ "7691be035e5020a8ac6e618529f9a0dc",
+ "00e0017b27777f3f4a1786f0",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223",
+ "c1cf48a89f2ffdd9cf4652e9efdb72d74540a42bde6d7836d59a5ceaaef3105325b2072f",
+
+ "16af5b145fc9f579c175f93e3bfb0eed863d06ccfdb78515",
+ "0000004836733c147d6d93cb",
+ "53696e676c6520626c6f636b206d7367",
+ "4b55384fe259c9c84e7935a003cbe928",
+
+ "7c5cb2401b3dc33c19e7340819e0f69c678c3db8e6f6a91a",
+ "0096b03b020c6eadc2cb500d",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
+ "453243fc609b23327edfaafa7131cd9f8490701c5ad4a79cfc1fe0ff42f4fb00",
+
+ "02bf391ee8ecb159b959617b0965279bf59b60a786d3e0fe",
+ "0007bdfd5cbd60278dcc0912",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223",
+ "96893fc55e5c722f540b7dd1ddf7e758d288bc95c69165884536c811662f2188abee0935",
+
+ "776beff2851db06f4c8a0542c8696f6c6a81af1eec96b4d37fc1d689e6c1c104",
+ "00000060db5672c97aa8f0b2",
+ "53696e676c6520626c6f636b206d7367",
+ "145ad01dbf824ec7560863dc71e3e0c0",
+
+ "f6d66d6bd52d59bb0796365879eff886c66dd51a5b6a99744b50590c87a23884",
+ "00faac24c1585ef15a43d875",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
+ "f05e231b3894612c49ee000b804eb2a9b8306b508f839d6a5530831d9344af1c",
+
+ "ff7a617ce69148e4f1726e2f43581de2aa62d9f805532edff1eed687fb54153d",
+ "001cc5b751a51d70a1c11148",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223",
+ "eb6c52821d0bbbf7ce7594462aca4faab407df866569fd07f48cc0b583d6071f1ec0e6b8",
+
+ /*
+ * End-of-table marker.
+ */
+ NULL
+};
+
+static void
+monte_carlo_AES_encrypt(const br_block_cbcenc_class *ve,
+ char *skey, char *splain, char *scipher)
+{
+ unsigned char key[32];
+ unsigned char buf[16];
+ unsigned char pbuf[16];
+ unsigned char cipher[16];
+ size_t key_len;
+ int i, j, k;
+ br_aes_gen_cbcenc_keys v_ec;
+ const br_block_cbcenc_class **ec;
+
+ ec = &v_ec.vtable;
+ key_len = hextobin(key, skey);
+ hextobin(buf, splain);
+ hextobin(cipher, scipher);
+ for (i = 0; i < 100; i ++) {
+ ve->init(ec, key, key_len);
+ for (j = 0; j < 1000; j ++) {
+ unsigned char iv[16];
+
+ memcpy(pbuf, buf, sizeof buf);
+ memset(iv, 0, sizeof iv);
+ ve->run(ec, iv, buf, sizeof buf);
+ }
+ switch (key_len) {
+ case 16:
+ for (k = 0; k < 16; k ++) {
+ key[k] ^= buf[k];
+ }
+ break;
+ case 24:
+ for (k = 0; k < 8; k ++) {
+ key[k] ^= pbuf[8 + k];
+ }
+ for (k = 0; k < 16; k ++) {
+ key[8 + k] ^= buf[k];
+ }
+ break;
+ default:
+ for (k = 0; k < 16; k ++) {
+ key[k] ^= pbuf[k];
+ key[16 + k] ^= buf[k];
+ }
+ break;
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ printf(" ");
+ fflush(stdout);
+ check_equals("MC AES encrypt", buf, cipher, sizeof buf);
+}
+
+static void
+monte_carlo_AES_decrypt(const br_block_cbcdec_class *vd,
+ char *skey, char *scipher, char *splain)
+{
+ unsigned char key[32];
+ unsigned char buf[16];
+ unsigned char pbuf[16];
+ unsigned char plain[16];
+ size_t key_len;
+ int i, j, k;
+ br_aes_gen_cbcdec_keys v_dc;
+ const br_block_cbcdec_class **dc;
+
+ dc = &v_dc.vtable;
+ key_len = hextobin(key, skey);
+ hextobin(buf, scipher);
+ hextobin(plain, splain);
+ for (i = 0; i < 100; i ++) {
+ vd->init(dc, key, key_len);
+ for (j = 0; j < 1000; j ++) {
+ unsigned char iv[16];
+
+ memcpy(pbuf, buf, sizeof buf);
+ memset(iv, 0, sizeof iv);
+ vd->run(dc, iv, buf, sizeof buf);
+ }
+ switch (key_len) {
+ case 16:
+ for (k = 0; k < 16; k ++) {
+ key[k] ^= buf[k];
+ }
+ break;
+ case 24:
+ for (k = 0; k < 8; k ++) {
+ key[k] ^= pbuf[8 + k];
+ }
+ for (k = 0; k < 16; k ++) {
+ key[8 + k] ^= buf[k];
+ }
+ break;
+ default:
+ for (k = 0; k < 16; k ++) {
+ key[k] ^= pbuf[k];
+ key[16 + k] ^= buf[k];
+ }
+ break;
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ printf(" ");
+ fflush(stdout);
+ check_equals("MC AES decrypt", buf, plain, sizeof buf);
+}
+
+static void
+test_AES_generic(char *name,
+ const br_block_cbcenc_class *ve,
+ const br_block_cbcdec_class *vd,
+ const br_block_ctr_class *vc,
+ int with_MC, int with_CBC)
+{
+ size_t u;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ if (ve->block_size != 16 || vd->block_size != 16
+ || ve->log_block_size != 4 || vd->log_block_size != 4)
+ {
+ fprintf(stderr, "%s failed: wrong block size\n", name);
+ exit(EXIT_FAILURE);
+ }
+
+ for (u = 0; KAT_AES[u]; u += 3) {
+ unsigned char key[32];
+ unsigned char plain[16];
+ unsigned char cipher[16];
+ unsigned char buf[16];
+ unsigned char iv[16];
+ size_t key_len;
+ br_aes_gen_cbcenc_keys v_ec;
+ br_aes_gen_cbcdec_keys v_dc;
+ const br_block_cbcenc_class **ec;
+ const br_block_cbcdec_class **dc;
+
+ ec = &v_ec.vtable;
+ dc = &v_dc.vtable;
+ key_len = hextobin(key, KAT_AES[u]);
+ hextobin(plain, KAT_AES[u + 1]);
+ hextobin(cipher, KAT_AES[u + 2]);
+ ve->init(ec, key, key_len);
+ memcpy(buf, plain, sizeof plain);
+ memset(iv, 0, sizeof iv);
+ ve->run(ec, iv, buf, sizeof buf);
+ check_equals("KAT AES encrypt", buf, cipher, sizeof cipher);
+ vd->init(dc, key, key_len);
+ memset(iv, 0, sizeof iv);
+ vd->run(dc, iv, buf, sizeof buf);
+ check_equals("KAT AES decrypt", buf, plain, sizeof plain);
+ }
+
+ if (with_CBC) {
+ for (u = 0; KAT_AES_CBC[u]; u += 4) {
+ unsigned char key[32];
+ unsigned char ivref[16];
+ unsigned char plain[200];
+ unsigned char cipher[200];
+ unsigned char buf[200];
+ unsigned char iv[16];
+ size_t key_len, data_len, v;
+ br_aes_gen_cbcenc_keys v_ec;
+ br_aes_gen_cbcdec_keys v_dc;
+ const br_block_cbcenc_class **ec;
+ const br_block_cbcdec_class **dc;
+
+ ec = &v_ec.vtable;
+ dc = &v_dc.vtable;
+ key_len = hextobin(key, KAT_AES_CBC[u]);
+ hextobin(ivref, KAT_AES_CBC[u + 1]);
+ data_len = hextobin(plain, KAT_AES_CBC[u + 2]);
+ hextobin(cipher, KAT_AES_CBC[u + 3]);
+ ve->init(ec, key, key_len);
+
+ memcpy(buf, plain, data_len);
+ memcpy(iv, ivref, 16);
+ ve->run(ec, iv, buf, data_len);
+ check_equals("KAT CBC AES encrypt",
+ buf, cipher, data_len);
+ vd->init(dc, key, key_len);
+ memcpy(iv, ivref, 16);
+ vd->run(dc, iv, buf, data_len);
+ check_equals("KAT CBC AES decrypt",
+ buf, plain, data_len);
+
+ memcpy(buf, plain, data_len);
+ memcpy(iv, ivref, 16);
+ for (v = 0; v < data_len; v += 16) {
+ ve->run(ec, iv, buf + v, 16);
+ }
+ check_equals("KAT CBC AES encrypt (2)",
+ buf, cipher, data_len);
+ memcpy(iv, ivref, 16);
+ for (v = 0; v < data_len; v += 16) {
+ vd->run(dc, iv, buf + v, 16);
+ }
+ check_equals("KAT CBC AES decrypt (2)",
+ buf, plain, data_len);
+ }
+
+ /*
+ * We want to check proper IV management for CBC:
+ * encryption and decryption must properly copy the _last_
+ * encrypted block as new IV, for all sizes.
+ */
+ for (u = 1; u <= 35; u ++) {
+ br_hmac_drbg_context rng;
+ unsigned char x;
+ size_t key_len, data_len;
+ size_t v;
+
+ br_hmac_drbg_init(&rng, &br_sha256_vtable,
+ "seed for AES/CBC", 16);
+ x = u;
+ br_hmac_drbg_update(&rng, &x, 1);
+ data_len = u << 4;
+ for (key_len = 16; key_len <= 32; key_len += 16) {
+ unsigned char key[32];
+ unsigned char iv[16], iv1[16], iv2[16];
+ unsigned char plain[35 * 16];
+ unsigned char tmp1[sizeof plain];
+ unsigned char tmp2[sizeof plain];
+ br_aes_gen_cbcenc_keys v_ec;
+ br_aes_gen_cbcdec_keys v_dc;
+ const br_block_cbcenc_class **ec;
+ const br_block_cbcdec_class **dc;
+
+ br_hmac_drbg_generate(&rng, key, key_len);
+ br_hmac_drbg_generate(&rng, iv, sizeof iv);
+ br_hmac_drbg_generate(&rng, plain, data_len);
+
+ ec = &v_ec.vtable;
+ ve->init(ec, key, key_len);
+ memcpy(iv1, iv, sizeof iv);
+ memcpy(tmp1, plain, data_len);
+ ve->run(ec, iv1, tmp1, data_len);
+ check_equals("IV CBC AES (1)",
+ tmp1 + data_len - 16, iv1, 16);
+ memcpy(iv2, iv, sizeof iv);
+ memcpy(tmp2, plain, data_len);
+ for (v = 0; v < data_len; v += 16) {
+ ve->run(ec, iv2, tmp2 + v, 16);
+ }
+ check_equals("IV CBC AES (2)",
+ tmp2 + data_len - 16, iv2, 16);
+ check_equals("IV CBC AES (3)",
+ tmp1, tmp2, data_len);
+
+ dc = &v_dc.vtable;
+ vd->init(dc, key, key_len);
+ memcpy(iv1, iv, sizeof iv);
+ vd->run(dc, iv1, tmp1, data_len);
+ check_equals("IV CBC AES (4)", iv1, iv2, 16);
+ check_equals("IV CBC AES (5)",
+ tmp1, plain, data_len);
+ memcpy(iv2, iv, sizeof iv);
+ for (v = 0; v < data_len; v += 16) {
+ vd->run(dc, iv2, tmp2 + v, 16);
+ }
+ check_equals("IV CBC AES (6)", iv1, iv2, 16);
+ check_equals("IV CBC AES (7)",
+ tmp2, plain, data_len);
+ }
+ }
+ }
+
+ if (vc != NULL) {
+ if (vc->block_size != 16 || vc->log_block_size != 4) {
+ fprintf(stderr, "%s failed: wrong block size\n", name);
+ exit(EXIT_FAILURE);
+ }
+ for (u = 0; KAT_AES_CTR[u]; u += 4) {
+ unsigned char key[32];
+ unsigned char iv[12];
+ unsigned char plain[200];
+ unsigned char cipher[200];
+ unsigned char buf[200];
+ size_t key_len, data_len, v;
+ uint32_t c;
+ br_aes_gen_ctr_keys v_xc;
+ const br_block_ctr_class **xc;
+
+ xc = &v_xc.vtable;
+ key_len = hextobin(key, KAT_AES_CTR[u]);
+ hextobin(iv, KAT_AES_CTR[u + 1]);
+ data_len = hextobin(plain, KAT_AES_CTR[u + 2]);
+ hextobin(cipher, KAT_AES_CTR[u + 3]);
+ vc->init(xc, key, key_len);
+ memcpy(buf, plain, data_len);
+ vc->run(xc, iv, 1, buf, data_len);
+ check_equals("KAT CTR AES (1)", buf, cipher, data_len);
+ vc->run(xc, iv, 1, buf, data_len);
+ check_equals("KAT CTR AES (2)", buf, plain, data_len);
+
+ memcpy(buf, plain, data_len);
+ c = 1;
+ for (v = 0; v < data_len; v += 32) {
+ size_t clen;
+
+ clen = data_len - v;
+ if (clen > 32) {
+ clen = 32;
+ }
+ c = vc->run(xc, iv, c, buf + v, clen);
+ }
+ check_equals("KAT CTR AES (3)", buf, cipher, data_len);
+
+ memcpy(buf, plain, data_len);
+ c = 1;
+ for (v = 0; v < data_len; v += 16) {
+ size_t clen;
+
+ clen = data_len - v;
+ if (clen > 16) {
+ clen = 16;
+ }
+ c = vc->run(xc, iv, c, buf + v, clen);
+ }
+ check_equals("KAT CTR AES (4)", buf, cipher, data_len);
+ }
+ }
+
+ if (with_MC) {
+ monte_carlo_AES_encrypt(
+ ve,
+ "139a35422f1d61de3c91787fe0507afd",
+ "b9145a768b7dc489a096b546f43b231f",
+ "fb2649694783b551eacd9d5db6126d47");
+ monte_carlo_AES_decrypt(
+ vd,
+ "0c60e7bf20ada9baa9e1ddf0d1540726",
+ "b08a29b11a500ea3aca42c36675b9785",
+ "d1d2bfdc58ffcad2341b095bce55221e");
+
+ monte_carlo_AES_encrypt(
+ ve,
+ "b9a63e09e1dfc42e93a90d9bad739e5967aef672eedd5da9",
+ "85a1f7a58167b389cddc8a9ff175ee26",
+ "5d1196da8f184975e240949a25104554");
+ monte_carlo_AES_decrypt(
+ vd,
+ "4b97585701c03fbebdfa8555024f589f1482c58a00fdd9fd",
+ "d0bd0e02ded155e4516be83f42d347a4",
+ "b63ef1b79507a62eba3dafcec54a6328");
+
+ monte_carlo_AES_encrypt(
+ ve,
+ "f9e8389f5b80712e3886cc1fa2d28a3b8c9cd88a2d4a54c6aa86ce0fef944be0",
+ "b379777f9050e2a818f2940cbbd9aba4",
+ "c5d2cb3d5b7ff0e23e308967ee074825");
+ monte_carlo_AES_decrypt(
+ vd,
+ "2b09ba39b834062b9e93f48373b8dd018dedf1e5ba1b8af831ebbacbc92a2643",
+ "89649bd0115f30bd878567610223a59d",
+ "e3d3868f578caf34e36445bf14cefc68");
+ }
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_AES_big(void)
+{
+ test_AES_generic("AES_big",
+ &br_aes_big_cbcenc_vtable,
+ &br_aes_big_cbcdec_vtable,
+ &br_aes_big_ctr_vtable,
+ 1, 1);
+}
+
+static void
+test_AES_small(void)
+{
+ test_AES_generic("AES_small",
+ &br_aes_small_cbcenc_vtable,
+ &br_aes_small_cbcdec_vtable,
+ &br_aes_small_ctr_vtable,
+ 1, 1);
+}
+
+static void
+test_AES_ct(void)
+{
+ test_AES_generic("AES_ct",
+ &br_aes_ct_cbcenc_vtable,
+ &br_aes_ct_cbcdec_vtable,
+ &br_aes_ct_ctr_vtable,
+ 1, 1);
+}
+
+static void
+test_AES_ct64(void)
+{
+ test_AES_generic("AES_ct64",
+ &br_aes_ct64_cbcenc_vtable,
+ &br_aes_ct64_cbcdec_vtable,
+ &br_aes_ct64_ctr_vtable,
+ 1, 1);
+}
+
+static void
+test_AES_x86ni(void)
+{
+ const br_block_cbcenc_class *x_cbcenc;
+ const br_block_cbcdec_class *x_cbcdec;
+ const br_block_ctr_class *x_ctr;
+ int hcbcenc, hcbcdec, hctr;
+
+ x_cbcenc = br_aes_x86ni_cbcenc_get_vtable();
+ x_cbcdec = br_aes_x86ni_cbcdec_get_vtable();
+ x_ctr = br_aes_x86ni_ctr_get_vtable();
+ hcbcenc = (x_cbcenc != NULL);
+ hcbcdec = (x_cbcdec != NULL);
+ hctr = (x_ctr != NULL);
+ if (hcbcenc != hctr || hcbcdec != hctr) {
+ fprintf(stderr, "AES_x86ni availability mismatch (%d/%d/%d)\n",
+ hcbcenc, hcbcdec, hctr);
+ exit(EXIT_FAILURE);
+ }
+ if (hctr) {
+ test_AES_generic("AES_x86ni",
+ x_cbcenc, x_cbcdec, x_ctr, 1, 1);
+ } else {
+ printf("Test AES_x86ni: UNAVAILABLE\n");
+ }
+}
+
+static void
+test_AES_pwr8(void)
+{
+ const br_block_cbcenc_class *x_cbcenc;
+ const br_block_cbcdec_class *x_cbcdec;
+ const br_block_ctr_class *x_ctr;
+ int hcbcenc, hcbcdec, hctr;
+
+ x_cbcenc = br_aes_pwr8_cbcenc_get_vtable();
+ x_cbcdec = br_aes_pwr8_cbcdec_get_vtable();
+ x_ctr = br_aes_pwr8_ctr_get_vtable();
+ hcbcenc = (x_cbcenc != NULL);
+ hcbcdec = (x_cbcdec != NULL);
+ hctr = (x_ctr != NULL);
+ if (hcbcenc != hctr || hcbcdec != hctr) {
+ fprintf(stderr, "AES_pwr8 availability mismatch (%d/%d/%d)\n",
+ hcbcenc, hcbcdec, hctr);
+ exit(EXIT_FAILURE);
+ }
+ if (hctr) {
+ test_AES_generic("AES_pwr8",
+ x_cbcenc, x_cbcdec, x_ctr, 1, 1);
+ } else {
+ printf("Test AES_pwr8: UNAVAILABLE\n");
+ }
+}
+
+/*
+ * Custom CTR + CBC-MAC AES implementation. Can also do CTR-only, and
+ * CBC-MAC-only. The 'aes_big' implementation (CTR) is used. This is
+ * meant for comparisons.
+ *
+ * If 'ctr' is NULL then no encryption/decryption is done; otherwise,
+ * CTR encryption/decryption is performed (full-block counter) and the
+ * 'ctr' array is updated with the new counter value.
+ *
+ * If 'cbcmac' is NULL then no CBC-MAC is done; otherwise, CBC-MAC is
+ * applied on the encrypted data, with 'cbcmac' as IV and destination
+ * buffer for the output. If 'ctr' is not NULL and 'encrypt' is non-zero,
+ * then CBC-MAC is computed over the result of CTR processing; otherwise,
+ * CBC-MAC is computed over the input data itself.
+ */
+static void
+do_aes_ctrcbc(const void *key, size_t key_len, int encrypt,
+ void *ctr, void *cbcmac, unsigned char *data, size_t len)
+{
+ br_aes_big_ctr_keys bc;
+ int i;
+
+ br_aes_big_ctr_init(&bc, key, key_len);
+ for (i = 0; i < 2; i ++) {
+ /*
+ * CBC-MAC is computed on the encrypted data, so in
+ * first pass if decrypting, second pass if encrypting.
+ */
+ if (cbcmac != NULL
+ && ((encrypt && i == 1) || (!encrypt && i == 0)))
+ {
+ unsigned char zz[16];
+ size_t u;
+
+ memcpy(zz, cbcmac, sizeof zz);
+ for (u = 0; u < len; u += 16) {
+ unsigned char tmp[16];
+ size_t v;
+
+ for (v = 0; v < 16; v ++) {
+ tmp[v] = zz[v] ^ data[u + v];
+ }
+ memset(zz, 0, sizeof zz);
+ br_aes_big_ctr_run(&bc,
+ tmp, br_dec32be(tmp + 12), zz, 16);
+ }
+ memcpy(cbcmac, zz, sizeof zz);
+ }
+
+ /*
+ * CTR encryption/decryption is done only in the first pass.
+ * We process data block per block, because the CTR-only
+ * class uses a 32-bit counter, while the CTR+CBC-MAC
+ * class uses a 128-bit counter.
+ */
+ if (ctr != NULL && i == 0) {
+ unsigned char zz[16];
+ size_t u;
+
+ memcpy(zz, ctr, sizeof zz);
+ for (u = 0; u < len; u += 16) {
+ int i;
+
+ br_aes_big_ctr_run(&bc,
+ zz, br_dec32be(zz + 12), data + u, 16);
+ for (i = 15; i >= 0; i --) {
+ zz[i] = (zz[i] + 1) & 0xFF;
+ if (zz[i] != 0) {
+ break;
+ }
+ }
+ }
+ memcpy(ctr, zz, sizeof zz);
+ }
+ }
+}
+
+static void
+test_AES_CTRCBC_inner(const char *name, const br_block_ctrcbc_class *vt)
+{
+ br_hmac_drbg_context rng;
+ size_t key_len;
+
+ printf("Test AES CTR/CBC-MAC %s: ", name);
+ fflush(stdout);
+
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, name, strlen(name));
+ for (key_len = 16; key_len <= 32; key_len += 8) {
+ br_aes_gen_ctrcbc_keys bc;
+ unsigned char key[32];
+ size_t data_len;
+
+ br_hmac_drbg_generate(&rng, key, key_len);
+ vt->init(&bc.vtable, key, key_len);
+ for (data_len = 0; data_len <= 512; data_len += 16) {
+ unsigned char plain[512];
+ unsigned char data1[sizeof plain];
+ unsigned char data2[sizeof plain];
+ unsigned char ctr[16], cbcmac[16];
+ unsigned char ctr1[16], cbcmac1[16];
+ unsigned char ctr2[16], cbcmac2[16];
+ int i;
+
+ br_hmac_drbg_generate(&rng, plain, data_len);
+
+ for (i = 0; i <= 16; i ++) {
+ if (i == 0) {
+ br_hmac_drbg_generate(&rng, ctr, 16);
+ } else {
+ memset(ctr, 0, i - 1);
+ memset(ctr + i - 1, 0xFF, 17 - i);
+ }
+ br_hmac_drbg_generate(&rng, cbcmac, 16);
+
+ memcpy(data1, plain, data_len);
+ memcpy(ctr1, ctr, 16);
+ vt->ctr(&bc.vtable, ctr1, data1, data_len);
+ memcpy(data2, plain, data_len);
+ memcpy(ctr2, ctr, 16);
+ do_aes_ctrcbc(key, key_len, 1,
+ ctr2, NULL, data2, data_len);
+ check_equals("CTR-only data",
+ data1, data2, data_len);
+ check_equals("CTR-only counter",
+ ctr1, ctr2, 16);
+
+ memcpy(data1, plain, data_len);
+ memcpy(cbcmac1, cbcmac, 16);
+ vt->mac(&bc.vtable, cbcmac1, data1, data_len);
+ memcpy(data2, plain, data_len);
+ memcpy(cbcmac2, cbcmac, 16);
+ do_aes_ctrcbc(key, key_len, 1,
+ NULL, cbcmac2, data2, data_len);
+ check_equals("CBC-MAC-only",
+ cbcmac1, cbcmac2, 16);
+
+ memcpy(data1, plain, data_len);
+ memcpy(ctr1, ctr, 16);
+ memcpy(cbcmac1, cbcmac, 16);
+ vt->encrypt(&bc.vtable,
+ ctr1, cbcmac1, data1, data_len);
+ memcpy(data2, plain, data_len);
+ memcpy(ctr2, ctr, 16);
+ memcpy(cbcmac2, cbcmac, 16);
+ do_aes_ctrcbc(key, key_len, 1,
+ ctr2, cbcmac2, data2, data_len);
+ check_equals("encrypt: combined data",
+ data1, data2, data_len);
+ check_equals("encrypt: combined counter",
+ ctr1, ctr2, 16);
+ check_equals("encrypt: combined CBC-MAC",
+ cbcmac1, cbcmac2, 16);
+
+ memcpy(ctr1, ctr, 16);
+ memcpy(cbcmac1, cbcmac, 16);
+ vt->decrypt(&bc.vtable,
+ ctr1, cbcmac1, data1, data_len);
+ memcpy(ctr2, ctr, 16);
+ memcpy(cbcmac2, cbcmac, 16);
+ do_aes_ctrcbc(key, key_len, 0,
+ ctr2, cbcmac2, data2, data_len);
+ check_equals("decrypt: combined data",
+ data1, data2, data_len);
+ check_equals("decrypt: combined counter",
+ ctr1, ctr2, 16);
+ check_equals("decrypt: combined CBC-MAC",
+ cbcmac1, cbcmac2, 16);
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" ");
+ fflush(stdout);
+ }
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_AES_CTRCBC_big(void)
+{
+ test_AES_CTRCBC_inner("big", &br_aes_big_ctrcbc_vtable);
+}
+
+static void
+test_AES_CTRCBC_small(void)
+{
+ test_AES_CTRCBC_inner("small", &br_aes_small_ctrcbc_vtable);
+}
+
+static void
+test_AES_CTRCBC_ct(void)
+{
+ test_AES_CTRCBC_inner("ct", &br_aes_ct_ctrcbc_vtable);
+}
+
+static void
+test_AES_CTRCBC_ct64(void)
+{
+ test_AES_CTRCBC_inner("ct64", &br_aes_ct64_ctrcbc_vtable);
+}
+
+static void
+test_AES_CTRCBC_x86ni(void)
+{
+ const br_block_ctrcbc_class *vt;
+
+ vt = br_aes_x86ni_ctrcbc_get_vtable();
+ if (vt != NULL) {
+ test_AES_CTRCBC_inner("x86ni", vt);
+ } else {
+ printf("Test AES CTR/CBC-MAC x86ni: UNAVAILABLE\n");
+ }
+}
+
+static void
+test_AES_CTRCBC_pwr8(void)
+{
+ const br_block_ctrcbc_class *vt;
+
+ vt = br_aes_pwr8_ctrcbc_get_vtable();
+ if (vt != NULL) {
+ test_AES_CTRCBC_inner("pwr8", vt);
+ } else {
+ printf("Test AES CTR/CBC-MAC pwr8: UNAVAILABLE\n");
+ }
+}
+
+/*
+ * DES known-answer tests. Order: plaintext, key, ciphertext.
+ * (mostly from NIST SP 800-20).
+ */
+static const char *const KAT_DES[] = {
+ "10316E028C8F3B4A", "0000000000000000", "82DCBAFBDEAB6602",
+ "8000000000000000", "0000000000000000", "95A8D72813DAA94D",
+ "4000000000000000", "0000000000000000", "0EEC1487DD8C26D5",
+ "2000000000000000", "0000000000000000", "7AD16FFB79C45926",
+ "1000000000000000", "0000000000000000", "D3746294CA6A6CF3",
+ "0800000000000000", "0000000000000000", "809F5F873C1FD761",
+ "0400000000000000", "0000000000000000", "C02FAFFEC989D1FC",
+ "0200000000000000", "0000000000000000", "4615AA1D33E72F10",
+ "0100000000000000", "0000000000000000", "8CA64DE9C1B123A7",
+ "0080000000000000", "0000000000000000", "2055123350C00858",
+ "0040000000000000", "0000000000000000", "DF3B99D6577397C8",
+ "0020000000000000", "0000000000000000", "31FE17369B5288C9",
+ "0010000000000000", "0000000000000000", "DFDD3CC64DAE1642",
+ "0008000000000000", "0000000000000000", "178C83CE2B399D94",
+ "0004000000000000", "0000000000000000", "50F636324A9B7F80",
+ "0002000000000000", "0000000000000000", "A8468EE3BC18F06D",
+ "0001000000000000", "0000000000000000", "8CA64DE9C1B123A7",
+ "0000800000000000", "0000000000000000", "A2DC9E92FD3CDE92",
+ "0000400000000000", "0000000000000000", "CAC09F797D031287",
+ "0000200000000000", "0000000000000000", "90BA680B22AEB525",
+ "0000100000000000", "0000000000000000", "CE7A24F350E280B6",
+ "0000080000000000", "0000000000000000", "882BFF0AA01A0B87",
+ "0000040000000000", "0000000000000000", "25610288924511C2",
+ "0000020000000000", "0000000000000000", "C71516C29C75D170",
+ "0000010000000000", "0000000000000000", "8CA64DE9C1B123A7",
+ "0000008000000000", "0000000000000000", "5199C29A52C9F059",
+ "0000004000000000", "0000000000000000", "C22F0A294A71F29F",
+ "0000002000000000", "0000000000000000", "EE371483714C02EA",
+ "0000001000000000", "0000000000000000", "A81FBD448F9E522F",
+ "0000000800000000", "0000000000000000", "4F644C92E192DFED",
+ "0000000400000000", "0000000000000000", "1AFA9A66A6DF92AE",
+ "0000000200000000", "0000000000000000", "B3C1CC715CB879D8",
+ "0000000100000000", "0000000000000000", "8CA64DE9C1B123A7",
+ "0000000080000000", "0000000000000000", "19D032E64AB0BD8B",
+ "0000000040000000", "0000000000000000", "3CFAA7A7DC8720DC",
+ "0000000020000000", "0000000000000000", "B7265F7F447AC6F3",
+ "0000000010000000", "0000000000000000", "9DB73B3C0D163F54",
+ "0000000008000000", "0000000000000000", "8181B65BABF4A975",
+ "0000000004000000", "0000000000000000", "93C9B64042EAA240",
+ "0000000002000000", "0000000000000000", "5570530829705592",
+ "0000000001000000", "0000000000000000", "8CA64DE9C1B123A7",
+ "0000000000800000", "0000000000000000", "8638809E878787A0",
+ "0000000000400000", "0000000000000000", "41B9A79AF79AC208",
+ "0000000000200000", "0000000000000000", "7A9BE42F2009A892",
+ "0000000000100000", "0000000000000000", "29038D56BA6D2745",
+ "0000000000080000", "0000000000000000", "5495C6ABF1E5DF51",
+ "0000000000040000", "0000000000000000", "AE13DBD561488933",
+ "0000000000020000", "0000000000000000", "024D1FFA8904E389",
+ "0000000000010000", "0000000000000000", "8CA64DE9C1B123A7",
+ "0000000000008000", "0000000000000000", "D1399712F99BF02E",
+ "0000000000004000", "0000000000000000", "14C1D7C1CFFEC79E",
+ "0000000000002000", "0000000000000000", "1DE5279DAE3BED6F",
+ "0000000000001000", "0000000000000000", "E941A33F85501303",
+ "0000000000000800", "0000000000000000", "DA99DBBC9A03F379",
+ "0000000000000400", "0000000000000000", "B7FC92F91D8E92E9",
+ "0000000000000200", "0000000000000000", "AE8E5CAA3CA04E85",
+ "0000000000000100", "0000000000000000", "8CA64DE9C1B123A7",
+ "0000000000000080", "0000000000000000", "9CC62DF43B6EED74",
+ "0000000000000040", "0000000000000000", "D863DBB5C59A91A0",
+ "0000000000000020", "0000000000000000", "A1AB2190545B91D7",
+ "0000000000000010", "0000000000000000", "0875041E64C570F7",
+ "0000000000000008", "0000000000000000", "5A594528BEBEF1CC",
+ "0000000000000004", "0000000000000000", "FCDB3291DE21F0C0",
+ "0000000000000002", "0000000000000000", "869EFD7F9F265A09",
+ "0000000000000001", "0000000000000000", "8CA64DE9C1B123A7",
+ "0000000000000000", "8000000000000000", "95F8A5E5DD31D900",
+ "0000000000000000", "4000000000000000", "DD7F121CA5015619",
+ "0000000000000000", "2000000000000000", "2E8653104F3834EA",
+ "0000000000000000", "1000000000000000", "4BD388FF6CD81D4F",
+ "0000000000000000", "0800000000000000", "20B9E767B2FB1456",
+ "0000000000000000", "0400000000000000", "55579380D77138EF",
+ "0000000000000000", "0200000000000000", "6CC5DEFAAF04512F",
+ "0000000000000000", "0100000000000000", "0D9F279BA5D87260",
+ "0000000000000000", "0080000000000000", "D9031B0271BD5A0A",
+ "0000000000000000", "0040000000000000", "424250B37C3DD951",
+ "0000000000000000", "0020000000000000", "B8061B7ECD9A21E5",
+ "0000000000000000", "0010000000000000", "F15D0F286B65BD28",
+ "0000000000000000", "0008000000000000", "ADD0CC8D6E5DEBA1",
+ "0000000000000000", "0004000000000000", "E6D5F82752AD63D1",
+ "0000000000000000", "0002000000000000", "ECBFE3BD3F591A5E",
+ "0000000000000000", "0001000000000000", "F356834379D165CD",
+ "0000000000000000", "0000800000000000", "2B9F982F20037FA9",
+ "0000000000000000", "0000400000000000", "889DE068A16F0BE6",
+ "0000000000000000", "0000200000000000", "E19E275D846A1298",
+ "0000000000000000", "0000100000000000", "329A8ED523D71AEC",
+ "0000000000000000", "0000080000000000", "E7FCE22557D23C97",
+ "0000000000000000", "0000040000000000", "12A9F5817FF2D65D",
+ "0000000000000000", "0000020000000000", "A484C3AD38DC9C19",
+ "0000000000000000", "0000010000000000", "FBE00A8A1EF8AD72",
+ "0000000000000000", "0000008000000000", "750D079407521363",
+ "0000000000000000", "0000004000000000", "64FEED9C724C2FAF",
+ "0000000000000000", "0000002000000000", "F02B263B328E2B60",
+ "0000000000000000", "0000001000000000", "9D64555A9A10B852",
+ "0000000000000000", "0000000800000000", "D106FF0BED5255D7",
+ "0000000000000000", "0000000400000000", "E1652C6B138C64A5",
+ "0000000000000000", "0000000200000000", "E428581186EC8F46",
+ "0000000000000000", "0000000100000000", "AEB5F5EDE22D1A36",
+ "0000000000000000", "0000000080000000", "E943D7568AEC0C5C",
+ "0000000000000000", "0000000040000000", "DF98C8276F54B04B",
+ "0000000000000000", "0000000020000000", "B160E4680F6C696F",
+ "0000000000000000", "0000000010000000", "FA0752B07D9C4AB8",
+ "0000000000000000", "0000000008000000", "CA3A2B036DBC8502",
+ "0000000000000000", "0000000004000000", "5E0905517BB59BCF",
+ "0000000000000000", "0000000002000000", "814EEB3B91D90726",
+ "0000000000000000", "0000000001000000", "4D49DB1532919C9F",
+ "0000000000000000", "0000000000800000", "25EB5FC3F8CF0621",
+ "0000000000000000", "0000000000400000", "AB6A20C0620D1C6F",
+ "0000000000000000", "0000000000200000", "79E90DBC98F92CCA",
+ "0000000000000000", "0000000000100000", "866ECEDD8072BB0E",
+ "0000000000000000", "0000000000080000", "8B54536F2F3E64A8",
+ "0000000000000000", "0000000000040000", "EA51D3975595B86B",
+ "0000000000000000", "0000000000020000", "CAFFC6AC4542DE31",
+ "0000000000000000", "0000000000010000", "8DD45A2DDF90796C",
+ "0000000000000000", "0000000000008000", "1029D55E880EC2D0",
+ "0000000000000000", "0000000000004000", "5D86CB23639DBEA9",
+ "0000000000000000", "0000000000002000", "1D1CA853AE7C0C5F",
+ "0000000000000000", "0000000000001000", "CE332329248F3228",
+ "0000000000000000", "0000000000000800", "8405D1ABE24FB942",
+ "0000000000000000", "0000000000000400", "E643D78090CA4207",
+ "0000000000000000", "0000000000000200", "48221B9937748A23",
+ "0000000000000000", "0000000000000100", "DD7C0BBD61FAFD54",
+ "0000000000000000", "0000000000000080", "2FBC291A570DB5C4",
+ "0000000000000000", "0000000000000040", "E07C30D7E4E26E12",
+ "0000000000000000", "0000000000000020", "0953E2258E8E90A1",
+ "0000000000000000", "0000000000000010", "5B711BC4CEEBF2EE",
+ "0000000000000000", "0000000000000008", "CC083F1E6D9E85F6",
+ "0000000000000000", "0000000000000004", "D2FD8867D50D2DFE",
+ "0000000000000000", "0000000000000002", "06E7EA22CE92708F",
+ "0000000000000000", "0000000000000001", "166B40B44ABA4BD6",
+ "0000000000000000", "0000000000000000", "8CA64DE9C1B123A7",
+ "0101010101010101", "0101010101010101", "994D4DC157B96C52",
+ "0202020202020202", "0202020202020202", "E127C2B61D98E6E2",
+ "0303030303030303", "0303030303030303", "984C91D78A269CE3",
+ "0404040404040404", "0404040404040404", "1F4570BB77550683",
+ "0505050505050505", "0505050505050505", "3990ABF98D672B16",
+ "0606060606060606", "0606060606060606", "3F5150BBA081D585",
+ "0707070707070707", "0707070707070707", "C65242248C9CF6F2",
+ "0808080808080808", "0808080808080808", "10772D40FAD24257",
+ "0909090909090909", "0909090909090909", "F0139440647A6E7B",
+ "0A0A0A0A0A0A0A0A", "0A0A0A0A0A0A0A0A", "0A288603044D740C",
+ "0B0B0B0B0B0B0B0B", "0B0B0B0B0B0B0B0B", "6359916942F7438F",
+ "0C0C0C0C0C0C0C0C", "0C0C0C0C0C0C0C0C", "934316AE443CF08B",
+ "0D0D0D0D0D0D0D0D", "0D0D0D0D0D0D0D0D", "E3F56D7F1130A2B7",
+ "0E0E0E0E0E0E0E0E", "0E0E0E0E0E0E0E0E", "A2E4705087C6B6B4",
+ "0F0F0F0F0F0F0F0F", "0F0F0F0F0F0F0F0F", "D5D76E09A447E8C3",
+ "1010101010101010", "1010101010101010", "DD7515F2BFC17F85",
+ "1111111111111111", "1111111111111111", "F40379AB9E0EC533",
+ "1212121212121212", "1212121212121212", "96CD27784D1563E5",
+ "1313131313131313", "1313131313131313", "2911CF5E94D33FE1",
+ "1414141414141414", "1414141414141414", "377B7F7CA3E5BBB3",
+ "1515151515151515", "1515151515151515", "701AA63832905A92",
+ "1616161616161616", "1616161616161616", "2006E716C4252D6D",
+ "1717171717171717", "1717171717171717", "452C1197422469F8",
+ "1818181818181818", "1818181818181818", "C33FD1EB49CB64DA",
+ "1919191919191919", "1919191919191919", "7572278F364EB50D",
+ "1A1A1A1A1A1A1A1A", "1A1A1A1A1A1A1A1A", "69E51488403EF4C3",
+ "1B1B1B1B1B1B1B1B", "1B1B1B1B1B1B1B1B", "FF847E0ADF192825",
+ "1C1C1C1C1C1C1C1C", "1C1C1C1C1C1C1C1C", "521B7FB3B41BB791",
+ "1D1D1D1D1D1D1D1D", "1D1D1D1D1D1D1D1D", "26059A6A0F3F6B35",
+ "1E1E1E1E1E1E1E1E", "1E1E1E1E1E1E1E1E", "F24A8D2231C77538",
+ "1F1F1F1F1F1F1F1F", "1F1F1F1F1F1F1F1F", "4FD96EC0D3304EF6",
+ "2020202020202020", "2020202020202020", "18A9D580A900B699",
+ "2121212121212121", "2121212121212121", "88586E1D755B9B5A",
+ "2222222222222222", "2222222222222222", "0F8ADFFB11DC2784",
+ "2323232323232323", "2323232323232323", "2F30446C8312404A",
+ "2424242424242424", "2424242424242424", "0BA03D9E6C196511",
+ "2525252525252525", "2525252525252525", "3E55E997611E4B7D",
+ "2626262626262626", "2626262626262626", "B2522FB5F158F0DF",
+ "2727272727272727", "2727272727272727", "2109425935406AB8",
+ "2828282828282828", "2828282828282828", "11A16028F310FF16",
+ "2929292929292929", "2929292929292929", "73F0C45F379FE67F",
+ "2A2A2A2A2A2A2A2A", "2A2A2A2A2A2A2A2A", "DCAD4338F7523816",
+ "2B2B2B2B2B2B2B2B", "2B2B2B2B2B2B2B2B", "B81634C1CEAB298C",
+ "2C2C2C2C2C2C2C2C", "2C2C2C2C2C2C2C2C", "DD2CCB29B6C4C349",
+ "2D2D2D2D2D2D2D2D", "2D2D2D2D2D2D2D2D", "7D07A77A2ABD50A7",
+ "2E2E2E2E2E2E2E2E", "2E2E2E2E2E2E2E2E", "30C1B0C1FD91D371",
+ "2F2F2F2F2F2F2F2F", "2F2F2F2F2F2F2F2F", "C4427B31AC61973B",
+ "3030303030303030", "3030303030303030", "F47BB46273B15EB5",
+ "3131313131313131", "3131313131313131", "655EA628CF62585F",
+ "3232323232323232", "3232323232323232", "AC978C247863388F",
+ "3333333333333333", "3333333333333333", "0432ED386F2DE328",
+ "3434343434343434", "3434343434343434", "D254014CB986B3C2",
+ "3535353535353535", "3535353535353535", "B256E34BEDB49801",
+ "3636363636363636", "3636363636363636", "37F8759EB77E7BFC",
+ "3737373737373737", "3737373737373737", "5013CA4F62C9CEA0",
+ "3838383838383838", "3838383838383838", "8940F7B3EACA5939",
+ "3939393939393939", "3939393939393939", "E22B19A55086774B",
+ "3A3A3A3A3A3A3A3A", "3A3A3A3A3A3A3A3A", "B04A2AAC925ABB0B",
+ "3B3B3B3B3B3B3B3B", "3B3B3B3B3B3B3B3B", "8D250D58361597FC",
+ "3C3C3C3C3C3C3C3C", "3C3C3C3C3C3C3C3C", "51F0114FB6A6CD37",
+ "3D3D3D3D3D3D3D3D", "3D3D3D3D3D3D3D3D", "9D0BB4DB830ECB73",
+ "3E3E3E3E3E3E3E3E", "3E3E3E3E3E3E3E3E", "E96089D6368F3E1A",
+ "3F3F3F3F3F3F3F3F", "3F3F3F3F3F3F3F3F", "5C4CA877A4E1E92D",
+ "4040404040404040", "4040404040404040", "6D55DDBC8DEA95FF",
+ "4141414141414141", "4141414141414141", "19DF84AC95551003",
+ "4242424242424242", "4242424242424242", "724E7332696D08A7",
+ "4343434343434343", "4343434343434343", "B91810B8CDC58FE2",
+ "4444444444444444", "4444444444444444", "06E23526EDCCD0C4",
+ "4545454545454545", "4545454545454545", "EF52491D5468D441",
+ "4646464646464646", "4646464646464646", "48019C59E39B90C5",
+ "4747474747474747", "4747474747474747", "0544083FB902D8C0",
+ "4848484848484848", "4848484848484848", "63B15CADA668CE12",
+ "4949494949494949", "4949494949494949", "EACC0C1264171071",
+ "4A4A4A4A4A4A4A4A", "4A4A4A4A4A4A4A4A", "9D2B8C0AC605F274",
+ "4B4B4B4B4B4B4B4B", "4B4B4B4B4B4B4B4B", "C90F2F4C98A8FB2A",
+ "4C4C4C4C4C4C4C4C", "4C4C4C4C4C4C4C4C", "03481B4828FD1D04",
+ "4D4D4D4D4D4D4D4D", "4D4D4D4D4D4D4D4D", "C78FC45A1DCEA2E2",
+ "4E4E4E4E4E4E4E4E", "4E4E4E4E4E4E4E4E", "DB96D88C3460D801",
+ "4F4F4F4F4F4F4F4F", "4F4F4F4F4F4F4F4F", "6C69E720F5105518",
+ "5050505050505050", "5050505050505050", "0D262E418BC893F3",
+ "5151515151515151", "5151515151515151", "6AD84FD7848A0A5C",
+ "5252525252525252", "5252525252525252", "C365CB35B34B6114",
+ "5353535353535353", "5353535353535353", "1155392E877F42A9",
+ "5454545454545454", "5454545454545454", "531BE5F9405DA715",
+ "5555555555555555", "5555555555555555", "3BCDD41E6165A5E8",
+ "5656565656565656", "5656565656565656", "2B1FF5610A19270C",
+ "5757575757575757", "5757575757575757", "D90772CF3F047CFD",
+ "5858585858585858", "5858585858585858", "1BEA27FFB72457B7",
+ "5959595959595959", "5959595959595959", "85C3E0C429F34C27",
+ "5A5A5A5A5A5A5A5A", "5A5A5A5A5A5A5A5A", "F9038021E37C7618",
+ "5B5B5B5B5B5B5B5B", "5B5B5B5B5B5B5B5B", "35BC6FF838DBA32F",
+ "5C5C5C5C5C5C5C5C", "5C5C5C5C5C5C5C5C", "4927ACC8CE45ECE7",
+ "5D5D5D5D5D5D5D5D", "5D5D5D5D5D5D5D5D", "E812EE6E3572985C",
+ "5E5E5E5E5E5E5E5E", "5E5E5E5E5E5E5E5E", "9BB93A89627BF65F",
+ "5F5F5F5F5F5F5F5F", "5F5F5F5F5F5F5F5F", "EF12476884CB74CA",
+ "6060606060606060", "6060606060606060", "1BF17E00C09E7CBF",
+ "6161616161616161", "6161616161616161", "29932350C098DB5D",
+ "6262626262626262", "6262626262626262", "B476E6499842AC54",
+ "6363636363636363", "6363636363636363", "5C662C29C1E96056",
+ "6464646464646464", "6464646464646464", "3AF1703D76442789",
+ "6565656565656565", "6565656565656565", "86405D9B425A8C8C",
+ "6666666666666666", "6666666666666666", "EBBF4810619C2C55",
+ "6767676767676767", "6767676767676767", "F8D1CD7367B21B5D",
+ "6868686868686868", "6868686868686868", "9EE703142BF8D7E2",
+ "6969696969696969", "6969696969696969", "5FDFFFC3AAAB0CB3",
+ "6A6A6A6A6A6A6A6A", "6A6A6A6A6A6A6A6A", "26C940AB13574231",
+ "6B6B6B6B6B6B6B6B", "6B6B6B6B6B6B6B6B", "1E2DC77E36A84693",
+ "6C6C6C6C6C6C6C6C", "6C6C6C6C6C6C6C6C", "0F4FF4D9BC7E2244",
+ "6D6D6D6D6D6D6D6D", "6D6D6D6D6D6D6D6D", "A4C9A0D04D3280CD",
+ "6E6E6E6E6E6E6E6E", "6E6E6E6E6E6E6E6E", "9FAF2C96FE84919D",
+ "6F6F6F6F6F6F6F6F", "6F6F6F6F6F6F6F6F", "115DBC965E6096C8",
+ "7070707070707070", "7070707070707070", "AF531E9520994017",
+ "7171717171717171", "7171717171717171", "B971ADE70E5C89EE",
+ "7272727272727272", "7272727272727272", "415D81C86AF9C376",
+ "7373737373737373", "7373737373737373", "8DFB864FDB3C6811",
+ "7474747474747474", "7474747474747474", "10B1C170E3398F91",
+ "7575757575757575", "7575757575757575", "CFEF7A1C0218DB1E",
+ "7676767676767676", "7676767676767676", "DBAC30A2A40B1B9C",
+ "7777777777777777", "7777777777777777", "89D3BF37052162E9",
+ "7878787878787878", "7878787878787878", "80D9230BDAEB67DC",
+ "7979797979797979", "7979797979797979", "3440911019AD68D7",
+ "7A7A7A7A7A7A7A7A", "7A7A7A7A7A7A7A7A", "9626FE57596E199E",
+ "7B7B7B7B7B7B7B7B", "7B7B7B7B7B7B7B7B", "DEA0B796624BB5BA",
+ "7C7C7C7C7C7C7C7C", "7C7C7C7C7C7C7C7C", "E9E40542BDDB3E9D",
+ "7D7D7D7D7D7D7D7D", "7D7D7D7D7D7D7D7D", "8AD99914B354B911",
+ "7E7E7E7E7E7E7E7E", "7E7E7E7E7E7E7E7E", "6F85B98DD12CB13B",
+ "7F7F7F7F7F7F7F7F", "7F7F7F7F7F7F7F7F", "10130DA3C3A23924",
+ "8080808080808080", "8080808080808080", "EFECF25C3C5DC6DB",
+ "8181818181818181", "8181818181818181", "907A46722ED34EC4",
+ "8282828282828282", "8282828282828282", "752666EB4CAB46EE",
+ "8383838383838383", "8383838383838383", "161BFABD4224C162",
+ "8484848484848484", "8484848484848484", "215F48699DB44A45",
+ "8585858585858585", "8585858585858585", "69D901A8A691E661",
+ "8686868686868686", "8686868686868686", "CBBF6EEFE6529728",
+ "8787878787878787", "8787878787878787", "7F26DCF425149823",
+ "8888888888888888", "8888888888888888", "762C40C8FADE9D16",
+ "8989898989898989", "8989898989898989", "2453CF5D5BF4E463",
+ "8A8A8A8A8A8A8A8A", "8A8A8A8A8A8A8A8A", "301085E3FDE724E1",
+ "8B8B8B8B8B8B8B8B", "8B8B8B8B8B8B8B8B", "EF4E3E8F1CC6706E",
+ "8C8C8C8C8C8C8C8C", "8C8C8C8C8C8C8C8C", "720479B024C397EE",
+ "8D8D8D8D8D8D8D8D", "8D8D8D8D8D8D8D8D", "BEA27E3795063C89",
+ "8E8E8E8E8E8E8E8E", "8E8E8E8E8E8E8E8E", "468E5218F1A37611",
+ "8F8F8F8F8F8F8F8F", "8F8F8F8F8F8F8F8F", "50ACE16ADF66BFE8",
+ "9090909090909090", "9090909090909090", "EEA24369A19F6937",
+ "9191919191919191", "9191919191919191", "6050D369017B6E62",
+ "9292929292929292", "9292929292929292", "5B365F2FB2CD7F32",
+ "9393939393939393", "9393939393939393", "F0B00B264381DDBB",
+ "9494949494949494", "9494949494949494", "E1D23881C957B96C",
+ "9595959595959595", "9595959595959595", "D936BF54ECA8BDCE",
+ "9696969696969696", "9696969696969696", "A020003C5554F34C",
+ "9797979797979797", "9797979797979797", "6118FCEBD407281D",
+ "9898989898989898", "9898989898989898", "072E328C984DE4A2",
+ "9999999999999999", "9999999999999999", "1440B7EF9E63D3AA",
+ "9A9A9A9A9A9A9A9A", "9A9A9A9A9A9A9A9A", "79BFA264BDA57373",
+ "9B9B9B9B9B9B9B9B", "9B9B9B9B9B9B9B9B", "C50E8FC289BBD876",
+ "9C9C9C9C9C9C9C9C", "9C9C9C9C9C9C9C9C", "A399D3D63E169FA9",
+ "9D9D9D9D9D9D9D9D", "9D9D9D9D9D9D9D9D", "4B8919B667BD53AB",
+ "9E9E9E9E9E9E9E9E", "9E9E9E9E9E9E9E9E", "D66CDCAF3F6724A2",
+ "9F9F9F9F9F9F9F9F", "9F9F9F9F9F9F9F9F", "E40E81FF3F618340",
+ "A0A0A0A0A0A0A0A0", "A0A0A0A0A0A0A0A0", "10EDB8977B348B35",
+ "A1A1A1A1A1A1A1A1", "A1A1A1A1A1A1A1A1", "6446C5769D8409A0",
+ "A2A2A2A2A2A2A2A2", "A2A2A2A2A2A2A2A2", "17ED1191CA8D67A3",
+ "A3A3A3A3A3A3A3A3", "A3A3A3A3A3A3A3A3", "B6D8533731BA1318",
+ "A4A4A4A4A4A4A4A4", "A4A4A4A4A4A4A4A4", "CA439007C7245CD0",
+ "A5A5A5A5A5A5A5A5", "A5A5A5A5A5A5A5A5", "06FC7FDE1C8389E7",
+ "A6A6A6A6A6A6A6A6", "A6A6A6A6A6A6A6A6", "7A3C1F3BD60CB3D8",
+ "A7A7A7A7A7A7A7A7", "A7A7A7A7A7A7A7A7", "E415D80048DBA848",
+ "A8A8A8A8A8A8A8A8", "A8A8A8A8A8A8A8A8", "26F88D30C0FB8302",
+ "A9A9A9A9A9A9A9A9", "A9A9A9A9A9A9A9A9", "D4E00A9EF5E6D8F3",
+ "AAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAA", "C4322BE19E9A5A17",
+ "ABABABABABABABAB", "ABABABABABABABAB", "ACE41A06BFA258EA",
+ "ACACACACACACACAC", "ACACACACACACACAC", "EEAAC6D17880BD56",
+ "ADADADADADADADAD", "ADADADADADADADAD", "3C9A34CA4CB49EEB",
+ "AEAEAEAEAEAEAEAE", "AEAEAEAEAEAEAEAE", "9527B0287B75F5A3",
+ "AFAFAFAFAFAFAFAF", "AFAFAFAFAFAFAFAF", "F2D9D1BE74376C0C",
+ "B0B0B0B0B0B0B0B0", "B0B0B0B0B0B0B0B0", "939618DF0AEFAAE7",
+ "B1B1B1B1B1B1B1B1", "B1B1B1B1B1B1B1B1", "24692773CB9F27FE",
+ "B2B2B2B2B2B2B2B2", "B2B2B2B2B2B2B2B2", "38703BA5E2315D1D",
+ "B3B3B3B3B3B3B3B3", "B3B3B3B3B3B3B3B3", "FCB7E4B7D702E2FB",
+ "B4B4B4B4B4B4B4B4", "B4B4B4B4B4B4B4B4", "36F0D0B3675704D5",
+ "B5B5B5B5B5B5B5B5", "B5B5B5B5B5B5B5B5", "62D473F539FA0D8B",
+ "B6B6B6B6B6B6B6B6", "B6B6B6B6B6B6B6B6", "1533F3ED9BE8EF8E",
+ "B7B7B7B7B7B7B7B7", "B7B7B7B7B7B7B7B7", "9C4EA352599731ED",
+ "B8B8B8B8B8B8B8B8", "B8B8B8B8B8B8B8B8", "FABBF7C046FD273F",
+ "B9B9B9B9B9B9B9B9", "B9B9B9B9B9B9B9B9", "B7FE63A61C646F3A",
+ "BABABABABABABABA", "BABABABABABABABA", "10ADB6E2AB972BBE",
+ "BBBBBBBBBBBBBBBB", "BBBBBBBBBBBBBBBB", "F91DCAD912332F3B",
+ "BCBCBCBCBCBCBCBC", "BCBCBCBCBCBCBCBC", "46E7EF47323A701D",
+ "BDBDBDBDBDBDBDBD", "BDBDBDBDBDBDBDBD", "8DB18CCD9692F758",
+ "BEBEBEBEBEBEBEBE", "BEBEBEBEBEBEBEBE", "E6207B536AAAEFFC",
+ "BFBFBFBFBFBFBFBF", "BFBFBFBFBFBFBFBF", "92AA224372156A00",
+ "C0C0C0C0C0C0C0C0", "C0C0C0C0C0C0C0C0", "A3B357885B1E16D2",
+ "C1C1C1C1C1C1C1C1", "C1C1C1C1C1C1C1C1", "169F7629C970C1E5",
+ "C2C2C2C2C2C2C2C2", "C2C2C2C2C2C2C2C2", "62F44B247CF1348C",
+ "C3C3C3C3C3C3C3C3", "C3C3C3C3C3C3C3C3", "AE0FEEB0495932C8",
+ "C4C4C4C4C4C4C4C4", "C4C4C4C4C4C4C4C4", "72DAF2A7C9EA6803",
+ "C5C5C5C5C5C5C5C5", "C5C5C5C5C5C5C5C5", "4FB5D5536DA544F4",
+ "C6C6C6C6C6C6C6C6", "C6C6C6C6C6C6C6C6", "1DD4E65AAF7988B4",
+ "C7C7C7C7C7C7C7C7", "C7C7C7C7C7C7C7C7", "76BF084C1535A6C6",
+ "C8C8C8C8C8C8C8C8", "C8C8C8C8C8C8C8C8", "AFEC35B09D36315F",
+ "C9C9C9C9C9C9C9C9", "C9C9C9C9C9C9C9C9", "C8078A6148818403",
+ "CACACACACACACACA", "CACACACACACACACA", "4DA91CB4124B67FE",
+ "CBCBCBCBCBCBCBCB", "CBCBCBCBCBCBCBCB", "2DABFEB346794C3D",
+ "CCCCCCCCCCCCCCCC", "CCCCCCCCCCCCCCCC", "FBCD12C790D21CD7",
+ "CDCDCDCDCDCDCDCD", "CDCDCDCDCDCDCDCD", "536873DB879CC770",
+ "CECECECECECECECE", "CECECECECECECECE", "9AA159D7309DA7A0",
+ "CFCFCFCFCFCFCFCF", "CFCFCFCFCFCFCFCF", "0B844B9D8C4EA14A",
+ "D0D0D0D0D0D0D0D0", "D0D0D0D0D0D0D0D0", "3BBD84CE539E68C4",
+ "D1D1D1D1D1D1D1D1", "D1D1D1D1D1D1D1D1", "CF3E4F3E026E2C8E",
+ "D2D2D2D2D2D2D2D2", "D2D2D2D2D2D2D2D2", "82F85885D542AF58",
+ "D3D3D3D3D3D3D3D3", "D3D3D3D3D3D3D3D3", "22D334D6493B3CB6",
+ "D4D4D4D4D4D4D4D4", "D4D4D4D4D4D4D4D4", "47E9CB3E3154D673",
+ "D5D5D5D5D5D5D5D5", "D5D5D5D5D5D5D5D5", "2352BCC708ADC7E9",
+ "D6D6D6D6D6D6D6D6", "D6D6D6D6D6D6D6D6", "8C0F3BA0C8601980",
+ "D7D7D7D7D7D7D7D7", "D7D7D7D7D7D7D7D7", "EE5E9FD70CEF00E9",
+ "D8D8D8D8D8D8D8D8", "D8D8D8D8D8D8D8D8", "DEF6BDA6CABF9547",
+ "D9D9D9D9D9D9D9D9", "D9D9D9D9D9D9D9D9", "4DADD04A0EA70F20",
+ "DADADADADADADADA", "DADADADADADADADA", "C1AA16689EE1B482",
+ "DBDBDBDBDBDBDBDB", "DBDBDBDBDBDBDBDB", "F45FC26193E69AEE",
+ "DCDCDCDCDCDCDCDC", "DCDCDCDCDCDCDCDC", "D0CFBB937CEDBFB5",
+ "DDDDDDDDDDDDDDDD", "DDDDDDDDDDDDDDDD", "F0752004EE23D87B",
+ "DEDEDEDEDEDEDEDE", "DEDEDEDEDEDEDEDE", "77A791E28AA464A5",
+ "DFDFDFDFDFDFDFDF", "DFDFDFDFDFDFDFDF", "E7562A7F56FF4966",
+ "E0E0E0E0E0E0E0E0", "E0E0E0E0E0E0E0E0", "B026913F2CCFB109",
+ "E1E1E1E1E1E1E1E1", "E1E1E1E1E1E1E1E1", "0DB572DDCE388AC7",
+ "E2E2E2E2E2E2E2E2", "E2E2E2E2E2E2E2E2", "D9FA6595F0C094CA",
+ "E3E3E3E3E3E3E3E3", "E3E3E3E3E3E3E3E3", "ADE4804C4BE4486E",
+ "E4E4E4E4E4E4E4E4", "E4E4E4E4E4E4E4E4", "007B81F520E6D7DA",
+ "E5E5E5E5E5E5E5E5", "E5E5E5E5E5E5E5E5", "961AEB77BFC10B3C",
+ "E6E6E6E6E6E6E6E6", "E6E6E6E6E6E6E6E6", "8A8DD870C9B14AF2",
+ "E7E7E7E7E7E7E7E7", "E7E7E7E7E7E7E7E7", "3CC02E14B6349B25",
+ "E8E8E8E8E8E8E8E8", "E8E8E8E8E8E8E8E8", "BAD3EE68BDDB9607",
+ "E9E9E9E9E9E9E9E9", "E9E9E9E9E9E9E9E9", "DFF918E93BDAD292",
+ "EAEAEAEAEAEAEAEA", "EAEAEAEAEAEAEAEA", "8FE559C7CD6FA56D",
+ "EBEBEBEBEBEBEBEB", "EBEBEBEBEBEBEBEB", "C88480835C1A444C",
+ "ECECECECECECECEC", "ECECECECECECECEC", "D6EE30A16B2CC01E",
+ "EDEDEDEDEDEDEDED", "EDEDEDEDEDEDEDED", "6932D887B2EA9C1A",
+ "EEEEEEEEEEEEEEEE", "EEEEEEEEEEEEEEEE", "0BFC865461F13ACC",
+ "EFEFEFEFEFEFEFEF", "EFEFEFEFEFEFEFEF", "228AEA0D403E807A",
+ "F0F0F0F0F0F0F0F0", "F0F0F0F0F0F0F0F0", "2A2891F65BB8173C",
+ "F1F1F1F1F1F1F1F1", "F1F1F1F1F1F1F1F1", "5D1B8FAF7839494B",
+ "F2F2F2F2F2F2F2F2", "F2F2F2F2F2F2F2F2", "1C0A9280EECF5D48",
+ "F3F3F3F3F3F3F3F3", "F3F3F3F3F3F3F3F3", "6CBCE951BBC30F74",
+ "F4F4F4F4F4F4F4F4", "F4F4F4F4F4F4F4F4", "9CA66E96BD08BC70",
+ "F5F5F5F5F5F5F5F5", "F5F5F5F5F5F5F5F5", "F5D779FCFBB28BF3",
+ "F6F6F6F6F6F6F6F6", "F6F6F6F6F6F6F6F6", "0FEC6BBF9B859184",
+ "F7F7F7F7F7F7F7F7", "F7F7F7F7F7F7F7F7", "EF88D2BF052DBDA8",
+ "F8F8F8F8F8F8F8F8", "F8F8F8F8F8F8F8F8", "39ADBDDB7363090D",
+ "F9F9F9F9F9F9F9F9", "F9F9F9F9F9F9F9F9", "C0AEAF445F7E2A7A",
+ "FAFAFAFAFAFAFAFA", "FAFAFAFAFAFAFAFA", "C66F54067298D4E9",
+ "FBFBFBFBFBFBFBFB", "FBFBFBFBFBFBFBFB", "E0BA8F4488AAF97C",
+ "FCFCFCFCFCFCFCFC", "FCFCFCFCFCFCFCFC", "67B36E2875D9631C",
+ "FDFDFDFDFDFDFDFD", "FDFDFDFDFDFDFDFD", "1ED83D49E267191D",
+ "FEFEFEFEFEFEFEFE", "FEFEFEFEFEFEFEFE", "66B2B23EA84693AD",
+ "FFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFF", "7359B2163E4EDC58",
+ "0001020304050607", "0011223344556677", "3EF0A891CF8ED990",
+ "2BD6459F82C5B300", "EA024714AD5C4D84", "126EFE8ED312190A",
+
+ NULL
+};
+
+/*
+ * Known-answer tests for DES/3DES in CBC mode. Order: key, IV,
+ * plaintext, ciphertext.
+ */
+static const char *const KAT_DES_CBC[] = {
+ /*
+ * From NIST validation suite (tdesmmt.zip).
+ */
+ "34a41a8c293176c1b30732ecfe38ae8a34a41a8c293176c1",
+ "f55b4855228bd0b4",
+ "7dd880d2a9ab411c",
+ "c91892948b6cadb4",
+
+ "70a88fa1dfb9942fa77f40157ffef2ad70a88fa1dfb9942f",
+ "ece08ce2fdc6ce80",
+ "bc225304d5a3a5c9918fc5006cbc40cc",
+ "27f67dc87af7ddb4b68f63fa7c2d454a",
+
+ "e091790be55be0bc0780153861a84adce091790be55be0bc",
+ "fd7d430f86fbbffe",
+ "03c7fffd7f36499c703dedc9df4de4a92dd4382e576d6ae9",
+ "053aeba85dd3a23bfbe8440a432f9578f312be60fb9f0035",
+
+ "857feacd16157c58e5347a70e56e578a857feacd16157c58",
+ "002dcb6d46ef0969",
+ "1f13701c7f0d7385307507a18e89843ebd295bd5e239ef109347a6898c6d3fd5",
+ "a0e4edde34f05bd8397ce279e49853e9387ba04be562f5fa19c3289c3f5a3391",
+
+ "a173545b265875ba852331fbb95b49a8a173545b265875ba",
+ "ab385756391d364c",
+ "d08894c565608d9ae51dda63b85b3b33b1703bb5e4f1abcbb8794e743da5d6f3bf630f2e9b6d5b54",
+ "370b47acf89ac6bdbb13c9a7336787dc41e1ad8beead32281d0609fb54968404bdf2894892590658",
+
+ "26376bcb2f23df1083cd684fe00ed3c726376bcb2f23df10",
+ "33acfb0f3d240ea6",
+ "903a1911da1e6877f23c1985a9b61786ef438e0ce1240885035ad60fc916b18e5d71a1fb9c5d1eff61db75c0076f6efb",
+ "7a4f7510f6ec0b93e2495d21a8355684d303a770ebda2e0e51ff33d72b20cb73e58e2e3de2ef6b2e12c504c0f181ba63",
+
+ "3e1f98135d027cec752f67765408a7913e1f98135d027cec",
+ "11f5f2304b28f68b",
+ "7c022f5af24f7925d323d4d0e20a2ce49272c5e764b22c806f4b6ddc406d864fe5bd1c3f45556d3eb30c8676c2f8b54a5a32423a0bd95a07",
+ "2bb4b131fa4ae0b4f0378a2cdb68556af6eee837613016d7ea936f3931f25f8b3ae351d5e9d00be665676e2400408b5db9892d95421e7f1a",
+
+ "13b9d549cd136ec7bf9e9810ef2cdcbf13b9d549cd136ec7",
+ "a82c1b1057badcc8",
+ "1fff1563bc1645b55cb23ea34a0049dfc06607150614b621dedcb07f20433402a2d869c95ac4a070c7a3da838c928a385f899c5d21ecb58f4e5cbdad98d39b8c",
+ "75f804d4a2c542a31703e23df26cc38861a0729090e6eae5672c1db8c0b09fba9b125bbca7d6c7d330b3859e6725c6d26de21c4e3af7f5ea94df3cde2349ce37",
+
+ "20320dfdad579bb57c6e4acd769dbadf20320dfdad579bb5",
+ "879201b5857ccdea",
+ "0431283cc8bb4dc7750a9d5c68578486932091632a12d0a79f2c54e3d122130881fff727050f317a40fcd1a8d13793458b99fc98254ba6a233e3d95b55cf5a3faff78809999ea4bf",
+ "85d17840eb2af5fc727027336bfd71a2b31bd14a1d9eb64f8a08bfc4f56eaa9ca7654a5ae698287869cc27324813730de4f1384e0b8cfbc472ff5470e3c5e4bd8ceb23dc2d91988c",
+
+ "23abb073a2df34cb3d1fdce6b092582c23abb073a2df34cb",
+ "7d7fbf19e8562d32",
+ "31e718fd95e6d7ca4f94763191add2674ab07c909d88c486916c16d60a048a0cf8cdb631cebec791362cd0c202eb61e166b65c1f65d0047c8aec57d3d84b9e17032442dce148e1191b06a12c284cc41e",
+ "c9a3f75ab6a7cd08a7fd53ca540aafe731d257ee1c379fadcc4cc1a06e7c12bddbeb7562c436d1da849ed072629e82a97b56d9becc25ff4f16f21c5f2a01911604f0b5c49df96cb641faee662ca8aa68",
+
+ "b5cb1504802326c73df186e3e352a20de643b0d63ee30e37",
+ "43f791134c5647ba",
+ "dcc153cef81d6f24",
+ "92538bd8af18d3ba",
+
+ "a49d7564199e97cb529d2c9d97bf2f98d35edf57ba1f7358",
+ "c2e999cb6249023c",
+ "c689aee38a301bb316da75db36f110b5",
+ "e9afaba5ec75ea1bbe65506655bb4ecb",
+
+ "1a5d4c0825072a15a8ad9dfdaeda8c048adffb85bc4fced0",
+ "7fcfa736f7548b6f",
+ "983c3edacd939406010e1bc6ff9e12320ac5008117fa8f84",
+ "d84fa24f38cf451ca2c9adc960120bd8ff9871584fe31cee",
+
+ "d98aadc76d4a3716158c32866efbb9ce834af2297379a49d",
+ "3c5220327c502b44",
+ "6174079dda53ca723ebf00a66837f8d5ce648c08acaa5ee45ffe62210ef79d3e",
+ "f5bd4d600bed77bec78409e3530ebda1d815506ed53103015b87e371ae000958",
+
+ "ef6d3e54266d978ffb0b8ce6689d803e2cd34cc802fd0252",
+ "38bae5bce06d0ad9",
+ "c4f228b537223cd01c0debb5d9d4e12ba71656618d119b2f8f0af29d23efa3a9e43c4c458a1b79a0",
+ "9e3289fb18379f55aa4e45a7e0e6df160b33b75f8627ad0954f8fdcb78cee55a4664caeda1000fe5",
+
+ "625bc19b19df83abfb2f5bec9d4f2062017525a75bc26e70",
+ "bd0cff364ff69a91",
+ "8152d2ab876c3c8201403a5a406d3feaf27319dbea6ad01e24f4d18203704b86de70da6bbb6d638e5aba3ff576b79b28",
+ "706fe7a973fac40e25b2b4499ce527078944c70e976d017b6af86a3a7a6b52943a72ba18a58000d2b61fdc3bfef2bc4a",
+
+ "b6383176046e6880a1023bf45768b5bf5119022fe054bfe5",
+ "ec13ca541c43401e",
+ "cd5a886e9af011346c4dba36a424f96a78a1ddf28aaa4188bf65451f4efaffc7179a6dd237c0ae35d9b672314e5cb032612597f7e462c6f3",
+ "b030f976f46277ee211c4a324d5c87555d1084513a1223d3b84416b52bbc28f4b77f3a9d8d0d91dc37d3dbe8af8be98f74674b02f9a38527",
+
+ "3d8cf273d343b9aedccddacb91ad86206737adc86b4a49a7",
+ "bb3a9a0c71c62ef0",
+ "1fde3991c32ce220b5b6666a9234f2fd7bd24b921829fd9cdc6eb4218be9eac9faa9c2351777349128086b6d58776bc86ff2f76ee1b3b2850a318462b8983fa1",
+ "422ce705a46bb52ad928dab6c863166d617c6fc24003633120d91918314bbf464cea7345c3c35f2042f2d6929735d74d7728f22fea618a0b9cf5b1281acb13fb",
+
+ "fbceb5cb646b925be0b92f7f6b493d5e5b16e9159732732a",
+ "2e17b3c7025ae86b",
+ "4c309bc8e1e464fdd2a2b8978645d668d455f7526bd8d7b6716a722f6a900b815c4a73cc30e788065c1dfca7bf5958a6cc5440a5ebe7f8691c20278cde95db764ff8ce8994ece89c",
+ "c02129bdf4bbbd75e71605a00b12c80db6b4e05308e916615011f09147ed915dd1bc67f27f9e027e4e13df36b55464a31c11b4d1fe3d855d89df492e1a7201b995c1ba16a8dbabee",
+
+ "9b162a0df8ad9b61c88676e3d586434570b902f12a2046e0",
+ "ebd6fefe029ad54b",
+ "f4c1c918e77355c8156f0fd778da52bff121ae5f2f44eaf4d2754946d0e10d1f18ce3a0176e69c18b7d20b6e0d0bee5eb5edfe4bd60e4d92adcd86bce72e76f94ee5cbcaa8b01cfddcea2ade575e66ac",
+ "1ff3c8709f403a8eff291aedf50c010df5c5ff64a8b205f1fce68564798897a390db16ee0d053856b75898009731da290fcc119dad987277aacef694872e880c4bb41471063fae05c89f25e4bd0cad6a",
+
+ NULL
+};
+
+static void
+xor_buf(unsigned char *dst, const unsigned char *src, size_t len)
+{
+ while (len -- > 0) {
+ *dst ++ ^= *src ++;
+ }
+}
+
+static void
+monte_carlo_DES_encrypt(const br_block_cbcenc_class *ve)
+{
+ unsigned char k1[8], k2[8], k3[8];
+ unsigned char buf[8];
+ unsigned char cipher[8];
+ int i, j;
+ br_des_gen_cbcenc_keys v_ec;
+ void *ec;
+
+ ec = &v_ec;
+ hextobin(k1, "9ec2372c86379df4");
+ hextobin(k2, "ad7ac4464f73805d");
+ hextobin(k3, "20c4f87564527c91");
+ hextobin(buf, "b624d6bd41783ab1");
+ hextobin(cipher, "eafd97b190b167fe");
+ for (i = 0; i < 400; i ++) {
+ unsigned char key[24];
+
+ memcpy(key, k1, 8);
+ memcpy(key + 8, k2, 8);
+ memcpy(key + 16, k3, 8);
+ ve->init(ec, key, sizeof key);
+ for (j = 0; j < 10000; j ++) {
+ unsigned char iv[8];
+
+ memset(iv, 0, sizeof iv);
+ ve->run(ec, iv, buf, sizeof buf);
+ switch (j) {
+ case 9997: xor_buf(k3, buf, 8); break;
+ case 9998: xor_buf(k2, buf, 8); break;
+ case 9999: xor_buf(k1, buf, 8); break;
+ }
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ printf(" ");
+ fflush(stdout);
+ check_equals("MC DES encrypt", buf, cipher, sizeof buf);
+}
+
+static void
+monte_carlo_DES_decrypt(const br_block_cbcdec_class *vd)
+{
+ unsigned char k1[8], k2[8], k3[8];
+ unsigned char buf[8];
+ unsigned char plain[8];
+ int i, j;
+ br_des_gen_cbcdec_keys v_dc;
+ void *dc;
+
+ dc = &v_dc;
+ hextobin(k1, "79b63486e0ce37e0");
+ hextobin(k2, "08e65231abae3710");
+ hextobin(k3, "1f5eb69e925ef185");
+ hextobin(buf, "2783aa729432fe96");
+ hextobin(plain, "44937ca532cdbf98");
+ for (i = 0; i < 400; i ++) {
+ unsigned char key[24];
+
+ memcpy(key, k1, 8);
+ memcpy(key + 8, k2, 8);
+ memcpy(key + 16, k3, 8);
+ vd->init(dc, key, sizeof key);
+ for (j = 0; j < 10000; j ++) {
+ unsigned char iv[8];
+
+ memset(iv, 0, sizeof iv);
+ vd->run(dc, iv, buf, sizeof buf);
+ switch (j) {
+ case 9997: xor_buf(k3, buf, 8); break;
+ case 9998: xor_buf(k2, buf, 8); break;
+ case 9999: xor_buf(k1, buf, 8); break;
+ }
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ printf(" ");
+ fflush(stdout);
+ check_equals("MC DES decrypt", buf, plain, sizeof buf);
+}
+
+static void
+test_DES_generic(char *name,
+ const br_block_cbcenc_class *ve,
+ const br_block_cbcdec_class *vd,
+ int with_MC, int with_CBC)
+{
+ size_t u;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ if (ve->block_size != 8 || vd->block_size != 8) {
+ fprintf(stderr, "%s failed: wrong block size\n", name);
+ exit(EXIT_FAILURE);
+ }
+
+ for (u = 0; KAT_DES[u]; u += 3) {
+ unsigned char key[24];
+ unsigned char plain[8];
+ unsigned char cipher[8];
+ unsigned char buf[8];
+ unsigned char iv[8];
+ size_t key_len;
+ br_des_gen_cbcenc_keys v_ec;
+ br_des_gen_cbcdec_keys v_dc;
+ const br_block_cbcenc_class **ec;
+ const br_block_cbcdec_class **dc;
+
+ ec = &v_ec.vtable;
+ dc = &v_dc.vtable;
+ key_len = hextobin(key, KAT_DES[u]);
+ hextobin(plain, KAT_DES[u + 1]);
+ hextobin(cipher, KAT_DES[u + 2]);
+ ve->init(ec, key, key_len);
+ memcpy(buf, plain, sizeof plain);
+ memset(iv, 0, sizeof iv);
+ ve->run(ec, iv, buf, sizeof buf);
+ check_equals("KAT DES encrypt", buf, cipher, sizeof cipher);
+ vd->init(dc, key, key_len);
+ memset(iv, 0, sizeof iv);
+ vd->run(dc, iv, buf, sizeof buf);
+ check_equals("KAT DES decrypt", buf, plain, sizeof plain);
+
+ if (key_len == 8) {
+ memcpy(key + 8, key, 8);
+ memcpy(key + 16, key, 8);
+ ve->init(ec, key, 24);
+ memcpy(buf, plain, sizeof plain);
+ memset(iv, 0, sizeof iv);
+ ve->run(ec, iv, buf, sizeof buf);
+ check_equals("KAT DES->3 encrypt",
+ buf, cipher, sizeof cipher);
+ vd->init(dc, key, 24);
+ memset(iv, 0, sizeof iv);
+ vd->run(dc, iv, buf, sizeof buf);
+ check_equals("KAT DES->3 decrypt",
+ buf, plain, sizeof plain);
+ }
+ }
+
+ if (with_CBC) {
+ for (u = 0; KAT_DES_CBC[u]; u += 4) {
+ unsigned char key[24];
+ unsigned char ivref[8];
+ unsigned char plain[200];
+ unsigned char cipher[200];
+ unsigned char buf[200];
+ unsigned char iv[8];
+ size_t key_len, data_len, v;
+ br_des_gen_cbcenc_keys v_ec;
+ br_des_gen_cbcdec_keys v_dc;
+ const br_block_cbcenc_class **ec;
+ const br_block_cbcdec_class **dc;
+
+ ec = &v_ec.vtable;
+ dc = &v_dc.vtable;
+ key_len = hextobin(key, KAT_DES_CBC[u]);
+ hextobin(ivref, KAT_DES_CBC[u + 1]);
+ data_len = hextobin(plain, KAT_DES_CBC[u + 2]);
+ hextobin(cipher, KAT_DES_CBC[u + 3]);
+ ve->init(ec, key, key_len);
+
+ memcpy(buf, plain, data_len);
+ memcpy(iv, ivref, 8);
+ ve->run(ec, iv, buf, data_len);
+ check_equals("KAT CBC DES encrypt",
+ buf, cipher, data_len);
+ vd->init(dc, key, key_len);
+ memcpy(iv, ivref, 8);
+ vd->run(dc, iv, buf, data_len);
+ check_equals("KAT CBC DES decrypt",
+ buf, plain, data_len);
+
+ memcpy(buf, plain, data_len);
+ memcpy(iv, ivref, 8);
+ for (v = 0; v < data_len; v += 8) {
+ ve->run(ec, iv, buf + v, 8);
+ }
+ check_equals("KAT CBC DES encrypt (2)",
+ buf, cipher, data_len);
+ memcpy(iv, ivref, 8);
+ for (v = 0; v < data_len; v += 8) {
+ vd->run(dc, iv, buf + v, 8);
+ }
+ check_equals("KAT CBC DES decrypt (2)",
+ buf, plain, data_len);
+ }
+ }
+
+ if (with_MC) {
+ monte_carlo_DES_encrypt(ve);
+ monte_carlo_DES_decrypt(vd);
+ }
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_DES_tab(void)
+{
+ test_DES_generic("DES_tab",
+ &br_des_tab_cbcenc_vtable,
+ &br_des_tab_cbcdec_vtable,
+ 1, 1);
+}
+
+static void
+test_DES_ct(void)
+{
+ test_DES_generic("DES_ct",
+ &br_des_ct_cbcenc_vtable,
+ &br_des_ct_cbcdec_vtable,
+ 1, 1);
+}
+
+static const struct {
+ const char *skey;
+ const char *snonce;
+ uint32_t counter;
+ const char *splain;
+ const char *scipher;
+} KAT_CHACHA20[] = {
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "000000000000000000000000",
+ 0,
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000001",
+ "000000000000000000000002",
+ 1,
+ "416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f",
+ "a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6ccc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221"
+ },
+ {
+ "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
+ "000000000000000000000002",
+ 42,
+ "2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e",
+ "62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553ebf39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1"
+ },
+ { 0, 0, 0, 0, 0 }
+};
+
+static void
+test_ChaCha20_generic(const char *name, br_chacha20_run cr)
+{
+ size_t u;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+ if (cr == 0) {
+ printf("UNAVAILABLE\n");
+ return;
+ }
+
+ for (u = 0; KAT_CHACHA20[u].skey; u ++) {
+ unsigned char key[32], nonce[12], plain[400], cipher[400];
+ uint32_t cc;
+ size_t v, len;
+
+ hextobin(key, KAT_CHACHA20[u].skey);
+ hextobin(nonce, KAT_CHACHA20[u].snonce);
+ cc = KAT_CHACHA20[u].counter;
+ len = hextobin(plain, KAT_CHACHA20[u].splain);
+ hextobin(cipher, KAT_CHACHA20[u].scipher);
+
+ for (v = 0; v < len; v ++) {
+ unsigned char tmp[400];
+ size_t w;
+ uint32_t cc2;
+
+ memset(tmp, 0, sizeof tmp);
+ memcpy(tmp, plain, v);
+ if (cr(key, nonce, cc, tmp, v)
+ != cc + (uint32_t)((v + 63) >> 6))
+ {
+ fprintf(stderr, "ChaCha20: wrong counter\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(tmp, cipher, v) != 0) {
+ fprintf(stderr, "ChaCha20 KAT fail (1)\n");
+ exit(EXIT_FAILURE);
+ }
+ for (w = v; w < sizeof tmp; w ++) {
+ if (tmp[w] != 0) {
+ fprintf(stderr, "ChaCha20: overrun\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ for (w = 0, cc2 = cc; w < v; w += 64, cc2 ++) {
+ size_t x;
+
+ x = v - w;
+ if (x > 64) {
+ x = 64;
+ }
+ if (cr(key, nonce, cc2, tmp + w, x)
+ != (cc2 + 1))
+ {
+ fprintf(stderr, "ChaCha20:"
+ " wrong counter (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (memcmp(tmp, plain, v) != 0) {
+ fprintf(stderr, "ChaCha20 KAT fail (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_ChaCha20_ct(void)
+{
+ test_ChaCha20_generic("ChaCha20_ct", &br_chacha20_ct_run);
+}
+
+static void
+test_ChaCha20_sse2(void)
+{
+ test_ChaCha20_generic("ChaCha20_sse2", br_chacha20_sse2_get());
+}
+
+static const struct {
+ const char *splain;
+ const char *saad;
+ const char *skey;
+ const char *snonce;
+ const char *scipher;
+ const char *stag;
+} KAT_POLY1305[] = {
+ {
+ "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e",
+ "50515253c0c1c2c3c4c5c6c7",
+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
+ "070000004041424344454647",
+ "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116",
+ "1ae10b594f09e26a7e902ecbd0600691"
+ },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+static void
+test_Poly1305_inner(const char *name, br_poly1305_run ipoly,
+ br_poly1305_run iref)
+{
+ size_t u;
+ br_hmac_drbg_context rng;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ for (u = 0; KAT_POLY1305[u].skey; u ++) {
+ unsigned char key[32], nonce[12], plain[400], cipher[400];
+ unsigned char aad[400], tag[16], data[400], tmp[16];
+ size_t len, aad_len;
+
+ len = hextobin(plain, KAT_POLY1305[u].splain);
+ aad_len = hextobin(aad, KAT_POLY1305[u].saad);
+ hextobin(key, KAT_POLY1305[u].skey);
+ hextobin(nonce, KAT_POLY1305[u].snonce);
+ hextobin(cipher, KAT_POLY1305[u].scipher);
+ hextobin(tag, KAT_POLY1305[u].stag);
+
+ memcpy(data, plain, len);
+ ipoly(key, nonce, data, len,
+ aad, aad_len, tmp, br_chacha20_ct_run, 1);
+ check_equals("ChaCha20+Poly1305 KAT (1)", data, cipher, len);
+ check_equals("ChaCha20+Poly1305 KAT (2)", tmp, tag, 16);
+ ipoly(key, nonce, data, len,
+ aad, aad_len, tmp, br_chacha20_ct_run, 0);
+ check_equals("ChaCha20+Poly1305 KAT (3)", data, plain, len);
+ check_equals("ChaCha20+Poly1305 KAT (4)", tmp, tag, 16);
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" ");
+ fflush(stdout);
+
+ /*
+ * We compare the "ipoly" and "iref" implementations together on
+ * a bunch of pseudo-random messages.
+ */
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, "seed for Poly1305", 17);
+ for (u = 0; u < 100; u ++) {
+ unsigned char plain[100], aad[100], tmp[100];
+ unsigned char key[32], iv[12], tag1[16], tag2[16];
+
+ br_hmac_drbg_generate(&rng, key, sizeof key);
+ br_hmac_drbg_generate(&rng, iv, sizeof iv);
+ br_hmac_drbg_generate(&rng, plain, u);
+ br_hmac_drbg_generate(&rng, aad, u);
+ memcpy(tmp, plain, u);
+ memset(tmp + u, 0xFF, (sizeof tmp) - u);
+ ipoly(key, iv, tmp, u, aad, u, tag1,
+ &br_chacha20_ct_run, 1);
+ memset(tmp + u, 0x00, (sizeof tmp) - u);
+ iref(key, iv, tmp, u, aad, u, tag2,
+ &br_chacha20_ct_run, 0);
+ if (memcmp(tmp, plain, u) != 0) {
+ fprintf(stderr, "cross enc/dec failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(tag1, tag2, sizeof tag1) != 0) {
+ fprintf(stderr, "cross MAC failed\n");
+ exit(EXIT_FAILURE);
+ }
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_Poly1305_ctmul(void)
+{
+ test_Poly1305_inner("Poly1305_ctmul", &br_poly1305_ctmul_run,
+ &br_poly1305_i15_run);
+}
+
+static void
+test_Poly1305_ctmul32(void)
+{
+ test_Poly1305_inner("Poly1305_ctmul32", &br_poly1305_ctmul32_run,
+ &br_poly1305_i15_run);
+}
+
+static void
+test_Poly1305_i15(void)
+{
+ test_Poly1305_inner("Poly1305_i15", &br_poly1305_i15_run,
+ &br_poly1305_ctmul_run);
+}
+
+static void
+test_Poly1305_ctmulq(void)
+{
+ br_poly1305_run bp;
+
+ bp = br_poly1305_ctmulq_get();
+ if (bp == 0) {
+ printf("Test Poly1305_ctmulq: UNAVAILABLE\n");
+ } else {
+ test_Poly1305_inner("Poly1305_ctmulq", bp,
+ &br_poly1305_ctmul_run);
+ }
+}
+
+/*
+ * A 1024-bit RSA key, generated with OpenSSL.
+ */
+static const unsigned char RSA_N[] = {
+ 0xBF, 0xB4, 0xA6, 0x2E, 0x87, 0x3F, 0x9C, 0x8D,
+ 0xA0, 0xC4, 0x2E, 0x7B, 0x59, 0x36, 0x0F, 0xB0,
+ 0xFF, 0xE1, 0x25, 0x49, 0xE5, 0xE6, 0x36, 0xB0,
+ 0x48, 0xC2, 0x08, 0x6B, 0x77, 0xA7, 0xC0, 0x51,
+ 0x66, 0x35, 0x06, 0xA9, 0x59, 0xDF, 0x17, 0x7F,
+ 0x15, 0xF6, 0xB4, 0xE5, 0x44, 0xEE, 0x72, 0x3C,
+ 0x53, 0x11, 0x52, 0xC9, 0xC9, 0x61, 0x4F, 0x92,
+ 0x33, 0x64, 0x70, 0x43, 0x07, 0xF1, 0x3F, 0x7F,
+ 0x15, 0xAC, 0xF0, 0xC1, 0x54, 0x7D, 0x55, 0xC0,
+ 0x29, 0xDC, 0x9E, 0xCC, 0xE4, 0x1D, 0x11, 0x72,
+ 0x45, 0xF4, 0xD2, 0x70, 0xFC, 0x34, 0xB2, 0x1F,
+ 0xF3, 0xAD, 0x6A, 0xF0, 0xE5, 0x56, 0x11, 0xF8,
+ 0x0C, 0x3A, 0x8B, 0x04, 0x46, 0x7C, 0x77, 0xD9,
+ 0x41, 0x1F, 0x40, 0xBE, 0x93, 0x80, 0x9D, 0x23,
+ 0x75, 0x80, 0x12, 0x26, 0x5A, 0x72, 0x1C, 0xDD,
+ 0x47, 0xB3, 0x2A, 0x33, 0xD8, 0x19, 0x61, 0xE3
+};
+static const unsigned char RSA_E[] = {
+ 0x01, 0x00, 0x01
+};
+/* unused
+static const unsigned char RSA_D[] = {
+ 0xAE, 0x56, 0x0B, 0x56, 0x7E, 0xDA, 0x83, 0x75,
+ 0x6C, 0xC1, 0x5C, 0x00, 0x02, 0x96, 0x1E, 0x58,
+ 0xF9, 0xA9, 0xF7, 0x2E, 0x27, 0xEB, 0x5E, 0xCA,
+ 0x9B, 0xB0, 0x10, 0xD6, 0x22, 0x7F, 0xA4, 0x6E,
+ 0xA2, 0x03, 0x10, 0xE6, 0xCB, 0x7B, 0x0D, 0x34,
+ 0x1E, 0x76, 0x37, 0xF5, 0xD3, 0xE5, 0x00, 0x70,
+ 0x09, 0x9E, 0xD4, 0x69, 0xFB, 0x40, 0x0A, 0x8B,
+ 0xCB, 0x3E, 0xC8, 0xB4, 0xBC, 0xB1, 0x50, 0xEA,
+ 0x9D, 0xD9, 0x89, 0x8A, 0x98, 0x40, 0x79, 0xD1,
+ 0x07, 0x66, 0xA7, 0x90, 0x63, 0x82, 0xB1, 0xE0,
+ 0x24, 0xD0, 0x89, 0x6A, 0xEC, 0xC5, 0xF3, 0x21,
+ 0x7D, 0xB8, 0xA5, 0x45, 0x3A, 0x3B, 0x34, 0x42,
+ 0xC2, 0x82, 0x3C, 0x8D, 0xFA, 0x5D, 0xA0, 0xA8,
+ 0x24, 0xC8, 0x40, 0x22, 0x19, 0xCB, 0xB5, 0x85,
+ 0x67, 0x69, 0x60, 0xE4, 0xD0, 0x7E, 0xA3, 0x3B,
+ 0xF7, 0x70, 0x50, 0xC9, 0x5C, 0x97, 0x29, 0x49
+};
+*/
+static const unsigned char RSA_P[] = {
+ 0xF2, 0xE7, 0x6F, 0x66, 0x2E, 0xC4, 0x03, 0xD4,
+ 0x89, 0x24, 0xCC, 0xE1, 0xCD, 0x3F, 0x01, 0x82,
+ 0xC1, 0xFB, 0xAF, 0x44, 0xFA, 0xCC, 0x0E, 0xAA,
+ 0x9D, 0x74, 0xA9, 0x65, 0xEF, 0xED, 0x4C, 0x87,
+ 0xF0, 0xB3, 0xC6, 0xEA, 0x61, 0x85, 0xDE, 0x4E,
+ 0x66, 0xB2, 0x5A, 0x9F, 0x7A, 0x41, 0xC5, 0x66,
+ 0x57, 0xDF, 0x88, 0xF0, 0xB5, 0xF2, 0xC7, 0x7E,
+ 0xE6, 0x55, 0x21, 0x96, 0x83, 0xD8, 0xAB, 0x57
+};
+static const unsigned char RSA_Q[] = {
+ 0xCA, 0x0A, 0x92, 0xBF, 0x58, 0xB0, 0x2E, 0xF6,
+ 0x66, 0x50, 0xB1, 0x48, 0x29, 0x42, 0x86, 0x6C,
+ 0x98, 0x06, 0x7E, 0xB8, 0xB5, 0x4F, 0xFB, 0xC4,
+ 0xF3, 0xC3, 0x36, 0x91, 0x07, 0xB6, 0xDB, 0xE9,
+ 0x56, 0x3C, 0x51, 0x7D, 0xB5, 0xEC, 0x0A, 0xA9,
+ 0x7C, 0x66, 0xF9, 0xD8, 0x25, 0xDE, 0xD2, 0x94,
+ 0x5A, 0x58, 0xF1, 0x93, 0xE4, 0xF0, 0x5F, 0x27,
+ 0xBD, 0x83, 0xC7, 0xCA, 0x48, 0x6A, 0xB2, 0x55
+};
+static const unsigned char RSA_DP[] = {
+ 0xAF, 0x97, 0xBE, 0x60, 0x0F, 0xCE, 0x83, 0x36,
+ 0x51, 0x2D, 0xD9, 0x2E, 0x22, 0x41, 0x39, 0xC6,
+ 0x5C, 0x94, 0xA4, 0xCF, 0x28, 0xBD, 0xFA, 0x9C,
+ 0x3B, 0xD6, 0xE9, 0xDE, 0x56, 0xE3, 0x24, 0x3F,
+ 0xE1, 0x31, 0x14, 0xCA, 0xBA, 0x55, 0x1B, 0xAF,
+ 0x71, 0x6D, 0xDD, 0x35, 0x0C, 0x1C, 0x1F, 0xA7,
+ 0x2C, 0x3E, 0xDB, 0xAF, 0xA6, 0xD8, 0x2A, 0x7F,
+ 0x01, 0xE2, 0xE8, 0xB4, 0xF5, 0xFA, 0xDB, 0x61
+};
+static const unsigned char RSA_DQ[] = {
+ 0x29, 0xC0, 0x4B, 0x98, 0xFD, 0x13, 0xD3, 0x70,
+ 0x99, 0xAE, 0x1D, 0x24, 0x83, 0x5A, 0x3A, 0xFB,
+ 0x1F, 0xE3, 0x5F, 0xB6, 0x7D, 0xC9, 0x5C, 0x86,
+ 0xD3, 0xB4, 0xC8, 0x86, 0xE9, 0xE8, 0x30, 0xC3,
+ 0xA4, 0x4D, 0x6C, 0xAD, 0xA4, 0xB5, 0x75, 0x72,
+ 0x96, 0xC1, 0x94, 0xE9, 0xC4, 0xD1, 0xAA, 0x04,
+ 0x7C, 0x33, 0x1B, 0x20, 0xEB, 0xD3, 0x7C, 0x66,
+ 0x72, 0xF4, 0x53, 0x8A, 0x0A, 0xB2, 0xF9, 0xCD
+};
+static const unsigned char RSA_IQ[] = {
+ 0xE8, 0xEB, 0x04, 0x79, 0xA5, 0xC1, 0x79, 0xDE,
+ 0xD5, 0x49, 0xA1, 0x0B, 0x48, 0xB9, 0x0E, 0x55,
+ 0x74, 0x2C, 0x54, 0xEE, 0xA8, 0xB0, 0x01, 0xC2,
+ 0xD2, 0x3C, 0x3E, 0x47, 0x3A, 0x7C, 0xC8, 0x3D,
+ 0x2E, 0x33, 0x54, 0x4D, 0x40, 0x29, 0x41, 0x74,
+ 0xBA, 0xE1, 0x93, 0x09, 0xEC, 0xE0, 0x1B, 0x4D,
+ 0x1F, 0x2A, 0xCA, 0x4A, 0x0B, 0x5F, 0xE6, 0xBE,
+ 0x59, 0x0A, 0xC4, 0xC9, 0xD9, 0x82, 0xAC, 0xE1
+};
+
+static const br_rsa_public_key RSA_PK = {
+ (void *)RSA_N, sizeof RSA_N,
+ (void *)RSA_E, sizeof RSA_E
+};
+
+static const br_rsa_private_key RSA_SK = {
+ 1024,
+ (void *)RSA_P, sizeof RSA_P,
+ (void *)RSA_Q, sizeof RSA_Q,
+ (void *)RSA_DP, sizeof RSA_DP,
+ (void *)RSA_DQ, sizeof RSA_DQ,
+ (void *)RSA_IQ, sizeof RSA_IQ
+};
+
+/*
+ * A 2048-bit RSA key, generated with OpenSSL.
+ */
+static const unsigned char RSA2048_N[] = {
+ 0xEA, 0xB1, 0xB0, 0x87, 0x60, 0xE2, 0x69, 0xF5,
+ 0xC9, 0x3F, 0xCB, 0x4F, 0x9E, 0x7D, 0xD0, 0x56,
+ 0x54, 0x8F, 0xF5, 0x59, 0x97, 0x04, 0x3F, 0x30,
+ 0xE1, 0xFB, 0x7B, 0xF5, 0xA0, 0xEB, 0xA7, 0x7B,
+ 0x29, 0x96, 0x7B, 0x32, 0x48, 0x48, 0xA4, 0x99,
+ 0x90, 0x92, 0x48, 0xFB, 0xDC, 0xEC, 0x8A, 0x3B,
+ 0xE0, 0x57, 0x6E, 0xED, 0x1C, 0x5B, 0x78, 0xCF,
+ 0x07, 0x41, 0x96, 0x4C, 0x2F, 0xA2, 0xD1, 0xC8,
+ 0xA0, 0x5F, 0xFC, 0x2A, 0x5B, 0x3F, 0xBC, 0xD7,
+ 0xE6, 0x91, 0xF1, 0x44, 0xD6, 0xD8, 0x41, 0x66,
+ 0x3E, 0x80, 0xEE, 0x98, 0x73, 0xD5, 0x32, 0x60,
+ 0x7F, 0xDF, 0xBF, 0xB2, 0x0B, 0xA5, 0xCA, 0x11,
+ 0x88, 0x1A, 0x0E, 0xA1, 0x61, 0x4C, 0x5A, 0x70,
+ 0xCE, 0x12, 0xC0, 0x61, 0xF5, 0x50, 0x0E, 0xF6,
+ 0xC1, 0xC2, 0x88, 0x8B, 0xE5, 0xCE, 0xAE, 0x90,
+ 0x65, 0x23, 0xA7, 0xAD, 0xCB, 0x04, 0x17, 0x00,
+ 0xA2, 0xDB, 0xB0, 0x21, 0x49, 0xDD, 0x3C, 0x2E,
+ 0x8C, 0x47, 0x27, 0xF2, 0x84, 0x51, 0x63, 0xEB,
+ 0xF8, 0xAF, 0x63, 0xA7, 0x89, 0xE1, 0xF0, 0x2F,
+ 0xF9, 0x9C, 0x0A, 0x8A, 0xBC, 0x57, 0x05, 0xB0,
+ 0xEF, 0xA0, 0xDA, 0x67, 0x70, 0xAF, 0x3F, 0xA4,
+ 0x92, 0xFC, 0x4A, 0xAC, 0xEF, 0x89, 0x41, 0x58,
+ 0x57, 0x63, 0x0F, 0x6A, 0x89, 0x68, 0x45, 0x4C,
+ 0x20, 0xF9, 0x7F, 0x50, 0x9D, 0x8C, 0x52, 0xC4,
+ 0xC1, 0x33, 0xCD, 0x42, 0x35, 0x12, 0xEC, 0x82,
+ 0xF9, 0xC1, 0xB7, 0x60, 0x7B, 0x52, 0x61, 0xD0,
+ 0xAE, 0xFD, 0x4B, 0x68, 0xB1, 0x55, 0x0E, 0xAB,
+ 0x99, 0x24, 0x52, 0x60, 0x8E, 0xDB, 0x90, 0x34,
+ 0x61, 0xE3, 0x95, 0x7C, 0x34, 0x64, 0x06, 0xCB,
+ 0x44, 0x17, 0x70, 0x78, 0xC1, 0x1B, 0x87, 0x8F,
+ 0xCF, 0xB0, 0x7D, 0x93, 0x59, 0x84, 0x49, 0xF5,
+ 0x55, 0xBB, 0x48, 0xCA, 0xD3, 0x76, 0x1E, 0x7F
+};
+static const unsigned char RSA2048_E[] = {
+ 0x01, 0x00, 0x01
+};
+static const unsigned char RSA2048_P[] = {
+ 0xF9, 0xA7, 0xB5, 0xC4, 0xE8, 0x52, 0xEC, 0xB1,
+ 0x33, 0x6A, 0x68, 0x32, 0x63, 0x2D, 0xBA, 0xE5,
+ 0x61, 0x14, 0x69, 0x82, 0xC8, 0x31, 0x14, 0xD5,
+ 0xC2, 0x6C, 0x1A, 0xBE, 0xA0, 0x68, 0xA6, 0xC5,
+ 0xEA, 0x40, 0x59, 0xFB, 0x0A, 0x30, 0x3D, 0xD5,
+ 0xDD, 0x94, 0xAE, 0x0C, 0x9F, 0xEE, 0x19, 0x0C,
+ 0xA8, 0xF2, 0x85, 0x27, 0x60, 0xAA, 0xD5, 0x7C,
+ 0x59, 0x91, 0x1F, 0xAF, 0x5E, 0x00, 0xC8, 0x2D,
+ 0xCA, 0xB4, 0x70, 0xA1, 0xF8, 0x8C, 0x0A, 0xB3,
+ 0x08, 0x95, 0x03, 0x9E, 0xA4, 0x6B, 0x9D, 0x55,
+ 0x47, 0xE0, 0xEC, 0xB3, 0x21, 0x7C, 0xE4, 0x16,
+ 0x91, 0xE3, 0xD7, 0x1B, 0x3D, 0x81, 0xF1, 0xED,
+ 0x16, 0xF9, 0x05, 0x0E, 0xA6, 0x9F, 0x37, 0x73,
+ 0x18, 0x1B, 0x9C, 0x9D, 0x33, 0xAD, 0x25, 0xEF,
+ 0x3A, 0xC0, 0x4B, 0x34, 0x24, 0xF5, 0xFD, 0x59,
+ 0xF5, 0x65, 0xE6, 0x92, 0x2A, 0x04, 0x06, 0x3D
+};
+static const unsigned char RSA2048_Q[] = {
+ 0xF0, 0xA8, 0xA4, 0x20, 0xDD, 0xF3, 0x99, 0xE6,
+ 0x1C, 0xB1, 0x21, 0xE8, 0x66, 0x68, 0x48, 0x00,
+ 0x04, 0xE3, 0x21, 0xA3, 0xE8, 0xC5, 0xFD, 0x85,
+ 0x6D, 0x2C, 0x98, 0xE3, 0x36, 0x39, 0x3E, 0x80,
+ 0xB7, 0x36, 0xA5, 0xA9, 0xBB, 0xEB, 0x1E, 0xB8,
+ 0xEB, 0x44, 0x65, 0xE8, 0x81, 0x7D, 0xE0, 0x87,
+ 0xC1, 0x08, 0x94, 0xDD, 0x92, 0x40, 0xF4, 0x8B,
+ 0x3C, 0xB5, 0xC1, 0xAD, 0x9D, 0x4C, 0x14, 0xCD,
+ 0xD9, 0x2D, 0xB6, 0xE4, 0x99, 0xB3, 0x71, 0x63,
+ 0x64, 0xE1, 0x31, 0x7E, 0x34, 0x95, 0x96, 0x52,
+ 0x85, 0x27, 0xBE, 0x40, 0x10, 0x0A, 0x9E, 0x01,
+ 0x1C, 0xBB, 0xB2, 0x5B, 0x40, 0x85, 0x65, 0x6E,
+ 0xA0, 0x88, 0x73, 0xF6, 0x22, 0xCC, 0x23, 0x26,
+ 0x62, 0xAD, 0x92, 0x57, 0x57, 0xF4, 0xD4, 0xDF,
+ 0xD9, 0x7C, 0xDE, 0xAD, 0xD2, 0x1F, 0x32, 0x29,
+ 0xBA, 0xE7, 0xE2, 0x32, 0xA1, 0xA0, 0xBF, 0x6B
+};
+static const unsigned char RSA2048_DP[] = {
+ 0xB2, 0xF9, 0xD7, 0x66, 0xC5, 0x83, 0x05, 0x6A,
+ 0x77, 0xC8, 0xB5, 0xD0, 0x41, 0xA7, 0xBC, 0x0F,
+ 0xCB, 0x4B, 0xFD, 0xE4, 0x23, 0x2E, 0x84, 0x98,
+ 0x46, 0x1C, 0x88, 0x03, 0xD7, 0x2D, 0x8F, 0x39,
+ 0xDD, 0x98, 0xAA, 0xA9, 0x3D, 0x01, 0x9E, 0xA2,
+ 0xDE, 0x8A, 0x43, 0x48, 0x8B, 0xB2, 0xFE, 0xC4,
+ 0x43, 0xAE, 0x31, 0x65, 0x2C, 0x78, 0xEC, 0x39,
+ 0x8C, 0x60, 0x6C, 0xCD, 0xA4, 0xDF, 0x7C, 0xA2,
+ 0xCF, 0x6A, 0x12, 0x41, 0x1B, 0xD5, 0x11, 0xAA,
+ 0x8D, 0xE1, 0x7E, 0x49, 0xD1, 0xE7, 0xD0, 0x50,
+ 0x1E, 0x0A, 0x92, 0xC6, 0x4C, 0xA0, 0xA3, 0x47,
+ 0xC6, 0xE9, 0x07, 0x01, 0xE1, 0x53, 0x72, 0x23,
+ 0x9D, 0x4F, 0x82, 0x9F, 0xA1, 0x36, 0x0D, 0x63,
+ 0x76, 0x89, 0xFC, 0xF9, 0xF9, 0xDD, 0x0C, 0x8F,
+ 0xF7, 0x97, 0x79, 0x92, 0x75, 0x58, 0xE0, 0x7B,
+ 0x08, 0x61, 0x38, 0x2D, 0xDA, 0xEF, 0x2D, 0xA5
+};
+static const unsigned char RSA2048_DQ[] = {
+ 0x8B, 0x69, 0x56, 0x33, 0x08, 0x00, 0x8F, 0x3D,
+ 0xC3, 0x8F, 0x45, 0x52, 0x48, 0xC8, 0xCE, 0x34,
+ 0xDC, 0x9F, 0xEB, 0x23, 0xF5, 0xBB, 0x84, 0x62,
+ 0xDF, 0xDC, 0xBE, 0xF0, 0x98, 0xBF, 0xCE, 0x9A,
+ 0x68, 0x08, 0x4B, 0x2D, 0xA9, 0x83, 0xC9, 0xF7,
+ 0x5B, 0xAA, 0xF2, 0xD2, 0x1E, 0xF9, 0x99, 0xB1,
+ 0x6A, 0xBC, 0x9A, 0xE8, 0x44, 0x4A, 0x46, 0x9F,
+ 0xC6, 0x5A, 0x90, 0x49, 0x0F, 0xDF, 0x3C, 0x0A,
+ 0x07, 0x6E, 0xB9, 0x0D, 0x72, 0x90, 0x85, 0xF6,
+ 0x0B, 0x41, 0x7D, 0x17, 0x5C, 0x44, 0xEF, 0xA0,
+ 0xFC, 0x2C, 0x0A, 0xC5, 0x37, 0xC5, 0xBE, 0xC4,
+ 0x6C, 0x2D, 0xBB, 0x63, 0xAB, 0x5B, 0xDB, 0x67,
+ 0x9B, 0xAD, 0x90, 0x67, 0x9C, 0xBE, 0xDE, 0xF9,
+ 0xE4, 0x9E, 0x22, 0x31, 0x60, 0xED, 0x9E, 0xC7,
+ 0xD2, 0x48, 0xC9, 0x02, 0xAE, 0xBF, 0x8D, 0xA2,
+ 0xA8, 0xF8, 0x9D, 0x8B, 0xB1, 0x1F, 0xDA, 0xE3
+};
+static const unsigned char RSA2048_IQ[] = {
+ 0xB5, 0x48, 0xD4, 0x48, 0x5A, 0x33, 0xCD, 0x13,
+ 0xFE, 0xC6, 0xF7, 0x01, 0x0A, 0x3E, 0x40, 0xA3,
+ 0x45, 0x94, 0x6F, 0x85, 0xE4, 0x68, 0x66, 0xEC,
+ 0x69, 0x6A, 0x3E, 0xE0, 0x62, 0x3F, 0x0C, 0xEF,
+ 0x21, 0xCC, 0xDA, 0xAD, 0x75, 0x98, 0x12, 0xCA,
+ 0x9E, 0x31, 0xDD, 0x95, 0x0D, 0xBD, 0x55, 0xEB,
+ 0x92, 0xF7, 0x9E, 0xBD, 0xFC, 0x28, 0x35, 0x96,
+ 0x31, 0xDC, 0x53, 0x80, 0xA3, 0x57, 0x89, 0x3C,
+ 0x4A, 0xEC, 0x40, 0x75, 0x13, 0xAC, 0x4F, 0x36,
+ 0x3A, 0x86, 0x9A, 0xA6, 0x58, 0xC9, 0xED, 0xCB,
+ 0xD6, 0xBB, 0xB2, 0xD9, 0xAA, 0x04, 0xC4, 0xE8,
+ 0x47, 0x3E, 0xBD, 0x14, 0x9B, 0x8F, 0x61, 0x70,
+ 0x69, 0x66, 0x23, 0x62, 0x18, 0xE3, 0x52, 0x98,
+ 0xE3, 0x22, 0xE9, 0x6F, 0xDA, 0x28, 0x68, 0x08,
+ 0xB8, 0xB9, 0x8B, 0x97, 0x8B, 0x77, 0x3F, 0xCA,
+ 0x9D, 0x9D, 0xBE, 0xD5, 0x2D, 0x3E, 0xC2, 0x11
+};
+
+static const br_rsa_public_key RSA2048_PK = {
+ (void *)RSA2048_N, sizeof RSA2048_N,
+ (void *)RSA2048_E, sizeof RSA2048_E
+};
+
+static const br_rsa_private_key RSA2048_SK = {
+ 2048,
+ (void *)RSA2048_P, sizeof RSA2048_P,
+ (void *)RSA2048_Q, sizeof RSA2048_Q,
+ (void *)RSA2048_DP, sizeof RSA2048_DP,
+ (void *)RSA2048_DQ, sizeof RSA2048_DQ,
+ (void *)RSA2048_IQ, sizeof RSA2048_IQ
+};
+
+/*
+ * A 4096-bit RSA key, generated with OpenSSL.
+ */
+static const unsigned char RSA4096_N[] = {
+ 0xAA, 0x17, 0x71, 0xBC, 0x92, 0x3E, 0xB5, 0xBD,
+ 0x3E, 0x64, 0xCF, 0x03, 0x9B, 0x24, 0x65, 0x33,
+ 0x5F, 0xB4, 0x47, 0x89, 0xE5, 0x63, 0xE4, 0xA0,
+ 0x5A, 0x51, 0x95, 0x07, 0x73, 0xEE, 0x00, 0xF6,
+ 0x3E, 0x31, 0x0E, 0xDA, 0x15, 0xC3, 0xAA, 0x21,
+ 0x6A, 0xCD, 0xFF, 0x46, 0x6B, 0xDF, 0x0A, 0x7F,
+ 0x8A, 0xC2, 0x25, 0x19, 0x47, 0x44, 0xD8, 0x52,
+ 0xC1, 0x56, 0x25, 0x6A, 0xE0, 0xD2, 0x61, 0x11,
+ 0x2C, 0xF7, 0x73, 0x9F, 0x5F, 0x74, 0xAA, 0xDD,
+ 0xDE, 0xAF, 0x81, 0xF6, 0x0C, 0x1A, 0x3A, 0xF9,
+ 0xC5, 0x47, 0x82, 0x75, 0x1D, 0x41, 0xF0, 0xB2,
+ 0xFD, 0xBA, 0xE2, 0xA4, 0xA1, 0xB8, 0x32, 0x48,
+ 0x06, 0x0D, 0x29, 0x2F, 0x44, 0x14, 0xF5, 0xAC,
+ 0x54, 0x83, 0xC4, 0xB6, 0x85, 0x85, 0x9B, 0x1C,
+ 0x05, 0x61, 0x28, 0x62, 0x24, 0xA8, 0xF0, 0xE6,
+ 0x80, 0xA7, 0x91, 0xE8, 0xC7, 0x8E, 0x52, 0x17,
+ 0xBE, 0xAF, 0xC6, 0x0A, 0xA3, 0xFB, 0xD1, 0x04,
+ 0x15, 0x3B, 0x14, 0x35, 0xA5, 0x41, 0xF5, 0x30,
+ 0xFE, 0xEF, 0x53, 0xA7, 0x89, 0x91, 0x78, 0x30,
+ 0xBE, 0x3A, 0xB1, 0x4B, 0x2E, 0x4A, 0x0E, 0x25,
+ 0x1D, 0xCF, 0x51, 0x54, 0x52, 0xF1, 0x88, 0x85,
+ 0x36, 0x23, 0xDE, 0xBA, 0x66, 0x25, 0x60, 0x8D,
+ 0x45, 0xD7, 0xD8, 0x10, 0x41, 0x64, 0xC7, 0x4B,
+ 0xCE, 0x72, 0x13, 0xD7, 0x20, 0xF8, 0x2A, 0x74,
+ 0xA5, 0x05, 0xF4, 0x5A, 0x90, 0xF4, 0x9C, 0xE7,
+ 0xC9, 0xCF, 0x1E, 0xD5, 0x9C, 0xAC, 0xE5, 0x00,
+ 0x83, 0x73, 0x9F, 0xE7, 0xC6, 0x93, 0xC0, 0x06,
+ 0xA7, 0xB8, 0xF8, 0x46, 0x90, 0xC8, 0x78, 0x27,
+ 0x2E, 0xCC, 0xC0, 0x2A, 0x20, 0xC5, 0xFC, 0x63,
+ 0x22, 0xA1, 0xD6, 0x16, 0xAD, 0x9C, 0xD6, 0xFC,
+ 0x7A, 0x6E, 0x9C, 0x98, 0x51, 0xEE, 0x6B, 0x6D,
+ 0x8F, 0xEF, 0xCE, 0x7C, 0x5D, 0x16, 0xB0, 0xCE,
+ 0x9C, 0xEE, 0x92, 0xCF, 0xB7, 0xEB, 0x41, 0x36,
+ 0x3A, 0x6C, 0xF2, 0x0D, 0x26, 0x11, 0x2F, 0x6C,
+ 0x27, 0x62, 0xA2, 0xCC, 0x63, 0x53, 0xBD, 0xFC,
+ 0x9F, 0xBE, 0x9B, 0xBD, 0xE5, 0xA7, 0xDA, 0xD4,
+ 0xF8, 0xED, 0x5E, 0x59, 0x2D, 0xAC, 0xCD, 0x13,
+ 0xEB, 0xE5, 0x9E, 0x39, 0x82, 0x8B, 0xFD, 0xA8,
+ 0xFB, 0xCB, 0x86, 0x27, 0xC7, 0x4B, 0x4C, 0xD0,
+ 0xBA, 0x12, 0xD0, 0x76, 0x1A, 0xDB, 0x30, 0xC5,
+ 0xB3, 0x2C, 0x4C, 0xC5, 0x32, 0x03, 0x05, 0x67,
+ 0x8D, 0xD0, 0x14, 0x37, 0x59, 0x2B, 0xE3, 0x1C,
+ 0x25, 0x3E, 0xA5, 0xE4, 0xF1, 0x0D, 0x34, 0xBB,
+ 0xD5, 0xF6, 0x76, 0x45, 0x5B, 0x0F, 0x1E, 0x07,
+ 0x0A, 0xBA, 0x9D, 0x71, 0x87, 0xDE, 0x45, 0x50,
+ 0xE5, 0x0F, 0x32, 0xBB, 0x5C, 0x32, 0x2D, 0x40,
+ 0xCD, 0x19, 0x95, 0x4E, 0xC5, 0x54, 0x3A, 0x9A,
+ 0x46, 0x9B, 0x85, 0xFE, 0x53, 0xB7, 0xD8, 0x65,
+ 0x6D, 0x68, 0x0C, 0xBB, 0xE3, 0x3D, 0x8E, 0x64,
+ 0xBE, 0x27, 0x15, 0xAB, 0x12, 0x20, 0xD9, 0x84,
+ 0xF5, 0x02, 0xE4, 0xBB, 0xDD, 0xAB, 0x59, 0x51,
+ 0xF4, 0xE1, 0x79, 0xBE, 0xB8, 0xA3, 0x8E, 0xD1,
+ 0x1C, 0xB0, 0xFA, 0x48, 0x76, 0xC2, 0x9D, 0x7A,
+ 0x01, 0xA5, 0xAF, 0x8C, 0xBA, 0xAA, 0x4C, 0x06,
+ 0x2B, 0x0A, 0x62, 0xF0, 0x79, 0x5B, 0x42, 0xFC,
+ 0xF8, 0xBF, 0xD4, 0xDD, 0x62, 0x32, 0xE3, 0xCE,
+ 0xF1, 0x2C, 0xE6, 0xED, 0xA8, 0x8A, 0x41, 0xA3,
+ 0xC1, 0x1E, 0x07, 0xB6, 0x43, 0x10, 0x80, 0xB7,
+ 0xF3, 0xD0, 0x53, 0x2A, 0x9A, 0x98, 0xA7, 0x4F,
+ 0x9E, 0xA3, 0x3E, 0x1B, 0xDA, 0x93, 0x15, 0xF2,
+ 0xF4, 0x20, 0xA5, 0xA8, 0x4F, 0x8A, 0xBA, 0xED,
+ 0xB1, 0x17, 0x6C, 0x0F, 0xD9, 0x8F, 0x38, 0x11,
+ 0xF3, 0xD9, 0x5E, 0x88, 0xA1, 0xA1, 0x82, 0x8B,
+ 0x30, 0xD7, 0xC6, 0xCE, 0x4E, 0x30, 0x55, 0x57
+};
+static const unsigned char RSA4096_E[] = {
+ 0x01, 0x00, 0x01
+};
+static const unsigned char RSA4096_P[] = {
+ 0xD3, 0x7A, 0x22, 0xD8, 0x9B, 0xBF, 0x42, 0xB4,
+ 0x53, 0x04, 0x10, 0x6A, 0x84, 0xFD, 0x7C, 0x1D,
+ 0xF6, 0xF4, 0x10, 0x65, 0xAA, 0xE5, 0xE1, 0x4E,
+ 0xB4, 0x37, 0xF7, 0xAC, 0xF7, 0xD3, 0xB2, 0x3B,
+ 0xFE, 0xE7, 0x63, 0x42, 0xE9, 0xF0, 0x3C, 0xE0,
+ 0x42, 0xB4, 0xBB, 0x09, 0xD0, 0xB2, 0x7C, 0x70,
+ 0xA4, 0x11, 0x97, 0x90, 0x01, 0xD0, 0x0E, 0x7B,
+ 0xAF, 0x7D, 0x30, 0x4E, 0x6B, 0x3A, 0xCC, 0x50,
+ 0x4E, 0xAF, 0x2F, 0xC3, 0xC2, 0x4F, 0x7E, 0xC5,
+ 0xB3, 0x76, 0x33, 0xFB, 0xA7, 0xB1, 0x96, 0xA5,
+ 0x46, 0x41, 0xC6, 0xDA, 0x5A, 0xFD, 0x17, 0x0A,
+ 0x6A, 0x86, 0x54, 0x83, 0xE1, 0x57, 0xE7, 0xAF,
+ 0x8C, 0x42, 0xE5, 0x39, 0xF2, 0xC7, 0xFC, 0x4A,
+ 0x3D, 0x3C, 0x94, 0x89, 0xC2, 0xC6, 0x2D, 0x0A,
+ 0x5F, 0xD0, 0x21, 0x23, 0x5C, 0xC9, 0xC8, 0x44,
+ 0x8A, 0x96, 0x72, 0x4D, 0x96, 0xC6, 0x17, 0x0C,
+ 0x36, 0x43, 0x7F, 0xD8, 0xA0, 0x7A, 0x31, 0x7E,
+ 0xCE, 0x13, 0xE3, 0x13, 0x2E, 0xE0, 0x91, 0xC2,
+ 0x61, 0x13, 0x16, 0x8D, 0x99, 0xCB, 0xA9, 0x2C,
+ 0x4D, 0x9D, 0xDD, 0x1D, 0x03, 0xE7, 0xA7, 0x50,
+ 0xF4, 0x16, 0x43, 0xB1, 0x7F, 0x99, 0x61, 0x3F,
+ 0xA5, 0x59, 0x91, 0x16, 0xC3, 0x06, 0x63, 0x59,
+ 0xE9, 0xDA, 0xB5, 0x06, 0x2E, 0x0C, 0xD9, 0xAB,
+ 0x93, 0x89, 0x12, 0x82, 0xFB, 0x90, 0xD9, 0x30,
+ 0x60, 0xF7, 0x35, 0x2D, 0x18, 0x78, 0xEB, 0x2B,
+ 0xA1, 0x06, 0x67, 0x37, 0xDE, 0x72, 0x20, 0xD2,
+ 0x80, 0xE5, 0x2C, 0xD7, 0x5E, 0xC7, 0x67, 0x2D,
+ 0x40, 0xE7, 0x7A, 0xCF, 0x4A, 0x69, 0x9D, 0xA7,
+ 0x90, 0x9F, 0x3B, 0xDF, 0x07, 0x97, 0x64, 0x69,
+ 0x06, 0x4F, 0xBA, 0xF4, 0xE5, 0xBD, 0x71, 0x60,
+ 0x36, 0xB7, 0xA3, 0xDE, 0x76, 0xC5, 0x38, 0xD7,
+ 0x1D, 0x9A, 0xFC, 0x36, 0x3D, 0x3B, 0xDC, 0xCF
+};
+static const unsigned char RSA4096_Q[] = {
+ 0xCD, 0xE6, 0xC6, 0xA6, 0x42, 0x4C, 0x45, 0x65,
+ 0x8B, 0x85, 0x76, 0xFC, 0x21, 0xB6, 0x57, 0x79,
+ 0x3C, 0xE4, 0xE3, 0x85, 0x55, 0x2F, 0x59, 0xD3,
+ 0x3F, 0x74, 0xAF, 0x9F, 0x11, 0x04, 0x10, 0x8B,
+ 0xF9, 0x5F, 0x4D, 0x25, 0xEE, 0x20, 0xF9, 0x69,
+ 0x3B, 0x02, 0xB6, 0x43, 0x0D, 0x0C, 0xED, 0x30,
+ 0x31, 0x57, 0xE7, 0x9A, 0x57, 0x24, 0x6B, 0x4A,
+ 0x5E, 0xA2, 0xBF, 0xD4, 0x47, 0x7D, 0xFA, 0x78,
+ 0x51, 0x86, 0x80, 0x68, 0x85, 0x7C, 0x7B, 0x08,
+ 0x4A, 0x35, 0x24, 0x4F, 0x8B, 0x24, 0x49, 0xF8,
+ 0x16, 0x06, 0x9C, 0x57, 0x4E, 0x94, 0x4C, 0xBD,
+ 0x6E, 0x53, 0x52, 0xC9, 0xC1, 0x64, 0x43, 0x22,
+ 0x1E, 0xDD, 0xEB, 0xAC, 0x90, 0x58, 0xCA, 0xBA,
+ 0x9C, 0xAC, 0xCF, 0xDD, 0x08, 0x6D, 0xB7, 0x31,
+ 0xDB, 0x0D, 0x83, 0xE6, 0x50, 0xA6, 0x69, 0xB1,
+ 0x1C, 0x68, 0x92, 0xB4, 0xB5, 0x76, 0xDE, 0xBD,
+ 0x4F, 0xA5, 0x30, 0xED, 0x23, 0xFF, 0xE5, 0x80,
+ 0x21, 0xAB, 0xED, 0xE6, 0xDC, 0x32, 0x3D, 0xF7,
+ 0x45, 0xB8, 0x19, 0x3D, 0x8E, 0x15, 0x7C, 0xE5,
+ 0x0D, 0xC8, 0x9B, 0x7D, 0x1F, 0x7C, 0x14, 0x14,
+ 0x41, 0x09, 0xA7, 0xEB, 0xFB, 0xD9, 0x5F, 0x9A,
+ 0x94, 0xB6, 0xD5, 0xA0, 0x2C, 0xAF, 0xB5, 0xEF,
+ 0x5C, 0x5A, 0x8E, 0x34, 0xA1, 0x8F, 0xEB, 0x38,
+ 0x0F, 0x31, 0x6E, 0x45, 0x21, 0x7A, 0xAA, 0xAF,
+ 0x6C, 0xB1, 0x8E, 0xB2, 0xB9, 0xD4, 0x1E, 0xEF,
+ 0x66, 0xD8, 0x4E, 0x3D, 0xF2, 0x0C, 0xF1, 0xBA,
+ 0xFB, 0xA9, 0x27, 0xD2, 0x45, 0x54, 0x83, 0x4B,
+ 0x10, 0xC4, 0x9A, 0x32, 0x9C, 0xC7, 0x9A, 0xCF,
+ 0x4E, 0xBF, 0x07, 0xFC, 0x27, 0xB7, 0x96, 0x1D,
+ 0xDE, 0x9D, 0xE4, 0x84, 0x68, 0x00, 0x9A, 0x9F,
+ 0x3D, 0xE6, 0xC7, 0x26, 0x11, 0x48, 0x79, 0xFA,
+ 0x09, 0x76, 0xC8, 0x25, 0x3A, 0xE4, 0x70, 0xF9
+};
+static const unsigned char RSA4096_DP[] = {
+ 0x5C, 0xE3, 0x3E, 0xBF, 0x09, 0xD9, 0xFE, 0x80,
+ 0x9A, 0x1E, 0x24, 0xDF, 0xC4, 0xBE, 0x5A, 0x70,
+ 0x06, 0xF2, 0xB8, 0xE9, 0x0F, 0x21, 0x9D, 0xCF,
+ 0x26, 0x15, 0x97, 0x32, 0x60, 0x40, 0x99, 0xFF,
+ 0x04, 0x3D, 0xBA, 0x39, 0xBF, 0xEB, 0x87, 0xB1,
+ 0xB1, 0x5B, 0x14, 0xF4, 0x80, 0xB8, 0x85, 0x34,
+ 0x2C, 0xBC, 0x95, 0x67, 0xE9, 0x83, 0xEB, 0x78,
+ 0xA4, 0x62, 0x46, 0x7F, 0x8B, 0x55, 0xEE, 0x3C,
+ 0x2F, 0xF3, 0x7E, 0xF5, 0x6B, 0x39, 0xE3, 0xA3,
+ 0x0E, 0xEA, 0x92, 0x76, 0xAC, 0xF7, 0xB2, 0x05,
+ 0xB2, 0x50, 0x5D, 0xF9, 0xB7, 0x11, 0x87, 0xB7,
+ 0x49, 0x86, 0xEB, 0x44, 0x6A, 0x0C, 0x64, 0x75,
+ 0x95, 0x14, 0x24, 0xFF, 0x49, 0x06, 0x52, 0x68,
+ 0x81, 0x71, 0x44, 0x85, 0x26, 0x0A, 0x49, 0xEA,
+ 0x4E, 0x9F, 0x6A, 0x8E, 0xCF, 0xC8, 0xC9, 0xB0,
+ 0x61, 0x77, 0x27, 0x89, 0xB0, 0xFA, 0x1D, 0x51,
+ 0x7D, 0xDC, 0x34, 0x21, 0x80, 0x8B, 0x6B, 0x86,
+ 0x19, 0x1A, 0x5F, 0x19, 0x23, 0xF3, 0xFB, 0xD1,
+ 0xF7, 0x35, 0x9D, 0x28, 0x61, 0x2F, 0x35, 0x85,
+ 0x82, 0x2A, 0x1E, 0xDF, 0x09, 0xC2, 0x0C, 0x99,
+ 0xE0, 0x3C, 0x8F, 0x4B, 0x3D, 0x92, 0xAF, 0x46,
+ 0x77, 0x68, 0x59, 0xF4, 0x37, 0x81, 0x6C, 0xCE,
+ 0x27, 0x8B, 0xAB, 0x0B, 0xA5, 0xDA, 0x7B, 0x19,
+ 0x83, 0xDA, 0x27, 0x49, 0x65, 0x1A, 0x00, 0x6B,
+ 0xE1, 0x8B, 0x73, 0xCD, 0xF4, 0xFB, 0xD7, 0xBF,
+ 0xF8, 0x20, 0x89, 0xE1, 0xDE, 0x51, 0x1E, 0xDD,
+ 0x97, 0x44, 0x12, 0x68, 0x1E, 0xF7, 0x52, 0xF8,
+ 0x6B, 0x93, 0xC1, 0x3B, 0x9F, 0xA1, 0xB8, 0x5F,
+ 0xCB, 0x84, 0x45, 0x95, 0xF7, 0x0D, 0xA6, 0x4B,
+ 0x03, 0x3C, 0xAE, 0x0F, 0xB7, 0x81, 0x78, 0x75,
+ 0x1C, 0x53, 0x99, 0x24, 0xB3, 0xE2, 0x78, 0xCE,
+ 0xF3, 0xF0, 0x09, 0x6C, 0x01, 0x85, 0x73, 0xBD
+};
+static const unsigned char RSA4096_DQ[] = {
+ 0xCD, 0x88, 0xAC, 0x8B, 0x92, 0x6A, 0xA8, 0x6B,
+ 0x71, 0x16, 0xCD, 0x6B, 0x6A, 0x0B, 0xA6, 0xCD,
+ 0xF3, 0x27, 0x58, 0xA6, 0xE4, 0x1D, 0xDC, 0x40,
+ 0xAF, 0x7B, 0x3F, 0x44, 0x3D, 0xAC, 0x1D, 0x08,
+ 0x5C, 0xE9, 0xF1, 0x0D, 0x07, 0xE4, 0x0A, 0x94,
+ 0x2C, 0xBF, 0xCC, 0x48, 0xAA, 0x62, 0x58, 0xF2,
+ 0x5E, 0x8F, 0x2D, 0x36, 0x37, 0xFE, 0xB6, 0xCB,
+ 0x0A, 0x24, 0xD3, 0xF0, 0x87, 0x5D, 0x0E, 0x05,
+ 0xC4, 0xFB, 0xCA, 0x7A, 0x8B, 0xA5, 0x72, 0xFB,
+ 0x17, 0x78, 0x6C, 0xC2, 0xAA, 0x56, 0x93, 0x2F,
+ 0xFE, 0x6C, 0xA2, 0xEB, 0xD4, 0x18, 0xDD, 0x71,
+ 0xCB, 0x0B, 0x89, 0xFC, 0xB3, 0xFB, 0xED, 0xB7,
+ 0xC5, 0xB0, 0x29, 0x6D, 0x9C, 0xB9, 0xC5, 0xC4,
+ 0xFA, 0x58, 0xD7, 0x36, 0x01, 0x0F, 0xE4, 0x6A,
+ 0xF4, 0x0B, 0x4D, 0xBB, 0x3E, 0x8E, 0x9F, 0xBA,
+ 0x98, 0x6D, 0x1A, 0xE5, 0x20, 0xAF, 0x84, 0x30,
+ 0xDD, 0xAC, 0x3C, 0x66, 0xBC, 0x24, 0xD9, 0x67,
+ 0x4A, 0x35, 0x61, 0xC9, 0xAD, 0xCC, 0xC9, 0x66,
+ 0x68, 0x46, 0x19, 0x8C, 0x04, 0xA5, 0x16, 0x83,
+ 0x5F, 0x7A, 0xFD, 0x1B, 0xAD, 0xAE, 0x22, 0x2D,
+ 0x05, 0xAF, 0x29, 0xDC, 0xBB, 0x0E, 0x86, 0x0C,
+ 0xBC, 0x9E, 0xB6, 0x28, 0xA9, 0xF2, 0xCC, 0x5E,
+ 0x1F, 0x86, 0x95, 0xA5, 0x9C, 0x11, 0x19, 0xF0,
+ 0x5F, 0xDA, 0x2C, 0x04, 0xFE, 0x22, 0x80, 0xF7,
+ 0x94, 0x3C, 0xBA, 0x01, 0x56, 0xD6, 0x93, 0xFA,
+ 0xCE, 0x62, 0xE5, 0xD7, 0x98, 0x23, 0xAB, 0xB9,
+ 0xC7, 0x35, 0x57, 0xF6, 0xE2, 0x16, 0x36, 0xE9,
+ 0x5B, 0xD7, 0xA5, 0x45, 0x18, 0x93, 0x77, 0xC9,
+ 0xB1, 0x05, 0xA8, 0x66, 0xE1, 0x0E, 0xB5, 0xDF,
+ 0x23, 0x35, 0xE1, 0xC2, 0xFA, 0x3E, 0x80, 0x1A,
+ 0xAD, 0xA4, 0x0C, 0xEF, 0xC7, 0x18, 0xDE, 0x09,
+ 0xE6, 0x20, 0x98, 0x31, 0xF1, 0xD3, 0xCF, 0xA1
+};
+static const unsigned char RSA4096_IQ[] = {
+ 0x76, 0xD7, 0x75, 0xDF, 0xA3, 0x0C, 0x9D, 0x64,
+ 0x6E, 0x00, 0x82, 0x2E, 0x5C, 0x5E, 0x43, 0xC4,
+ 0xD2, 0x28, 0xB0, 0xB1, 0xA8, 0xD8, 0x26, 0x91,
+ 0xA0, 0xF5, 0xC8, 0x69, 0xFF, 0x24, 0x33, 0xAB,
+ 0x67, 0xC7, 0xA3, 0xAE, 0xBB, 0x17, 0x27, 0x5B,
+ 0x5A, 0xCD, 0x67, 0xA3, 0x70, 0x91, 0x9E, 0xD5,
+ 0xF1, 0x97, 0x00, 0x0A, 0x30, 0x64, 0x3D, 0x9B,
+ 0xBF, 0xB5, 0x8C, 0xAC, 0xC7, 0x20, 0x0A, 0xD2,
+ 0x76, 0x36, 0x36, 0x5D, 0xE4, 0xAC, 0x5D, 0xBC,
+ 0x44, 0x32, 0xB0, 0x76, 0x33, 0x40, 0xDD, 0x29,
+ 0x22, 0xE0, 0xFF, 0x55, 0x4C, 0xCE, 0x3F, 0x43,
+ 0x34, 0x95, 0x94, 0x7C, 0x22, 0x0D, 0xAB, 0x20,
+ 0x38, 0x70, 0xC3, 0x4A, 0x19, 0xCF, 0x81, 0xCE,
+ 0x79, 0x28, 0x6C, 0xC2, 0xA3, 0xB3, 0x48, 0x20,
+ 0x2D, 0x3E, 0x74, 0x45, 0x2C, 0xAA, 0x9F, 0xA5,
+ 0xC2, 0xE3, 0x2D, 0x41, 0x95, 0xBD, 0x78, 0xAB,
+ 0x6A, 0xA8, 0x7A, 0x45, 0x52, 0xE2, 0x66, 0xE7,
+ 0x6C, 0x38, 0x03, 0xA5, 0xDA, 0xAD, 0x94, 0x3C,
+ 0x6A, 0xA1, 0xA2, 0xD5, 0xCD, 0xDE, 0x05, 0xCC,
+ 0x6E, 0x3D, 0x8A, 0xF6, 0x9A, 0xA5, 0x0F, 0xA9,
+ 0x18, 0xC4, 0xF9, 0x9C, 0x2F, 0xB3, 0xF1, 0x30,
+ 0x38, 0x60, 0x69, 0x09, 0x67, 0x2C, 0xE9, 0x42,
+ 0x68, 0x3C, 0x70, 0x32, 0x1A, 0x44, 0x32, 0x02,
+ 0x82, 0x9F, 0x60, 0xE8, 0xA4, 0x42, 0x74, 0xA2,
+ 0xA2, 0x5A, 0x99, 0xDC, 0xC8, 0xCA, 0x15, 0x4D,
+ 0xFF, 0xF1, 0x8A, 0x23, 0xD8, 0xD3, 0xB1, 0x9A,
+ 0xB4, 0x0B, 0xBB, 0xE8, 0x38, 0x74, 0x0C, 0x52,
+ 0xC7, 0x8B, 0x63, 0x4C, 0xEA, 0x7D, 0x5F, 0x58,
+ 0x34, 0x53, 0x3E, 0x23, 0x10, 0xBB, 0x60, 0x6B,
+ 0x52, 0x9D, 0x89, 0x9F, 0xF0, 0x5F, 0xCE, 0xB3,
+ 0x9C, 0x0E, 0x75, 0x0F, 0x87, 0xF6, 0x66, 0xA5,
+ 0x4C, 0x94, 0x84, 0xFE, 0x94, 0xB9, 0x04, 0xB7
+};
+
+static const br_rsa_public_key RSA4096_PK = {
+ (void *)RSA4096_N, sizeof RSA4096_N,
+ (void *)RSA4096_E, sizeof RSA4096_E
+};
+
+static const br_rsa_private_key RSA4096_SK = {
+ 4096,
+ (void *)RSA4096_P, sizeof RSA4096_P,
+ (void *)RSA4096_Q, sizeof RSA4096_Q,
+ (void *)RSA4096_DP, sizeof RSA4096_DP,
+ (void *)RSA4096_DQ, sizeof RSA4096_DQ,
+ (void *)RSA4096_IQ, sizeof RSA4096_IQ
+};
+
+static void
+test_RSA_core(const char *name, br_rsa_public fpub, br_rsa_private fpriv)
+{
+ unsigned char t1[512], t2[512], t3[512];
+ size_t len;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ /*
+ * A KAT test (computed with OpenSSL).
+ */
+ len = hextobin(t1, "45A3DC6A106BCD3BD0E48FB579643AA3FF801E5903E80AA9B43A695A8E7F454E93FA208B69995FF7A6D5617C2FEB8E546375A664977A48931842AAE796B5A0D64393DCA35F3490FC157F5BD83B9D58C2F7926E6AE648A2BD96CAB8FCCD3D35BB11424AD47D973FF6D69CA774841AEC45DFAE99CCF79893E7047FDE6CB00AA76D");
+ hextobin(t2, "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003021300906052B0E03021A05000414A94A8FE5CCB19BA61C4C0873D391E987982FBBD3");
+ memcpy(t3, t1, len);
+ if (!fpub(t3, len, &RSA_PK)) {
+ fprintf(stderr, "RSA public operation failed (1)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA pub", t2, t3, len);
+ if (!fpriv(t3, &RSA_SK)) {
+ fprintf(stderr, "RSA private operation failed (1)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA priv (1)", t1, t3, len);
+
+ /*
+ * Another KAT test, with a (fake) hash value slightly different
+ * (last byte is 0xD9 instead of 0xD3).
+ */
+ len = hextobin(t1, "32C2DB8B2C73BBCA9960CB3F11FEDEE7B699359EF2EEC3A632E56B7FF3DE2F371E5179BAB03F17E0BB20D2891ACAB679F95DA9B43A01DAAD192FADD25D8ACCF1498EC80F5BBCAC88EA59D60E3BC9D3CE27743981DE42385FFFFF04DD2D716E1A46C04A28ECAF6CD200DAB81083A830D61538D69BB39A183107BD50302AA6BC28");
+ hextobin(t2, "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003021300906052B0E03021A05000414A94A8FE5CCB19BA61C4C0873D391E987982FBBD9");
+ memcpy(t3, t1, len);
+ if (!fpub(t3, len, &RSA_PK)) {
+ fprintf(stderr, "RSA public operation failed (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA pub", t2, t3, len);
+ if (!fpriv(t3, &RSA_SK)) {
+ fprintf(stderr, "RSA private operation failed (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA priv (2)", t1, t3, len);
+
+ /*
+ * Third KAT vector is invalid, because the encrypted value is
+ * out of range: instead of x, value is x+n (where n is the
+ * modulus). Mathematically, this still works, but implementations
+ * are supposed to reject such cases.
+ */
+ len = hextobin(t1, "F27781B9B3B358583A24F9BA6B34EE98B67A5AE8D8D4FA567BA773EB6B85EF88848680640A1E2F5FD117876E5FB928B64C6EFC7E03632A3F4C941E15657C0C705F3BB8D0B03A0249143674DB1FE6E5406D690BF2DA76EA7FF3AC6FCE12C7801252FAD52D332BE4AB41F9F8CF1728CDF98AB8E8C20E0C350E4F707A6402C01E0B");
+ hextobin(t2, "BFB6A62E873F9C8DA0C42E7B59360FB0FFE12549E5E636B048C2086B77A7C051663506A959DF177F15F6B4E544EE723C531152C9C9614F923364704307F13F7F15ACF0C1547D55C029DC9ECCE41D117245F4D270FC34B21FF3AD6AEFE58633281540902F547F79F3461F44D33CCB2D094231ADCC76BE25511B4513BB70491DBC");
+ memcpy(t3, t1, len);
+ if (fpub(t3, len, &RSA_PK)) {
+ size_t u;
+ fprintf(stderr, "RSA public operation should have failed"
+ " (value out of range)\n");
+ fprintf(stderr, "x = ");
+ for (u = 0; u < len; u ++) {
+ fprintf(stderr, "%02X", t3[u]);
+ }
+ fprintf(stderr, "\n");
+ exit(EXIT_FAILURE);
+ }
+ memcpy(t3, t2, len);
+ if (fpriv(t3, &RSA_SK)) {
+ size_t u;
+ fprintf(stderr, "RSA private operation should have failed"
+ " (value out of range)\n");
+ fprintf(stderr, "x = ");
+ for (u = 0; u < len; u ++) {
+ fprintf(stderr, "%02X", t3[u]);
+ }
+ fprintf(stderr, "\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * RSA-2048 test vector.
+ */
+ len = hextobin(t1, "B188ED4EF173A30AED3889926E3CF1CE03FE3BAA7AB122B119A8CD529062F235A7B321008FB898894A624B3E6C8C5374950E78FAC86651345FE2ABA0791968284F23B0D794F8DCDDA924518854822CB7FF2AA9F205AACD909BB5EA541534CC00DBC2EF7727B9FE1BAFE6241B931E8BD01E13632E5AF9E94F4A335772B61F24D6F6AA642AEABB173E36F546CB02B19A1E5D4E27E3EB67F2E986E9F084D4BD266543800B1DC96088A05DFA9AFA595398E9A766D41DD8DA4F74F36C9D74867F0BF7BFA8622EE43C79DA0CEAC14B5D39DE074BDB89D84145BC19D8B2D0EA74DBF2DC29E907BF7C7506A2603CD8BC25EFE955D0125EDB2685EF158B020C9FC539242A");
+ hextobin(t2, "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003031300D060960864801650304020105000420A5A0A792A09438811584A68E240C6C89F1FB1C53C0C86E270B942635F4F6B24A");
+ memcpy(t3, t1, len);
+ if (!fpub(t3, len, &RSA2048_PK)) {
+ fprintf(stderr, "RSA public operation failed (2048)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA pub", t2, t3, len);
+ if (!fpriv(t3, &RSA2048_SK)) {
+ fprintf(stderr, "RSA private operation failed (2048)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA priv (2048)", t1, t3, len);
+
+ /*
+ * RSA-4096 test vector.
+ */
+ len = hextobin(t1, "7D35B6B4D85252D08A2658C0B04126CC617B0E56B2A782A5FA2722AD05BD49538111682C12DA2C5FA1B9C30FB1AB8DA2C6A49EB4226A4D32290CF091FBB22EC499C7B18192C230B29F957DAF551F1EAD1917BA9E03D757100BD1F96B829708A6188A3927436113BB21E175D436BBB7A90E20162203FFB8F675313DFB21EFDA3EA0C7CC9B605AE7FB47E2DD2A9C4D5F124D7DE1B690AF9ADFEDC6055E0F9D2C9A891FB2501F3055D6DA7E94D51672BA1E86AEB782E4B020F70E0DF5399262909FC5B4770B987F2826EF2099A15F3CD5A0D6FE82E0C85FBA2C53C77305F534A7B0C7EA0D5244E37F1C1318EEF7079995F0642E4AB80EB0ED60DB4955FB652ED372DAC787581054A827C37A25C7B4DE7AE7EF3D099D47D6682ADF02BCC4DE04DDF2920F7124CF5B4955705E4BDB97A0BF341B584797878B4D3795134A9469FB391E4E4988F0AA451027CBC2ED6121FC23B26BF593E3C51DEDD53B62E23050D5B41CA34204679916A87AF1B17873A0867924D0C303942ADA478B769487FCEF861D4B20DCEE6942CCB84184833CDB258167258631C796BC1977D001354E2EE168ABE3B45FC969EA7F22B8E133C57A10FBB25ED19694E89C399CF7723B3C0DF0CC9F57A8ED0959EFC392FB31B8ADAEA969E2DEE8282CB245E5677368F00CCE4BA52C07C16BE7F9889D57191D5B2FE552D72B3415C64C09EE622457766EC809344A1EFE");
+ hextobin(t2, "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003031300D0609608648016503040201050004205B60DD5AD5B3C62E0DA25FD0D8CB26325E1CE32CC9ED234B288235BCCF6ED2C8");
+ memcpy(t3, t1, len);
+ if (!fpub(t3, len, &RSA4096_PK)) {
+ fprintf(stderr, "RSA public operation failed (4096)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA pub", t2, t3, len);
+ if (!fpriv(t3, &RSA4096_SK)) {
+ fprintf(stderr, "RSA private operation failed (4096)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA priv (4096)", t1, t3, len);
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static const unsigned char SHA1_OID[] = {
+ 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
+};
+
+static void
+test_RSA_sign(const char *name, br_rsa_private fpriv,
+ br_rsa_pkcs1_sign fsign, br_rsa_pkcs1_vrfy fvrfy)
+{
+ unsigned char t1[128], t2[128];
+ unsigned char hv[20], tmp[20];
+ unsigned char rsa_n[128], rsa_e[3], rsa_p[64], rsa_q[64];
+ unsigned char rsa_dp[64], rsa_dq[64], rsa_iq[64];
+ br_rsa_public_key rsa_pk;
+ br_rsa_private_key rsa_sk;
+ unsigned char hv2[64], tmp2[64], sig[128];
+ br_sha1_context hc;
+ size_t u;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ /*
+ * Verify the KAT test (computed with OpenSSL).
+ */
+ hextobin(t1, "45A3DC6A106BCD3BD0E48FB579643AA3FF801E5903E80AA9B43A695A8E7F454E93FA208B69995FF7A6D5617C2FEB8E546375A664977A48931842AAE796B5A0D64393DCA35F3490FC157F5BD83B9D58C2F7926E6AE648A2BD96CAB8FCCD3D35BB11424AD47D973FF6D69CA774841AEC45DFAE99CCF79893E7047FDE6CB00AA76D");
+ br_sha1_init(&hc);
+ br_sha1_update(&hc, "test", 4);
+ br_sha1_out(&hc, hv);
+ if (!fvrfy(t1, sizeof t1, SHA1_OID, sizeof tmp, &RSA_PK, tmp)) {
+ fprintf(stderr, "Signature verification failed\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("Extracted hash value", hv, tmp, sizeof tmp);
+
+ /*
+ * Regenerate the signature. This should yield the same value as
+ * the KAT test, since PKCS#1 v1.5 signatures are deterministic
+ * (except the usual detail about hash function parameter
+ * encoding, but OpenSSL uses the same convention as BearSSL).
+ */
+ if (!fsign(SHA1_OID, hv, 20, &RSA_SK, t2)) {
+ fprintf(stderr, "Signature generation failed\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("Regenerated signature", t1, t2, sizeof t1);
+
+ /*
+ * Use the raw private core to generate fake signatures, where
+ * one byte of the padded hash value is altered. They should all be
+ * rejected.
+ */
+ hextobin(t2, "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003021300906052B0E03021A05000414A94A8FE5CCB19BA61C4C0873D391E987982FBBD3");
+ for (u = 0; u < (sizeof t2) - 20; u ++) {
+ memcpy(t1, t2, sizeof t2);
+ t1[u] ^= 0x01;
+ if (!fpriv(t1, &RSA_SK)) {
+ fprintf(stderr, "RSA private key operation failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (fvrfy(t1, sizeof t1, SHA1_OID, sizeof tmp, &RSA_PK, tmp)) {
+ fprintf(stderr,
+ "Signature verification should have failed\n");
+ exit(EXIT_FAILURE);
+ }
+ printf(".");
+ fflush(stdout);
+ }
+
+ /*
+ * Another KAT test, which historically showed a bug.
+ */
+ rsa_pk.n = rsa_n;
+ rsa_pk.nlen = hextobin(rsa_n, "E65DAEF196D22C300B3DAE1CE5157EDF821BB6038E419D8D363A8B2DA84A1321042330E6F87A8BD8FE6BA1D2A17031955ED2315CC5FD2397197E238A5E0D2D0AFD25717E814EC4D2BBA887327A3C5B3A450FD8D547BDFCBB0F73B997CA13DD5E7572C4D5BAA764A349BAB2F868ACF4574AE2C7AEC94B77D2EE00A21B6CB175BB");
+ rsa_pk.e = rsa_e;
+ rsa_pk.elen = hextobin(rsa_e, "010001");
+
+ rsa_sk.n_bitlen = 1024;
+ rsa_sk.p = rsa_p;
+ rsa_sk.plen = hextobin(rsa_p, "FF58513DBA4F3F42DFDFD3E6AFB6BD62DE27E06BA3C9D9F9B542CB21228C2AAE67936514161C8FDC1A248A50195CAF22ADC50DA89BFED1B9EEFBB37304241357");
+ rsa_sk.q = rsa_q;
+ rsa_sk.qlen = hextobin(rsa_q, "E6F4F66818B7442297DDEB45E9B3D438E5B57BB5EF86EFF2462AD6B9C10F383517CDD2E7E36EAD4BEBCC57CFE8AA985F7E7B38B96D30FFBE9ED9FE21B1CFB63D");
+ rsa_sk.dp = rsa_dp;
+ rsa_sk.dplen = hextobin(rsa_dp, "6F89517B682D83919F9EF2BDBA955526A1A9C382E139A3A84AC01160B8E9871F458901C7035D988D6931FAE4C01F57350BB89E9DBEFE50F829E6F25CD43B39E3");
+ rsa_sk.dq = rsa_dq;
+ rsa_sk.dqlen = hextobin(rsa_dq, "409E08D2D7176F58BE64B88EB6F4394C31F8B4C412600E821A5FA1F416AFCB6A0F5EE6C33A3E9CFDC0DB4B3640427A9F3D23FC9AE491F0FBC435F98433DB8981");
+ rsa_sk.iq = rsa_iq;
+ rsa_sk.iqlen = hextobin(rsa_iq, "CF333D6AD66D02B4D11C8C23CA669D14D71803ADC3943BE03B1E48F52F385BCFDDFD0F85AD02A984E504FC6612549D4E7867B7D09DD13196BFC3FAA4B57393A9");
+ hextobin(sig, "CFB84D161E6DB130736FC6212EBE575571AF341CEF5757C19952A5364C90E3C47549E520E26253DAE70F645F31FA8B5DA9AE282741D3CA4B1CC365B7BD75D6D61D4CFD9AD9EDD17D23E0BA7D9775138DBABC7FF2A57587FE1EA1B51E8F3C68326E26FF89D8CF92BDD4C787D04857DFC3266E6B33B92AA08809929C72642F35C2");
+
+ hextobin(hv2, "F66C62B38E1CC69C378C0E16574AE5C6443FDFA3E85C6205C00B3231CAA3074EC1481BDC22AB575E6CF3CCD9EDA6B39F83923FC0E6475C799D257545F77233B4");
+ if (!fsign(BR_HASH_OID_SHA512, hv2, 64, &rsa_sk, t2)) {
+ fprintf(stderr, "Signature generation failed (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("Regenerated signature (2)", t2, sig, sizeof t2);
+ if (!fvrfy(t2, sizeof t2, BR_HASH_OID_SHA512,
+ sizeof tmp2, &rsa_pk, tmp2))
+ {
+ fprintf(stderr, "Signature verification failed (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("Extracted hash value (2)", hv2, tmp2, sizeof tmp2);
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+/*
+ * Fake RNG that returns exactly the provided bytes.
+ */
+typedef struct {
+ const br_prng_class *vtable;
+ unsigned char buf[128];
+ size_t ptr, len;
+} rng_fake_ctx;
+
+static void rng_fake_init(rng_fake_ctx *cc,
+ const void *params, const void *seed, size_t len);
+static void rng_fake_generate(rng_fake_ctx *cc, void *dst, size_t len);
+static void rng_fake_update(rng_fake_ctx *cc, const void *src, size_t len);
+
+static const br_prng_class rng_fake_vtable = {
+ sizeof(rng_fake_ctx),
+ (void (*)(const br_prng_class **,
+ const void *, const void *, size_t))&rng_fake_init,
+ (void (*)(const br_prng_class **,
+ void *, size_t))&rng_fake_generate,
+ (void (*)(const br_prng_class **,
+ const void *, size_t))&rng_fake_update
+};
+
+static void
+rng_fake_init(rng_fake_ctx *cc, const void *params,
+ const void *seed, size_t len)
+{
+ (void)params;
+ if (len > sizeof cc->buf) {
+ fprintf(stderr, "seed is too large (%lu bytes)\n",
+ (unsigned long)len);
+ exit(EXIT_FAILURE);
+ }
+ cc->vtable = &rng_fake_vtable;
+ memcpy(cc->buf, seed, len);
+ cc->ptr = 0;
+ cc->len = len;
+}
+
+static void
+rng_fake_generate(rng_fake_ctx *cc, void *dst, size_t len)
+{
+ if (len > (cc->len - cc->ptr)) {
+ fprintf(stderr, "asking for more data than expected\n");
+ exit(EXIT_FAILURE);
+ }
+ memcpy(dst, cc->buf + cc->ptr, len);
+ cc->ptr += len;
+}
+
+static void
+rng_fake_update(rng_fake_ctx *cc, const void *src, size_t len)
+{
+ (void)cc;
+ (void)src;
+ (void)len;
+ fprintf(stderr, "unexpected update\n");
+ exit(EXIT_FAILURE);
+}
+
+/*
+ * Test vectors from pkcs-1v2-1d2-vec.zip (originally from ftp.rsa.com).
+ * There are ten RSA keys, and for each RSA key, there are 6 messages,
+ * each with an explicit salt.
+ *
+ * Field order:
+ * modulus (n)
+ * public exponent (e)
+ * first factor (p)
+ * second factor (q)
+ * first private exponent (dp)
+ * second private exponent (dq)
+ * CRT coefficient (iq)
+ * message 1
+ * salt 1 (20-byte random value)
+ * signature 1
+ * message 2
+ * salt 2 (20-byte random value)
+ * signature 2
+ * ...
+ * message 6
+ * salt 6 (20-byte random value)
+ * signature 6
+ *
+ * This pattern is repeated for all keys. The array stops on a NULL.
+ */
+static const char *KAT_RSA_PSS[] = {
+
+ /* 1024-bit key */
+ "a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",
+ "010001",
+ "33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",
+ "e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",
+ "b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",
+ "28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",
+ "1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",
+ "27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",
+
+ "cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0",
+ "dee959c7e06411361420ff80185ed57f3e6776af",
+ "9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c",
+
+ "851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e",
+ "ef2869fa40c346cb183dab3d7bffc98fd56df42d",
+ "3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843",
+
+ "a4b159941761c40c6a82f2b80d1b94f5aa2654fd17e12d588864679b54cd04ef8bd03012be8dc37f4b83af7963faff0dfa225477437c48017ff2be8191cf3955fc07356eab3f322f7f620e21d254e5db4324279fe067e0910e2e81ca2cab31c745e67a54058eb50d993cdb9ed0b4d029c06d21a94ca661c3ce27fae1d6cb20f4564d66ce4767583d0e5f060215b59017be85ea848939127bd8c9c4d47b51056c031cf336f17c9980f3b8f5b9b6878e8b797aa43b882684333e17893fe9caa6aa299f7ed1a18ee2c54864b7b2b99b72618fb02574d139ef50f019c9eef416971338e7d470",
+ "710b9c4747d800d4de87f12afdce6df18107cc77",
+ "666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1",
+
+ "bc656747fa9eafb3f0",
+ "056f00985de14d8ef5cea9e82f8c27bef720335e",
+ "4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87",
+
+ "b45581547e5427770c768e8b82b75564e0ea4e9c32594d6bff706544de0a8776c7a80b4576550eee1b2acabc7e8b7d3ef7bb5b03e462c11047eadd00629ae575480ac1470fe046f13a2bf5af17921dc4b0aa8b02bee6334911651d7f8525d10f32b51d33be520d3ddf5a709955a3dfe78283b9e0ab54046d150c177f037fdccc5be4ea5f68b5e5a38c9d7edcccc4975f455a6909b4",
+ "80e70ff86a08de3ec60972b39b4fbfdcea67ae8e",
+ "1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad",
+
+ "10aae9a0ab0b595d0841207b700d48d75faedde3b775cd6b4cc88ae06e4694ec74ba18f8520d4f5ea69cbbe7cc2beba43efdc10215ac4eb32dc302a1f53dc6c4352267e7936cfebf7c8d67035784a3909fa859c7b7b59b8e39c5c2349f1886b705a30267d402f7486ab4f58cad5d69adb17ab8cd0ce1caf5025af4ae24b1fb8794c6070cc09a51e2f9911311e3877d0044c71c57a993395008806b723ac38373d395481818528c1e7053739282053529510e935cd0fa77b8fa53cc2d474bd4fb3cc5c672d6ffdc90a00f9848712c4bcfe46c60573659b11e6457e861f0f604b6138d144f8ce4e2da73",
+ "a8ab69dd801f0074c2a1fc60649836c616d99681",
+ "2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58",
+
+ /* 1025-bit key */
+ "01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9",
+ "010001",
+ "027d147e4673057377fd1ea201565772176a7dc38358d376045685a2e787c23c15576bc16b9f444402d6bfc5d98a3e88ea13ef67c353eca0c0ddba9255bd7b8bb50a644afdfd1dd51695b252d22e7318d1b6687a1c10ff75545f3db0fe602d5f2b7f294e3601eab7b9d1cecd767f64692e3e536ca2846cb0c2dd486a39fa75b1",
+ "016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1",
+ "014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079",
+ "e247cce504939b8f0a36090de200938755e2444b29539a7da7a902f6056835c0db7b52559497cfe2c61a8086d0213c472c78851800b171f6401de2e9c2756f31",
+ "b12fba757855e586e46f64c38a70c68b3f548d93d787b399999d4c8f0bbd2581c21e19ed0018a6d5d3df86424b3abcad40199d31495b61309f27c1bf55d487c1",
+ "564b1e1fa003bda91e89090425aac05b91da9ee25061e7628d5f51304a84992fdc33762bd378a59f030a334d532bd0dae8f298ea9ed844636ad5fb8cbdc03cad",
+
+ "daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360",
+ "57bf160bcb02bb1dc7280cf0458530b7d2832ff7",
+ "014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3",
+
+ "e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe",
+ "7f6dd359e604e60870e898e47b19bf2e5a7b2a90",
+ "010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea",
+
+ "52a1d96c8ac39e41e455809801b927a5b445c10d902a0dcd3850d22a66d2bb0703e67d5867114595aabf5a7aeb5a8f87034bbb30e13cfd4817a9be76230023606d0286a3faf8a4d22b728ec518079f9e64526e3a0cc7941aa338c437997c680ccac67c66bfa1",
+ "fca862068bce2246724b708a0519da17e648688c",
+ "007f0030018f53cdc71f23d03659fde54d4241f758a750b42f185f87578520c30742afd84359b6e6e8d3ed959dc6fe486bedc8e2cf001f63a7abe16256a1b84df0d249fc05d3194ce5f0912742dbbf80dd174f6c51f6bad7f16cf3364eba095a06267dc3793803ac7526aebe0a475d38b8c2247ab51c4898df7047dc6adf52c6c4",
+
+ "a7182c83ac18be6570a106aa9d5c4e3dbbd4afaeb0c60c4a23e1969d79ff",
+ "8070ef2de945c02387684ba0d33096732235d440",
+ "009cd2f4edbe23e12346ae8c76dd9ad3230a62076141f16c152ba18513a48ef6f010e0e37fd3df10a1ec629a0cb5a3b5d2893007298c30936a95903b6ba85555d9ec3673a06108fd62a2fda56d1ce2e85c4db6b24a81ca3b496c36d4fd06eb7c9166d8e94877c42bea622b3bfe9251fdc21d8d5371badad78a488214796335b40b",
+
+ "86a83d4a72ee932a4f5630af6579a386b78fe88999e0abd2d49034a4bfc854dd94f1094e2e8cd7a179d19588e4aefc1b1bd25e95e3dd461f",
+ "17639a4e88d722c4fca24d079a8b29c32433b0c9",
+ "00ec430824931ebd3baa43034dae98ba646b8c36013d1671c3cf1cf8260c374b19f8e1cc8d965012405e7e9bf7378612dfcc85fce12cda11f950bd0ba8876740436c1d2595a64a1b32efcfb74a21c873b3cc33aaf4e3dc3953de67f0674c0453b4fd9f604406d441b816098cb106fe3472bc251f815f59db2e4378a3addc181ecf",
+
+ "049f9154d871ac4a7c7ab45325ba7545a1ed08f70525b2667cf1",
+ "37810def1055ed922b063df798de5d0aabf886ee",
+ "00475b1648f814a8dc0abdc37b5527f543b666bb6e39d30e5b49d3b876dccc58eac14e32a2d55c2616014456ad2f246fc8e3d560da3ddf379a1c0bd200f10221df078c219a151bc8d4ec9d2fc2564467811014ef15d8ea01c2ebbff8c2c8efab38096e55fcbe3285c7aa558851254faffa92c1c72b78758663ef4582843139d7a6",
+
+ /* 1026-bit key */
+ "02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443",
+ "010001",
+ "651451733b56de5ac0a689a4aeb6e6894a69014e076c88dd7a667eab3232bbccd2fc44ba2fa9c31db46f21edd1fdb23c5c128a5da5bab91e7f952b67759c7cff705415ac9fa0907c7ca6178f668fb948d869da4cc3b7356f4008dfd5449d32ee02d9a477eb69fc29266e5d9070512375a50fbbcc27e238ad98425f6ebbf88991",
+ "01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853",
+ "01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651",
+ "1f2779fd2e3e5e6bae05539518fba0cd0ead1aa4513a7cba18f1cf10e3f68195693d278a0f0ee72f89f9bc760d80e2f9d0261d516501c6ae39f14a476ce2ccf5",
+ "011a0d36794b04a854aab4b2462d439a5046c91d940b2bc6f75b62956fef35a2a6e63c5309817f307bbff9d59e7e331bd363f6d66849b18346adea169f0ae9aec1",
+ "0b30f0ecf558752fb3a6ce4ba2b8c675f659eba6c376585a1b39712d038ae3d2b46fcb418ae15d0905da6440e1513a30b9b7d6668fbc5e88e5ab7a175e73ba35",
+
+ "594b37333bbb2c84524a87c1a01f75fcec0e3256f108e38dca36d70d0057",
+ "f31ad6c8cf89df78ed77feacbcc2f8b0a8e4cfaa",
+ "0088b135fb1794b6b96c4a3e678197f8cac52b64b2fe907d6f27de761124964a99a01a882740ecfaed6c01a47464bb05182313c01338a8cd097214cd68ca103bd57d3bc9e816213e61d784f182467abf8a01cf253e99a156eaa8e3e1f90e3c6e4e3aa2d83ed0345b89fafc9c26077c14b6ac51454fa26e446e3a2f153b2b16797f",
+
+ "8b769528884a0d1ffd090cf102993e796dadcfbddd38e44ff6324ca451",
+ "fcf9f0e1f199a3d1d0da681c5b8606fc642939f7",
+ "02a5f0a858a0864a4f65017a7d69454f3f973a2999839b7bbc48bf78641169179556f595fa41f6ff18e286c2783079bc0910ee9cc34f49ba681124f923dfa88f426141a368a5f5a930c628c2c3c200e18a7644721a0cbec6dd3f6279bde3e8f2be5e2d4ee56f97e7ceaf33054be7042bd91a63bb09f897bd41e81197dee99b11af",
+
+ "1abdba489c5ada2f995ed16f19d5a94d9e6ec34a8d84f84557d26e5ef9b02b22887e3f9a4b690ad1149209c20c61431f0c017c36c2657b35d7b07d3f5ad8708507a9c1b831df835a56f831071814ea5d3d8d8f6ade40cba38b42db7a2d3d7a29c8f0a79a7838cf58a9757fa2fe4c40df9baa193bfc6f92b123ad57b07ace3e6ac068c9f106afd9eeb03b4f37c25dbfbcfb3071f6f9771766d072f3bb070af6605532973ae25051",
+ "986e7c43dbb671bd41b9a7f4b6afc80e805f2423",
+ "0244bcd1c8c16955736c803be401272e18cb990811b14f72db964124d5fa760649cbb57afb8755dbb62bf51f466cf23a0a1607576e983d778fceffa92df7548aea8ea4ecad2c29dd9f95bc07fe91ecf8bee255bfe8762fd7690aa9bfa4fa0849ef728c2c42c4532364522df2ab7f9f8a03b63f7a499175828668f5ef5a29e3802c",
+
+ "8fb431f5ee792b6c2ac7db53cc428655aeb32d03f4e889c5c25de683c461b53acf89f9f8d3aabdf6b9f0c2a1de12e15b49edb3919a652fe9491c25a7fce1f722c2543608b69dc375ec",
+ "f8312d9c8eea13ec0a4c7b98120c87509087c478",
+ "0196f12a005b98129c8df13c4cb16f8aa887d3c40d96df3a88e7532ef39cd992f273abc370bc1be6f097cfebbf0118fd9ef4b927155f3df22b904d90702d1f7ba7a52bed8b8942f412cd7bd676c9d18e170391dcd345c06a730964b3f30bcce0bb20ba106f9ab0eeb39cf8a6607f75c0347f0af79f16afa081d2c92d1ee6f836b8",
+
+ "fef4161dfaaf9c5295051dfc1ff3810c8c9ec2e866f7075422c8ec4216a9c4ff49427d483cae10c8534a41b2fd15fee06960ec6fb3f7a7e94a2f8a2e3e43dc4a40576c3097ac953b1de86f0b4ed36d644f23ae14425529622464ca0cbf0b1741347238157fab59e4de5524096d62baec63ac64",
+ "50327efec6292f98019fc67a2a6638563e9b6e2d",
+ "021eca3ab4892264ec22411a752d92221076d4e01c0e6f0dde9afd26ba5acf6d739ef987545d16683e5674c9e70f1de649d7e61d48d0caeb4fb4d8b24fba84a6e3108fee7d0705973266ac524b4ad280f7ae17dc59d96d3351586b5a3bdb895d1e1f7820ac6135d8753480998382ba32b7349559608c38745290a85ef4e9f9bd83",
+
+ "efd237bb098a443aeeb2bf6c3f8c81b8c01b7fcb3feb",
+ "b0de3fc25b65f5af96b1d5cc3b27d0c6053087b3",
+ "012fafec862f56e9e92f60ab0c77824f4299a0ca734ed26e0644d5d222c7f0bde03964f8e70a5cb65ed44e44d56ae0edf1ff86ca032cc5dd4404dbb76ab854586c44eed8336d08d457ce6c03693b45c0f1efef93624b95b8ec169c616d20e5538ebc0b6737a6f82b4bc0570924fc6b35759a3348426279f8b3d7744e2d222426ce",
+
+ /* 1027-bit key */
+ "054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705",
+ "010001",
+ "fa041f8cd9697ceed38ec8caa275523b4dd72b09a301d3541d72f5d31c05cbce2d6983b36183af10690bd46c46131e35789431a556771dd0049b57461bf060c1f68472e8a67c25f357e5b6b4738fa541a730346b4a07649a2dfa806a69c975b6aba64678acc7f5913e89c622f2d8abb1e3e32554e39df94ba60c002e387d9011",
+ "029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995",
+ "020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1",
+ "026e7e28010ecf2412d9523ad704647fb4fe9b66b1a681581b0e15553a89b1542828898f27243ebab45ff5e1acb9d4df1b051fbc62824dbc6f6c93261a78b9a759",
+ "012ddcc86ef655998c39ddae11718669e5e46cf1495b07e13b1014cd69b3af68304ad2a6b64321e78bf3bbca9bb494e91d451717e2d97564c6549465d0205cf421",
+ "010600c4c21847459fe576703e2ebecae8a5094ee63f536bf4ac68d3c13e5e4f12ac5cc10ab6a2d05a199214d1824747d551909636b774c22cac0b837599abcc75",
+
+ "9fb03b827c8217d9",
+ "ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d",
+ "0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948",
+
+ "0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f",
+ "22d71d54363a4217aa55113f059b3384e3e57e44",
+ "049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598",
+
+ "288062afc08fcdb7c5f8650b29837300461dd5676c17a20a3c8fb5148949e3f73d66b3ae82c7240e27c5b3ec4328ee7d6ddf6a6a0c9b5b15bcda196a9d0c76b119d534d85abd123962d583b76ce9d180bce1ca",
+ "4af870fbc6516012ca916c70ba862ac7e8243617",
+ "03fbc410a2ced59500fb99f9e2af2781ada74e13145624602782e2994813eefca0519ecd253b855fb626a90d771eae028b0c47a199cbd9f8e3269734af4163599090713a3fa910fa0960652721432b971036a7181a2bc0cab43b0b598bc6217461d7db305ff7e954c5b5bb231c39e791af6bcfa76b147b081321f72641482a2aad",
+
+ "6f4f9ab9501199cef55c6cf408fe7b36c557c49d420a4763d2463c8ad44b3cfc5be2742c0e7d9b0f6608f08c7f47b693ee",
+ "40d2e180fae1eac439c190b56c2c0e14ddf9a226",
+ "0486644bc66bf75d28335a6179b10851f43f09bded9fac1af33252bb9953ba4298cd6466b27539a70adaa3f89b3db3c74ab635d122f4ee7ce557a61e59b82ffb786630e5f9db53c77d9a0c12fab5958d4c2ce7daa807cd89ba2cc7fcd02ff470ca67b229fcce814c852c73cc93bea35be68459ce478e9d4655d121c8472f371d4f",
+
+ "e17d20385d501955823c3f666254c1d3dd36ad5168b8f18d286fdcf67a7dad94097085fab7ed86fe2142a28771717997ef1a7a08884efc39356d76077aaf82459a7fad45848875f2819b098937fe923bcc9dc442d72d754d812025090c9bc03db3080c138dd63b355d0b4b85d6688ac19f4de15084a0ba4e373b93ef4a555096691915dc23c00e954cdeb20a47cd55d16c3d8681d46ed7f2ed5ea42795be17baed25f0f4d113b3636addd585f16a8b5aec0c8fa9c5f03cbf3b9b73",
+ "2497dc2b4615dfae5a663d49ffd56bf7efc11304",
+ "022a80045353904cb30cbb542d7d4990421a6eec16a8029a8422adfd22d6aff8c4cc0294af110a0c067ec86a7d364134459bb1ae8ff836d5a8a2579840996b320b19f13a13fad378d931a65625dae2739f0c53670b35d9d3cbac08e733e4ec2b83af4b9196d63e7c4ff1ddeae2a122791a125bfea8deb0de8ccf1f4ffaf6e6fb0a",
+
+ "afbc19d479249018fdf4e09f618726440495de11ddeee38872d775fcea74a23896b5343c9c38d46af0dba224d047580cc60a65e9391cf9b59b36a860598d4e8216722f993b91cfae87bc255af89a6a199bca4a391eadbc3a24903c0bd667368f6be78e3feabfb4ffd463122763740ffbbefeab9a25564bc5d1c24c93e422f75073e2ad72bf45b10df00b52a147128e73fee33fa3f0577d77f80fbc2df1bed313290c12777f50",
+ "a334db6faebf11081a04f87c2d621cdec7930b9b",
+ "00938dcb6d583046065f69c78da7a1f1757066a7fa75125a9d2929f0b79a60b627b082f11f5b196f28eb9daa6f21c05e5140f6aef1737d2023075c05ecf04a028c686a2ab3e7d5a0664f295ce12995e890908b6ad21f0839eb65b70393a7b5afd9871de0caa0cedec5b819626756209d13ab1e7bb9546a26ff37e9a51af9fd562e",
+
+ /* 1028-bit key */
+ "0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507",
+ "010001",
+ "03ce08b104fff396a979bd3e4e46925b6319ddb63acbcfd819f17d16b8077b3a87101ff34b77fe48b8b205a96e9151ba8ecea64d0cce7b23c3e6a6b83058bc49dae816ae736db5a4708e2ad435232b567f9096ce59ff28061e79ab1c02d717e6b23cea6db8eb5192fa7c1eab227dba74621c45601896eef13792c8440beb15aac1",
+ "03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f",
+ "034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839",
+ "02aa663adbf51ab887a018cb426e78bc2fe182dcb2f7bcb50441d17fdf0f06798b5071c6e2f5feb4d54ad8182311c1ef62d4c49f18d1f51f54b2d2cffba4da1be5",
+ "02bbe706078b5c0b391512d411db1b199b5a5664b84042ead37fe994ae72b9532dfbfb3e9e6981a0fbb806513141b7c2163fe56c395e4bfaee57e3833f9b918df9",
+ "0242b6cd00d30a767aee9a898ead453c8eaea63d500b7d1e00713edae51ce36b23b664df26e63e266ec8f76e6e63ed1ba41eb033b120f7ea5212ae21a98fbc16",
+
+ "30c7d557458b436decfdc14d06cb7b96b06718c48d7de57482a868ae7f065870a6216506d11b779323dfdf046cf5775129134b4d5689e4d9c0ce1e12d7d4b06cb5fc5820decfa41baf59bf257b32f025b7679b445b9499c92555145885992f1b76f84891ee4d3be0f5150fd5901e3a4c8ed43fd36b61d022e65ad5008dbf33293c22bfbfd07321f0f1d5fa9fdf0014c2fcb0358aad0e354b0d29",
+ "081b233b43567750bd6e78f396a88b9f6a445151",
+ "0ba373f76e0921b70a8fbfe622f0bf77b28a3db98e361051c3d7cb92ad0452915a4de9c01722f6823eeb6adf7e0ca8290f5de3e549890ac2a3c5950ab217ba58590894952de96f8df111b2575215da6c161590c745be612476ee578ed384ab33e3ece97481a252f5c79a98b5532ae00cdd62f2ecc0cd1baefe80d80b962193ec1d",
+
+ "e7b32e1556ea1b2795046ac69739d22ac8966bf11c116f614b166740e96b90653e5750945fcf772186c03790a07fda323e1a61916b06ee2157db3dff80d67d5e39a53ae268c8f09ed99a732005b0bc6a04af4e08d57a00e7201b3060efaadb73113bfc087fd837093aa25235b8c149f56215f031c24ad5bde7f29960df7d524070f7449c6f785084be1a0f733047f336f9154738674547db02a9f44dfc6e60301081e1ce99847f3b5b601ff06b4d5776a9740b9aa0d34058fd3b906e4f7859dfb07d7173e5e6f6350adac21f27b2307469",
+ "bd0ce19549d0700120cbe51077dbbbb00a8d8b09",
+ "08180de825e4b8b014a32da8ba761555921204f2f90d5f24b712908ff84f3e220ad17997c0dd6e706630ba3e84add4d5e7ab004e58074b549709565d43ad9e97b5a7a1a29e85b9f90f4aafcdf58321de8c5974ef9abf2d526f33c0f2f82e95d158ea6b81f1736db8d1af3d6ac6a83b32d18bae0ff1b2fe27de4c76ed8c7980a34e",
+
+ "8d8396e36507fe1ef6a19017548e0c716674c2fec233adb2f775665ec41f2bd0ba396b061a9daa7e866f7c23fd3531954300a342f924535ea1498c48f6c879932865fc02000c528723b7ad0335745b51209a0afed932af8f0887c219004d2abd894ea92559ee3198af3a734fe9b9638c263a728ad95a5ae8ce3eb15839f3aa7852bb390706e7760e43a71291a2e3f827237deda851874c517665f545f27238df86557f375d09ccd8bd15d8ccf61f5d78ca5c7f5cde782e6bf5d0057056d4bad98b3d2f9575e824ab7a33ff57b0ac100ab0d6ead7aa0b50f6e4d3e5ec0b966b",
+ "815779a91b3a8bd049bf2aeb920142772222c9ca",
+ "05e0fdbdf6f756ef733185ccfa8ced2eb6d029d9d56e35561b5db8e70257ee6fd019d2f0bbf669fe9b9821e78df6d41e31608d58280f318ee34f559941c8df13287574bac000b7e58dc4f414ba49fb127f9d0f8936638c76e85356c994f79750f7fa3cf4fd482df75e3fb9978cd061f7abb17572e6e63e0bde12cbdcf18c68b979",
+
+ "328c659e0a6437433cceb73c14",
+ "9aec4a7480d5bbc42920d7ca235db674989c9aac",
+ "0bc989853bc2ea86873271ce183a923ab65e8a53100e6df5d87a24c4194eb797813ee2a187c097dd872d591da60c568605dd7e742d5af4e33b11678ccb63903204a3d080b0902c89aba8868f009c0f1c0cb85810bbdd29121abb8471ff2d39e49fd92d56c655c8e037ad18fafbdc92c95863f7f61ea9efa28fea401369d19daea1",
+
+ "f37b962379a47d415a376eec8973150bcb34edd5ab654041b61430560c2144582ba133c867d852d6b8e23321901302ecb45b09ec88b1527178fa043263f3067d9ffe973032a99f4cb08ad2c7e0a2456cdd57a7df56fe6053527a5aeb67d7e552063c1ca97b1beffa7b39e997caf27878ea0f62cbebc8c21df4c889a202851e949088490c249b6e9acf1d8063f5be2343989bf95c4da01a2be78b4ab6b378015bc37957f76948b5e58e440c28453d40d7cfd57e7d690600474ab5e75973b1ea0c5f1e45d14190afe2f4eb6d3bdf71f1d2f8bb156a1c295d04aaeb9d689dce79ed62bc443e",
+ "e20c1e9878512c39970f58375e1549a68b64f31d",
+ "0aefa943b698b9609edf898ad22744ac28dc239497cea369cbbd84f65c95c0ad776b594740164b59a739c6ff7c2f07c7c077a86d95238fe51e1fcf33574a4ae0684b42a3f6bf677d91820ca89874467b2c23add77969c80717430d0efc1d3695892ce855cb7f7011630f4df26def8ddf36fc23905f57fa6243a485c770d5681fcd",
+
+ "c6103c330c1ef718c141e47b8fa859be4d5b96259e7d142070ecd485839dba5a8369c17c1114035e532d195c74f44a0476a2d3e8a4da210016caced0e367cb867710a4b5aa2df2b8e5daf5fdc647807d4d5ebb6c56b9763ccdae4dea3308eb0ac2a89501cb209d2639fa5bf87ce790747d3cb2d295e84564f2f637824f0c13028129b0aa4a422d162282",
+ "23291e4a3307e8bbb776623ab34e4a5f4cc8a8db",
+ "02802dccfa8dfaf5279bf0b4a29ba1b157611faeaaf419b8919d15941900c1339e7e92e6fae562c53e6cc8e84104b110bce03ad18525e3c49a0eadad5d3f28f244a8ed89edbafbb686277cfa8ae909714d6b28f4bf8e293aa04c41efe7c0a81266d5c061e2575be032aa464674ff71626219bd74cc45f0e7ed4e3ff96eee758e8f",
+
+ /* 1029-bit key */
+ "164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1",
+ "010001",
+ "03b664ee3b7566723fc6eaf28abb430a3980f1126c81de8ad709eab39ac9dcd0b1550b3729d87068e952009df544534c1f50829a78f4591eb8fd57140426a6bb0405b6a6f51a57d9267b7bbc653391a699a2a90dac8ae226bcc60fa8cd934c73c7b03b1f6b818158631838a8612e6e6ea92be24f8324faf5b1fd8587225267ba6f",
+ "04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543",
+ "0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b",
+ "03a8e8aea9920c1aa3b2f0d846e4b850d81ca306a51c83544f949f64f90dcf3f8e2661f07e561220a180388fbe273e70e2e5dca83a0e1348dd6490c731d6ece1ab",
+ "0135bdcdb60bf2197c436ed34b32cd8b4fc77778832ba76703551fb242b301699593af77fd8fc394a8526ad23cc41a03806bd897fe4b0ea646558aaddcc99e8a25",
+ "0304c03d9c736503a984abbd9ba22301407c4a2ab1dd85766481b60d45401152e692be14f4121d9aa3fd6e0b4d1d3a973538a31d42ee6e1e5ef620231a2bbaf35f",
+
+ "0a20b774addc2fa51245ed7cb9da609e50cac6636a52543f97458eed7340f8d53ffc64918f949078ee03ef60d42b5fec246050bd5505cd8cb597bad3c4e713b0ef30644e76adabb0de01a1561efb255158c74fc801e6e919e581b46f0f0ddd08e4f34c7810b5ed8318f91d7c8c",
+ "5b4ea2ef629cc22f3b538e016904b47b1e40bfd5",
+ "04c0cfacec04e5badbece159a5a1103f69b3f32ba593cb4cc4b1b7ab455916a96a27cd2678ea0f46ba37f7fc9c86325f29733b389f1d97f43e7201c0f348fc45fe42892335362eee018b5b161f2f9393031225c713012a576bc88e23052489868d9010cbf033ecc568e8bc152bdc59d560e41291915d28565208e22aeec9ef85d1",
+
+ "2aaff6631f621ce615760a9ebce94bb333077ad86488c861d4b76d29c1f48746c611ae1e03ced4445d7cfa1fe5f62e1b3f08452bde3b6ef81973bafbb57f97bceef873985395b8260589aa88cb7db50ab469262e551bdcd9a56f275a0ac4fe484700c35f3dbf2b469ede864741b86fa59172a360ba95a02e139be50ddfb7cf0b42faeabbfbbaa86a4497699c4f2dfd5b08406af7e14144427c253ec0efa20eaf9a8be8cd49ce1f1bc4e93e619cf2aa8ed4fb39bc8590d0f7b96488f7317ac9abf7bee4e3a0e715",
+ "83146a9e782722c28b014f98b4267bda2ac9504f",
+ "0a2314250cf52b6e4e908de5b35646bcaa24361da8160fb0f9257590ab3ace42b0dc3e77ad2db7c203a20bd952fbb56b1567046ecfaa933d7b1000c3de9ff05b7d989ba46fd43bc4c2d0a3986b7ffa13471d37eb5b47d64707bd290cfd6a9f393ad08ec1e3bd71bb5792615035cdaf2d8929aed3be098379377e777ce79aaa4773",
+
+ "0f6195d04a6e6fc7e2c9600dbf840c39ea8d4d624fd53507016b0e26858a5e0aecd7ada543ae5c0ab3a62599cba0a54e6bf446e262f989978f9ddf5e9a41",
+ "a87b8aed07d7b8e2daf14ddca4ac68c4d0aabff8",
+ "086df6b500098c120f24ff8423f727d9c61a5c9007d3b6a31ce7cf8f3cbec1a26bb20e2bd4a046793299e03e37a21b40194fb045f90b18bf20a47992ccd799cf9c059c299c0526854954aade8a6ad9d97ec91a1145383f42468b231f4d72f23706d9853c3fa43ce8ace8bfe7484987a1ec6a16c8daf81f7c8bf42774707a9df456",
+
+ "337d25fe9810ebca0de4d4658d3ceb8e0fe4c066aba3bcc48b105d3bf7e0257d44fecea6596f4d0c59a08402833678f70620f9138dfeb7ded905e4a6d5f05c473d55936652e2a5df43c0cfda7bacaf3087f4524b06cf42157d01539739f7fddec9d58125df31a32eab06c19b71f1d5bf",
+ "a37932f8a7494a942d6f767438e724d6d0c0ef18",
+ "0b5b11ad549863ffa9c51a14a1106c2a72cc8b646e5c7262509786105a984776534ca9b54c1cc64bf2d5a44fd7e8a69db699d5ea52087a4748fd2abc1afed1e5d6f7c89025530bdaa2213d7e030fa55df6f34bcf1ce46d2edf4e3ae4f3b01891a068c9e3a44bbc43133edad6ecb9f35400c4252a5762d65744b99cb9f4c559329f",
+
+ "84ec502b072e8287789d8f9235829ea3b187afd4d4c785611bda5f9eb3cb96717efa7007227f1c08cbcb972e667235e0fb7d431a6570326d2ecce35adb373dc753b3be5f829b89175493193fab16badb41371b3aac0ae670076f24bef420c135add7cee8d35fbc944d79fafb9e307a13b0f556cb654a06f973ed22672330197ef5a748bf826a5db2383a25364b686b9372bb2339aeb1ac9e9889327d016f1670776db06201adbdcaf8a5e3b74e108b73",
+ "7b790c1d62f7b84e94df6af28917cf571018110e",
+ "02d71fa9b53e4654fefb7f08385cf6b0ae3a817942ebf66c35ac67f0b069952a3ce9c7e1f1b02e480a9500836de5d64cdb7ecde04542f7a79988787e24c2ba05f5fd482c023ed5c30e04839dc44bed2a3a3a4fee01113c891a47d32eb8025c28cb050b5cdb576c70fe76ef523405c08417faf350b037a43c379339fcb18d3a356b",
+
+ "9906d89f97a9fdedd3ccd824db687326f30f00aa25a7fca2afcb3b0f86cd41e73f0e8ff7d2d83f59e28ed31a5a0d551523374de22e4c7e8ff568b386ee3dc41163f10bf67bb006261c9082f9af90bf1d9049a6b9fae71c7f84fbe6e55f02789de774f230f115026a4b4e96c55b04a95da3aacbb2cece8f81764a1f1c99515411087cf7d34aeded0932c183",
+ "fbbe059025b69b89fb14ae2289e7aaafe60c0fcd",
+ "0a40a16e2fe2b38d1df90546167cf9469c9e3c3681a3442b4b2c2f581deb385ce99fc6188bb02a841d56e76d301891e24560550fcc2a26b55f4ccb26d837d350a154bcaca8392d98fa67959e9727b78cad03269f56968fc56b68bd679926d83cc9cb215550645ccda31c760ff35888943d2d8a1d351e81e5d07b86182e751081ef",
+
+ /* 1030-bit key */
+ "37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3",
+ "010001",
+ "3bed999052d957bc06d651eef6e3a98094b1621bd38b5449bd6c4aea3de7e084679a4484ded25be0f0826cf3377825414b14d4d61db14de626fbb80e5f4faec956f9a0a2d24f99576380f084eb62e46a57d554278b535626193ce02060575eb66c5798d36f6c5d40fb00d809b42a73102c1c74ee95bd71420fffef6318b52c29",
+ "07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535",
+ "070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547",
+ "0524d20c3d95cff75af2313483227d8702717aa576de155f960515501adb1d70e1c04de91b75b161dbf0398356127ededa7bbc19a32dc1621cc9f53c265d0ce331",
+ "05f984a1f23c938d6a0e89724bcf3dd93f9946926037fe7c6b13a29e5284855f89089591d440975627bf5c9e3a8b5ca79c772ad273e40d321af4a6c97dfded78d3",
+ "ddd918adada29dcab981ff9acba4257023c09a3801ccce098ce268f855d0df570cd6e7b9b14bd9a5a9254cbc315be6f8ba1e2546ddd569c5ea19eed8353bde5e",
+
+ "9ead0e01945640674eb41cad435e2374eaefa8ad7197d97913c44957d8d83f40d76ee60e39bf9c0f9eaf3021421a074d1ade962c6e9d3dc3bb174fe4dfe652b09115495b8fd2794174020a0602b5ca51848cfc96ce5eb57fc0a2adc1dda36a7cc452641a14911b37e45bfa11daa5c7ecdb74f6d0100d1d3e39e752800e203397de0233077b9a88855537fae927f924380d780f98e18dcff39c5ea741b17d6fdd1885bc9d581482d771ceb562d78a8bf88f0c75b11363e5e36cd479ceb0545f9da84203e0e6e508375cc9e844b88b7ac7a0a201ea0f1bee9a2c577920ca02c01b9d8320e974a56f4efb5763b96255abbf8037bf1802cf018f56379493e569a9",
+ "b7867a59958cb54328f8775e6546ec06d27eaa50",
+ "187f390723c8902591f0154bae6d4ecbffe067f0e8b795476ea4f4d51ccc810520bb3ca9bca7d0b1f2ea8a17d873fa27570acd642e3808561cb9e975ccfd80b23dc5771cdb3306a5f23159dacbd3aa2db93d46d766e09ed15d900ad897a8d274dc26b47e994a27e97e2268a766533ae4b5e42a2fcaf755c1c4794b294c60555823",
+
+ "8d80d2d08dbd19c154df3f14673a14bd03735231f24e86bf153d0e69e74cbff7b1836e664de83f680124370fc0f96c9b65c07a366b644c4ab3",
+ "0c09582266df086310821ba7e18df64dfee6de09",
+ "10fd89768a60a67788abb5856a787c8561f3edcf9a83e898f7dc87ab8cce79429b43e56906941a886194f137e591fe7c339555361fbbe1f24feb2d4bcdb80601f3096bc9132deea60ae13082f44f9ad41cd628936a4d51176e42fc59cb76db815ce5ab4db99a104aafea68f5d330329ebf258d4ede16064bd1d00393d5e1570eb8",
+
+ "808405cdfc1a58b9bb0397c720722a81fffb76278f335917ef9c473814b3e016ba2973cd2765f8f3f82d6cc38aa7f8551827fe8d1e3884b7e61c94683b8f82f1843bdae2257eeec9812ad4c2cf283c34e0b0ae0fe3cb990cf88f2ef9",
+ "28039dcfe106d3b8296611258c4a56651c9e92dd",
+ "2b31fde99859b977aa09586d8e274662b25a2a640640b457f594051cb1e7f7a911865455242926cf88fe80dfa3a75ba9689844a11e634a82b075afbd69c12a0df9d25f84ad4945df3dc8fe90c3cefdf26e95f0534304b5bdba20d3e5640a2ebfb898aac35ae40f26fce5563c2f9f24f3042af76f3c7072d687bbfb959a88460af1",
+
+ "f337b9bad937de22a1a052dff11134a8ce26976202981939b91e0715ae5e609649da1adfcef3f4cca59b238360e7d1e496c7bf4b204b5acff9bbd6166a1d87a36ef2247373751039f8a800b8399807b3a85f44893497c0d05fb7017b82228152de6f25e6116dcc7503c786c875c28f3aa607e94ab0f19863ab1b5073770b0cd5f533acde30c6fb953cf3da680264e30fc11bff9a19bffab4779b6223c3fb3fe0f71abade4eb7c09c41e24c22d23fa148e6a173feb63984d1bc6ee3a02d915b752ceaf92a3015eceb38ca586c6801b37c34cefb2cff25ea23c08662dcab26a7a93a285d05d3044c",
+ "a77821ebbbef24628e4e12e1d0ea96de398f7b0f",
+ "32c7ca38ff26949a15000c4ba04b2b13b35a3810e568184d7ecabaa166b7ffabddf2b6cf4ba07124923790f2e5b1a5be040aea36fe132ec130e1f10567982d17ac3e89b8d26c3094034e762d2e031264f01170beecb3d1439e05846f25458367a7d9c02060444672671e64e877864559ca19b2074d588a281b5804d23772fbbe19",
+
+ "45013cebafd960b255476a8e2598b9aa32efbe6dc1f34f4a498d8cf5a2b4548d08c55d5f95f7bcc9619163056f2d58b52fa032",
+ "9d5ad8eb452134b65dc3a98b6a73b5f741609cd6",
+ "07eb651d75f1b52bc263b2e198336e99fbebc4f332049a922a10815607ee2d989db3a4495b7dccd38f58a211fb7e193171a3d891132437ebca44f318b280509e52b5fa98fcce8205d9697c8ee4b7ff59d4c59c79038a1970bd2a0d451ecdc5ef11d9979c9d35f8c70a6163717607890d586a7c6dc01c79f86a8f28e85235f8c2f1",
+
+ "2358097086c899323e75d9c90d0c09f12d9d54edfbdf70a9c2eb5a04d8f36b9b2bdf2aabe0a5bda1968937f9d6ebd3b6b257efb3136d4131f9acb59b85e2602c2a3fcdc835494a1f4e5ec18b226c80232b36a75a45fdf09a7ea9e98efbde1450d1194bf12e15a4c5f9eb5c0bce5269e0c3b28cfab655d81a61a20b4be2f54459bb25a0db94c52218be109a7426de83014424789aaa90e5056e632a698115e282c1a56410f26c2072f193481a9dcd880572005e64f4082ecf",
+ "3f2efc595880a7d47fcf3cba04983ea54c4b73fb",
+ "18da3cdcfe79bfb77fd9c32f377ad399146f0a8e810620233271a6e3ed3248903f5cdc92dc79b55d3e11615aa056a795853792a3998c349ca5c457e8ca7d29d796aa24f83491709befcfb1510ea513c92829a3f00b104f655634f320752e130ec0ccf6754ff893db302932bb025eb60e87822598fc619e0e981737a9a4c4152d33",
+
+ /* 1031-bit key */
+ "495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f",
+ "010001",
+ "6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701c2d6266d517219ad0ec6d347dbe9",
+ "08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb",
+ "0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d",
+ "05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fce69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee103deb771d105fd85",
+ "04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b3669bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e30a7e7d241551e1b9",
+ "07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef531b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7b06e45307dc91f3f",
+
+ "81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb",
+ "1d65491d79c864b373009be6f6f2467bac4c78fa",
+ "0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5",
+
+ "e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08",
+ "435c098aa9909eb2377f1248b091b68987ff1838",
+ "2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e",
+
+ "e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7",
+ "c6ebbe76df0c4aea32c474175b2f136862d04529",
+ "2ad20509d78cf26d1b6c406146086e4b0c91a91c2bd164c87b966b8faa42aa0ca446022323ba4b1a1b89706d7f4c3be57d7b69702d168ab5955ee290356b8c4a29ed467d547ec23cbadf286ccb5863c6679da467fc9324a151c7ec55aac6db4084f82726825cfe1aa421bc64049fb42f23148f9c25b2dc300437c38d428aa75f96",
+
+ "dbc5f750a7a14be2b93e838d18d14a8695e52e8add9c0ac733b8f56d2747e529a0cca532dd49b902aefed514447f9e81d16195c2853868cb9b30f7d0d495c69d01b5c5d50b27045db3866c2324a44a110b1717746de457d1c8c45c3cd2a92970c3d59632055d4c98a41d6e99e2a3ddd5f7f9979ab3cd18f37505d25141de2a1bff17b3a7dce9419ecc385cf11d72840f19953fd0509251f6cafde2893d0e75c781ba7a5012ca401a4fa99e04b3c3249f926d5afe82cc87dab22c3c1b105de48e34ace9c9124e59597ac7ebf8",
+ "021fdcc6ebb5e19b1cb16e9c67f27681657fe20a",
+ "1e24e6e58628e5175044a9eb6d837d48af1260b0520e87327de7897ee4d5b9f0df0be3e09ed4dea8c1454ff3423bb08e1793245a9df8bf6ab3968c8eddc3b5328571c77f091cc578576912dfebd164b9de5454fe0be1c1f6385b328360ce67ec7a05f6e30eb45c17c48ac70041d2cab67f0a2ae7aafdcc8d245ea3442a6300ccc7",
+
+ "04dc251be72e88e5723485b6383a637e2fefe07660c519a560b8bc18bdedb86eae2364ea53ba9dca6eb3d2e7d6b806af42b3e87f291b4a8881d5bf572cc9a85e19c86acb28f098f9da0383c566d3c0f58cfd8f395dcf602e5cd40e8c7183f714996e2297ef",
+ "c558d7167cbb4508ada042971e71b1377eea4269",
+ "33341ba3576a130a50e2a5cf8679224388d5693f5accc235ac95add68e5eb1eec31666d0ca7a1cda6f70a1aa762c05752a51950cdb8af3c5379f18cfe6b5bc55a4648226a15e912ef19ad77adeea911d67cfefd69ba43fa4119135ff642117ba985a7e0100325e9519f1ca6a9216bda055b5785015291125e90dcd07a2ca9673ee",
+
+ "0ea37df9a6fea4a8b610373c24cf390c20fa6e2135c400c8a34f5c183a7e8ea4c9ae090ed31759f42dc77719cca400ecdcc517acfc7ac6902675b2ef30c509665f3321482fc69a9fb570d15e01c845d0d8e50d2a24cbf1cf0e714975a5db7b18d9e9e9cb91b5cb16869060ed18b7b56245503f0caf90352b8de81cb5a1d9c6336092f0cd",
+ "76fd4e64fdc98eb927a0403e35a084e76ba9f92a",
+ "1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e",
+
+ /* 1536-bit key */
+ "e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b",
+ "010001",
+ "6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d51410b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf21311666070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab328ce420689903c00c7b5fd31b75503a6d419684d629",
+ "f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367",
+ "ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d",
+ "2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0ab556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec993e9353e480d9eec6289f",
+ "4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56ee4dba42c5fdb61aec2669",
+ "77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124cbbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65757bb3f857a58dce52156",
+
+ "a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5",
+ "c0a425313df8d7564bd2434d311523d5257eed80",
+ "586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e",
+
+ "c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e",
+ "b307c43b4850a8dac2f15f32e37839ef8c5c0e91",
+ "80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958",
+
+ "0afad42ccd4fc60654a55002d228f52a4a5fe03b8bbb08ca82daca558b44dbe1266e50c0e745a36d9d2904e3408abcd1fd569994063f4a75cc72f2fee2a0cd893a43af1c5b8b487df0a71610024e4f6ddf9f28ad0813c1aab91bcb3c9064d5ff742deffea657094139369e5ea6f4a96319a5cc8224145b545062758fefd1fe3409ae169259c6cdfd6b5f2958e314faecbe69d2cace58ee55179ab9b3e6d1ecc14a557c5febe988595264fc5da1c571462eca798a18a1a4940cdab4a3e92009ccd42e1e947b1314e32238a2dece7d23a89b5b30c751fd0a4a430d2c548594",
+ "9a2b007e80978bbb192c354eb7da9aedfc74dbf5",
+ "484408f3898cd5f53483f80819efbf2708c34d27a8b2a6fae8b322f9240237f981817aca1846f1084daa6d7c0795f6e5bf1af59c38e1858437ce1f7ec419b98c8736adf6dd9a00b1806d2bd3ad0a73775e05f52dfef3a59ab4b08143f0df05cd1ad9d04bececa6daa4a2129803e200cbc77787caf4c1d0663a6c5987b605952019782caf2ec1426d68fb94ed1d4be816a7ed081b77e6ab330b3ffc073820fecde3727fcbe295ee61a050a343658637c3fd659cfb63736de32d9f90d3c2f63eca",
+
+ "1dfd43b46c93db82629bdae2bd0a12b882ea04c3b465f5cf93023f01059626dbbe99f26bb1be949dddd16dc7f3debb19a194627f0b224434df7d8700e9e98b06e360c12fdbe3d19f51c9684eb9089ecbb0a2f0450399d3f59eac7294085d044f5393c6ce737423d8b86c415370d389e30b9f0a3c02d25d0082e8ad6f3f1ef24a45c3cf82b383367063a4d4613e4264f01b2dac2e5aa42043f8fb5f69fa871d14fb273e767a531c40f02f343bc2fb45a0c7e0f6be2561923a77211d66a6e2dbb43c366350beae22da3ac2c1f5077096fcb5c4bf255f7574351ae0b1e1f03632817c0856d4a8ba97afbdc8b85855402bc56926fcec209f9ea8",
+ "70f382bddf4d5d2dd88b3bc7b7308be632b84045",
+ "84ebeb481be59845b46468bafb471c0112e02b235d84b5d911cbd1926ee5074ae0424495cb20e82308b8ebb65f419a03fb40e72b78981d88aad143053685172c97b29c8b7bf0ae73b5b2263c403da0ed2f80ff7450af7828eb8b86f0028bd2a8b176a4d228cccea18394f238b09ff758cc00bc04301152355742f282b54e663a919e709d8da24ade5500a7b9aa50226e0ca52923e6c2d860ec50ff480fa57477e82b0565f4379f79c772d5c2da80af9fbf325ece6fc20b00961614bee89a183e",
+
+ "1bdc6e7c98fb8cf54e9b097b66a831e9cfe52d9d4888448ee4b0978093ba1d7d73ae78b3a62ba4ad95cd289ccb9e005226bb3d178bccaa821fb044a4e21ee97696c14d0678c94c2dae93b0ad73922218553daa7e44ebe57725a7a45cc72b9b2138a6b17c8db411ce8279ee1241aff0a8bec6f77f87edb0c69cb27236e3435a800b192e4f11e519e3fe30fc30eaccca4fbb41769029bf708e817a9e683805be67fa100984683b74838e3bcffa79366eed1d481c76729118838f31ba8a048a93c1be4424598e8df6328b7a77880a3f9c7e2e8dfca8eb5a26fb86bdc556d42bbe01d9fa6ed80646491c9341",
+ "d689257a86effa68212c5e0c619eca295fb91b67",
+ "82102df8cb91e7179919a04d26d335d64fbc2f872c44833943241de8454810274cdf3db5f42d423db152af7135f701420e39b494a67cbfd19f9119da233a23da5c6439b5ba0d2bc373eee3507001378d4a4073856b7fe2aba0b5ee93b27f4afec7d4d120921c83f606765b02c19e4d6a1a3b95fa4c422951be4f52131077ef17179729cddfbdb56950dbaceefe78cb16640a099ea56d24389eef10f8fecb31ba3ea3b227c0a86698bb89e3e9363905bf22777b2a3aa521b65b4cef76d83bde4c",
+
+ "88c7a9f1360401d90e53b101b61c5325c3c75db1b411fbeb8e830b75e96b56670ad245404e16793544ee354bc613a90cc9848715a73db5893e7f6d279815c0c1de83ef8e2956e3a56ed26a888d7a9cdcd042f4b16b7fa51ef1a0573662d16a302d0ec5b285d2e03ad96529c87b3d374db372d95b2443d061b6b1a350ba87807ed083afd1eb05c3f52f4eba5ed2227714fdb50b9d9d9dd6814f62f6272fcd5cdbce7a9ef797",
+ "c25f13bf67d081671a0481a1f1820d613bba2276",
+ "a7fdb0d259165ca2c88d00bbf1028a867d337699d061193b17a9648e14ccbbaadeacaacdec815e7571294ebb8a117af205fa078b47b0712c199e3ad05135c504c24b81705115740802487992ffd511d4afc6b854491eb3f0dd523139542ff15c3101ee85543517c6a3c79417c67e2dd9aa741e9a29b06dcb593c2336b3670ae3afbac7c3e76e215473e866e338ca244de00b62624d6b9426822ceae9f8cc460895f41250073fd45c5a1e7b425c204a423a699159f6903e710b37a7bb2bc8049f",
+
+ /* 2048-bit key */
+ "a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05",
+ "010001",
+ "2d2ff567b3fe74e06191b7fded6de112290c670692430d5969184047da234c9693deed1673ed429539c969d372c04d6b47e0f5b8cee0843e5c22835dbd3b05a0997984ae6058b11bc4907cbf67ed84fa9ae252dfb0d0cd49e618e35dfdfe59bca3ddd66c33cebbc77ad441aa695e13e324b518f01c60f5a85c994ad179f2a6b5fbe93402b11767be01bf073444d6ba1dd2bca5bd074d4a5fae3531ad1303d84b30d897318cbbba04e03c2e66de6d91f82f96ea1d4bb54a5aae102d594657f5c9789553512b296dea29d8023196357e3e3a6e958f39e3c2344038ea604b31edc6f0f7ff6e7181a57c92826a268f86768e96f878562fc71d85d69e448612f7048f",
+ "cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb",
+ "cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf",
+ "1c2d1fc32f6bc4004fd85dfde0fbbf9a4c38f9c7c4e41dea1aa88234a201cd92f3b7da526583a98ad85bb360fb983b711e23449d561d1778d7a515486bcbf47b46c9e9e1a3a1f77000efbeb09a8afe47e5b857cda99cb16d7fff9b712e3bd60ca96d9c7973d616d46934a9c050281c004399ceff1db7dda78766a8a9b9cb0873",
+ "cb3b3c04caa58c60be7d9b2debb3e39643f4f57397be08236a1e9eafaa706536e71c3acfe01cc651f23c9e05858fee13bb6a8afc47df4edc9a4ba30bcecb73d0157852327ee789015c2e8dee7b9f05a0f31ac94eb6173164740c5c95147cd5f3b5ae2cb4a83787f01d8ab31f27c2d0eea2dd8a11ab906aba207c43c6ee125331",
+ "12f6b2cf1374a736fad05616050f96ab4b61d1177c7f9d525a29f3d180e77667e99d99abf0525d0758660f3752655b0f25b8df8431d9a8ff77c16c12a0a5122a9f0bf7cfd5a266a35c159f991208b90316ff444f3e0b6bd0e93b8a7a2448e957e3dda6cfcf2266b106013ac46808d3b3887b3b00344baac9530b4ce708fc32b6",
+
+ "883177e5126b9be2d9a9680327d5370c6f26861f5820c43da67a3ad609",
+ "04e215ee6ff934b9da70d7730c8734abfcecde89",
+ "82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666",
+
+ "dd670a01465868adc93f26131957a50c52fb777cdbaa30892c9e12361164ec13979d43048118e4445db87bee58dd987b3425d02071d8dbae80708b039dbb64dbd1de5657d9fed0c118a54143742e0ff3c87f74e45857647af3f79eb0a14c9d75ea9a1a04b7cf478a897a708fd988f48e801edb0b7039df8c23bb3c56f4e821ac",
+ "8b2bdd4b40faf545c778ddf9bc1a49cb57f9b71b",
+ "14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3",
+
+ "48b2b6a57a63c84cea859d65c668284b08d96bdcaabe252db0e4a96cb1bac6019341db6fbefb8d106b0e90eda6bcc6c6262f37e7ea9c7e5d226bd7df85ec5e71efff2f54c5db577ff729ff91b842491de2741d0c631607df586b905b23b91af13da12304bf83eca8a73e871ff9db",
+ "4e96fc1b398f92b44671010c0dc3efd6e20c2d73",
+ "6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb",
+
+ "0b8777c7f839baf0a64bbbdbc5ce79755c57a205b845c174e2d2e90546a089c4e6ec8adffa23a7ea97bae6b65d782b82db5d2b5a56d22a29a05e7c4433e2b82a621abba90add05ce393fc48a840542451a",
+ "c7cd698d84b65128d8835e3a8b1eb0e01cb541ec",
+ "34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb",
+
+ "f1036e008e71e964dadc9219ed30e17f06b4b68a955c16b312b1eddf028b74976bed6b3f6a63d4e77859243c9cccdc98016523abb02483b35591c33aad81213bb7c7bb1a470aabc10d44256c4d4559d916",
+ "efa8bff96212b2f4a3f371a10d574152655f5dfb",
+ "7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc",
+
+ "25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7",
+ "ad8b1523703646224b660b550885917ca2d1df28",
+ "6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f",
+
+ NULL
+};
+
+static void
+test_RSA_PSS(const char *name,
+ br_rsa_pss_sign sign, br_rsa_pss_vrfy vrfy)
+{
+ size_t u;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ u = 0;
+ while (KAT_RSA_PSS[u] != NULL) {
+ unsigned char n[512];
+ unsigned char e[8];
+ unsigned char d[512];
+ unsigned char p[256];
+ unsigned char q[256];
+ unsigned char dp[256];
+ unsigned char dq[256];
+ unsigned char iq[256];
+ br_rsa_public_key pk;
+ br_rsa_private_key sk;
+ size_t v;
+
+ pk.n = n;
+ pk.nlen = hextobin(n, KAT_RSA_PSS[u ++]);
+ pk.e = e;
+ pk.elen = hextobin(e, KAT_RSA_PSS[u ++]);
+
+ /*
+ * 'd' is in the test vectors, but we don't use it.
+ */
+ hextobin(d, KAT_RSA_PSS[u ++]);
+
+ for (v = 0; n[v] == 0; v ++);
+ sk.n_bitlen = BIT_LENGTH(n[v]) + ((pk.nlen - 1 - v) << 3);
+ sk.p = p;
+ sk.plen = hextobin(p, KAT_RSA_PSS[u ++]);
+ sk.q = q;
+ sk.qlen = hextobin(q, KAT_RSA_PSS[u ++]);
+ sk.dp = dp;
+ sk.dplen = hextobin(dp, KAT_RSA_PSS[u ++]);
+ sk.dq = dq;
+ sk.dqlen = hextobin(dq, KAT_RSA_PSS[u ++]);
+ sk.iq = iq;
+ sk.iqlen = hextobin(iq, KAT_RSA_PSS[u ++]);
+
+ for (v = 0; v < 6; v ++) {
+ unsigned char plain[512], salt[128], sig[512];
+ size_t plain_len, salt_len, sig_len;
+ rng_fake_ctx rng;
+ unsigned char hash[20], tmp[513];
+ br_sha1_context sc;
+
+ plain_len = hextobin(plain, KAT_RSA_PSS[u ++]);
+ salt_len = hextobin(salt, KAT_RSA_PSS[u ++]);
+ sig_len = hextobin(sig, KAT_RSA_PSS[u ++]);
+
+ br_sha1_init(&sc);
+ br_sha1_update(&sc, plain, plain_len);
+ br_sha1_out(&sc, hash);
+ rng_fake_init(&rng, NULL, salt, salt_len);
+
+ memset(tmp, 0, sizeof tmp);
+ if (sign(&rng.vtable,
+ &br_sha1_vtable, &br_sha1_vtable,
+ hash, salt_len, &sk, tmp) != 1)
+ {
+ fprintf(stderr, "signature failed\n");
+ }
+ if (rng.ptr != rng.len) {
+ fprintf(stderr, "salt not fully consumed\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA/PSS sign", tmp, sig, sig_len);
+
+ if (vrfy(sig, sig_len,
+ &br_sha1_vtable, &br_sha1_vtable,
+ hash, salt_len, &pk) != 1)
+ {
+ fprintf(stderr, "verification failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ sig[sig_len >> 1] ^= 0x01;
+ if (vrfy(sig, sig_len,
+ &br_sha1_vtable, &br_sha1_vtable,
+ hash, salt_len, &pk) != 0)
+ {
+ fprintf(stderr,
+ "verification should have failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+/*
+ * Test vectors from pkcs-1v2-1d2-vec.zip (originally from ftp.rsa.com).
+ * There are ten RSA keys, and for each RSA key, there are 6 messages,
+ * each with an explicit seed.
+ *
+ * Field order:
+ * modulus (n)
+ * public exponent (e)
+ * first factor (p)
+ * second factor (q)
+ * first private exponent (dp)
+ * second private exponent (dq)
+ * CRT coefficient (iq)
+ * cleartext 1
+ * seed 1 (20-byte random value)
+ * ciphertext 1
+ * cleartext 2
+ * seed 2 (20-byte random value)
+ * ciphertext 2
+ * ...
+ * cleartext 6
+ * seed 6 (20-byte random value)
+ * ciphertext 6
+ *
+ * This pattern is repeated for all keys. The array stops on a NULL.
+ */
+static const char *KAT_RSA_OAEP[] = {
+ /* 1024-bit key, from oeap-int.txt */
+ "BBF82F090682CE9C2338AC2B9DA871F7368D07EED41043A440D6B6F07454F51FB8DFBAAF035C02AB61EA48CEEB6FCD4876ED520D60E1EC4619719D8A5B8B807FAFB8E0A3DFC737723EE6B4B7D93A2584EE6A649D060953748834B2454598394EE0AAB12D7B61A51F527A9A41F6C1687FE2537298CA2A8F5946F8E5FD091DBDCB",
+ "11",
+ "EECFAE81B1B9B3C908810B10A1B5600199EB9F44AEF4FDA493B81A9E3D84F632124EF0236E5D1E3B7E28FAE7AA040A2D5B252176459D1F397541BA2A58FB6599",
+ "C97FB1F027F453F6341233EAAAD1D9353F6C42D08866B1D05A0F2035028B9D869840B41666B42E92EA0DA3B43204B5CFCE3352524D0416A5A441E700AF461503",
+ "54494CA63EBA0337E4E24023FCD69A5AEB07DDDC0183A4D0AC9B54B051F2B13ED9490975EAB77414FF59C1F7692E9A2E202B38FC910A474174ADC93C1F67C981",
+ "471E0290FF0AF0750351B7F878864CA961ADBD3A8A7E991C5C0556A94C3146A7F9803F8F6F8AE342E931FD8AE47A220D1B99A495849807FE39F9245A9836DA3D",
+ "B06C4FDABB6301198D265BDBAE9423B380F271F73453885093077FCD39E2119FC98632154F5883B167A967BF402B4E9E2E0F9656E698EA3666EDFB25798039F7",
+
+ /* oaep-int.txt contains only one message, so we repeat it six
+ times to respect our array format. */
+ "D436E99569FD32A7C8A05BBC90D32C49",
+ "AAFD12F659CAE63489B479E5076DDEC2F06CB58F",
+ "1253E04DC0A5397BB44A7AB87E9BF2A039A33D1E996FC82A94CCD30074C95DF763722017069E5268DA5D1C0B4F872CF653C11DF82314A67968DFEAE28DEF04BB6D84B1C31D654A1970E5783BD6EB96A024C2CA2F4A90FE9F2EF5C9C140E5BB48DA9536AD8700C84FC9130ADEA74E558D51A74DDF85D8B50DE96838D6063E0955",
+
+ "D436E99569FD32A7C8A05BBC90D32C49",
+ "AAFD12F659CAE63489B479E5076DDEC2F06CB58F",
+ "1253E04DC0A5397BB44A7AB87E9BF2A039A33D1E996FC82A94CCD30074C95DF763722017069E5268DA5D1C0B4F872CF653C11DF82314A67968DFEAE28DEF04BB6D84B1C31D654A1970E5783BD6EB96A024C2CA2F4A90FE9F2EF5C9C140E5BB48DA9536AD8700C84FC9130ADEA74E558D51A74DDF85D8B50DE96838D6063E0955",
+
+ "D436E99569FD32A7C8A05BBC90D32C49",
+ "AAFD12F659CAE63489B479E5076DDEC2F06CB58F",
+ "1253E04DC0A5397BB44A7AB87E9BF2A039A33D1E996FC82A94CCD30074C95DF763722017069E5268DA5D1C0B4F872CF653C11DF82314A67968DFEAE28DEF04BB6D84B1C31D654A1970E5783BD6EB96A024C2CA2F4A90FE9F2EF5C9C140E5BB48DA9536AD8700C84FC9130ADEA74E558D51A74DDF85D8B50DE96838D6063E0955",
+
+ "D436E99569FD32A7C8A05BBC90D32C49",
+ "AAFD12F659CAE63489B479E5076DDEC2F06CB58F",
+ "1253E04DC0A5397BB44A7AB87E9BF2A039A33D1E996FC82A94CCD30074C95DF763722017069E5268DA5D1C0B4F872CF653C11DF82314A67968DFEAE28DEF04BB6D84B1C31D654A1970E5783BD6EB96A024C2CA2F4A90FE9F2EF5C9C140E5BB48DA9536AD8700C84FC9130ADEA74E558D51A74DDF85D8B50DE96838D6063E0955",
+
+ "D436E99569FD32A7C8A05BBC90D32C49",
+ "AAFD12F659CAE63489B479E5076DDEC2F06CB58F",
+ "1253E04DC0A5397BB44A7AB87E9BF2A039A33D1E996FC82A94CCD30074C95DF763722017069E5268DA5D1C0B4F872CF653C11DF82314A67968DFEAE28DEF04BB6D84B1C31D654A1970E5783BD6EB96A024C2CA2F4A90FE9F2EF5C9C140E5BB48DA9536AD8700C84FC9130ADEA74E558D51A74DDF85D8B50DE96838D6063E0955",
+
+ "D436E99569FD32A7C8A05BBC90D32C49",
+ "AAFD12F659CAE63489B479E5076DDEC2F06CB58F",
+ "1253E04DC0A5397BB44A7AB87E9BF2A039A33D1E996FC82A94CCD30074C95DF763722017069E5268DA5D1C0B4F872CF653C11DF82314A67968DFEAE28DEF04BB6D84B1C31D654A1970E5783BD6EB96A024C2CA2F4A90FE9F2EF5C9C140E5BB48DA9536AD8700C84FC9130ADEA74E558D51A74DDF85D8B50DE96838D6063E0955",
+
+ /* 1024-bit key */
+ "A8B3B284AF8EB50B387034A860F146C4919F318763CD6C5598C8AE4811A1E0ABC4C7E0B082D693A5E7FCED675CF4668512772C0CBC64A742C6C630F533C8CC72F62AE833C40BF25842E984BB78BDBF97C0107D55BDB662F5C4E0FAB9845CB5148EF7392DD3AAFF93AE1E6B667BB3D4247616D4F5BA10D4CFD226DE88D39F16FB",
+ "010001",
+ "D32737E7267FFE1341B2D5C0D150A81B586FB3132BED2F8D5262864A9CB9F30AF38BE448598D413A172EFB802C21ACF1C11C520C2F26A471DCAD212EAC7CA39D",
+ "CC8853D1D54DA630FAC004F471F281C7B8982D8224A490EDBEB33D3E3D5CC93C4765703D1DD791642F1F116A0DD852BE2419B2AF72BFE9A030E860B0288B5D77",
+ "0E12BF1718E9CEF5599BA1C3882FE8046A90874EEFCE8F2CCC20E4F2741FB0A33A3848AEC9C9305FBECBD2D76819967D4671ACC6431E4037968DB37878E695C1",
+ "95297B0F95A2FA67D00707D609DFD4FC05C89DAFC2EF6D6EA55BEC771EA333734D9251E79082ECDA866EFEF13C459E1A631386B7E354C899F5F112CA85D71583",
+ "4F456C502493BDC0ED2AB756A3A6ED4D67352A697D4216E93212B127A63D5411CE6FA98D5DBEFD73263E3728142743818166ED7DD63687DD2A8CA1D2F4FBD8E1",
+
+ "6628194E12073DB03BA94CDA9EF9532397D50DBA79B987004AFEFE34",
+ "18B776EA21069D69776A33E96BAD48E1DDA0A5EF",
+ "354FE67B4A126D5D35FE36C777791A3F7BA13DEF484E2D3908AFF722FAD468FB21696DE95D0BE911C2D3174F8AFCC201035F7B6D8E69402DE5451618C21A535FA9D7BFC5B8DD9FC243F8CF927DB31322D6E881EAA91A996170E657A05A266426D98C88003F8477C1227094A0D9FA1E8C4024309CE1ECCCB5210035D47AC72E8A",
+
+ "750C4047F547E8E41411856523298AC9BAE245EFAF1397FBE56F9DD5",
+ "0CC742CE4A9B7F32F951BCB251EFD925FE4FE35F",
+ "640DB1ACC58E0568FE5407E5F9B701DFF8C3C91E716C536FC7FCEC6CB5B71C1165988D4A279E1577D730FC7A29932E3F00C81515236D8D8E31017A7A09DF4352D904CDEB79AA583ADCC31EA698A4C05283DABA9089BE5491F67C1A4EE48DC74BBBE6643AEF846679B4CB395A352D5ED115912DF696FFE0702932946D71492B44",
+
+ "D94AE0832E6445CE42331CB06D531A82B1DB4BAAD30F746DC916DF24D4E3C2451FFF59A6423EB0E1D02D4FE646CF699DFD818C6E97B051",
+ "2514DF4695755A67B288EAF4905C36EEC66FD2FD",
+ "423736ED035F6026AF276C35C0B3741B365E5F76CA091B4E8C29E2F0BEFEE603595AA8322D602D2E625E95EB81B2F1C9724E822ECA76DB8618CF09C5343503A4360835B5903BC637E3879FB05E0EF32685D5AEC5067CD7CC96FE4B2670B6EAC3066B1FCF5686B68589AAFB7D629B02D8F8625CA3833624D4800FB081B1CF94EB",
+
+ "52E650D98E7F2A048B4F86852153B97E01DD316F346A19F67A85",
+ "C4435A3E1A18A68B6820436290A37CEFB85DB3FB",
+ "45EAD4CA551E662C9800F1ACA8283B0525E6ABAE30BE4B4ABA762FA40FD3D38E22ABEFC69794F6EBBBC05DDBB11216247D2F412FD0FBA87C6E3ACD888813646FD0E48E785204F9C3F73D6D8239562722DDDD8771FEC48B83A31EE6F592C4CFD4BC88174F3B13A112AAE3B9F7B80E0FC6F7255BA880DC7D8021E22AD6A85F0755",
+
+ "8DA89FD9E5F974A29FEFFB462B49180F6CF9E802",
+ "B318C42DF3BE0F83FEA823F5A7B47ED5E425A3B5",
+ "36F6E34D94A8D34DAACBA33A2139D00AD85A9345A86051E73071620056B920E219005855A213A0F23897CDCD731B45257C777FE908202BEFDD0B58386B1244EA0CF539A05D5D10329DA44E13030FD760DCD644CFEF2094D1910D3F433E1C7C6DD18BC1F2DF7F643D662FB9DD37EAD9059190F4FA66CA39E869C4EB449CBDC439",
+
+ "26521050844271",
+ "E4EC0982C2336F3A677F6A356174EB0CE887ABC2",
+ "42CEE2617B1ECEA4DB3F4829386FBD61DAFBF038E180D837C96366DF24C097B4AB0FAC6BDF590D821C9F10642E681AD05B8D78B378C0F46CE2FAD63F74E0AD3DF06B075D7EB5F5636F8D403B9059CA761B5C62BB52AA45002EA70BAACE08DED243B9D8CBD62A68ADE265832B56564E43A6FA42ED199A099769742DF1539E8255",
+
+ /* 1025-bit key */
+ "01947C7FCE90425F47279E70851F25D5E62316FE8A1DF19371E3E628E260543E4901EF6081F68C0B8141190D2AE8DABA7D1250EC6DB636E944EC3722877C7C1D0A67F14B1694C5F0379451A43E49A32DDE83670B73DA91A1C99BC23B436A60055C610F0BAF99C1A079565B95A3F1526632D1D4DA60F20EDA25E653C4F002766F45",
+ "010001",
+ "0159DBDE04A33EF06FB608B80B190F4D3E22BCC13AC8E4A081033ABFA416EDB0B338AA08B57309EA5A5240E7DC6E54378C69414C31D97DDB1F406DB3769CC41A43",
+ "012B652F30403B38B40995FD6FF41A1ACC8ADA70373236B7202D39B2EE30CFB46DB09511F6F307CC61CC21606C18A75B8A62F822DF031BA0DF0DAFD5506F568BD7",
+ "436EF508DE736519C2DA4C580D98C82CB7452A3FB5EFADC3B9C7789A1BC6584F795ADDBBD32439C74686552ECB6C2C307A4D3AF7F539EEC157248C7B31F1A255",
+ "012B15A89F3DFB2B39073E73F02BDD0C1A7B379DD435F05CDDE2EFF9E462948B7CEC62EE9050D5E0816E0785A856B49108DCB75F3683874D1CA6329A19013066FF",
+ "0270DB17D5914B018D76118B24389A7350EC836B0063A21721236FD8EDB6D89B51E7EEB87B611B7132CB7EA7356C23151C1E7751507C786D9EE1794170A8C8E8",
+
+ "8FF00CAA605C702830634D9A6C3D42C652B58CF1D92FEC570BEEE7",
+ "8C407B5EC2899E5099C53E8CE793BF94E71B1782",
+ "0181AF8922B9FCB4D79D92EBE19815992FC0C1439D8BCD491398A0F4AD3A329A5BD9385560DB532683C8B7DA04E4B12AED6AACDF471C34C9CDA891ADDCC2DF3456653AA6382E9AE59B54455257EB099D562BBE10453F2B6D13C59C02E10F1F8ABB5DA0D0570932DACF2D0901DB729D0FEFCC054E70968EA540C81B04BCAEFE720E",
+
+ "2D",
+ "B600CF3C2E506D7F16778C910D3A8B003EEE61D5",
+ "018759FF1DF63B2792410562314416A8AEAF2AC634B46F940AB82D64DBF165EEE33011DA749D4BAB6E2FCD18129C9E49277D8453112B429A222A8471B070993998E758861C4D3F6D749D91C4290D332C7A4AB3F7EA35FF3A07D497C955FF0FFC95006B62C6D296810D9BFAB024196C7934012C2DF978EF299ABA239940CBA10245",
+
+ "74FC88C51BC90F77AF9D5E9A4A70133D4B4E0B34DA3C37C7EF8E",
+ "A73768AEEAA91F9D8C1ED6F9D2B63467F07CCAE3",
+ "018802BAB04C60325E81C4962311F2BE7C2ADCE93041A00719C88F957575F2C79F1B7BC8CED115C706B311C08A2D986CA3B6A9336B147C29C6F229409DDEC651BD1FDD5A0B7F610C9937FDB4A3A762364B8B3206B4EA485FD098D08F63D4AA8BB2697D027B750C32D7F74EAF5180D2E9B66B17CB2FA55523BC280DA10D14BE2053",
+
+ "A7EB2A5036931D27D4E891326D99692FFADDA9BF7EFD3E34E622C4ADC085F721DFE885072C78A203B151739BE540FA8C153A10F00A",
+ "9A7B3B0E708BD96F8190ECAB4FB9B2B3805A8156",
+ "00A4578CBC176318A638FBA7D01DF15746AF44D4F6CD96D7E7C495CBF425B09C649D32BF886DA48FBAF989A2117187CAFB1FB580317690E3CCD446920B7AF82B31DB5804D87D01514ACBFA9156E782F867F6BED9449E0E9A2C09BCECC6AA087636965E34B3EC766F2FE2E43018A2FDDEB140616A0E9D82E5331024EE0652FC7641",
+
+ "2EF2B066F854C33F3BDCBB5994A435E73D6C6C",
+ "EB3CEBBC4ADC16BB48E88C8AEC0E34AF7F427FD3",
+ "00EBC5F5FDA77CFDAD3C83641A9025E77D72D8A6FB33A810F5950F8D74C73E8D931E8634D86AB1246256AE07B6005B71B7F2FB98351218331CE69B8FFBDC9DA08BBC9C704F876DEB9DF9FC2EC065CAD87F9090B07ACC17AA7F997B27ACA48806E897F771D95141FE4526D8A5301B678627EFAB707FD40FBEBD6E792A25613E7AEC",
+
+ "8A7FB344C8B6CB2CF2EF1F643F9A3218F6E19BBA89C0",
+ "4C45CF4D57C98E3D6D2095ADC51C489EB50DFF84",
+ "010839EC20C27B9052E55BEFB9B77E6FC26E9075D7A54378C646ABDF51E445BD5715DE81789F56F1803D9170764A9E93CB78798694023EE7393CE04BC5D8F8C5A52C171D43837E3ACA62F609EB0AA5FFB0960EF04198DD754F57F7FBE6ABF765CF118B4CA443B23B5AAB266F952326AC4581100644325F8B721ACD5D04FF14EF3A",
+
+ /* 2048-bit key */
+ "AE45ED5601CEC6B8CC05F803935C674DDBE0D75C4C09FD7951FC6B0CAEC313A8DF39970C518BFFBA5ED68F3F0D7F22A4029D413F1AE07E4EBE9E4177CE23E7F5404B569E4EE1BDCF3C1FB03EF113802D4F855EB9B5134B5A7C8085ADCAE6FA2FA1417EC3763BE171B0C62B760EDE23C12AD92B980884C641F5A8FAC26BDAD4A03381A22FE1B754885094C82506D4019A535A286AFEB271BB9BA592DE18DCF600C2AEEAE56E02F7CF79FC14CF3BDC7CD84FEBBBF950CA90304B2219A7AA063AEFA2C3C1980E560CD64AFE779585B6107657B957857EFDE6010988AB7DE417FC88D8F384C4E6E72C3F943E0C31C0C4A5CC36F879D8A3AC9D7D59860EAADA6B83BB",
+ "010001",
+ "ECF5AECD1E5515FFFACBD75A2816C6EBF49018CDFB4638E185D66A7396B6F8090F8018C7FD95CC34B857DC17F0CC6516BB1346AB4D582CADAD7B4103352387B70338D084047C9D9539B6496204B3DD6EA442499207BEC01F964287FF6336C3984658336846F56E46861881C10233D2176BF15A5E96DDC780BC868AA77D3CE769",
+ "BC46C464FC6AC4CA783B0EB08A3C841B772F7E9B2F28BABD588AE885E1A0C61E4858A0FB25AC299990F35BE85164C259BA1175CDD7192707135184992B6C29B746DD0D2CABE142835F7D148CC161524B4A09946D48B828473F1CE76B6CB6886C345C03E05F41D51B5C3A90A3F24073C7D74A4FE25D9CF21C75960F3FC3863183",
+ "C73564571D00FB15D08A3DE9957A50915D7126E9442DACF42BC82E862E5673FF6A008ED4D2E374617DF89F17A160B43B7FDA9CB6B6B74218609815F7D45CA263C159AA32D272D127FAF4BC8CA2D77378E8AEB19B0AD7DA3CB3DE0AE7314980F62B6D4B0A875D1DF03C1BAE39CCD833EF6CD7E2D9528BF084D1F969E794E9F6C1",
+ "2658B37F6DF9C1030BE1DB68117FA9D87E39EA2B693B7E6D3A2F70947413EEC6142E18FB8DFCB6AC545D7C86A0AD48F8457170F0EFB26BC48126C53EFD1D16920198DC2A1107DC282DB6A80CD3062360BA3FA13F70E4312FF1A6CD6B8FC4CD9C5C3DB17C6D6A57212F73AE29F619327BAD59B153858585BA4E28B60A62A45E49",
+ "6F38526B3925085534EF3E415A836EDE8B86158A2C7CBFECCB0BD834304FEC683BA8D4F479C433D43416E63269623CEA100776D85AFF401D3FFF610EE65411CE3B1363D63A9709EEDE42647CEA561493D54570A879C18682CD97710B96205EC31117D73B5F36223FADD6E8BA90DD7C0EE61D44E163251E20C7F66EB305117CB8",
+
+ "8BBA6BF82A6C0F86D5F1756E97956870B08953B06B4EB205BC1694EE",
+ "47E1AB7119FEE56C95EE5EAAD86F40D0AA63BD33",
+ "53EA5DC08CD260FB3B858567287FA91552C30B2FEBFBA213F0AE87702D068D19BAB07FE574523DFB42139D68C3C5AFEEE0BFE4CB7969CBF382B804D6E61396144E2D0E60741F8993C3014B58B9B1957A8BABCD23AF854F4C356FB1662AA72BFCC7E586559DC4280D160C126785A723EBEEBEFF71F11594440AAEF87D10793A8774A239D4A04C87FE1467B9DAF85208EC6C7255794A96CC29142F9A8BD418E3C1FD67344B0CD0829DF3B2BEC60253196293C6B34D3F75D32F213DD45C6273D505ADF4CCED1057CB758FC26AEEFA441255ED4E64C199EE075E7F16646182FDB464739B68AB5DAFF0E63E9552016824F054BF4D3C8C90A97BB6B6553284EB429FCC",
+
+ "E6AD181F053B58A904F2457510373E57",
+ "6D17F5B4C1FFAC351D195BF7B09D09F09A4079CF",
+ "A2B1A430A9D657E2FA1C2BB5ED43FFB25C05A308FE9093C01031795F5874400110828AE58FB9B581CE9DDDD3E549AE04A0985459BDE6C626594E7B05DC4278B2A1465C1368408823C85E96DC66C3A30983C639664FC4569A37FE21E5A195B5776EED2DF8D8D361AF686E750229BBD663F161868A50615E0C337BEC0CA35FEC0BB19C36EB2E0BBCC0582FA1D93AACDB061063F59F2CE1EE43605E5D89ECA183D2ACDFE9F81011022AD3B43A3DD417DAC94B4E11EA81B192966E966B182082E71964607B4F8002F36299844A11F2AE0FAEAC2EAE70F8F4F98088ACDCD0AC556E9FCCC511521908FAD26F04C64201450305778758B0538BF8B5BB144A828E629795",
+
+ "510A2CF60E866FA2340553C94EA39FBC256311E83E94454B4124",
+ "385387514DECCC7C740DD8CDF9DAEE49A1CBFD54",
+ "9886C3E6764A8B9A84E84148EBD8C3B1AA8050381A78F668714C16D9CFD2A6EDC56979C535D9DEE3B44B85C18BE8928992371711472216D95DDA98D2EE8347C9B14DFFDFF84AA48D25AC06F7D7E65398AC967B1CE90925F67DCE049B7F812DB0742997A74D44FE81DBE0E7A3FEAF2E5C40AF888D550DDBBE3BC20657A29543F8FC2913B9BD1A61B2AB2256EC409BBD7DC0D17717EA25C43F42ED27DF8738BF4AFC6766FF7AFF0859555EE283920F4C8A63C4A7340CBAFDDC339ECDB4B0515002F96C932B5B79167AF699C0AD3FCCFDF0F44E85A70262BF2E18FE34B850589975E867FF969D48EABF212271546CDC05A69ECB526E52870C836F307BD798780EDE",
+
+ "BCDD190DA3B7D300DF9A06E22CAAE2A75F10C91FF667B7C16BDE8B53064A2649A94045C9",
+ "5CACA6A0F764161A9684F85D92B6E0EF37CA8B65",
+ "6318E9FB5C0D05E5307E1683436E903293AC4642358AAA223D7163013ABA87E2DFDA8E60C6860E29A1E92686163EA0B9175F329CA3B131A1EDD3A77759A8B97BAD6A4F8F4396F28CF6F39CA58112E48160D6E203DAA5856F3ACA5FFED577AF499408E3DFD233E3E604DBE34A9C4C9082DE65527CAC6331D29DC80E0508A0FA7122E7F329F6CCA5CFA34D4D1DA417805457E008BEC549E478FF9E12A763C477D15BBB78F5B69BD57830FC2C4ED686D79BC72A95D85F88134C6B0AFE56A8CCFBC855828BB339BD17909CF1D70DE3335AE07039093E606D655365DE6550B872CD6DE1D440EE031B61945F629AD8A353B0D40939E96A3C450D2A8D5EEE9F678093C8",
+
+ "A7DD6C7DC24B46F9DD5F1E91ADA4C3B3DF947E877232A9",
+ "95BCA9E3859894B3DD869FA7ECD5BBC6401BF3E4",
+ "75290872CCFD4A4505660D651F56DA6DAA09CA1301D890632F6A992F3D565CEE464AFDED40ED3B5BE9356714EA5AA7655F4A1366C2F17C728F6F2C5A5D1F8E28429BC4E6F8F2CFF8DA8DC0E0A9808E45FD09EA2FA40CB2B6CE6FFFF5C0E159D11B68D90A85F7B84E103B09E682666480C657505C0929259468A314786D74EAB131573CF234BF57DB7D9E66CC6748192E002DC0DEEA930585F0831FDCD9BC33D51F79ED2FFC16BCF4D59812FCEBCAA3F9069B0E445686D644C25CCF63B456EE5FA6FFE96F19CDF751FED9EAF35957754DBF4BFEA5216AA1844DC507CB2D080E722EBA150308C2B5FF1193620F1766ECF4481BAFB943BD292877F2136CA494ABA0",
+
+ "EAF1A73A1B0C4609537DE69CD9228BBCFB9A8CA8C6C3EFAF056FE4A7F4634ED00B7C39EC6922D7B8EA2C04EBAC",
+ "9F47DDF42E97EEA856A9BDBC714EB3AC22F6EB32",
+ "2D207A73432A8FB4C03051B3F73B28A61764098DFA34C47A20995F8115AA6816679B557E82DBEE584908C6E69782D7DEB34DBD65AF063D57FCA76A5FD069492FD6068D9984D209350565A62E5C77F23038C12CB10C6634709B547C46F6B4A709BD85CA122D74465EF97762C29763E06DBC7A9E738C78BFCA0102DC5E79D65B973F28240CAAB2E161A78B57D262457ED8195D53E3C7AE9DA021883C6DB7C24AFDD2322EAC972AD3C354C5FCEF1E146C3A0290FB67ADF007066E00428D2CEC18CE58F9328698DEFEF4B2EB5EC76918FDE1C198CBB38B7AFC67626A9AEFEC4322BFD90D2563481C9A221F78C8272C82D1B62AB914E1C69F6AF6EF30CA5260DB4A46",
+
+ NULL
+};
+
+static void
+test_RSA_OAEP(const char *name,
+ br_rsa_oaep_encrypt menc, br_rsa_oaep_decrypt mdec)
+{
+ size_t u;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ u = 0;
+ while (KAT_RSA_OAEP[u] != NULL) {
+ unsigned char n[512];
+ unsigned char e[8];
+ unsigned char p[256];
+ unsigned char q[256];
+ unsigned char dp[256];
+ unsigned char dq[256];
+ unsigned char iq[256];
+ br_rsa_public_key pk;
+ br_rsa_private_key sk;
+ size_t v;
+
+ pk.n = n;
+ pk.nlen = hextobin(n, KAT_RSA_OAEP[u ++]);
+ pk.e = e;
+ pk.elen = hextobin(e, KAT_RSA_OAEP[u ++]);
+
+ for (v = 0; n[v] == 0; v ++);
+ sk.n_bitlen = BIT_LENGTH(n[v]) + ((pk.nlen - 1 - v) << 3);
+ sk.p = p;
+ sk.plen = hextobin(p, KAT_RSA_OAEP[u ++]);
+ sk.q = q;
+ sk.qlen = hextobin(q, KAT_RSA_OAEP[u ++]);
+ sk.dp = dp;
+ sk.dplen = hextobin(dp, KAT_RSA_OAEP[u ++]);
+ sk.dq = dq;
+ sk.dqlen = hextobin(dq, KAT_RSA_OAEP[u ++]);
+ sk.iq = iq;
+ sk.iqlen = hextobin(iq, KAT_RSA_OAEP[u ++]);
+
+ for (v = 0; v < 6; v ++) {
+ unsigned char plain[512], seed[128], cipher[512];
+ size_t plain_len, seed_len, cipher_len;
+ rng_fake_ctx rng;
+ unsigned char tmp[513];
+ size_t len;
+
+ plain_len = hextobin(plain, KAT_RSA_OAEP[u ++]);
+ seed_len = hextobin(seed, KAT_RSA_OAEP[u ++]);
+ cipher_len = hextobin(cipher, KAT_RSA_OAEP[u ++]);
+ rng_fake_init(&rng, NULL, seed, seed_len);
+
+ len = menc(&rng.vtable, &br_sha1_vtable, NULL, 0, &pk,
+ tmp, sizeof tmp, plain, plain_len);
+ if (len != cipher_len) {
+ fprintf(stderr,
+ "wrong encrypted length: %lu vs %lu\n",
+ (unsigned long)len,
+ (unsigned long)cipher_len);
+ }
+ if (rng.ptr != rng.len) {
+ fprintf(stderr, "seed not fully consumed\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA/OAEP encrypt", tmp, cipher, len);
+
+ if (mdec(&br_sha1_vtable, NULL, 0,
+ &sk, tmp, &len) != 1)
+ {
+ fprintf(stderr, "decryption failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (len != plain_len) {
+ fprintf(stderr,
+ "wrong decrypted length: %lu vs %lu\n",
+ (unsigned long)len,
+ (unsigned long)plain_len);
+ }
+ check_equals("KAT RSA/OAEP decrypt", tmp, plain, len);
+
+ /*
+ * Try with a different label; it should fail.
+ */
+ memcpy(tmp, cipher, cipher_len);
+ len = cipher_len;
+ if (mdec(&br_sha1_vtable, "T", 1,
+ &sk, tmp, &len) != 0)
+ {
+ fprintf(stderr, "decryption should have failed"
+ " (wrong label)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Try with a the wrong length; it should fail.
+ */
+ tmp[0] = 0x00;
+ memcpy(tmp + 1, cipher, cipher_len);
+ len = cipher_len + 1;
+ if (mdec(&br_sha1_vtable, "T", 1,
+ &sk, tmp, &len) != 0)
+ {
+ fprintf(stderr, "decryption should have failed"
+ " (wrong length)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_RSA_keygen(const char *name, br_rsa_keygen kg, br_rsa_compute_modulus cm,
+ br_rsa_compute_pubexp ce, br_rsa_compute_privexp cd,
+ br_rsa_public pub, br_rsa_pkcs1_sign sign, br_rsa_pkcs1_vrfy vrfy)
+{
+ br_hmac_drbg_context rng;
+ int i;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, "seed for RSA keygen", 19);
+
+ for (i = 0; i <= 42; i ++) {
+ unsigned size;
+ uint32_t pubexp, z;
+ br_rsa_private_key sk;
+ br_rsa_public_key pk, pk2;
+ unsigned char kbuf_priv[BR_RSA_KBUF_PRIV_SIZE(2048)];
+ unsigned char kbuf_pub[BR_RSA_KBUF_PUB_SIZE(2048)];
+ unsigned char n2[256], d[256], msg1[256], msg2[256];
+ uint32_t mod[256];
+ uint32_t cc;
+ size_t u, v;
+ unsigned char sig[257], hv[32], hv2[sizeof hv];
+ unsigned mask1, mask2;
+ int j;
+
+ if (i <= 35) {
+ size = 1024 + i;
+ pubexp = 17;
+ } else if (i <= 40) {
+ size = 2048;
+ pubexp = (i << 1) - 69;
+ } else {
+ size = 2048;
+ pubexp = 0xFFFFFFFF;
+ }
+
+ if (!kg(&rng.vtable,
+ &sk, kbuf_priv, &pk, kbuf_pub, size, pubexp))
+ {
+ fprintf(stderr, "RSA key pair generation failure\n");
+ exit(EXIT_FAILURE);
+ }
+
+ z = pubexp;
+ for (u = pk.elen; u > 0; u --) {
+ if (pk.e[u - 1] != (z & 0xFF)) {
+ fprintf(stderr, "wrong public exponent\n");
+ exit(EXIT_FAILURE);
+ }
+ z >>= 8;
+ }
+ if (z != 0) {
+ fprintf(stderr, "truncated public exponent\n");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(mod, 0, sizeof mod);
+ for (u = 0; u < sk.plen; u ++) {
+ for (v = 0; v < sk.qlen; v ++) {
+ mod[u + v] += (uint32_t)sk.p[sk.plen - 1 - u]
+ * (uint32_t)sk.q[sk.qlen - 1 - v];
+ }
+ }
+ cc = 0;
+ for (u = 0; u < sk.plen + sk.qlen; u ++) {
+ mod[u] += cc;
+ cc = mod[u] >> 8;
+ mod[u] &= 0xFF;
+ }
+ for (u = 0; u < pk.nlen; u ++) {
+ if (mod[pk.nlen - 1 - u] != pk.n[u]) {
+ fprintf(stderr, "wrong modulus\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (sk.n_bitlen != size) {
+ fprintf(stderr, "wrong key size\n");
+ exit(EXIT_FAILURE);
+ }
+ if (pk.nlen != (size + 7) >> 3) {
+ fprintf(stderr, "wrong modulus size (bytes)\n");
+ exit(EXIT_FAILURE);
+ }
+ mask1 = 0x01 << ((size + 7) & 7);
+ mask2 = 0xFF & -mask1;
+ if ((pk.n[0] & mask2) != mask1) {
+ fprintf(stderr, "wrong modulus size (bits)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (cm(NULL, &sk) != pk.nlen) {
+ fprintf(stderr, "wrong recomputed modulus length\n");
+ exit(EXIT_FAILURE);
+ }
+ if (cm(n2, &sk) != pk.nlen || memcmp(pk.n, n2, pk.nlen) != 0) {
+ fprintf(stderr, "wrong recomputed modulus value\n");
+ exit(EXIT_FAILURE);
+ }
+
+ z = ce(&sk);
+ if (z != pubexp) {
+ fprintf(stderr,
+ "wrong recomputed pubexp: %lu (exp: %lu)\n",
+ (unsigned long)z, (unsigned long)pubexp);
+ exit(EXIT_FAILURE);
+ }
+
+ if (cd(NULL, &sk, pubexp) != pk.nlen) {
+ fprintf(stderr,
+ "wrong recomputed privexp length (1)\n");
+ exit(EXIT_FAILURE);
+ }
+ if (cd(d, &sk, pubexp) != pk.nlen) {
+ fprintf(stderr,
+ "wrong recomputed privexp length (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ /*
+ * To check that the private exponent is correct, we make
+ * it into a _public_ key, and use the public-key operation
+ * to perform the modular exponentiation.
+ */
+ pk2 = pk;
+ pk2.e = d;
+ pk2.elen = pk.nlen;
+ rng.vtable->generate(&rng.vtable, msg1, pk.nlen);
+ msg1[0] = 0x00;
+ memcpy(msg2, msg1, pk.nlen);
+ if (!pub(msg2, pk.nlen, &pk2) || !pub(msg2, pk.nlen, &pk)) {
+ fprintf(stderr, "public-key operation error\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(msg1, msg2, pk.nlen) != 0) {
+ fprintf(stderr, "wrong recomputed privexp\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * We test the RSA operation over a some random messages.
+ */
+ for (j = 0; j < 20; j ++) {
+ rng.vtable->generate(&rng.vtable, hv, sizeof hv);
+ memset(sig, 0, sizeof sig);
+ sig[pk.nlen] = 0x00;
+ if (!sign(BR_HASH_OID_SHA256,
+ hv, sizeof hv, &sk, sig))
+ {
+ fprintf(stderr,
+ "signature error (%d)\n", j);
+ exit(EXIT_FAILURE);
+ }
+ if (sig[pk.nlen] != 0x00) {
+ fprintf(stderr,
+ "signature length error (%d)\n", j);
+ exit(EXIT_FAILURE);
+ }
+ if (!vrfy(sig, pk.nlen, BR_HASH_OID_SHA256, sizeof hv,
+ &pk, hv2))
+ {
+ fprintf(stderr,
+ "signature verif error (%d)\n", j);
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(hv, hv2, sizeof hv) != 0) {
+ fprintf(stderr,
+ "signature extract error (%d)\n", j);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_RSA_i15(void)
+{
+ test_RSA_core("RSA i15 core", &br_rsa_i15_public, &br_rsa_i15_private);
+ test_RSA_sign("RSA i15 sign", &br_rsa_i15_private,
+ &br_rsa_i15_pkcs1_sign, &br_rsa_i15_pkcs1_vrfy);
+ test_RSA_OAEP("RSA i15 OAEP",
+ &br_rsa_i15_oaep_encrypt, &br_rsa_i15_oaep_decrypt);
+ test_RSA_PSS("RSA i15 PSS",
+ &br_rsa_i15_pss_sign, &br_rsa_i15_pss_vrfy);
+ test_RSA_keygen("RSA i15 keygen", &br_rsa_i15_keygen,
+ &br_rsa_i15_compute_modulus, &br_rsa_i15_compute_pubexp,
+ &br_rsa_i15_compute_privexp, &br_rsa_i15_public,
+ &br_rsa_i15_pkcs1_sign, &br_rsa_i15_pkcs1_vrfy);
+}
+
+static void
+test_RSA_i31(void)
+{
+ test_RSA_core("RSA i31 core", &br_rsa_i31_public, &br_rsa_i31_private);
+ test_RSA_sign("RSA i31 sign", &br_rsa_i31_private,
+ &br_rsa_i31_pkcs1_sign, &br_rsa_i31_pkcs1_vrfy);
+ test_RSA_OAEP("RSA i31 OAEP",
+ &br_rsa_i31_oaep_encrypt, &br_rsa_i31_oaep_decrypt);
+ test_RSA_PSS("RSA i31 PSS",
+ &br_rsa_i31_pss_sign, &br_rsa_i31_pss_vrfy);
+ test_RSA_keygen("RSA i31 keygen", &br_rsa_i31_keygen,
+ &br_rsa_i31_compute_modulus, &br_rsa_i31_compute_pubexp,
+ &br_rsa_i31_compute_privexp, &br_rsa_i31_public,
+ &br_rsa_i31_pkcs1_sign, &br_rsa_i31_pkcs1_vrfy);
+}
+
+static void
+test_RSA_i32(void)
+{
+ test_RSA_core("RSA i32 core", &br_rsa_i32_public, &br_rsa_i32_private);
+ test_RSA_sign("RSA i32 sign", &br_rsa_i32_private,
+ &br_rsa_i32_pkcs1_sign, &br_rsa_i32_pkcs1_vrfy);
+ test_RSA_OAEP("RSA i32 OAEP",
+ &br_rsa_i32_oaep_encrypt, &br_rsa_i32_oaep_decrypt);
+ test_RSA_PSS("RSA i32 PSS",
+ &br_rsa_i32_pss_sign, &br_rsa_i32_pss_vrfy);
+}
+
+static void
+test_RSA_i62(void)
+{
+ br_rsa_public pub;
+ br_rsa_private priv;
+ br_rsa_pkcs1_sign sign;
+ br_rsa_pkcs1_vrfy vrfy;
+ br_rsa_pss_sign pss_sign;
+ br_rsa_pss_vrfy pss_vrfy;
+ br_rsa_oaep_encrypt menc;
+ br_rsa_oaep_decrypt mdec;
+ br_rsa_keygen kgen;
+
+ pub = br_rsa_i62_public_get();
+ priv = br_rsa_i62_private_get();
+ sign = br_rsa_i62_pkcs1_sign_get();
+ vrfy = br_rsa_i62_pkcs1_vrfy_get();
+ pss_sign = br_rsa_i62_pss_sign_get();
+ pss_vrfy = br_rsa_i62_pss_vrfy_get();
+ menc = br_rsa_i62_oaep_encrypt_get();
+ mdec = br_rsa_i62_oaep_decrypt_get();
+ kgen = br_rsa_i62_keygen_get();
+ if (pub) {
+ if (!priv || !sign || !vrfy || !pss_sign || !pss_vrfy
+ || !menc || !mdec || !kgen)
+ {
+ fprintf(stderr, "Inconsistent i62 availability\n");
+ exit(EXIT_FAILURE);
+ }
+ test_RSA_core("RSA i62 core", pub, priv);
+ test_RSA_sign("RSA i62 sign", priv, sign, vrfy);
+ test_RSA_OAEP("RSA i62 OAEP", menc, mdec);
+ test_RSA_PSS("RSA i62 PSS", pss_sign, pss_vrfy);
+ test_RSA_keygen("RSA i62 keygen", kgen,
+ &br_rsa_i31_compute_modulus, &br_rsa_i31_compute_pubexp,
+ &br_rsa_i31_compute_privexp, pub,
+ sign, vrfy);
+ } else {
+ if (priv || sign || vrfy || pss_sign || pss_vrfy
+ || menc || mdec || kgen)
+ {
+ fprintf(stderr, "Inconsistent i62 availability\n");
+ exit(EXIT_FAILURE);
+ }
+ printf("Test RSA i62: UNAVAILABLE\n");
+ }
+}
+
+#if 0
+static void
+test_RSA_signatures(void)
+{
+ uint32_t n[40], e[2], p[20], q[20], dp[20], dq[20], iq[20], x[40];
+ unsigned char hv[20], sig[128];
+ unsigned char ref[128], tmp[128];
+ br_sha1_context hc;
+
+ printf("Test RSA signatures: ");
+ fflush(stdout);
+
+ /*
+ * Decode RSA key elements.
+ */
+ br_int_decode(n, sizeof n / sizeof n[0], RSA_N, sizeof RSA_N);
+ br_int_decode(e, sizeof e / sizeof e[0], RSA_E, sizeof RSA_E);
+ br_int_decode(p, sizeof p / sizeof p[0], RSA_P, sizeof RSA_P);
+ br_int_decode(q, sizeof q / sizeof q[0], RSA_Q, sizeof RSA_Q);
+ br_int_decode(dp, sizeof dp / sizeof dp[0], RSA_DP, sizeof RSA_DP);
+ br_int_decode(dq, sizeof dq / sizeof dq[0], RSA_DQ, sizeof RSA_DQ);
+ br_int_decode(iq, sizeof iq / sizeof iq[0], RSA_IQ, sizeof RSA_IQ);
+
+ /*
+ * Decode reference signature (computed with OpenSSL).
+ */
+ hextobin(ref, "45A3DC6A106BCD3BD0E48FB579643AA3FF801E5903E80AA9B43A695A8E7F454E93FA208B69995FF7A6D5617C2FEB8E546375A664977A48931842AAE796B5A0D64393DCA35F3490FC157F5BD83B9D58C2F7926E6AE648A2BD96CAB8FCCD3D35BB11424AD47D973FF6D69CA774841AEC45DFAE99CCF79893E7047FDE6CB00AA76D");
+
+ /*
+ * Recompute signature. Since PKCS#1 v1.5 signatures are
+ * deterministic, we should get the same as the reference signature.
+ */
+ br_sha1_init(&hc);
+ br_sha1_update(&hc, "test", 4);
+ br_sha1_out(&hc, hv);
+ if (!br_rsa_sign(sig, sizeof sig, p, q, dp, dq, iq, br_sha1_ID, hv)) {
+ fprintf(stderr, "RSA-1024/SHA-1 sig generate failed\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT RSA-sign 1", sig, ref, sizeof sig);
+
+ /*
+ * Verify signature.
+ */
+ if (!br_rsa_verify(sig, sizeof sig, n, e, br_sha1_ID, hv)) {
+ fprintf(stderr, "RSA-1024/SHA-1 sig verify failed\n");
+ exit(EXIT_FAILURE);
+ }
+ hv[5] ^= 0x01;
+ if (br_rsa_verify(sig, sizeof sig, n, e, br_sha1_ID, hv)) {
+ fprintf(stderr, "RSA-1024/SHA-1 sig verify should have failed\n");
+ exit(EXIT_FAILURE);
+ }
+ hv[5] ^= 0x01;
+
+ /*
+ * Generate a signature with the alternate encoding (no NULL) and
+ * verify it.
+ */
+ hextobin(tmp, "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00301F300706052B0E03021A0414A94A8FE5CCB19BA61C4C0873D391E987982FBBD3");
+ br_int_decode(x, sizeof x / sizeof x[0], tmp, sizeof tmp);
+ x[0] = n[0];
+ br_rsa_private_core(x, p, q, dp, dq, iq);
+ br_int_encode(sig, sizeof sig, x);
+ if (!br_rsa_verify(sig, sizeof sig, n, e, br_sha1_ID, hv)) {
+ fprintf(stderr, "RSA-1024/SHA-1 sig verify (alt) failed\n");
+ exit(EXIT_FAILURE);
+ }
+ hv[5] ^= 0x01;
+ if (br_rsa_verify(sig, sizeof sig, n, e, br_sha1_ID, hv)) {
+ fprintf(stderr, "RSA-1024/SHA-1 sig verify (alt) should have failed\n");
+ exit(EXIT_FAILURE);
+ }
+ hv[5] ^= 0x01;
+
+ printf("done.\n");
+ fflush(stdout);
+}
+#endif
+
+/*
+ * From: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+ */
+static const char *const KAT_GHASH[] = {
+
+ "66e94bd4ef8a2c3b884cfa59ca342b2e",
+ "",
+ "",
+ "00000000000000000000000000000000",
+
+ "66e94bd4ef8a2c3b884cfa59ca342b2e",
+ "",
+ "0388dace60b6a392f328c2b971b2fe78",
+ "f38cbb1ad69223dcc3457ae5b6b0f885",
+
+ "b83b533708bf535d0aa6e52980d53b78",
+ "",
+ "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985",
+ "7f1b32b81b820d02614f8895ac1d4eac",
+
+ "b83b533708bf535d0aa6e52980d53b78",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091",
+ "698e57f70e6ecc7fd9463b7260a9ae5f",
+
+ "b83b533708bf535d0aa6e52980d53b78",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598",
+ "df586bb4c249b92cb6922877e444d37b",
+
+ "b83b533708bf535d0aa6e52980d53b78",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5",
+ "1c5afe9760d3932f3c9a878aac3dc3de",
+
+ "aae06992acbf52a3e8f4a96ec9300bd7",
+ "",
+ "98e7247c07f0fe411c267e4384b0f600",
+ "e2c63f0ac44ad0e02efa05ab6743d4ce",
+
+ "466923ec9ae682214f2c082badb39249",
+ "",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256",
+ "51110d40f6c8fff0eb1ae33445a889f0",
+
+ "466923ec9ae682214f2c082badb39249",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710",
+ "ed2ce3062e4a8ec06db8b4c490e8a268",
+
+ "466923ec9ae682214f2c082badb39249",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
+ "1e6a133806607858ee80eaf237064089",
+
+ "466923ec9ae682214f2c082badb39249",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b",
+ "82567fb0b4cc371801eadec005968e94",
+
+ "dc95c078a2408989ad48a21492842087",
+ "",
+ "cea7403d4d606b6e074ec5d3baf39d18",
+ "83de425c5edc5d498f382c441041ca92",
+
+ "acbef20579b4b8ebce889bac8732dad7",
+ "",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
+ "4db870d37cb75fcb46097c36230d1612",
+
+ "acbef20579b4b8ebce889bac8732dad7",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
+ "8bd0c4d8aacd391e67cca447e8c38f65",
+
+ "acbef20579b4b8ebce889bac8732dad7",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f",
+ "75a34288b8c68f811c52b2e9a2f97f63",
+
+ "acbef20579b4b8ebce889bac8732dad7",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f",
+ "d5ffcf6fc5ac4d69722187421a7f170b",
+
+ NULL,
+};
+
+static void
+test_GHASH(const char *name, br_ghash gh)
+{
+ size_t u;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ for (u = 0; KAT_GHASH[u]; u += 4) {
+ unsigned char h[16];
+ unsigned char a[100];
+ size_t a_len;
+ unsigned char c[100];
+ size_t c_len;
+ unsigned char p[16];
+ unsigned char y[16];
+ unsigned char ref[16];
+
+ hextobin(h, KAT_GHASH[u]);
+ a_len = hextobin(a, KAT_GHASH[u + 1]);
+ c_len = hextobin(c, KAT_GHASH[u + 2]);
+ hextobin(ref, KAT_GHASH[u + 3]);
+ memset(y, 0, sizeof y);
+ gh(y, h, a, a_len);
+ gh(y, h, c, c_len);
+ memset(p, 0, sizeof p);
+ br_enc32be(p + 4, (uint32_t)a_len << 3);
+ br_enc32be(p + 12, (uint32_t)c_len << 3);
+ gh(y, h, p, sizeof p);
+ check_equals("KAT GHASH", y, ref, sizeof ref);
+ }
+
+ for (u = 0; u <= 1024; u ++) {
+ unsigned char key[32], iv[12];
+ unsigned char buf[1024 + 32];
+ unsigned char y0[16], y1[16];
+ char tmp[100];
+
+ memset(key, 0, sizeof key);
+ memset(iv, 0, sizeof iv);
+ br_enc32be(key, u);
+ memset(buf, 0, sizeof buf);
+ br_chacha20_ct_run(key, iv, 1, buf, sizeof buf);
+
+ memcpy(y0, buf, 16);
+ br_ghash_ctmul32(y0, buf + 16, buf + 32, u);
+ memcpy(y1, buf, 16);
+ gh(y1, buf + 16, buf + 32, u);
+ sprintf(tmp, "XREF %s (len = %u)", name, (unsigned)u);
+ check_equals(tmp, y0, y1, 16);
+
+ if ((u & 31) == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+ }
+
+ printf("done.\n");
+ fflush(stdout);
+}
+
+static void
+test_GHASH_ctmul(void)
+{
+ test_GHASH("GHASH_ctmul", br_ghash_ctmul);
+}
+
+static void
+test_GHASH_ctmul32(void)
+{
+ test_GHASH("GHASH_ctmul32", br_ghash_ctmul32);
+}
+
+static void
+test_GHASH_ctmul64(void)
+{
+ test_GHASH("GHASH_ctmul64", br_ghash_ctmul64);
+}
+
+static void
+test_GHASH_pclmul(void)
+{
+ br_ghash gh;
+
+ gh = br_ghash_pclmul_get();
+ if (gh == 0) {
+ printf("Test GHASH_pclmul: UNAVAILABLE\n");
+ } else {
+ test_GHASH("GHASH_pclmul", gh);
+ }
+}
+
+static void
+test_GHASH_pwr8(void)
+{
+ br_ghash gh;
+
+ gh = br_ghash_pwr8_get();
+ if (gh == 0) {
+ printf("Test GHASH_pwr8: UNAVAILABLE\n");
+ } else {
+ test_GHASH("GHASH_pwr8", gh);
+ }
+}
+
+/*
+ * From: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
+ *
+ * Order: key, plaintext, AAD, IV, ciphertext, tag
+ */
+static const char *const KAT_GCM[] = {
+ "00000000000000000000000000000000",
+ "",
+ "",
+ "000000000000000000000000",
+ "",
+ "58e2fccefa7e3061367f1d57a4e7455a",
+
+ "00000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "000000000000000000000000",
+ "0388dace60b6a392f328c2b971b2fe78",
+ "ab6e47d42cec13bdf53a67b21257bddf",
+
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "cafebabefacedbaddecaf888",
+ "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985",
+ "4d5c2af327cd64a62cf35abd2ba6fab4",
+
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbaddecaf888",
+ "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091",
+ "5bc94fbc3221a5db94fae95ae7121a47",
+
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbad",
+ "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598",
+ "3612d2e79e3b0785561be14aaca2fccb",
+
+ "feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5",
+ "619cc5aefffe0bfa462af43c1699d050",
+
+ "000000000000000000000000000000000000000000000000",
+ "",
+ "",
+ "000000000000000000000000",
+ "",
+ "cd33b28ac773f74ba00ed1f312572435",
+
+ "000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "000000000000000000000000",
+ "98e7247c07f0fe411c267e4384b0f600",
+ "2ff58d80033927ab8ef4d4587514f0fb",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "cafebabefacedbaddecaf888",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256",
+ "9924a7c8587336bfb118024db8674a14",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbaddecaf888",
+ "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710",
+ "2519498e80f1478f37ba55bd6d27618c",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbad",
+ "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7",
+ "65dcc57fcf623a24094fcca40d3533f8",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b",
+ "dcf566ff291c25bbb8568fc3d376a6d9",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "",
+ "",
+ "000000000000000000000000",
+ "",
+ "530f8afbc74536b9a963b4f1c4cb738b",
+
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "",
+ "000000000000000000000000",
+ "cea7403d4d606b6e074ec5d3baf39d18",
+ "d0d1c8a799996bf0265b98b5d48ab919",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255",
+ "",
+ "cafebabefacedbaddecaf888",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad",
+ "b094dac5d93471bdec1a502270e3cc6c",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbaddecaf888",
+ "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662",
+ "76fc6ece0f4e1768cddf8853bb2d551b",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "cafebabefacedbad",
+ "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f",
+ "3a337dbf46a792c45e454913fe2ea8f2",
+
+ "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308",
+ "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39",
+ "feedfacedeadbeeffeedfacedeadbeefabaddad2",
+ "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b",
+ "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f",
+ "a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
+
+ NULL
+};
+
+static void
+test_GCM(void)
+{
+ size_t u;
+
+ printf("Test GCM: ");
+ fflush(stdout);
+
+ for (u = 0; KAT_GCM[u]; u += 6) {
+ unsigned char key[32];
+ unsigned char plain[100];
+ unsigned char aad[100];
+ unsigned char iv[100];
+ unsigned char cipher[100];
+ unsigned char tag[100];
+ size_t key_len, plain_len, aad_len, iv_len;
+ br_aes_ct_ctr_keys bc;
+ br_gcm_context gc;
+ unsigned char tmp[100], out[16];
+ size_t v, tag_len;
+
+ key_len = hextobin(key, KAT_GCM[u]);
+ plain_len = hextobin(plain, KAT_GCM[u + 1]);
+ aad_len = hextobin(aad, KAT_GCM[u + 2]);
+ iv_len = hextobin(iv, KAT_GCM[u + 3]);
+ hextobin(cipher, KAT_GCM[u + 4]);
+ hextobin(tag, KAT_GCM[u + 5]);
+
+ br_aes_ct_ctr_init(&bc, key, key_len);
+ br_gcm_init(&gc, &bc.vtable, br_ghash_ctmul32);
+
+ memset(tmp, 0x54, sizeof tmp);
+
+ /*
+ * Basic operation.
+ */
+ memcpy(tmp, plain, plain_len);
+ br_gcm_reset(&gc, iv, iv_len);
+ br_gcm_aad_inject(&gc, aad, aad_len);
+ br_gcm_flip(&gc);
+ br_gcm_run(&gc, 1, tmp, plain_len);
+ br_gcm_get_tag(&gc, out);
+ check_equals("KAT GCM 1", tmp, cipher, plain_len);
+ check_equals("KAT GCM 2", out, tag, 16);
+
+ br_gcm_reset(&gc, iv, iv_len);
+ br_gcm_aad_inject(&gc, aad, aad_len);
+ br_gcm_flip(&gc);
+ br_gcm_run(&gc, 0, tmp, plain_len);
+ check_equals("KAT GCM 3", tmp, plain, plain_len);
+ if (!br_gcm_check_tag(&gc, tag)) {
+ fprintf(stderr, "Tag not verified (1)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (v = plain_len; v < sizeof tmp; v ++) {
+ if (tmp[v] != 0x54) {
+ fprintf(stderr, "overflow on data\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * Byte-by-byte injection.
+ */
+ br_gcm_reset(&gc, iv, iv_len);
+ for (v = 0; v < aad_len; v ++) {
+ br_gcm_aad_inject(&gc, aad + v, 1);
+ }
+ br_gcm_flip(&gc);
+ for (v = 0; v < plain_len; v ++) {
+ br_gcm_run(&gc, 1, tmp + v, 1);
+ }
+ check_equals("KAT GCM 4", tmp, cipher, plain_len);
+ if (!br_gcm_check_tag(&gc, tag)) {
+ fprintf(stderr, "Tag not verified (2)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ br_gcm_reset(&gc, iv, iv_len);
+ for (v = 0; v < aad_len; v ++) {
+ br_gcm_aad_inject(&gc, aad + v, 1);
+ }
+ br_gcm_flip(&gc);
+ for (v = 0; v < plain_len; v ++) {
+ br_gcm_run(&gc, 0, tmp + v, 1);
+ }
+ br_gcm_get_tag(&gc, out);
+ check_equals("KAT GCM 5", tmp, plain, plain_len);
+ check_equals("KAT GCM 6", out, tag, 16);
+
+ /*
+ * Check that alterations are detected.
+ */
+ for (v = 0; v < aad_len; v ++) {
+ memcpy(tmp, cipher, plain_len);
+ br_gcm_reset(&gc, iv, iv_len);
+ aad[v] ^= 0x04;
+ br_gcm_aad_inject(&gc, aad, aad_len);
+ aad[v] ^= 0x04;
+ br_gcm_flip(&gc);
+ br_gcm_run(&gc, 0, tmp, plain_len);
+ check_equals("KAT GCM 7", tmp, plain, plain_len);
+ if (br_gcm_check_tag(&gc, tag)) {
+ fprintf(stderr, "Tag should have changed\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * Tag truncation.
+ */
+ for (tag_len = 1; tag_len <= 16; tag_len ++) {
+ memset(out, 0x54, sizeof out);
+ memcpy(tmp, plain, plain_len);
+ br_gcm_reset(&gc, iv, iv_len);
+ br_gcm_aad_inject(&gc, aad, aad_len);
+ br_gcm_flip(&gc);
+ br_gcm_run(&gc, 1, tmp, plain_len);
+ br_gcm_get_tag_trunc(&gc, out, tag_len);
+ check_equals("KAT GCM 8", out, tag, tag_len);
+ for (v = tag_len; v < sizeof out; v ++) {
+ if (out[v] != 0x54) {
+ fprintf(stderr, "overflow on tag\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ memcpy(tmp, plain, plain_len);
+ br_gcm_reset(&gc, iv, iv_len);
+ br_gcm_aad_inject(&gc, aad, aad_len);
+ br_gcm_flip(&gc);
+ br_gcm_run(&gc, 1, tmp, plain_len);
+ if (!br_gcm_check_tag_trunc(&gc, out, tag_len)) {
+ fprintf(stderr, "Tag not verified (3)\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+/*
+ * From "The EAX Mode of Operation (A Two-Pass Authenticated Encryption
+ * Scheme Optimized for Simplicity and Efficiency)" (Bellare, Rogaway,
+ * Wagner), presented at FSE 2004. Full article is available at:
+ * http://web.cs.ucdavis.edu/~rogaway/papers/eax.html
+ *
+ * EAX specification concatenates the authentication tag at the end of
+ * the ciphertext; in our API and the vectors below, the tag is separate.
+ *
+ * Order is: plaintext, key, nonce, header, ciphertext, tag.
+ */
+static const char *const KAT_EAX[] = {
+ "",
+ "233952dee4d5ed5f9b9c6d6ff80ff478",
+ "62ec67f9c3a4a407fcb2a8c49031a8b3",
+ "6bfb914fd07eae6b",
+ "",
+ "e037830e8389f27b025a2d6527e79d01",
+
+ "f7fb",
+ "91945d3f4dcbee0bf45ef52255f095a4",
+ "becaf043b0a23d843194ba972c66debd",
+ "fa3bfd4806eb53fa",
+ "19dd",
+ "5c4c9331049d0bdab0277408f67967e5",
+
+ "1a47cb4933",
+ "01f74ad64077f2e704c0f60ada3dd523",
+ "70c3db4f0d26368400a10ed05d2bff5e",
+ "234a3463c1264ac6",
+ "d851d5bae0",
+ "3a59f238a23e39199dc9266626c40f80",
+
+ "481c9e39b1",
+ "d07cf6cbb7f313bdde66b727afd3c5e8",
+ "8408dfff3c1a2b1292dc199e46b7d617",
+ "33cce2eabff5a79d",
+ "632a9d131a",
+ "d4c168a4225d8e1ff755939974a7bede",
+
+ "40d0c07da5e4",
+ "35b6d0580005bbc12b0587124557d2c2",
+ "fdb6b06676eedc5c61d74276e1f8e816",
+ "aeb96eaebe2970e9",
+ "071dfe16c675",
+ "cb0677e536f73afe6a14b74ee49844dd",
+
+ "4de3b35c3fc039245bd1fb7d",
+ "bd8e6e11475e60b268784c38c62feb22",
+ "6eac5c93072d8e8513f750935e46da1b",
+ "d4482d1ca78dce0f",
+ "835bb4f15d743e350e728414",
+ "abb8644fd6ccb86947c5e10590210a4f",
+
+ "8b0a79306c9ce7ed99dae4f87f8dd61636",
+ "7c77d6e813bed5ac98baa417477a2e7d",
+ "1a8c98dcd73d38393b2bf1569deefc19",
+ "65d2017990d62528",
+ "02083e3979da014812f59f11d52630da30",
+ "137327d10649b0aa6e1c181db617d7f2",
+
+ "1bda122bce8a8dbaf1877d962b8592dd2d56",
+ "5fff20cafab119ca2fc73549e20f5b0d",
+ "dde59b97d722156d4d9aff2bc7559826",
+ "54b9f04e6a09189a",
+ "2ec47b2c4954a489afc7ba4897edcdae8cc3",
+ "3b60450599bd02c96382902aef7f832a",
+
+ "6cf36720872b8513f6eab1a8a44438d5ef11",
+ "a4a4782bcffd3ec5e7ef6d8c34a56123",
+ "b781fcf2f75fa5a8de97a9ca48e522ec",
+ "899a175897561d7e",
+ "0de18fd0fdd91e7af19f1d8ee8733938b1e8",
+ "e7f6d2231618102fdb7fe55ff1991700",
+
+ "ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7",
+ "8395fcf1e95bebd697bd010bc766aac3",
+ "22e7add93cfc6393c57ec0b3c17d6b44",
+ "126735fcc320d25a",
+ "cb8920f87a6c75cff39627b56e3ed197c552d295a7",
+ "cfc46afc253b4652b1af3795b124ab6e",
+
+ NULL
+};
+
+static void
+test_EAX_inner(const char *name, const br_block_ctrcbc_class *vt)
+{
+ size_t u;
+
+ printf("Test EAX %s: ", name);
+ fflush(stdout);
+
+ for (u = 0; KAT_EAX[u]; u += 6) {
+ unsigned char plain[100];
+ unsigned char key[32];
+ unsigned char nonce[100];
+ unsigned char aad[100];
+ unsigned char cipher[100];
+ unsigned char tag[100];
+ size_t plain_len, key_len, nonce_len, aad_len;
+ br_aes_gen_ctrcbc_keys bc;
+ br_eax_context ec;
+ br_eax_state st;
+ unsigned char tmp[100], out[16];
+ size_t v, tag_len;
+
+ plain_len = hextobin(plain, KAT_EAX[u]);
+ key_len = hextobin(key, KAT_EAX[u + 1]);
+ nonce_len = hextobin(nonce, KAT_EAX[u + 2]);
+ aad_len = hextobin(aad, KAT_EAX[u + 3]);
+ hextobin(cipher, KAT_EAX[u + 4]);
+ hextobin(tag, KAT_EAX[u + 5]);
+
+ vt->init(&bc.vtable, key, key_len);
+ br_eax_init(&ec, &bc.vtable);
+
+ memset(tmp, 0x54, sizeof tmp);
+
+ /*
+ * Basic operation.
+ */
+ memcpy(tmp, plain, plain_len);
+ br_eax_reset(&ec, nonce, nonce_len);
+ br_eax_aad_inject(&ec, aad, aad_len);
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 1, tmp, plain_len);
+ br_eax_get_tag(&ec, out);
+ check_equals("KAT EAX 1", tmp, cipher, plain_len);
+ check_equals("KAT EAX 2", out, tag, 16);
+
+ br_eax_reset(&ec, nonce, nonce_len);
+ br_eax_aad_inject(&ec, aad, aad_len);
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 0, tmp, plain_len);
+ check_equals("KAT EAX 3", tmp, plain, plain_len);
+ if (!br_eax_check_tag(&ec, tag)) {
+ fprintf(stderr, "Tag not verified (1)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (v = plain_len; v < sizeof tmp; v ++) {
+ if (tmp[v] != 0x54) {
+ fprintf(stderr, "overflow on data\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * Byte-by-byte injection.
+ */
+ br_eax_reset(&ec, nonce, nonce_len);
+ for (v = 0; v < aad_len; v ++) {
+ br_eax_aad_inject(&ec, aad + v, 1);
+ }
+ br_eax_flip(&ec);
+ for (v = 0; v < plain_len; v ++) {
+ br_eax_run(&ec, 1, tmp + v, 1);
+ }
+ check_equals("KAT EAX 4", tmp, cipher, plain_len);
+ if (!br_eax_check_tag(&ec, tag)) {
+ fprintf(stderr, "Tag not verified (2)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ br_eax_reset(&ec, nonce, nonce_len);
+ for (v = 0; v < aad_len; v ++) {
+ br_eax_aad_inject(&ec, aad + v, 1);
+ }
+ br_eax_flip(&ec);
+ for (v = 0; v < plain_len; v ++) {
+ br_eax_run(&ec, 0, tmp + v, 1);
+ }
+ br_eax_get_tag(&ec, out);
+ check_equals("KAT EAX 5", tmp, plain, plain_len);
+ check_equals("KAT EAX 6", out, tag, 16);
+
+ /*
+ * Check that alterations are detected.
+ */
+ for (v = 0; v < aad_len; v ++) {
+ memcpy(tmp, cipher, plain_len);
+ br_eax_reset(&ec, nonce, nonce_len);
+ aad[v] ^= 0x04;
+ br_eax_aad_inject(&ec, aad, aad_len);
+ aad[v] ^= 0x04;
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 0, tmp, plain_len);
+ check_equals("KAT EAX 7", tmp, plain, plain_len);
+ if (br_eax_check_tag(&ec, tag)) {
+ fprintf(stderr, "Tag should have changed\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * Tag truncation.
+ */
+ for (tag_len = 1; tag_len <= 16; tag_len ++) {
+ memset(out, 0x54, sizeof out);
+ memcpy(tmp, plain, plain_len);
+ br_eax_reset(&ec, nonce, nonce_len);
+ br_eax_aad_inject(&ec, aad, aad_len);
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 1, tmp, plain_len);
+ br_eax_get_tag_trunc(&ec, out, tag_len);
+ check_equals("KAT EAX 8", out, tag, tag_len);
+ for (v = tag_len; v < sizeof out; v ++) {
+ if (out[v] != 0x54) {
+ fprintf(stderr, "overflow on tag\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ memcpy(tmp, plain, plain_len);
+ br_eax_reset(&ec, nonce, nonce_len);
+ br_eax_aad_inject(&ec, aad, aad_len);
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 1, tmp, plain_len);
+ if (!br_eax_check_tag_trunc(&ec, out, tag_len)) {
+ fprintf(stderr, "Tag not verified (3)\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf(".");
+ fflush(stdout);
+
+ /*
+ * For capture tests, we need the message to be non-empty.
+ */
+ if (plain_len == 0) {
+ continue;
+ }
+
+ /*
+ * Captured state, pre-AAD. This requires the AAD and the
+ * message to be non-empty.
+ */
+ br_eax_capture(&ec, &st);
+
+ if (aad_len > 0) {
+ br_eax_reset_pre_aad(&ec, &st, nonce, nonce_len);
+ br_eax_aad_inject(&ec, aad, aad_len);
+ br_eax_flip(&ec);
+ memcpy(tmp, plain, plain_len);
+ br_eax_run(&ec, 1, tmp, plain_len);
+ br_eax_get_tag(&ec, out);
+ check_equals("KAT EAX 9", tmp, cipher, plain_len);
+ check_equals("KAT EAX 10", out, tag, 16);
+
+ br_eax_reset_pre_aad(&ec, &st, nonce, nonce_len);
+ br_eax_aad_inject(&ec, aad, aad_len);
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 0, tmp, plain_len);
+ br_eax_get_tag(&ec, out);
+ check_equals("KAT EAX 11", tmp, plain, plain_len);
+ check_equals("KAT EAX 12", out, tag, 16);
+ }
+
+ /*
+ * Captured state, post-AAD. This requires the message to
+ * be non-empty.
+ */
+ br_eax_reset(&ec, nonce, nonce_len);
+ br_eax_aad_inject(&ec, aad, aad_len);
+ br_eax_flip(&ec);
+ br_eax_get_aad_mac(&ec, &st);
+
+ br_eax_reset_post_aad(&ec, &st, nonce, nonce_len);
+ memcpy(tmp, plain, plain_len);
+ br_eax_run(&ec, 1, tmp, plain_len);
+ br_eax_get_tag(&ec, out);
+ check_equals("KAT EAX 13", tmp, cipher, plain_len);
+ check_equals("KAT EAX 14", out, tag, 16);
+
+ br_eax_reset_post_aad(&ec, &st, nonce, nonce_len);
+ br_eax_run(&ec, 0, tmp, plain_len);
+ br_eax_get_tag(&ec, out);
+ check_equals("KAT EAX 15", tmp, plain, plain_len);
+ check_equals("KAT EAX 16", out, tag, 16);
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_EAX(void)
+{
+ const br_block_ctrcbc_class *x_ctrcbc;
+
+ test_EAX_inner("aes_big", &br_aes_big_ctrcbc_vtable);
+ test_EAX_inner("aes_small", &br_aes_small_ctrcbc_vtable);
+ test_EAX_inner("aes_ct", &br_aes_ct_ctrcbc_vtable);
+ test_EAX_inner("aes_ct64", &br_aes_ct64_ctrcbc_vtable);
+
+ x_ctrcbc = br_aes_x86ni_ctrcbc_get_vtable();
+ if (x_ctrcbc != NULL) {
+ test_EAX_inner("aes_x86ni", x_ctrcbc);
+ } else {
+ printf("Test EAX aes_x86ni: UNAVAILABLE\n");
+ }
+
+ x_ctrcbc = br_aes_pwr8_ctrcbc_get_vtable();
+ if (x_ctrcbc != NULL) {
+ test_EAX_inner("aes_pwr8", x_ctrcbc);
+ } else {
+ printf("Test EAX aes_pwr8: UNAVAILABLE\n");
+ }
+}
+
+/*
+ * From NIST SP 800-38C, appendix C.
+ *
+ * CCM specification concatenates the authentication tag at the end of
+ * the ciphertext; in our API and the vectors below, the tag is separate.
+ *
+ * Order is: key, nonce, aad, plaintext, ciphertext, tag.
+ */
+static const char *const KAT_CCM[] = {
+ "404142434445464748494a4b4c4d4e4f",
+ "10111213141516",
+ "0001020304050607",
+ "20212223",
+ "7162015b",
+ "4dac255d",
+
+ "404142434445464748494a4b4c4d4e4f",
+ "1011121314151617",
+ "000102030405060708090a0b0c0d0e0f",
+ "202122232425262728292a2b2c2d2e2f",
+ "d2a1f0e051ea5f62081a7792073d593d",
+ "1fc64fbfaccd",
+
+ "404142434445464748494a4b4c4d4e4f",
+ "101112131415161718191a1b",
+ "000102030405060708090a0b0c0d0e0f10111213",
+ "202122232425262728292a2b2c2d2e2f3031323334353637",
+ "e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5",
+ "484392fbc1b09951",
+
+ "404142434445464748494a4b4c4d4e4f",
+ "101112131415161718191a1b1c",
+ NULL,
+ "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
+ "69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72",
+ "b4ac6bec93e8598e7f0dadbcea5b",
+
+ NULL
+};
+
+static void
+test_CCM_inner(const char *name, const br_block_ctrcbc_class *vt)
+{
+ size_t u;
+
+ printf("Test CCM %s: ", name);
+ fflush(stdout);
+
+ for (u = 0; KAT_CCM[u]; u += 6) {
+ unsigned char plain[100];
+ unsigned char key[32];
+ unsigned char nonce[100];
+ unsigned char aad_buf[100], *aad;
+ unsigned char cipher[100];
+ unsigned char tag[100];
+ size_t plain_len, key_len, nonce_len, aad_len, tag_len;
+ br_aes_gen_ctrcbc_keys bc;
+ br_ccm_context ec;
+ unsigned char tmp[100], out[16];
+ size_t v;
+
+ key_len = hextobin(key, KAT_CCM[u]);
+ nonce_len = hextobin(nonce, KAT_CCM[u + 1]);
+ if (KAT_CCM[u + 2] == NULL) {
+ aad_len = 65536;
+ aad = malloc(aad_len);
+ if (aad == NULL) {
+ fprintf(stderr, "OOM error\n");
+ exit(EXIT_FAILURE);
+ }
+ for (v = 0; v < 65536; v ++) {
+ aad[v] = (unsigned char)v;
+ }
+ } else {
+ aad = aad_buf;
+ aad_len = hextobin(aad, KAT_CCM[u + 2]);
+ }
+ plain_len = hextobin(plain, KAT_CCM[u + 3]);
+ hextobin(cipher, KAT_CCM[u + 4]);
+ tag_len = hextobin(tag, KAT_CCM[u + 5]);
+
+ vt->init(&bc.vtable, key, key_len);
+ br_ccm_init(&ec, &bc.vtable);
+
+ memset(tmp, 0x54, sizeof tmp);
+
+ /*
+ * Basic operation.
+ */
+ memcpy(tmp, plain, plain_len);
+ if (!br_ccm_reset(&ec, nonce, nonce_len,
+ aad_len, plain_len, tag_len))
+ {
+ fprintf(stderr, "CCM reset failed\n");
+ exit(EXIT_FAILURE);
+ }
+ br_ccm_aad_inject(&ec, aad, aad_len);
+ br_ccm_flip(&ec);
+ br_ccm_run(&ec, 1, tmp, plain_len);
+ if (br_ccm_get_tag(&ec, out) != tag_len) {
+ fprintf(stderr, "CCM returned wrong tag length\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("KAT CCM 1", tmp, cipher, plain_len);
+ check_equals("KAT CCM 2", out, tag, tag_len);
+
+ br_ccm_reset(&ec, nonce, nonce_len,
+ aad_len, plain_len, tag_len);
+ br_ccm_aad_inject(&ec, aad, aad_len);
+ br_ccm_flip(&ec);
+ br_ccm_run(&ec, 0, tmp, plain_len);
+ check_equals("KAT CCM 3", tmp, plain, plain_len);
+ if (!br_ccm_check_tag(&ec, tag)) {
+ fprintf(stderr, "Tag not verified (1)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (v = plain_len; v < sizeof tmp; v ++) {
+ if (tmp[v] != 0x54) {
+ fprintf(stderr, "overflow on data\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * Byte-by-byte injection.
+ */
+ br_ccm_reset(&ec, nonce, nonce_len,
+ aad_len, plain_len, tag_len);
+ for (v = 0; v < aad_len; v ++) {
+ br_ccm_aad_inject(&ec, aad + v, 1);
+ }
+ br_ccm_flip(&ec);
+ for (v = 0; v < plain_len; v ++) {
+ br_ccm_run(&ec, 1, tmp + v, 1);
+ }
+ check_equals("KAT CCM 4", tmp, cipher, plain_len);
+ if (!br_ccm_check_tag(&ec, tag)) {
+ fprintf(stderr, "Tag not verified (2)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ br_ccm_reset(&ec, nonce, nonce_len,
+ aad_len, plain_len, tag_len);
+ for (v = 0; v < aad_len; v ++) {
+ br_ccm_aad_inject(&ec, aad + v, 1);
+ }
+ br_ccm_flip(&ec);
+ for (v = 0; v < plain_len; v ++) {
+ br_ccm_run(&ec, 0, tmp + v, 1);
+ }
+ br_ccm_get_tag(&ec, out);
+ check_equals("KAT CCM 5", tmp, plain, plain_len);
+ check_equals("KAT CCM 6", out, tag, tag_len);
+
+ /*
+ * Check that alterations are detected.
+ */
+ for (v = 0; v < aad_len; v ++) {
+ memcpy(tmp, cipher, plain_len);
+ br_ccm_reset(&ec, nonce, nonce_len,
+ aad_len, plain_len, tag_len);
+ aad[v] ^= 0x04;
+ br_ccm_aad_inject(&ec, aad, aad_len);
+ aad[v] ^= 0x04;
+ br_ccm_flip(&ec);
+ br_ccm_run(&ec, 0, tmp, plain_len);
+ check_equals("KAT CCM 7", tmp, plain, plain_len);
+ if (br_ccm_check_tag(&ec, tag)) {
+ fprintf(stderr, "Tag should have changed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * When the AAD is really big, we don't want to do
+ * the complete quadratic operation.
+ */
+ if (v >= 32) {
+ break;
+ }
+ }
+
+ if (aad != aad_buf) {
+ free(aad);
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_CCM(void)
+{
+ const br_block_ctrcbc_class *x_ctrcbc;
+
+ test_CCM_inner("aes_big", &br_aes_big_ctrcbc_vtable);
+ test_CCM_inner("aes_small", &br_aes_small_ctrcbc_vtable);
+ test_CCM_inner("aes_ct", &br_aes_ct_ctrcbc_vtable);
+ test_CCM_inner("aes_ct64", &br_aes_ct64_ctrcbc_vtable);
+
+ x_ctrcbc = br_aes_x86ni_ctrcbc_get_vtable();
+ if (x_ctrcbc != NULL) {
+ test_CCM_inner("aes_x86ni", x_ctrcbc);
+ } else {
+ printf("Test CCM aes_x86ni: UNAVAILABLE\n");
+ }
+
+ x_ctrcbc = br_aes_pwr8_ctrcbc_get_vtable();
+ if (x_ctrcbc != NULL) {
+ test_CCM_inner("aes_pwr8", x_ctrcbc);
+ } else {
+ printf("Test CCM aes_pwr8: UNAVAILABLE\n");
+ }
+}
+
+static void
+test_EC_inner(const char *sk, const char *sU,
+ const br_ec_impl *impl, int curve)
+{
+ unsigned char bk[70];
+ unsigned char eG[150], eU[150];
+ uint32_t n[22], n0i;
+ size_t klen, ulen, nlen;
+ const br_ec_curve_def *cd;
+ br_hmac_drbg_context rng;
+ int i;
+
+ klen = hextobin(bk, sk);
+ ulen = hextobin(eU, sU);
+ switch (curve) {
+ case BR_EC_secp256r1:
+ cd = &br_secp256r1;
+ break;
+ case BR_EC_secp384r1:
+ cd = &br_secp384r1;
+ break;
+ case BR_EC_secp521r1:
+ cd = &br_secp521r1;
+ break;
+ default:
+ fprintf(stderr, "Unknown curve: %d\n", curve);
+ exit(EXIT_FAILURE);
+ break;
+ }
+ if (ulen != cd->generator_len) {
+ fprintf(stderr, "KAT vector wrong (%lu / %lu)\n",
+ (unsigned long)ulen,
+ (unsigned long)cd->generator_len);
+ }
+ memcpy(eG, cd->generator, ulen);
+ if (impl->mul(eG, ulen, bk, klen, curve) != 1) {
+ fprintf(stderr, "KAT multiplication failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(eG, eU, ulen) != 0) {
+ fprintf(stderr, "KAT mul: mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Test the two-point-mul function. We want to test the basic
+ * functionality, and the following special cases:
+ * x = y
+ * x + y = curve order
+ */
+ nlen = cd->order_len;
+ br_i31_decode(n, cd->order, nlen);
+ n0i = br_i31_ninv31(n[1]);
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, "seed for EC", 11);
+ for (i = 0; i < 10; i ++) {
+ unsigned char ba[80], bb[80], bx[80], by[80], bz[80];
+ uint32_t a[22], b[22], x[22], y[22], z[22], t1[22], t2[22];
+ uint32_t r;
+ unsigned char eA[160], eB[160], eC[160], eD[160];
+
+ /*
+ * Generate random a and b, and compute A = a*G and B = b*G.
+ */
+ br_hmac_drbg_generate(&rng, ba, sizeof ba);
+ br_i31_decode_reduce(a, ba, sizeof ba, n);
+ br_i31_encode(ba, nlen, a);
+ br_hmac_drbg_generate(&rng, bb, sizeof bb);
+ br_i31_decode_reduce(b, bb, sizeof bb, n);
+ br_i31_encode(bb, nlen, b);
+ memcpy(eA, cd->generator, ulen);
+ impl->mul(eA, ulen, ba, nlen, cd->curve);
+ memcpy(eB, cd->generator, ulen);
+ impl->mul(eB, ulen, bb, nlen, cd->curve);
+
+ /*
+ * Generate random x and y (modulo n).
+ */
+ br_hmac_drbg_generate(&rng, bx, sizeof bx);
+ br_i31_decode_reduce(x, bx, sizeof bx, n);
+ br_i31_encode(bx, nlen, x);
+ br_hmac_drbg_generate(&rng, by, sizeof by);
+ br_i31_decode_reduce(y, by, sizeof by, n);
+ br_i31_encode(by, nlen, y);
+
+ /*
+ * Compute z = a*x + b*y (mod n).
+ */
+ memcpy(t1, x, sizeof x);
+ br_i31_to_monty(t1, n);
+ br_i31_montymul(z, a, t1, n, n0i);
+ memcpy(t1, y, sizeof y);
+ br_i31_to_monty(t1, n);
+ br_i31_montymul(t2, b, t1, n, n0i);
+ r = br_i31_add(z, t2, 1);
+ r |= br_i31_sub(z, n, 0) ^ 1;
+ br_i31_sub(z, n, r);
+ br_i31_encode(bz, nlen, z);
+
+ /*
+ * Compute C = x*A + y*B with muladd(), and also
+ * D = z*G with mul(). The two points must match.
+ */
+ memcpy(eC, eA, ulen);
+ if (impl->muladd(eC, eB, ulen,
+ bx, nlen, by, nlen, cd->curve) != 1)
+ {
+ fprintf(stderr, "muladd() failed (1)\n");
+ exit(EXIT_FAILURE);
+ }
+ memcpy(eD, cd->generator, ulen);
+ if (impl->mul(eD, ulen, bz, nlen, cd->curve) != 1) {
+ fprintf(stderr, "mul() failed (1)\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(eC, eD, nlen) != 0) {
+ fprintf(stderr, "mul() / muladd() mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Also recomputed D = z*G with mulgen(). This must
+ * again match.
+ */
+ memset(eD, 0, ulen);
+ if (impl->mulgen(eD, bz, nlen, cd->curve) != ulen) {
+ fprintf(stderr, "mulgen() failed: wrong length\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(eC, eD, nlen) != 0) {
+ fprintf(stderr, "mulgen() / muladd() mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Check with x*A = y*B. We do so by setting b = x and y = a.
+ */
+ memcpy(b, x, sizeof x);
+ br_i31_encode(bb, nlen, b);
+ memcpy(eB, cd->generator, ulen);
+ impl->mul(eB, ulen, bb, nlen, cd->curve);
+ memcpy(y, a, sizeof a);
+ br_i31_encode(by, nlen, y);
+
+ memcpy(t1, x, sizeof x);
+ br_i31_to_monty(t1, n);
+ br_i31_montymul(z, a, t1, n, n0i);
+ memcpy(t1, y, sizeof y);
+ br_i31_to_monty(t1, n);
+ br_i31_montymul(t2, b, t1, n, n0i);
+ r = br_i31_add(z, t2, 1);
+ r |= br_i31_sub(z, n, 0) ^ 1;
+ br_i31_sub(z, n, r);
+ br_i31_encode(bz, nlen, z);
+
+ memcpy(eC, eA, ulen);
+ if (impl->muladd(eC, eB, ulen,
+ bx, nlen, by, nlen, cd->curve) != 1)
+ {
+ fprintf(stderr, "muladd() failed (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ memcpy(eD, cd->generator, ulen);
+ if (impl->mul(eD, ulen, bz, nlen, cd->curve) != 1) {
+ fprintf(stderr, "mul() failed (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(eC, eD, nlen) != 0) {
+ fprintf(stderr,
+ "mul() / muladd() mismatch (x*A=y*B)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Check with x*A + y*B = 0. At that point, b = x, so we
+ * just need to set y = -a (mod n).
+ */
+ memcpy(y, n, sizeof n);
+ br_i31_sub(y, a, 1);
+ br_i31_encode(by, nlen, y);
+ memcpy(eC, eA, ulen);
+ if (impl->muladd(eC, eB, ulen,
+ bx, nlen, by, nlen, cd->curve) != 0)
+ {
+ fprintf(stderr, "muladd() should have failed\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf(".");
+ fflush(stdout);
+}
+
+static void
+test_EC_P256_carry_inner(const br_ec_impl *impl, const char *sP, const char *sQ)
+{
+ unsigned char P[65], Q[sizeof P], k[1];
+ size_t plen, qlen;
+
+ plen = hextobin(P, sP);
+ qlen = hextobin(Q, sQ);
+ if (plen != sizeof P || qlen != sizeof P) {
+ fprintf(stderr, "KAT is incorrect\n");
+ exit(EXIT_FAILURE);
+ }
+ k[0] = 0x10;
+ if (impl->mul(P, plen, k, 1, BR_EC_secp256r1) != 1) {
+ fprintf(stderr, "P-256 multiplication failed\n");
+ exit(EXIT_FAILURE);
+ }
+ check_equals("P256_carry", P, Q, plen);
+ printf(".");
+ fflush(stdout);
+}
+
+static void
+test_EC_P256_carry(const br_ec_impl *impl)
+{
+ test_EC_P256_carry_inner(impl,
+ "0435BAA24B2B6E1B3C88E22A383BD88CC4B9A3166E7BCF94FF6591663AE066B33B821EBA1B4FC8EA609A87EB9A9C9A1CCD5C9F42FA1365306F64D7CAA718B8C978",
+ "0447752A76CA890328D34E675C4971EC629132D1FC4863EDB61219B72C4E58DC5E9D51E7B293488CFD913C3CF20E438BB65C2BA66A7D09EABB45B55E804260C5EB");
+ test_EC_P256_carry_inner(impl,
+ "04DCAE9D9CE211223602024A6933BD42F77B6BF4EAB9C8915F058C149419FADD2CC9FC0707B270A1B5362BA4D249AFC8AC3DA1EFCA8270176EEACA525B49EE19E6",
+ "048DAC7B0BE9B3206FCE8B24B6B4AEB122F2A67D13E536B390B6585CA193427E63F222388B5F51D744D6F5D47536D89EEEC89552BCB269E7828019C4410DFE980A");
+}
+
+static void
+test_EC_KAT(const char *name, const br_ec_impl *impl, uint32_t curve_mask)
+{
+ printf("Test %s: ", name);
+ fflush(stdout);
+
+ if (curve_mask & ((uint32_t)1 << BR_EC_secp256r1)) {
+ test_EC_inner(
+ "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721",
+ "0460FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB67903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299",
+ impl, BR_EC_secp256r1);
+ test_EC_P256_carry(impl);
+ }
+ if (curve_mask & ((uint32_t)1 << BR_EC_secp384r1)) {
+ test_EC_inner(
+ "6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5",
+ "04EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC138015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720",
+ impl, BR_EC_secp384r1);
+ }
+ if (curve_mask & ((uint32_t)1 << BR_EC_secp521r1)) {
+ test_EC_inner(
+ "00FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538",
+ "0401894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A400493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5",
+ impl, BR_EC_secp521r1);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_EC_keygen(const char *name, const br_ec_impl *impl, uint32_t curves)
+{
+ int curve;
+ br_hmac_drbg_context rng;
+
+ printf("Test %s keygen: ", name);
+ fflush(stdout);
+
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, "seed for EC keygen", 18);
+ br_hmac_drbg_update(&rng, name, strlen(name));
+
+ for (curve = -1; curve <= 35; curve ++) {
+ br_ec_private_key sk;
+ br_ec_public_key pk;
+ unsigned char kbuf_priv[BR_EC_KBUF_PRIV_MAX_SIZE];
+ unsigned char kbuf_pub[BR_EC_KBUF_PUB_MAX_SIZE];
+
+ if (curve < 0 || curve >= 32 || ((curves >> curve) & 1) == 0) {
+ if (br_ec_keygen(&rng.vtable, impl,
+ &sk, kbuf_priv, curve) != 0)
+ {
+ fprintf(stderr, "br_ec_keygen() did not"
+ " reject unsupported curve %d\n",
+ curve);
+ exit(EXIT_FAILURE);
+ }
+ sk.curve = curve;
+ if (br_ec_compute_pub(impl, NULL, NULL, &sk) != 0) {
+ fprintf(stderr, "br_ec_keygen() did not"
+ " reject unsupported curve %d\n",
+ curve);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ size_t len, u;
+ unsigned char tmp_priv[sizeof kbuf_priv];
+ unsigned char tmp_pub[sizeof kbuf_pub];
+ unsigned z;
+
+ len = br_ec_keygen(&rng.vtable, impl,
+ NULL, NULL, curve);
+ if (len == 0) {
+ fprintf(stderr, "br_ec_keygen() rejects"
+ " supported curve %d\n", curve);
+ exit(EXIT_FAILURE);
+ }
+ if (len > sizeof kbuf_priv) {
+ fprintf(stderr, "oversized kbuf_priv\n");
+ exit(EXIT_FAILURE);
+ }
+ memset(kbuf_priv, 0, sizeof kbuf_priv);
+ if (br_ec_keygen(&rng.vtable, impl,
+ NULL, kbuf_priv, curve) != len)
+ {
+ fprintf(stderr, "kbuf_priv length mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+ z = 0;
+ for (u = 0; u < len; u ++) {
+ z |= kbuf_priv[u];
+ }
+ if (z == 0) {
+ fprintf(stderr, "kbuf_priv not initialized\n");
+ exit(EXIT_FAILURE);
+ }
+ for (u = len; u < sizeof kbuf_priv; u ++) {
+ if (kbuf_priv[u] != 0) {
+ fprintf(stderr, "kbuf_priv overflow\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (br_ec_keygen(&rng.vtable, impl,
+ NULL, tmp_priv, curve) != len)
+ {
+ fprintf(stderr, "tmp_priv length mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(kbuf_priv, tmp_priv, len) == 0) {
+ fprintf(stderr, "keygen stutter\n");
+ exit(EXIT_FAILURE);
+ }
+ memset(&sk, 0, sizeof sk);
+ if (br_ec_keygen(&rng.vtable, impl,
+ &sk, kbuf_priv, curve) != len)
+ {
+ fprintf(stderr,
+ "kbuf_priv length mismatch (2)\n");
+ exit(EXIT_FAILURE);
+ }
+ if (sk.curve != curve || sk.x != kbuf_priv
+ || sk.xlen != len)
+ {
+ fprintf(stderr, "sk not initialized\n");
+ exit(EXIT_FAILURE);
+ }
+
+ len = br_ec_compute_pub(impl, NULL, NULL, &sk);
+ if (len > sizeof kbuf_pub) {
+ fprintf(stderr, "oversized kbuf_pub\n");
+ exit(EXIT_FAILURE);
+ }
+ memset(kbuf_pub, 0, sizeof kbuf_pub);
+ if (br_ec_compute_pub(impl, NULL,
+ kbuf_pub, &sk) != len)
+ {
+ fprintf(stderr, "kbuf_pub length mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+ for (u = len; u < sizeof kbuf_pub; u ++) {
+ if (kbuf_pub[u] != 0) {
+ fprintf(stderr, "kbuf_pub overflow\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ memset(&pk, 0, sizeof pk);
+ if (br_ec_compute_pub(impl, &pk,
+ tmp_pub, &sk) != len)
+ {
+ fprintf(stderr, "tmp_pub length mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(kbuf_pub, tmp_pub, len) != 0) {
+ fprintf(stderr, "pubkey mismatch\n");
+ exit(EXIT_FAILURE);
+ }
+ if (pk.curve != curve || pk.q != tmp_pub
+ || pk.qlen != len)
+ {
+ fprintf(stderr, "pk not initialized\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (impl->mulgen(kbuf_pub,
+ sk.x, sk.xlen, curve) != len
+ || memcmp(pk.q, kbuf_pub, len) != 0)
+ {
+ fprintf(stderr, "wrong pubkey\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_EC_prime_i15(void)
+{
+ test_EC_KAT("EC_prime_i15", &br_ec_prime_i15,
+ (uint32_t)1 << BR_EC_secp256r1
+ | (uint32_t)1 << BR_EC_secp384r1
+ | (uint32_t)1 << BR_EC_secp521r1);
+ test_EC_keygen("EC_prime_i15", &br_ec_prime_i15,
+ (uint32_t)1 << BR_EC_secp256r1
+ | (uint32_t)1 << BR_EC_secp384r1
+ | (uint32_t)1 << BR_EC_secp521r1);
+}
+
+static void
+test_EC_prime_i31(void)
+{
+ test_EC_KAT("EC_prime_i31", &br_ec_prime_i31,
+ (uint32_t)1 << BR_EC_secp256r1
+ | (uint32_t)1 << BR_EC_secp384r1
+ | (uint32_t)1 << BR_EC_secp521r1);
+ test_EC_keygen("EC_prime_i31", &br_ec_prime_i31,
+ (uint32_t)1 << BR_EC_secp256r1
+ | (uint32_t)1 << BR_EC_secp384r1
+ | (uint32_t)1 << BR_EC_secp521r1);
+}
+
+static void
+test_EC_p256_m15(void)
+{
+ test_EC_KAT("EC_p256_m15", &br_ec_p256_m15,
+ (uint32_t)1 << BR_EC_secp256r1);
+ test_EC_keygen("EC_p256_m15", &br_ec_p256_m15,
+ (uint32_t)1 << BR_EC_secp256r1);
+}
+
+static void
+test_EC_p256_m31(void)
+{
+ test_EC_KAT("EC_p256_m31", &br_ec_p256_m31,
+ (uint32_t)1 << BR_EC_secp256r1);
+ test_EC_keygen("EC_p256_m31", &br_ec_p256_m31,
+ (uint32_t)1 << BR_EC_secp256r1);
+}
+
+static void
+test_EC_p256_m62(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_p256_m62_get();
+ if (ec != NULL) {
+ test_EC_KAT("EC_p256_m62", ec,
+ (uint32_t)1 << BR_EC_secp256r1);
+ test_EC_keygen("EC_p256_m62", ec,
+ (uint32_t)1 << BR_EC_secp256r1);
+ } else {
+ printf("Test EC_p256_m62: UNAVAILABLE\n");
+ printf("Test EC_p256_m62 keygen: UNAVAILABLE\n");
+ }
+}
+
+static void
+test_EC_p256_m64(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_p256_m64_get();
+ if (ec != NULL) {
+ test_EC_KAT("EC_p256_m64", ec,
+ (uint32_t)1 << BR_EC_secp256r1);
+ test_EC_keygen("EC_p256_m64", ec,
+ (uint32_t)1 << BR_EC_secp256r1);
+ } else {
+ printf("Test EC_p256_m64: UNAVAILABLE\n");
+ printf("Test EC_p256_m64 keygen: UNAVAILABLE\n");
+ }
+}
+
+const struct {
+ const char *scalar_le;
+ const char *u_in;
+ const char *u_out;
+} C25519_KAT[] = {
+ { "A546E36BF0527C9D3B16154B82465EDD62144C0AC1FC5A18506A2244BA449AC4",
+ "E6DB6867583030DB3594C1A424B15F7C726624EC26B3353B10A903A6D0AB1C4C",
+ "C3DA55379DE9C6908E94EA4DF28D084F32ECCF03491C71F754B4075577A28552" },
+ { "4B66E9D4D1B4673C5AD22691957D6AF5C11B6421E0EA01D42CA4169E7918BA0D",
+ "E5210F12786811D3F4B7959D0538AE2C31DBE7106FC03C3EFC4CD549C715A493",
+ "95CBDE9476E8907D7AADE45CB4B873F88B595A68799FA152E6F8F7647AAC7957" },
+ { 0, 0, 0 }
+};
+
+static void
+revbytes(unsigned char *buf, size_t len)
+{
+ size_t u;
+
+ for (u = 0; u < (len >> 1); u ++) {
+ unsigned t;
+
+ t = buf[u];
+ buf[u] = buf[len - 1 - u];
+ buf[len - 1 - u] = t;
+ }
+}
+
+static void
+test_EC_c25519(const char *name, const br_ec_impl *iec)
+{
+ unsigned char bu[32], bk[32], br[32];
+ size_t v;
+ int i;
+
+ printf("Test %s: ", name);
+ fflush(stdout);
+ for (v = 0; C25519_KAT[v].scalar_le; v ++) {
+ hextobin(bk, C25519_KAT[v].scalar_le);
+ revbytes(bk, sizeof bk);
+ hextobin(bu, C25519_KAT[v].u_in);
+ hextobin(br, C25519_KAT[v].u_out);
+ if (!iec->mul(bu, sizeof bu, bk, sizeof bk, BR_EC_curve25519)) {
+ fprintf(stderr, "Curve25519 multiplication failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (memcmp(bu, br, sizeof bu) != 0) {
+ fprintf(stderr, "Curve25519 failed KAT\n");
+ exit(EXIT_FAILURE);
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ printf(" ");
+ fflush(stdout);
+
+ memset(bu, 0, sizeof bu);
+ bu[0] = 0x09;
+ memcpy(bk, bu, sizeof bu);
+ for (i = 1; i <= 1000; i ++) {
+ revbytes(bk, sizeof bk);
+ if (!iec->mul(bu, sizeof bu, bk, sizeof bk, BR_EC_curve25519)) {
+ fprintf(stderr, "Curve25519 multiplication failed"
+ " (iter=%d)\n", i);
+ exit(EXIT_FAILURE);
+ }
+ revbytes(bk, sizeof bk);
+ for (v = 0; v < sizeof bu; v ++) {
+ unsigned t;
+
+ t = bu[v];
+ bu[v] = bk[v];
+ bk[v] = t;
+ }
+ if (i == 1 || i == 1000) {
+ const char *sref;
+
+ sref = (i == 1)
+ ? "422C8E7A6227D7BCA1350B3E2BB7279F7897B87BB6854B783C60E80311AE3079"
+ : "684CF59BA83309552800EF566F2F4D3C1C3887C49360E3875F2EB94D99532C51";
+ hextobin(br, sref);
+ if (memcmp(bk, br, sizeof bk) != 0) {
+ fprintf(stderr,
+ "Curve25519 failed KAT (iter=%d)\n", i);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (i % 100 == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_EC_c25519_i15(void)
+{
+ test_EC_c25519("EC_c25519_i15", &br_ec_c25519_i15);
+ test_EC_keygen("EC_c25519_i15", &br_ec_c25519_i15,
+ (uint32_t)1 << BR_EC_curve25519);
+}
+
+static void
+test_EC_c25519_i31(void)
+{
+ test_EC_c25519("EC_c25519_i31", &br_ec_c25519_i31);
+ test_EC_keygen("EC_c25519_i31", &br_ec_c25519_i31,
+ (uint32_t)1 << BR_EC_curve25519);
+}
+
+static void
+test_EC_c25519_m15(void)
+{
+ test_EC_c25519("EC_c25519_m15", &br_ec_c25519_m15);
+ test_EC_keygen("EC_c25519_m15", &br_ec_c25519_m15,
+ (uint32_t)1 << BR_EC_curve25519);
+}
+
+static void
+test_EC_c25519_m31(void)
+{
+ test_EC_c25519("EC_c25519_m31", &br_ec_c25519_m31);
+ test_EC_keygen("EC_c25519_m31", &br_ec_c25519_m31,
+ (uint32_t)1 << BR_EC_curve25519);
+}
+
+static void
+test_EC_c25519_m62(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_c25519_m62_get();
+ if (ec != NULL) {
+ test_EC_c25519("EC_c25519_m62", ec);
+ test_EC_keygen("EC_c25519_m62", ec,
+ (uint32_t)1 << BR_EC_curve25519);
+ } else {
+ printf("Test EC_c25519_m62: UNAVAILABLE\n");
+ printf("Test EC_c25519_m62 keygen: UNAVAILABLE\n");
+ }
+}
+
+static void
+test_EC_c25519_m64(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_c25519_m64_get();
+ if (ec != NULL) {
+ test_EC_c25519("EC_c25519_m64", ec);
+ test_EC_keygen("EC_c25519_m64", ec,
+ (uint32_t)1 << BR_EC_curve25519);
+ } else {
+ printf("Test EC_c25519_m64: UNAVAILABLE\n");
+ printf("Test EC_c25519_m64 keygen: UNAVAILABLE\n");
+ }
+}
+
+static const unsigned char EC_P256_PUB_POINT[] = {
+ 0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D,
+ 0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D,
+ 0x68, 0xC0, 0x49, 0xB8, 0x92, 0x3B, 0x61, 0xFA,
+ 0x6C, 0xE6, 0x69, 0x62, 0x2E, 0x60, 0xF2, 0x9F,
+ 0xB6, 0x79, 0x03, 0xFE, 0x10, 0x08, 0xB8, 0xBC,
+ 0x99, 0xA4, 0x1A, 0xE9, 0xE9, 0x56, 0x28, 0xBC,
+ 0x64, 0xF2, 0xF1, 0xB2, 0x0C, 0x2D, 0x7E, 0x9F,
+ 0x51, 0x77, 0xA3, 0xC2, 0x94, 0xD4, 0x46, 0x22,
+ 0x99
+};
+
+static const unsigned char EC_P256_PRIV_X[] = {
+ 0xC9, 0xAF, 0xA9, 0xD8, 0x45, 0xBA, 0x75, 0x16,
+ 0x6B, 0x5C, 0x21, 0x57, 0x67, 0xB1, 0xD6, 0x93,
+ 0x4E, 0x50, 0xC3, 0xDB, 0x36, 0xE8, 0x9B, 0x12,
+ 0x7B, 0x8A, 0x62, 0x2B, 0x12, 0x0F, 0x67, 0x21
+};
+
+static const br_ec_public_key EC_P256_PUB = {
+ BR_EC_secp256r1,
+ (unsigned char *)EC_P256_PUB_POINT, sizeof EC_P256_PUB_POINT
+};
+
+static const br_ec_private_key EC_P256_PRIV = {
+ BR_EC_secp256r1,
+ (unsigned char *)EC_P256_PRIV_X, sizeof EC_P256_PRIV_X
+};
+
+static const unsigned char EC_P384_PUB_POINT[] = {
+ 0x04, 0xEC, 0x3A, 0x4E, 0x41, 0x5B, 0x4E, 0x19,
+ 0xA4, 0x56, 0x86, 0x18, 0x02, 0x9F, 0x42, 0x7F,
+ 0xA5, 0xDA, 0x9A, 0x8B, 0xC4, 0xAE, 0x92, 0xE0,
+ 0x2E, 0x06, 0xAA, 0xE5, 0x28, 0x6B, 0x30, 0x0C,
+ 0x64, 0xDE, 0xF8, 0xF0, 0xEA, 0x90, 0x55, 0x86,
+ 0x60, 0x64, 0xA2, 0x54, 0x51, 0x54, 0x80, 0xBC,
+ 0x13, 0x80, 0x15, 0xD9, 0xB7, 0x2D, 0x7D, 0x57,
+ 0x24, 0x4E, 0xA8, 0xEF, 0x9A, 0xC0, 0xC6, 0x21,
+ 0x89, 0x67, 0x08, 0xA5, 0x93, 0x67, 0xF9, 0xDF,
+ 0xB9, 0xF5, 0x4C, 0xA8, 0x4B, 0x3F, 0x1C, 0x9D,
+ 0xB1, 0x28, 0x8B, 0x23, 0x1C, 0x3A, 0xE0, 0xD4,
+ 0xFE, 0x73, 0x44, 0xFD, 0x25, 0x33, 0x26, 0x47,
+ 0x20
+};
+
+static const unsigned char EC_P384_PRIV_X[] = {
+ 0x6B, 0x9D, 0x3D, 0xAD, 0x2E, 0x1B, 0x8C, 0x1C,
+ 0x05, 0xB1, 0x98, 0x75, 0xB6, 0x65, 0x9F, 0x4D,
+ 0xE2, 0x3C, 0x3B, 0x66, 0x7B, 0xF2, 0x97, 0xBA,
+ 0x9A, 0xA4, 0x77, 0x40, 0x78, 0x71, 0x37, 0xD8,
+ 0x96, 0xD5, 0x72, 0x4E, 0x4C, 0x70, 0xA8, 0x25,
+ 0xF8, 0x72, 0xC9, 0xEA, 0x60, 0xD2, 0xED, 0xF5
+};
+
+static const br_ec_public_key EC_P384_PUB = {
+ BR_EC_secp384r1,
+ (unsigned char *)EC_P384_PUB_POINT, sizeof EC_P384_PUB_POINT
+};
+
+static const br_ec_private_key EC_P384_PRIV = {
+ BR_EC_secp384r1,
+ (unsigned char *)EC_P384_PRIV_X, sizeof EC_P384_PRIV_X
+};
+
+static const unsigned char EC_P521_PUB_POINT[] = {
+ 0x04, 0x01, 0x89, 0x45, 0x50, 0xD0, 0x78, 0x59,
+ 0x32, 0xE0, 0x0E, 0xAA, 0x23, 0xB6, 0x94, 0xF2,
+ 0x13, 0xF8, 0xC3, 0x12, 0x1F, 0x86, 0xDC, 0x97,
+ 0xA0, 0x4E, 0x5A, 0x71, 0x67, 0xDB, 0x4E, 0x5B,
+ 0xCD, 0x37, 0x11, 0x23, 0xD4, 0x6E, 0x45, 0xDB,
+ 0x6B, 0x5D, 0x53, 0x70, 0xA7, 0xF2, 0x0F, 0xB6,
+ 0x33, 0x15, 0x5D, 0x38, 0xFF, 0xA1, 0x6D, 0x2B,
+ 0xD7, 0x61, 0xDC, 0xAC, 0x47, 0x4B, 0x9A, 0x2F,
+ 0x50, 0x23, 0xA4, 0x00, 0x49, 0x31, 0x01, 0xC9,
+ 0x62, 0xCD, 0x4D, 0x2F, 0xDD, 0xF7, 0x82, 0x28,
+ 0x5E, 0x64, 0x58, 0x41, 0x39, 0xC2, 0xF9, 0x1B,
+ 0x47, 0xF8, 0x7F, 0xF8, 0x23, 0x54, 0xD6, 0x63,
+ 0x0F, 0x74, 0x6A, 0x28, 0xA0, 0xDB, 0x25, 0x74,
+ 0x1B, 0x5B, 0x34, 0xA8, 0x28, 0x00, 0x8B, 0x22,
+ 0xAC, 0xC2, 0x3F, 0x92, 0x4F, 0xAA, 0xFB, 0xD4,
+ 0xD3, 0x3F, 0x81, 0xEA, 0x66, 0x95, 0x6D, 0xFE,
+ 0xAA, 0x2B, 0xFD, 0xFC, 0xF5
+};
+
+static const unsigned char EC_P521_PRIV_X[] = {
+ 0x00, 0xFA, 0xD0, 0x6D, 0xAA, 0x62, 0xBA, 0x3B,
+ 0x25, 0xD2, 0xFB, 0x40, 0x13, 0x3D, 0xA7, 0x57,
+ 0x20, 0x5D, 0xE6, 0x7F, 0x5B, 0xB0, 0x01, 0x8F,
+ 0xEE, 0x8C, 0x86, 0xE1, 0xB6, 0x8C, 0x7E, 0x75,
+ 0xCA, 0xA8, 0x96, 0xEB, 0x32, 0xF1, 0xF4, 0x7C,
+ 0x70, 0x85, 0x58, 0x36, 0xA6, 0xD1, 0x6F, 0xCC,
+ 0x14, 0x66, 0xF6, 0xD8, 0xFB, 0xEC, 0x67, 0xDB,
+ 0x89, 0xEC, 0x0C, 0x08, 0xB0, 0xE9, 0x96, 0xB8,
+ 0x35, 0x38
+};
+
+static const br_ec_public_key EC_P521_PUB = {
+ BR_EC_secp521r1,
+ (unsigned char *)EC_P521_PUB_POINT, sizeof EC_P521_PUB_POINT
+};
+
+static const br_ec_private_key EC_P521_PRIV = {
+ BR_EC_secp521r1,
+ (unsigned char *)EC_P521_PRIV_X, sizeof EC_P521_PRIV_X
+};
+
+typedef struct {
+ const br_ec_public_key *pub;
+ const br_ec_private_key *priv;
+ const br_hash_class *hf;
+ const char *msg;
+ const char *sk;
+ const char *sraw;
+ const char *sasn1;
+} ecdsa_kat_vector;
+
+const ecdsa_kat_vector ECDSA_KAT[] = {
+
+ /* Test vectors for P-256, from RFC 6979. */
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha1_vtable, "sample",
+ "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4",
+ "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D326D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB",
+ "3044022061340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D3202206D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha224_vtable, "sample",
+ "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473",
+ "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3FB9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C",
+ "3045022053B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F022100B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha256_vtable, "sample",
+ "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60",
+ "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8",
+ "3046022100EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716022100F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha384_vtable, "sample",
+ "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4",
+ "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF77194861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954",
+ "304402200EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF771902204861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha512_vtable, "sample",
+ "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5",
+ "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F002362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE",
+ "30450221008496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F0002202362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha1_vtable, "test",
+ "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E",
+ "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A8901B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1",
+ "304402200CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89022001B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha224_vtable, "test",
+ "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7",
+ "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D",
+ "3046022100C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692022100C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha256_vtable, "test",
+ "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0",
+ "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083",
+ "3045022100F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D383670220019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha384_vtable, "test",
+ "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8",
+ "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB68DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C",
+ "304602210083910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB60221008DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C"
+ },
+ {
+ &EC_P256_PUB,
+ &EC_P256_PRIV,
+ &br_sha512_vtable, "test",
+ "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F",
+ "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A0439AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55",
+ "30440220461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04022039AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55"
+ },
+
+ /* Test vectors for P-384, from RFC 6979. */
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha1_vtable, "sample",
+ "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7",
+ "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443",
+ "3066023100EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2023100A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443"
+ },
+
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha224_vtable, "sample",
+ "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB8083EE4E3C45B06A5899EA56C51B5879",
+ "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE0601229DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D",
+ "3065023042356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE0601220231009DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha256_vtable, "sample",
+ "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60",
+ "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CDF3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0",
+ "3065023021B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD023100F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha384_vtable, "sample",
+ "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9",
+ "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE4699EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8",
+ "306602310094EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE4602310099EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha512_vtable, "sample",
+ "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3",
+ "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5",
+ "3065023100ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD78824337090230512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha1_vtable, "test",
+ "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497",
+ "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282",
+ "306502304BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7023100D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha224_vtable, "test",
+ "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E3D33BE4DC5EB8886A8ECD093F2935726",
+ "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E7207041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66",
+ "3065023100E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72023007041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha256_vtable, "test",
+ "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7",
+ "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265",
+ "306402306D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B02302D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha384_vtable, "test",
+ "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA",
+ "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DBDDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5",
+ "30660231008203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB023100DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5"
+ },
+ {
+ &EC_P384_PUB,
+ &EC_P384_PRIV,
+ &br_sha512_vtable, "test",
+ "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C",
+ "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736",
+ "3066023100A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277023100976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736"
+ },
+
+ /* Test vectors for P-521, from RFC 6979. */
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha1_vtable, "sample",
+ "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9",
+ "00343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D00E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16",
+ "3081870241343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D024200E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha224_vtable, "sample",
+ "0121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B92113F3",
+ "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E0050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F",
+ "308187024201776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E024150CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha256_vtable, "sample",
+ "00EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0",
+ "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7004A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC",
+ "308187024201511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A702414A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha384_vtable, "sample",
+ "01546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211",
+ "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C6745101F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61",
+ "308188024201EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451024201F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha512_vtable, "sample",
+ "01DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3",
+ "00C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA00617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A",
+ "308187024200C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA0241617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha1_vtable, "test",
+ "00BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222",
+ "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D036701E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF",
+ "3081880242013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367024201E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha224_vtable, "test",
+ "0040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A01136987E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F706",
+ "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4",
+ "308188024201C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB02420177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha256_vtable, "test",
+ "001DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258",
+ "000E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA800CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86",
+ "30818702410E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8024200CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha384_vtable, "test",
+ "01F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88",
+ "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979",
+ "3081880242014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C02420133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979"
+ },
+ {
+ &EC_P521_PUB,
+ &EC_P521_PRIV,
+ &br_sha512_vtable, "test",
+ "016200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D",
+ "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3",
+ "3081880242013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D024201FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3"
+ },
+
+ /* Terminator for list of test vectors. */
+ {
+ 0, 0, 0, 0, 0, 0, 0
+ }
+};
+
+static void
+test_ECDSA_KAT(const br_ec_impl *iec,
+ br_ecdsa_sign sign, br_ecdsa_vrfy vrfy, int asn1)
+{
+ size_t u;
+
+ for (u = 0;; u ++) {
+ const ecdsa_kat_vector *kv;
+ unsigned char hash[64];
+ size_t hash_len;
+ unsigned char sig[150], sig2[150];
+ size_t sig_len, sig2_len;
+ br_hash_compat_context hc;
+
+ kv = &ECDSA_KAT[u];
+ if (kv->pub == 0) {
+ break;
+ }
+ kv->hf->init(&hc.vtable);
+ kv->hf->update(&hc.vtable, kv->msg, strlen(kv->msg));
+ kv->hf->out(&hc.vtable, hash);
+ hash_len = (kv->hf->desc >> BR_HASHDESC_OUT_OFF)
+ & BR_HASHDESC_OUT_MASK;
+ if (asn1) {
+ sig_len = hextobin(sig, kv->sasn1);
+ } else {
+ sig_len = hextobin(sig, kv->sraw);
+ }
+
+ if (vrfy(iec, hash, hash_len,
+ kv->pub, sig, sig_len) != 1)
+ {
+ fprintf(stderr, "ECDSA KAT verify failed (1)\n");
+ exit(EXIT_FAILURE);
+ }
+ hash[0] ^= 0x80;
+ if (vrfy(iec, hash, hash_len,
+ kv->pub, sig, sig_len) != 0)
+ {
+ fprintf(stderr, "ECDSA KAT verify shoud have failed\n");
+ exit(EXIT_FAILURE);
+ }
+ hash[0] ^= 0x80;
+ if (vrfy(iec, hash, hash_len,
+ kv->pub, sig, sig_len) != 1)
+ {
+ fprintf(stderr, "ECDSA KAT verify failed (2)\n");
+ exit(EXIT_FAILURE);
+ }
+
+ sig2_len = sign(iec, kv->hf, hash, kv->priv, sig2);
+ if (sig2_len == 0) {
+ fprintf(stderr, "ECDSA KAT sign failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (sig2_len != sig_len || memcmp(sig, sig2, sig_len) != 0) {
+ fprintf(stderr, "ECDSA KAT wrong signature value\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf(".");
+ fflush(stdout);
+ }
+}
+
+static void
+test_ECDSA_i31(void)
+{
+ printf("Test ECDSA/i31: ");
+ fflush(stdout);
+ printf("[raw]");
+ fflush(stdout);
+ test_ECDSA_KAT(&br_ec_prime_i31,
+ &br_ecdsa_i31_sign_raw, &br_ecdsa_i31_vrfy_raw, 0);
+ printf(" [asn1]");
+ fflush(stdout);
+ test_ECDSA_KAT(&br_ec_prime_i31,
+ &br_ecdsa_i31_sign_asn1, &br_ecdsa_i31_vrfy_asn1, 1);
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_ECDSA_i15(void)
+{
+ printf("Test ECDSA/i15: ");
+ fflush(stdout);
+ printf("[raw]");
+ fflush(stdout);
+ test_ECDSA_KAT(&br_ec_prime_i15,
+ &br_ecdsa_i15_sign_raw, &br_ecdsa_i15_vrfy_raw, 0);
+ printf(" [asn1]");
+ fflush(stdout);
+ test_ECDSA_KAT(&br_ec_prime_i31,
+ &br_ecdsa_i15_sign_asn1, &br_ecdsa_i15_vrfy_asn1, 1);
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_modpow_i31(void)
+{
+ br_hmac_drbg_context hc;
+ int k;
+
+ printf("Test ModPow/i31: ");
+
+ br_hmac_drbg_init(&hc, &br_sha256_vtable, "seed modpow", 11);
+ for (k = 10; k <= 500; k ++) {
+ size_t blen;
+ unsigned char bm[128], bx[128], bx1[128], bx2[128];
+ unsigned char be[128];
+ unsigned mask;
+ uint32_t x1[35], m1[35];
+ uint16_t x2[70], m2[70];
+ uint32_t tmp1[1000];
+ uint16_t tmp2[2000];
+
+ blen = (k + 7) >> 3;
+ br_hmac_drbg_generate(&hc, bm, blen);
+ br_hmac_drbg_generate(&hc, bx, blen);
+ br_hmac_drbg_generate(&hc, be, blen);
+ bm[blen - 1] |= 0x01;
+ mask = 0xFF >> ((int)(blen << 3) - k);
+ bm[0] &= mask;
+ bm[0] |= (mask - (mask >> 1));
+ bx[0] &= (mask >> 1);
+
+ br_i31_decode(m1, bm, blen);
+ br_i31_decode_mod(x1, bx, blen, m1);
+ br_i31_modpow_opt(x1, be, blen, m1, br_i31_ninv31(m1[1]),
+ tmp1, (sizeof tmp1) / (sizeof tmp1[0]));
+ br_i31_encode(bx1, blen, x1);
+
+ br_i15_decode(m2, bm, blen);
+ br_i15_decode_mod(x2, bx, blen, m2);
+ br_i15_modpow_opt(x2, be, blen, m2, br_i15_ninv15(m2[1]),
+ tmp2, (sizeof tmp2) / (sizeof tmp2[0]));
+ br_i15_encode(bx2, blen, x2);
+
+ check_equals("ModPow i31/i15", bx1, bx2, blen);
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static void
+test_modpow_i62(void)
+{
+ br_hmac_drbg_context hc;
+ int k;
+
+ printf("Test ModPow/i62: ");
+
+ br_hmac_drbg_init(&hc, &br_sha256_vtable, "seed modpow", 11);
+ for (k = 10; k <= 500; k ++) {
+ size_t blen;
+ unsigned char bm[128], bx[128], bx1[128], bx2[128];
+ unsigned char be[128];
+ unsigned mask;
+ uint32_t x1[35], m1[35];
+ uint16_t x2[70], m2[70];
+ uint64_t tmp1[500];
+ uint16_t tmp2[2000];
+
+ blen = (k + 7) >> 3;
+ br_hmac_drbg_generate(&hc, bm, blen);
+ br_hmac_drbg_generate(&hc, bx, blen);
+ br_hmac_drbg_generate(&hc, be, blen);
+ bm[blen - 1] |= 0x01;
+ mask = 0xFF >> ((int)(blen << 3) - k);
+ bm[0] &= mask;
+ bm[0] |= (mask - (mask >> 1));
+ bx[0] &= (mask >> 1);
+
+ br_i31_decode(m1, bm, blen);
+ br_i31_decode_mod(x1, bx, blen, m1);
+ br_i62_modpow_opt(x1, be, blen, m1, br_i31_ninv31(m1[1]),
+ tmp1, (sizeof tmp1) / (sizeof tmp1[0]));
+ br_i31_encode(bx1, blen, x1);
+
+ br_i15_decode(m2, bm, blen);
+ br_i15_decode_mod(x2, bx, blen, m2);
+ br_i15_modpow_opt(x2, be, blen, m2, br_i15_ninv15(m2[1]),
+ tmp2, (sizeof tmp2) / (sizeof tmp2[0]));
+ br_i15_encode(bx2, blen, x2);
+
+ check_equals("ModPow i62/i15", bx1, bx2, blen);
+
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+static int
+eq_name(const char *s1, const char *s2)
+{
+ for (;;) {
+ int c1, c2;
+
+ for (;;) {
+ c1 = *s1 ++;
+ if (c1 >= 'A' && c1 <= 'Z') {
+ c1 += 'a' - 'A';
+ } else {
+ switch (c1) {
+ case '-': case '_': case '.': case ' ':
+ continue;
+ }
+ }
+ break;
+ }
+ for (;;) {
+ c2 = *s2 ++;
+ if (c2 >= 'A' && c2 <= 'Z') {
+ c2 += 'a' - 'A';
+ } else {
+ switch (c2) {
+ case '-': case '_': case '.': case ' ':
+ continue;
+ }
+ }
+ break;
+ }
+ if (c1 != c2) {
+ return 0;
+ }
+ if (c1 == 0) {
+ return 1;
+ }
+ }
+}
+
+#define STU(x) { &test_ ## x, #x }
+
+static const struct {
+ void (*fn)(void);
+ const char *name;
+} tfns[] = {
+ STU(MD5),
+ STU(SHA1),
+ STU(SHA224),
+ STU(SHA256),
+ STU(SHA384),
+ STU(SHA512),
+ STU(MD5_SHA1),
+ STU(multihash),
+ STU(HMAC),
+ STU(HKDF),
+ STU(SHAKE),
+ STU(HMAC_DRBG),
+ STU(AESCTR_DRBG),
+ STU(PRF),
+ STU(AES_big),
+ STU(AES_small),
+ STU(AES_ct),
+ STU(AES_ct64),
+ STU(AES_pwr8),
+ STU(AES_x86ni),
+ STU(AES_CTRCBC_big),
+ STU(AES_CTRCBC_small),
+ STU(AES_CTRCBC_ct),
+ STU(AES_CTRCBC_ct64),
+ STU(AES_CTRCBC_x86ni),
+ STU(AES_CTRCBC_pwr8),
+ STU(DES_tab),
+ STU(DES_ct),
+ STU(ChaCha20_ct),
+ STU(ChaCha20_sse2),
+ STU(Poly1305_ctmul),
+ STU(Poly1305_ctmul32),
+ STU(Poly1305_ctmulq),
+ STU(Poly1305_i15),
+ STU(RSA_i15),
+ STU(RSA_i31),
+ STU(RSA_i32),
+ STU(RSA_i62),
+ STU(GHASH_ctmul),
+ STU(GHASH_ctmul32),
+ STU(GHASH_ctmul64),
+ STU(GHASH_pclmul),
+ STU(GHASH_pwr8),
+ STU(CCM),
+ STU(EAX),
+ STU(GCM),
+ STU(EC_prime_i15),
+ STU(EC_prime_i31),
+ STU(EC_p256_m15),
+ STU(EC_p256_m31),
+ STU(EC_p256_m62),
+ STU(EC_p256_m64),
+ STU(EC_c25519_i15),
+ STU(EC_c25519_i31),
+ STU(EC_c25519_m15),
+ STU(EC_c25519_m31),
+ STU(EC_c25519_m62),
+ STU(EC_c25519_m64),
+ STU(ECDSA_i15),
+ STU(ECDSA_i31),
+ STU(modpow_i31),
+ STU(modpow_i62),
+ { 0, 0 }
+};
+
+int
+main(int argc, char *argv[])
+{
+ size_t u;
+
+ if (argc <= 1) {
+ printf("usage: testcrypto all | name...\n");
+ printf("individual test names:\n");
+ for (u = 0; tfns[u].name; u ++) {
+ printf(" %s\n", tfns[u].name);
+ }
+ } else {
+ for (u = 0; tfns[u].name; u ++) {
+ int i;
+
+ for (i = 1; i < argc; i ++) {
+ if (eq_name(argv[i], tfns[u].name)
+ || eq_name(argv[i], "all"))
+ {
+ tfns[u].fn();
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+}
Property changes on: stable/12/contrib/bearssl/test/test_crypto.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/test_math.c
===================================================================
--- stable/12/contrib/bearssl/test/test_math.c (nonexistent)
+++ stable/12/contrib/bearssl/test/test_math.c (revision 346145)
@@ -0,0 +1,482 @@
+/*
+ * 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 <stdarg.h>
+#include <time.h>
+
+#include <gmp.h>
+
+#include "bearssl.h"
+#include "inner.h"
+
+/*
+ * Pointers to implementations.
+ */
+typedef struct {
+ uint32_t word_size;
+ void (*zero)(uint32_t *x, uint32_t bit_len);
+ void (*decode)(uint32_t *x, const void *src, size_t len);
+ uint32_t (*decode_mod)(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m);
+ void (*reduce)(uint32_t *x, const uint32_t *a, const uint32_t *m);
+ void (*decode_reduce)(uint32_t *x,
+ const void *src, size_t len, const uint32_t *m);
+ void (*encode)(void *dst, size_t len, const uint32_t *x);
+ uint32_t (*add)(uint32_t *a, const uint32_t *b, uint32_t ctl);
+ uint32_t (*sub)(uint32_t *a, const uint32_t *b, uint32_t ctl);
+ uint32_t (*ninv)(uint32_t x);
+ void (*montymul)(uint32_t *d, const uint32_t *x, const uint32_t *y,
+ const uint32_t *m, uint32_t m0i);
+ void (*to_monty)(uint32_t *x, const uint32_t *m);
+ void (*from_monty)(uint32_t *x, const uint32_t *m, uint32_t m0i);
+ void (*modpow)(uint32_t *x, const unsigned char *e, size_t elen,
+ const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2);
+} int_impl;
+
+static const int_impl i31_impl = {
+ 31,
+ &br_i31_zero,
+ &br_i31_decode,
+ &br_i31_decode_mod,
+ &br_i31_reduce,
+ &br_i31_decode_reduce,
+ &br_i31_encode,
+ &br_i31_add,
+ &br_i31_sub,
+ &br_i31_ninv31,
+ &br_i31_montymul,
+ &br_i31_to_monty,
+ &br_i31_from_monty,
+ &br_i31_modpow
+};
+static const int_impl i32_impl = {
+ 32,
+ &br_i32_zero,
+ &br_i32_decode,
+ &br_i32_decode_mod,
+ &br_i32_reduce,
+ &br_i32_decode_reduce,
+ &br_i32_encode,
+ &br_i32_add,
+ &br_i32_sub,
+ &br_i32_ninv32,
+ &br_i32_montymul,
+ &br_i32_to_monty,
+ &br_i32_from_monty,
+ &br_i32_modpow
+};
+
+static const int_impl *impl;
+
+static gmp_randstate_t RNG;
+
+/*
+ * Get a random prime of length 'size' bits. This function also guarantees
+ * that x-1 is not a multiple of 65537.
+ */
+static void
+rand_prime(mpz_t x, int size)
+{
+ for (;;) {
+ mpz_urandomb(x, RNG, size - 1);
+ mpz_setbit(x, 0);
+ mpz_setbit(x, size - 1);
+ if (mpz_probab_prime_p(x, 50)) {
+ mpz_sub_ui(x, x, 1);
+ if (mpz_divisible_ui_p(x, 65537)) {
+ continue;
+ }
+ mpz_add_ui(x, x, 1);
+ return;
+ }
+ }
+}
+
+/*
+ * Print out a GMP integer (for debug).
+ */
+static void
+print_z(mpz_t z)
+{
+ unsigned char zb[1000];
+ size_t zlen, k;
+
+ mpz_export(zb, &zlen, 1, 1, 0, 0, z);
+ if (zlen == 0) {
+ printf(" 00");
+ return;
+ }
+ if ((zlen & 3) != 0) {
+ k = 4 - (zlen & 3);
+ memmove(zb + k, zb, zlen);
+ memset(zb, 0, k);
+ zlen += k;
+ }
+ for (k = 0; k < zlen; k += 4) {
+ printf(" %02X%02X%02X%02X",
+ zb[k], zb[k + 1], zb[k + 2], zb[k + 3]);
+ }
+}
+
+/*
+ * Print out an i31 or i32 integer (for debug).
+ */
+static void
+print_u(uint32_t *x)
+{
+ size_t k;
+
+ if (x[0] == 0) {
+ printf(" 00000000 (0, 0)");
+ return;
+ }
+ for (k = (x[0] + 31) >> 5; k > 0; k --) {
+ printf(" %08lX", (unsigned long)x[k]);
+ }
+ printf(" (%u, %u)", (unsigned)(x[0] >> 5), (unsigned)(x[0] & 31));
+}
+
+/*
+ * Check that an i31/i32 number and a GMP number are equal.
+ */
+static void
+check_eqz(uint32_t *x, mpz_t z)
+{
+ unsigned char xb[1000];
+ unsigned char zb[1000];
+ size_t xlen, zlen;
+ int good;
+
+ xlen = ((x[0] + 31) & ~(uint32_t)31) >> 3;
+ impl->encode(xb, xlen, x);
+ mpz_export(zb, &zlen, 1, 1, 0, 0, z);
+ good = 1;
+ if (xlen < zlen) {
+ good = 0;
+ } else if (xlen > zlen) {
+ size_t u;
+
+ for (u = xlen; u > zlen; u --) {
+ if (xb[xlen - u] != 0) {
+ good = 0;
+ break;
+ }
+ }
+ }
+ good = good && memcmp(xb + xlen - zlen, zb, zlen) == 0;
+ if (!good) {
+ size_t u;
+
+ printf("Mismatch:\n");
+ printf(" x = ");
+ print_u(x);
+ printf("\n");
+ printf(" ex = ");
+ for (u = 0; u < xlen; u ++) {
+ printf("%02X", xb[u]);
+ }
+ printf("\n");
+ printf(" z = ");
+ print_z(z);
+ printf("\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* obsolete
+static void
+mp_to_br(uint32_t *mx, uint32_t x_bitlen, mpz_t x)
+{
+ uint32_t x_ebitlen;
+ size_t xlen;
+
+ if (mpz_sizeinbase(x, 2) > x_bitlen) {
+ abort();
+ }
+ x_ebitlen = ((x_bitlen / 31) << 5) + (x_bitlen % 31);
+ br_i31_zero(mx, x_ebitlen);
+ mpz_export(mx + 1, &xlen, -1, sizeof *mx, 0, 1, x);
+}
+*/
+
+static void
+test_modint(void)
+{
+ int i, j, k;
+ mpz_t p, a, b, v, t1;
+
+ printf("Test modular integers: ");
+ fflush(stdout);
+
+ gmp_randinit_mt(RNG);
+ mpz_init(p);
+ mpz_init(a);
+ mpz_init(b);
+ mpz_init(v);
+ mpz_init(t1);
+ mpz_set_ui(t1, (unsigned long)time(NULL));
+ gmp_randseed(RNG, t1);
+ for (k = 2; k <= 128; k ++) {
+ for (i = 0; i < 10; i ++) {
+ unsigned char ep[100], ea[100], eb[100], ev[100];
+ size_t plen, alen, blen, vlen;
+ uint32_t mp[40], ma[40], mb[40], mv[60], mx[100];
+ uint32_t mt1[40], mt2[40], mt3[40];
+ uint32_t ctl;
+ uint32_t mp0i;
+
+ rand_prime(p, k);
+ mpz_urandomm(a, RNG, p);
+ mpz_urandomm(b, RNG, p);
+ mpz_urandomb(v, RNG, k + 60);
+ if (mpz_sgn(b) == 0) {
+ mpz_set_ui(b, 1);
+ }
+ mpz_export(ep, &plen, 1, 1, 0, 0, p);
+ mpz_export(ea, &alen, 1, 1, 0, 0, a);
+ mpz_export(eb, &blen, 1, 1, 0, 0, b);
+ mpz_export(ev, &vlen, 1, 1, 0, 0, v);
+
+ impl->decode(mp, ep, plen);
+ if (impl->decode_mod(ma, ea, alen, mp) != 1) {
+ printf("Decode error\n");
+ printf(" ea = ");
+ print_z(a);
+ printf("\n");
+ printf(" p = ");
+ print_u(mp);
+ printf("\n");
+ exit(EXIT_FAILURE);
+ }
+ mp0i = impl->ninv(mp[1]);
+ if (impl->decode_mod(mb, eb, blen, mp) != 1) {
+ printf("Decode error\n");
+ printf(" eb = ");
+ print_z(b);
+ printf("\n");
+ printf(" p = ");
+ print_u(mp);
+ printf("\n");
+ exit(EXIT_FAILURE);
+ }
+ impl->decode(mv, ev, vlen);
+ check_eqz(mp, p);
+ check_eqz(ma, a);
+ check_eqz(mb, b);
+ check_eqz(mv, v);
+
+ impl->decode_mod(ma, ea, alen, mp);
+ impl->decode_mod(mb, eb, blen, mp);
+ ctl = impl->add(ma, mb, 1);
+ ctl |= impl->sub(ma, mp, 0) ^ (uint32_t)1;
+ impl->sub(ma, mp, ctl);
+ mpz_add(t1, a, b);
+ mpz_mod(t1, t1, p);
+ check_eqz(ma, t1);
+
+ impl->decode_mod(ma, ea, alen, mp);
+ impl->decode_mod(mb, eb, blen, mp);
+ impl->add(ma, mp, impl->sub(ma, mb, 1));
+ mpz_sub(t1, a, b);
+ mpz_mod(t1, t1, p);
+ check_eqz(ma, t1);
+
+ impl->decode_reduce(ma, ev, vlen, mp);
+ mpz_mod(t1, v, p);
+ check_eqz(ma, t1);
+
+ impl->decode(mv, ev, vlen);
+ impl->reduce(ma, mv, mp);
+ mpz_mod(t1, v, p);
+ check_eqz(ma, t1);
+
+ impl->decode_mod(ma, ea, alen, mp);
+ impl->to_monty(ma, mp);
+ mpz_mul_2exp(t1, a, ((k + impl->word_size - 1)
+ / impl->word_size) * impl->word_size);
+ mpz_mod(t1, t1, p);
+ check_eqz(ma, t1);
+ impl->from_monty(ma, mp, mp0i);
+ check_eqz(ma, a);
+
+ impl->decode_mod(ma, ea, alen, mp);
+ impl->decode_mod(mb, eb, blen, mp);
+ impl->to_monty(ma, mp);
+ impl->montymul(mt1, ma, mb, mp, mp0i);
+ mpz_mul(t1, a, b);
+ mpz_mod(t1, t1, p);
+ check_eqz(mt1, t1);
+
+ impl->decode_mod(ma, ea, alen, mp);
+ impl->modpow(ma, ev, vlen, mp, mp0i, mt1, mt2);
+ mpz_powm(t1, a, v, p);
+ check_eqz(ma, t1);
+
+ /*
+ br_modint_decode(ma, mp, ea, alen);
+ br_modint_decode(mb, mp, eb, blen);
+ if (!br_modint_div(ma, mb, mp, mt1, mt2, mt3)) {
+ fprintf(stderr, "division failed\n");
+ exit(EXIT_FAILURE);
+ }
+ mpz_sub_ui(t1, p, 2);
+ mpz_powm(t1, b, t1, p);
+ mpz_mul(t1, a, t1);
+ mpz_mod(t1, t1, p);
+ check_eqz(ma, t1);
+
+ br_modint_decode(ma, mp, ea, alen);
+ br_modint_decode(mb, mp, eb, blen);
+ for (j = 0; j <= (2 * k + 5); j ++) {
+ br_int_add(mx, j, ma, mb);
+ mpz_add(t1, a, b);
+ mpz_tdiv_r_2exp(t1, t1, j);
+ check_eqz(mx, t1);
+
+ br_int_mul(mx, j, ma, mb);
+ mpz_mul(t1, a, b);
+ mpz_tdiv_r_2exp(t1, t1, j);
+ check_eqz(mx, t1);
+ }
+ */
+ }
+ printf(".");
+ fflush(stdout);
+ }
+ mpz_clear(p);
+ mpz_clear(a);
+ mpz_clear(b);
+ mpz_clear(v);
+ mpz_clear(t1);
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+
+#if 0
+static void
+test_RSA_core(void)
+{
+ int i, j, k;
+ mpz_t n, e, d, p, q, dp, dq, iq, t1, t2, phi;
+
+ printf("Test RSA core: ");
+ fflush(stdout);
+
+ gmp_randinit_mt(RNG);
+ mpz_init(n);
+ mpz_init(e);
+ mpz_init(d);
+ mpz_init(p);
+ mpz_init(q);
+ mpz_init(dp);
+ mpz_init(dq);
+ mpz_init(iq);
+ mpz_init(t1);
+ mpz_init(t2);
+ mpz_init(phi);
+ mpz_set_ui(t1, (unsigned long)time(NULL));
+ gmp_randseed(RNG, t1);
+
+ /*
+ * To test corner cases, we want to try RSA keys such that the
+ * lengths of both factors can be arbitrary modulo 2^32. Factors
+ * p and q need not be of the same length; p can be greater than
+ * q and q can be greater than p.
+ *
+ * To keep computation time reasonable, we use p and q factors of
+ * less than 128 bits; this is way too small for secure RSA,
+ * but enough to exercise all code paths (since we work only with
+ * 32-bit words).
+ */
+ for (i = 64; i <= 96; i ++) {
+ rand_prime(p, i);
+ for (j = i - 33; j <= i + 33; j ++) {
+ uint32_t mp[40], mq[40], mdp[40], mdq[40], miq[40];
+
+ /*
+ * Generate a RSA key pair, with p of length i bits,
+ * and q of length j bits.
+ */
+ do {
+ rand_prime(q, j);
+ } while (mpz_cmp(p, q) == 0);
+ mpz_mul(n, p, q);
+ mpz_set_ui(e, 65537);
+ mpz_sub_ui(t1, p, 1);
+ mpz_sub_ui(t2, q, 1);
+ mpz_mul(phi, t1, t2);
+ mpz_invert(d, e, phi);
+ mpz_mod(dp, d, t1);
+ mpz_mod(dq, d, t2);
+ mpz_invert(iq, q, p);
+
+ /*
+ * Convert the key pair elements to BearSSL arrays.
+ */
+ mp_to_br(mp, mpz_sizeinbase(p, 2), p);
+ mp_to_br(mq, mpz_sizeinbase(q, 2), q);
+ mp_to_br(mdp, mpz_sizeinbase(dp, 2), dp);
+ mp_to_br(mdq, mpz_sizeinbase(dq, 2), dq);
+ mp_to_br(miq, mp[0], iq);
+
+ /*
+ * Compute and check ten public/private operations.
+ */
+ for (k = 0; k < 10; k ++) {
+ uint32_t mx[40];
+
+ mpz_urandomm(t1, RNG, n);
+ mpz_powm(t2, t1, e, n);
+ mp_to_br(mx, mpz_sizeinbase(n, 2), t2);
+ br_rsa_private_core(mx, mp, mq, mdp, mdq, miq);
+ check_eqz(mx, t1);
+ }
+ }
+ printf(".");
+ fflush(stdout);
+ }
+
+ printf(" done.\n");
+ fflush(stdout);
+}
+#endif
+
+int
+main(void)
+{
+ printf("===== i32 ======\n");
+ impl = &i32_impl;
+ test_modint();
+ printf("===== i31 ======\n");
+ impl = &i31_impl;
+ test_modint();
+ /*
+ test_RSA_core();
+ */
+ return 0;
+}
Property changes on: stable/12/contrib/bearssl/test/test_math.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/test_speed.c
===================================================================
--- stable/12/contrib/bearssl/test/test_speed.c (nonexistent)
+++ stable/12/contrib/bearssl/test/test_speed.c (revision 346145)
@@ -0,0 +1,1772 @@
+/*
+ * 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 <time.h>
+#include "inner.h"
+
+#define HASH_SIZE(cname) br_ ## cname ## _SIZE
+
+#define SPEED_HASH(Name, cname) \
+static void \
+test_speed_ ## cname(void) \
+{ \
+ unsigned char buf[8192]; \
+ unsigned char tmp[HASH_SIZE(cname)]; \
+ br_ ## cname ## _context mc; \
+ int i; \
+ long num; \
+ \
+ memset(buf, 'T', sizeof buf); \
+ for (i = 0; i < 10; i ++) { \
+ br_ ## cname ## _init(&mc); \
+ br_ ## cname ## _update(&mc, buf, sizeof buf); \
+ br_ ## cname ## _out(&mc, tmp); \
+ } \
+ num = 10; \
+ for (;;) { \
+ clock_t begin, end; \
+ double tt; \
+ long k; \
+ \
+ br_ ## cname ## _init(&mc); \
+ begin = clock(); \
+ for (k = num; k > 0; k --) { \
+ br_ ## cname ## _update(&mc, buf, sizeof buf); \
+ } \
+ end = clock(); \
+ br_ ## cname ## _out(&mc, tmp); \
+ tt = (double)(end - begin) / CLOCKS_PER_SEC; \
+ if (tt >= 2.0) { \
+ printf("%-30s %8.2f MB/s\n", #Name, \
+ ((double)sizeof buf) * (double)num \
+ / (tt * 1000000.0)); \
+ fflush(stdout); \
+ return; \
+ } \
+ num <<= 1; \
+ } \
+}
+
+#define BLOCK_SIZE(cname) br_ ## cname ## _BLOCK_SIZE
+
+#define SPEED_BLOCKCIPHER_CBC(Name, fname, cname, klen, dir) \
+static void \
+test_speed_ ## fname(void) \
+{ \
+ unsigned char key[klen]; \
+ unsigned char buf[8192 - (8192 % BLOCK_SIZE(cname))]; \
+ unsigned char iv[BLOCK_SIZE(cname)]; \
+ const br_block_cbc ## dir ## _class *vt; \
+ br_ ## cname ## _cbc ## dir ## _keys ec; \
+ int i; \
+ long num; \
+ \
+ memset(key, 'T', sizeof key); \
+ memset(buf, 'P', sizeof buf); \
+ memset(iv, 'X', sizeof iv); \
+ vt = br_ ## cname ## _cbc ## dir ## _get_vtable(); \
+ if (vt == NULL) { \
+ printf("%-30s UNAVAILABLE\n", #Name); \
+ fflush(stdout); \
+ return; \
+ } \
+ for (i = 0; i < 10; i ++) { \
+ vt->init(&ec.vtable, key, sizeof key); \
+ vt->run(&ec.vtable, iv, buf, sizeof buf); \
+ } \
+ num = 10; \
+ for (;;) { \
+ clock_t begin, end; \
+ double tt; \
+ long k; \
+ \
+ vt->init(&ec.vtable, key, sizeof key); \
+ begin = clock(); \
+ for (k = num; k > 0; k --) { \
+ vt->run(&ec.vtable, iv, buf, sizeof buf); \
+ } \
+ end = clock(); \
+ tt = (double)(end - begin) / CLOCKS_PER_SEC; \
+ if (tt >= 2.0) { \
+ printf("%-30s %8.2f MB/s\n", #Name, \
+ ((double)sizeof buf) * (double)num \
+ / (tt * 1000000.0)); \
+ fflush(stdout); \
+ return; \
+ } \
+ num <<= 1; \
+ } \
+}
+
+#define SPEED_BLOCKCIPHER_CTR(Name, fname, cname, klen) \
+static void \
+test_speed_ ## fname(void) \
+{ \
+ unsigned char key[klen]; \
+ unsigned char buf[8192 - (8192 % BLOCK_SIZE(cname))]; \
+ unsigned char iv[BLOCK_SIZE(cname) - 4]; \
+ const br_block_ctr_class *vt; \
+ br_ ## cname ## _ctr_keys ec; \
+ int i; \
+ long num; \
+ \
+ memset(key, 'T', sizeof key); \
+ memset(buf, 'P', sizeof buf); \
+ memset(iv, 'X', sizeof iv); \
+ vt = br_ ## cname ## _ctr_get_vtable(); \
+ if (vt == NULL) { \
+ printf("%-30s UNAVAILABLE\n", #Name); \
+ fflush(stdout); \
+ return; \
+ } \
+ for (i = 0; i < 10; i ++) { \
+ vt->init(&ec.vtable, key, sizeof key); \
+ vt->run(&ec.vtable, iv, 1, buf, sizeof buf); \
+ } \
+ num = 10; \
+ for (;;) { \
+ clock_t begin, end; \
+ double tt; \
+ long k; \
+ \
+ vt->init(&ec.vtable, key, sizeof key); \
+ begin = clock(); \
+ for (k = num; k > 0; k --) { \
+ vt->run(&ec.vtable, iv, 1, buf, sizeof buf); \
+ } \
+ end = clock(); \
+ tt = (double)(end - begin) / CLOCKS_PER_SEC; \
+ if (tt >= 2.0) { \
+ printf("%-30s %8.2f MB/s\n", #Name, \
+ ((double)sizeof buf) * (double)num \
+ / (tt * 1000000.0)); \
+ fflush(stdout); \
+ return; \
+ } \
+ num <<= 1; \
+ } \
+}
+
+#define SPEED_CHACHA20(Name, fname) \
+static void \
+test_speed_ ## fname(void) \
+{ \
+ br_chacha20_run bc; \
+ unsigned char key[32]; \
+ unsigned char buf[8192]; \
+ unsigned char iv[12]; \
+ int i; \
+ long num; \
+ \
+ bc = br_ ## fname ## _get(); \
+ if (bc == 0) { \
+ printf("%-30s UNAVAILABLE\n", #Name); \
+ fflush(stdout); \
+ return; \
+ } \
+ memset(key, 'T', sizeof key); \
+ memset(buf, 'P', sizeof buf); \
+ memset(iv, 'X', sizeof iv); \
+ for (i = 0; i < 10; i ++) { \
+ bc(key, iv, i, buf, sizeof buf); \
+ } \
+ num = 10; \
+ for (;;) { \
+ clock_t begin, end; \
+ double tt; \
+ long k; \
+ \
+ begin = clock(); \
+ for (k = num; k > 0; k --) { \
+ bc(key, iv, (uint32_t)k, buf, sizeof buf); \
+ } \
+ end = clock(); \
+ tt = (double)(end - begin) / CLOCKS_PER_SEC; \
+ if (tt >= 2.0) { \
+ printf("%-30s %8.2f MB/s\n", #Name, \
+ ((double)sizeof buf) * (double)num \
+ / (tt * 1000000.0)); \
+ fflush(stdout); \
+ return; \
+ } \
+ num <<= 1; \
+ } \
+}
+
+SPEED_HASH(MD5, md5)
+SPEED_HASH(SHA-1, sha1)
+SPEED_HASH(SHA-256, sha256)
+SPEED_HASH(SHA-512, sha512)
+
+/*
+ * There are no vtable selection functions for the portable implementations,
+ * so we define some custom macros.
+ */
+#define br_aes_big_cbcenc_get_vtable() (&br_aes_big_cbcenc_vtable)
+#define br_aes_big_cbcdec_get_vtable() (&br_aes_big_cbcdec_vtable)
+#define br_aes_big_ctr_get_vtable() (&br_aes_big_ctr_vtable)
+#define br_aes_big_ctrcbc_get_vtable() (&br_aes_big_ctrcbc_vtable)
+#define br_aes_small_cbcenc_get_vtable() (&br_aes_small_cbcenc_vtable)
+#define br_aes_small_cbcdec_get_vtable() (&br_aes_small_cbcdec_vtable)
+#define br_aes_small_ctr_get_vtable() (&br_aes_small_ctr_vtable)
+#define br_aes_small_ctrcbc_get_vtable() (&br_aes_small_ctrcbc_vtable)
+#define br_aes_ct_cbcenc_get_vtable() (&br_aes_ct_cbcenc_vtable)
+#define br_aes_ct_cbcdec_get_vtable() (&br_aes_ct_cbcdec_vtable)
+#define br_aes_ct_ctr_get_vtable() (&br_aes_ct_ctr_vtable)
+#define br_aes_ct_ctrcbc_get_vtable() (&br_aes_ct_ctrcbc_vtable)
+#define br_aes_ct64_cbcenc_get_vtable() (&br_aes_ct64_cbcenc_vtable)
+#define br_aes_ct64_cbcdec_get_vtable() (&br_aes_ct64_cbcdec_vtable)
+#define br_aes_ct64_ctr_get_vtable() (&br_aes_ct64_ctr_vtable)
+#define br_aes_ct64_ctrcbc_get_vtable() (&br_aes_ct64_ctrcbc_vtable)
+#define br_chacha20_ct_get() (&br_chacha20_ct_run)
+
+#define SPEED_AES(iname) \
+SPEED_BLOCKCIPHER_CBC(AES-128 CBC encrypt (iname), aes128_ ## iname ## _cbcenc, aes_ ## iname, 16, enc) \
+SPEED_BLOCKCIPHER_CBC(AES-128 CBC decrypt (iname), aes128_ ## iname ## _cbcdec, aes_ ## iname, 16, dec) \
+SPEED_BLOCKCIPHER_CBC(AES-192 CBC encrypt (iname), aes192_ ## iname ## _cbcenc, aes_ ## iname, 24, enc) \
+SPEED_BLOCKCIPHER_CBC(AES-192 CBC decrypt (iname), aes192_ ## iname ## _cbcdec, aes_ ## iname, 24, dec) \
+SPEED_BLOCKCIPHER_CBC(AES-256 CBC encrypt (iname), aes256_ ## iname ## _cbcenc, aes_ ## iname, 32, enc) \
+SPEED_BLOCKCIPHER_CBC(AES-256 CBC decrypt (iname), aes256_ ## iname ## _cbcdec, aes_ ## iname, 32, dec) \
+SPEED_BLOCKCIPHER_CTR(AES-128 CTR (iname), aes128_ ## iname ## _ctr, aes_ ## iname, 16) \
+SPEED_BLOCKCIPHER_CTR(AES-192 CTR (iname), aes192_ ## iname ## _ctr, aes_ ## iname, 24) \
+SPEED_BLOCKCIPHER_CTR(AES-256 CTR (iname), aes256_ ## iname ## _ctr, aes_ ## iname, 32)
+
+SPEED_AES(big)
+SPEED_AES(small)
+SPEED_AES(ct)
+SPEED_AES(ct64)
+SPEED_AES(x86ni)
+SPEED_AES(pwr8)
+
+#define br_des_tab_cbcenc_get_vtable() (&br_des_tab_cbcenc_vtable)
+#define br_des_tab_cbcdec_get_vtable() (&br_des_tab_cbcdec_vtable)
+#define br_des_ct_cbcenc_get_vtable() (&br_des_ct_cbcenc_vtable)
+#define br_des_ct_cbcdec_get_vtable() (&br_des_ct_cbcdec_vtable)
+
+#define SPEED_DES(iname) \
+SPEED_BLOCKCIPHER_CBC(DES CBC encrypt (iname), des_ ## iname ## _cbcenc, des_ ## iname, 8, enc) \
+SPEED_BLOCKCIPHER_CBC(DES CBC decrypt (iname), des_ ## iname ## _cbcdec, des_ ## iname, 8, dec) \
+SPEED_BLOCKCIPHER_CBC(3DES CBC encrypt (iname), 3des_ ## iname ## _cbcenc, des_ ## iname, 24, enc) \
+SPEED_BLOCKCIPHER_CBC(3DES CBC decrypt (iname), 3des_ ## iname ## _cbcdec, des_ ## iname, 24, dec)
+
+SPEED_DES(tab)
+SPEED_DES(ct)
+
+SPEED_CHACHA20(ChaCha20 (ct), chacha20_ct)
+SPEED_CHACHA20(ChaCha20 (sse2), chacha20_sse2)
+
+static void
+test_speed_ghash_inner(char *name, br_ghash gh)
+{
+ unsigned char buf[8192], h[16], y[16];
+ int i;
+ long num;
+
+ memset(buf, 'T', sizeof buf);
+ memset(h, 'P', sizeof h);
+ memset(y, 0, sizeof y);
+ for (i = 0; i < 10; i ++) {
+ gh(y, h, buf, sizeof buf);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ gh(y, h, buf, sizeof buf);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f MB/s\n", name,
+ ((double)sizeof buf) * (double)num
+ / (tt * 1000000.0));
+ fflush(stdout);
+ return;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_ghash_ctmul(void)
+{
+ test_speed_ghash_inner("GHASH (ctmul)", &br_ghash_ctmul);
+}
+
+static void
+test_speed_ghash_ctmul32(void)
+{
+ test_speed_ghash_inner("GHASH (ctmul32)", &br_ghash_ctmul32);
+}
+
+static void
+test_speed_ghash_ctmul64(void)
+{
+ test_speed_ghash_inner("GHASH (ctmul64)", &br_ghash_ctmul64);
+}
+
+static void
+test_speed_ghash_pclmul(void)
+{
+ br_ghash gh;
+
+ gh = br_ghash_pclmul_get();
+ if (gh == 0) {
+ printf("%-30s UNAVAILABLE\n", "GHASH (pclmul)");
+ fflush(stdout);
+ } else {
+ test_speed_ghash_inner("GHASH (pclmul)", gh);
+ }
+}
+
+static void
+test_speed_ghash_pwr8(void)
+{
+ br_ghash gh;
+
+ gh = br_ghash_pwr8_get();
+ if (gh == 0) {
+ printf("%-30s UNAVAILABLE\n", "GHASH (pwr8)");
+ fflush(stdout);
+ } else {
+ test_speed_ghash_inner("GHASH (pwr8)", gh);
+ }
+}
+
+static uint32_t
+fake_chacha20(const void *key, const void *iv,
+ uint32_t cc, void *data, size_t len)
+{
+ (void)key;
+ (void)iv;
+ (void)data;
+ (void)len;
+ return cc + (uint32_t)((len + 63) >> 6);
+}
+
+/*
+ * To speed-test Poly1305, we run it with a do-nothing stub instead of
+ * ChaCha20.
+ */
+static void
+test_speed_poly1305_inner(char *name, br_poly1305_run pl)
+{
+ unsigned char buf[8192], key[32], iv[12], aad[13], tag[16];
+ int i;
+ long num;
+
+ memset(key, 'K', sizeof key);
+ memset(iv, 'I', sizeof iv);
+ memset(aad, 'A', sizeof aad);
+ memset(buf, 'T', sizeof buf);
+ for (i = 0; i < 10; i ++) {
+ pl(key, iv, buf, sizeof buf,
+ aad, sizeof aad, tag, &fake_chacha20, 0);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ pl(key, iv, buf, sizeof buf,
+ aad, sizeof aad, tag, &fake_chacha20, 0);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f MB/s\n", name,
+ ((double)sizeof buf) * (double)num
+ / (tt * 1000000.0));
+ fflush(stdout);
+ return;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_poly1305_ctmul(void)
+{
+ test_speed_poly1305_inner("Poly1305 (ctmul)", &br_poly1305_ctmul_run);
+}
+
+static void
+test_speed_poly1305_ctmul32(void)
+{
+ test_speed_poly1305_inner("Poly1305 (ctmul32)",
+ &br_poly1305_ctmul32_run);
+}
+
+static void
+test_speed_poly1305_ctmulq(void)
+{
+ br_poly1305_run bp;
+
+ bp = br_poly1305_ctmulq_get();
+ if (bp == 0) {
+ printf("%-30s UNAVAILABLE\n", "Poly1305 (ctmulq)");
+ } else {
+ test_speed_poly1305_inner("Poly1305 (ctmulq)", bp);
+ }
+}
+
+static void
+test_speed_poly1305_i15(void)
+{
+ test_speed_poly1305_inner("Poly1305 (i15)", &br_poly1305_i15_run);
+}
+
+static void
+test_speed_eax_inner(char *name,
+ const br_block_ctrcbc_class *vt, size_t key_len)
+{
+ unsigned char buf[8192], key[32], nonce[16], aad[16], tag[16];
+ int i;
+ long num;
+ br_aes_gen_ctrcbc_keys ac;
+ br_eax_context ec;
+
+ if (vt == NULL) {
+ printf("%-30s UNAVAILABLE\n", name);
+ fflush(stdout);
+ return;
+ }
+ memset(key, 'K', key_len);
+ memset(nonce, 'N', sizeof nonce);
+ memset(aad, 'A', sizeof aad);
+ memset(buf, 'T', sizeof buf);
+ for (i = 0; i < 10; i ++) {
+ vt->init(&ac.vtable, key, key_len);
+ br_eax_init(&ec, &ac.vtable);
+ br_eax_reset(&ec, nonce, sizeof nonce);
+ br_eax_aad_inject(&ec, aad, sizeof aad);
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 1, buf, sizeof buf);
+ br_eax_get_tag(&ec, tag);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ vt->init(&ac.vtable, key, key_len);
+ br_eax_init(&ec, &ac.vtable);
+ br_eax_reset(&ec, nonce, sizeof nonce);
+ br_eax_aad_inject(&ec, aad, sizeof aad);
+ br_eax_flip(&ec);
+ br_eax_run(&ec, 1, buf, sizeof buf);
+ br_eax_get_tag(&ec, tag);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f MB/s\n", name,
+ ((double)sizeof buf) * (double)num
+ / (tt * 1000000.0));
+ fflush(stdout);
+ return;
+ }
+ num <<= 1;
+ }
+}
+
+#define SPEED_EAX(Algo, algo, keysize, impl) \
+static void \
+test_speed_eax_ ## algo ## keysize ## _ ## impl(void) \
+{ \
+ test_speed_eax_inner("EAX " #Algo "-" #keysize "(" #impl ")", \
+ br_ ## algo ## _ ## impl ## _ctrcbc_get_vtable() \
+ , (keysize) >> 3); \
+}
+
+SPEED_EAX(AES, aes, 128, big)
+SPEED_EAX(AES, aes, 128, small)
+SPEED_EAX(AES, aes, 128, ct)
+SPEED_EAX(AES, aes, 128, ct64)
+SPEED_EAX(AES, aes, 128, x86ni)
+SPEED_EAX(AES, aes, 128, pwr8)
+SPEED_EAX(AES, aes, 192, big)
+SPEED_EAX(AES, aes, 192, small)
+SPEED_EAX(AES, aes, 192, ct)
+SPEED_EAX(AES, aes, 192, ct64)
+SPEED_EAX(AES, aes, 192, x86ni)
+SPEED_EAX(AES, aes, 192, pwr8)
+SPEED_EAX(AES, aes, 256, big)
+SPEED_EAX(AES, aes, 256, small)
+SPEED_EAX(AES, aes, 256, ct)
+SPEED_EAX(AES, aes, 256, ct64)
+SPEED_EAX(AES, aes, 256, x86ni)
+SPEED_EAX(AES, aes, 256, pwr8)
+
+static void
+test_speed_shake_inner(int security_level)
+{
+ unsigned char buf[8192];
+ br_shake_context sc;
+ int i;
+ long num;
+
+ memset(buf, 'D', sizeof buf);
+ br_shake_init(&sc, security_level);
+ for (i = 0; i < 10; i ++) {
+ br_shake_inject(&sc, buf, sizeof buf);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_shake_inject(&sc, buf, sizeof buf);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("SHAKE%-3d (inject) %8.2f MB/s\n",
+ security_level,
+ ((double)sizeof buf) * (double)num
+ / (tt * 1000000.0));
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+
+ br_shake_flip(&sc);
+ for (i = 0; i < 10; i ++) {
+ br_shake_produce(&sc, buf, sizeof buf);
+ }
+
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_shake_produce(&sc, buf, sizeof buf);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("SHAKE%-3d (produce) %8.2f MB/s\n",
+ security_level,
+ ((double)sizeof buf) * (double)num
+ / (tt * 1000000.0));
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_shake128(void)
+{
+ test_speed_shake_inner(128);
+}
+
+static void
+test_speed_shake256(void)
+{
+ test_speed_shake_inner(256);
+}
+
+static const unsigned char RSA_N[] = {
+ 0xE9, 0xF2, 0x4A, 0x2F, 0x96, 0xDF, 0x0A, 0x23,
+ 0x01, 0x85, 0xF1, 0x2C, 0xB2, 0xA8, 0xEF, 0x23,
+ 0xCE, 0x2E, 0xB0, 0x4E, 0x18, 0x31, 0x95, 0x5B,
+ 0x98, 0x2D, 0x9B, 0x8C, 0xE3, 0x1A, 0x2B, 0x96,
+ 0xB5, 0xC7, 0xEE, 0xED, 0x72, 0x43, 0x2D, 0xFE,
+ 0x7F, 0x61, 0x33, 0xEA, 0x14, 0xFC, 0xDE, 0x80,
+ 0x17, 0x42, 0xF0, 0xF3, 0xC3, 0xC7, 0x89, 0x47,
+ 0x76, 0x5B, 0xFA, 0x33, 0xC4, 0x8C, 0x94, 0xDE,
+ 0x6A, 0x75, 0xD8, 0x1A, 0xF4, 0x49, 0xBC, 0xF3,
+ 0xB7, 0x9E, 0x2C, 0x8D, 0xEC, 0x5A, 0xEE, 0xBF,
+ 0x4B, 0x5A, 0x7F, 0xEF, 0x21, 0x39, 0xDB, 0x1D,
+ 0x83, 0x5E, 0x7E, 0x2F, 0xAA, 0x5E, 0xBA, 0x28,
+ 0xC3, 0xA2, 0x53, 0x19, 0xFB, 0x2F, 0x78, 0x6B,
+ 0x14, 0x60, 0x49, 0x3C, 0xCC, 0x1B, 0xE9, 0x1E,
+ 0x3D, 0x10, 0xA4, 0xEB, 0x7F, 0x66, 0x98, 0xF6,
+ 0xC3, 0xAC, 0x35, 0xF5, 0x01, 0x84, 0xFF, 0x7D,
+ 0x1F, 0x72, 0xBE, 0xB4, 0xD1, 0x89, 0xC8, 0xDD,
+ 0x44, 0xE7, 0xB5, 0x2E, 0x2C, 0xE1, 0x85, 0xF5,
+ 0x15, 0x50, 0xA9, 0x08, 0xC7, 0x67, 0xD9, 0x2B,
+ 0x6C, 0x11, 0xB3, 0xEB, 0x28, 0x8D, 0xF4, 0xCC,
+ 0xE3, 0xC3, 0xC5, 0x04, 0x0E, 0x7C, 0x8D, 0xDB,
+ 0x39, 0x06, 0x6A, 0x74, 0x75, 0xDF, 0xA8, 0x0F,
+ 0xDA, 0x67, 0x5A, 0x73, 0x1E, 0xFD, 0x8E, 0x4C,
+ 0xEE, 0x17, 0xEE, 0x1E, 0x67, 0xDB, 0x98, 0x70,
+ 0x60, 0xF7, 0xB9, 0xB5, 0x1F, 0x19, 0x93, 0xD6,
+ 0x3F, 0x2F, 0x1F, 0xB6, 0x5B, 0x59, 0xAA, 0x85,
+ 0xBB, 0x25, 0xE4, 0x13, 0xEF, 0xE7, 0xB9, 0x87,
+ 0x9C, 0x3F, 0x5E, 0xE4, 0x08, 0xA3, 0x51, 0xCF,
+ 0x8B, 0xAD, 0xF4, 0xE6, 0x1A, 0x5F, 0x51, 0xDD,
+ 0xA8, 0xBE, 0xE8, 0xD1, 0x20, 0x19, 0x61, 0x6C,
+ 0x18, 0xAB, 0xCA, 0x0A, 0xD9, 0x82, 0xA6, 0x94,
+ 0xD5, 0x69, 0x2A, 0xF6, 0x43, 0x66, 0x31, 0x09
+};
+
+static const unsigned char RSA_E[] = {
+ 0x01, 0x00, 0x01
+};
+
+static const unsigned char RSA_P[] = {
+ 0xFD, 0x39, 0x40, 0x56, 0x20, 0x80, 0xC5, 0x81,
+ 0x4C, 0x5F, 0x0C, 0x1A, 0x52, 0x84, 0x03, 0x2F,
+ 0xCE, 0x82, 0xB0, 0xD8, 0x30, 0x23, 0x7F, 0x77,
+ 0x45, 0xC2, 0x01, 0xC4, 0x68, 0x96, 0x0D, 0xA7,
+ 0x22, 0xA9, 0x6C, 0xA9, 0x1A, 0x33, 0xE5, 0x2F,
+ 0xB5, 0x07, 0x9A, 0xF9, 0xEA, 0x33, 0xA5, 0xC8,
+ 0x96, 0x60, 0x6A, 0xCA, 0xEB, 0xE5, 0x6E, 0x09,
+ 0x46, 0x7E, 0x2D, 0xEF, 0x93, 0x7D, 0x56, 0xED,
+ 0x75, 0x70, 0x3B, 0x96, 0xC4, 0xD5, 0xDB, 0x0B,
+ 0x3F, 0x69, 0xDF, 0x06, 0x18, 0x76, 0xF4, 0xCF,
+ 0xF8, 0x84, 0x22, 0xDF, 0xBD, 0x71, 0x62, 0x7B,
+ 0x67, 0x99, 0xBC, 0x09, 0x95, 0x54, 0xA4, 0x98,
+ 0x83, 0xF5, 0xA9, 0xCF, 0x09, 0xA5, 0x1F, 0x61,
+ 0x25, 0xB4, 0x70, 0x6C, 0x91, 0xB8, 0xB3, 0xD0,
+ 0xCE, 0x9C, 0x45, 0x65, 0x9B, 0xEF, 0xD4, 0x70,
+ 0xBE, 0x86, 0xD2, 0x98, 0x5D, 0xEB, 0xE3, 0xFF
+};
+
+static const unsigned char RSA_Q[] = {
+ 0xEC, 0x82, 0xEE, 0x63, 0x5F, 0x40, 0x52, 0xDB,
+ 0x38, 0x7A, 0x37, 0x6A, 0x54, 0x5B, 0xD9, 0xA0,
+ 0x73, 0xB4, 0xBB, 0x52, 0xB2, 0x84, 0x07, 0xD0,
+ 0xCC, 0x82, 0x0D, 0x20, 0xB3, 0xFA, 0xD5, 0xB6,
+ 0x25, 0x92, 0x35, 0x4D, 0xB4, 0xC7, 0x36, 0x48,
+ 0xCE, 0x5E, 0x21, 0x4A, 0xA6, 0x74, 0x65, 0xF4,
+ 0x7D, 0x1D, 0xBC, 0x3B, 0xE2, 0xF4, 0x3E, 0x11,
+ 0x58, 0x10, 0x6C, 0x04, 0x46, 0x9E, 0x8D, 0x57,
+ 0xE0, 0x04, 0xE2, 0xEC, 0x47, 0xCF, 0xB3, 0x2A,
+ 0xFD, 0x4C, 0x55, 0x18, 0xDB, 0xDE, 0x3B, 0xDC,
+ 0xF4, 0x5B, 0xDA, 0xF3, 0x1A, 0xC8, 0x41, 0x6F,
+ 0x73, 0x3B, 0xFE, 0x3C, 0xA0, 0xDB, 0xBA, 0x6E,
+ 0x65, 0xA5, 0xE8, 0x02, 0xA5, 0x6C, 0xEA, 0x03,
+ 0xF6, 0x99, 0xF7, 0xCB, 0x4B, 0xB7, 0x11, 0x51,
+ 0x93, 0x88, 0x3F, 0xF9, 0x06, 0x85, 0xA9, 0x1E,
+ 0xCA, 0x64, 0xF8, 0x11, 0xA5, 0x1A, 0xCA, 0xF7
+};
+
+static const unsigned char RSA_DP[] = {
+ 0x77, 0x95, 0xE0, 0x02, 0x4C, 0x9B, 0x43, 0xAA,
+ 0xCA, 0x4C, 0x60, 0xC4, 0xD5, 0x8F, 0x2E, 0x8A,
+ 0x17, 0x36, 0xB5, 0x19, 0x83, 0xB2, 0x5F, 0xF2,
+ 0x0D, 0xE9, 0x8F, 0x38, 0x18, 0x44, 0x34, 0xF2,
+ 0x67, 0x76, 0x27, 0xB0, 0xBC, 0x85, 0x21, 0x89,
+ 0x24, 0x2F, 0x11, 0x4B, 0x51, 0x05, 0x4F, 0x17,
+ 0xA9, 0x9C, 0xA3, 0x12, 0x6D, 0xD1, 0x0D, 0xE4,
+ 0x27, 0x7C, 0x53, 0x69, 0x3E, 0xF8, 0x04, 0x63,
+ 0x64, 0x00, 0xBA, 0xC3, 0x7A, 0xF5, 0x9B, 0xDA,
+ 0x75, 0xFA, 0x23, 0xAF, 0x17, 0x42, 0xA6, 0x5E,
+ 0xC8, 0xF8, 0x6E, 0x17, 0xC7, 0xB9, 0x92, 0x4E,
+ 0xC1, 0x20, 0x63, 0x23, 0x0B, 0x78, 0xCB, 0xBA,
+ 0x93, 0x27, 0x23, 0x28, 0x79, 0x5F, 0x97, 0xB0,
+ 0x23, 0x44, 0x51, 0x8B, 0x94, 0x4D, 0xEB, 0xED,
+ 0x82, 0x85, 0x5E, 0x68, 0x9B, 0xF9, 0xE9, 0x13,
+ 0xCD, 0x86, 0x92, 0x52, 0x0E, 0x98, 0xE6, 0x35
+};
+
+static const unsigned char RSA_DQ[] = {
+ 0xD8, 0xDD, 0x71, 0xB3, 0x62, 0xBA, 0xBB, 0x7E,
+ 0xD1, 0xF9, 0x96, 0xE8, 0x83, 0xB3, 0xB9, 0x08,
+ 0x9C, 0x30, 0x03, 0x77, 0xDF, 0xC2, 0x9A, 0xDC,
+ 0x05, 0x39, 0xD6, 0xC9, 0xBE, 0xDE, 0x68, 0xA9,
+ 0xDD, 0x27, 0x84, 0x82, 0xDD, 0x19, 0xB1, 0x97,
+ 0xEE, 0xCA, 0x77, 0x22, 0x59, 0x20, 0xEF, 0xFF,
+ 0xCF, 0xDD, 0xBD, 0x24, 0xF8, 0x84, 0xD6, 0x88,
+ 0xD6, 0xC4, 0x30, 0x17, 0x77, 0x9D, 0x98, 0xA3,
+ 0x14, 0x01, 0xC7, 0x05, 0xBB, 0x0F, 0x23, 0x0D,
+ 0x6F, 0x37, 0x57, 0xEC, 0x34, 0x67, 0x41, 0x62,
+ 0xE8, 0x19, 0x75, 0xD9, 0x66, 0x1C, 0x6B, 0x8B,
+ 0xC3, 0x11, 0x26, 0x9C, 0xF7, 0x2E, 0xA3, 0x72,
+ 0xE8, 0xF7, 0xC8, 0x96, 0xEC, 0x92, 0xC2, 0xBD,
+ 0xA1, 0x98, 0x2A, 0x93, 0x99, 0xB8, 0xA2, 0x43,
+ 0xB7, 0xD0, 0xBE, 0x40, 0x1C, 0x8F, 0xE0, 0xB4,
+ 0x20, 0x07, 0x97, 0x43, 0xAE, 0xAD, 0xB3, 0x9F
+};
+
+static const unsigned char RSA_IQ[] = {
+ 0xB7, 0xE2, 0x60, 0xA9, 0x62, 0xEC, 0xEC, 0x0B,
+ 0x57, 0x02, 0x96, 0xF9, 0x36, 0x35, 0x2C, 0x37,
+ 0xAF, 0xC2, 0xEE, 0x71, 0x49, 0x26, 0x8E, 0x0F,
+ 0x27, 0xB1, 0xFA, 0x0F, 0xEA, 0xDC, 0xF0, 0x8B,
+ 0x53, 0x6C, 0xB2, 0x46, 0x27, 0xCD, 0x29, 0xA2,
+ 0x35, 0x0F, 0x5D, 0x8A, 0x3F, 0x20, 0x8C, 0x13,
+ 0x3D, 0xA1, 0xFF, 0x85, 0x91, 0x99, 0xE8, 0x50,
+ 0xED, 0xF1, 0x29, 0x00, 0xEE, 0x24, 0x90, 0xB5,
+ 0x5F, 0x3A, 0x74, 0x26, 0xD7, 0xA2, 0x24, 0x8D,
+ 0x89, 0x88, 0xD8, 0x35, 0x22, 0x22, 0x8A, 0x66,
+ 0x5D, 0x5C, 0xDE, 0x83, 0x8C, 0xFA, 0x27, 0xE6,
+ 0xB9, 0xEB, 0x72, 0x08, 0xCD, 0x53, 0x4B, 0x93,
+ 0x0F, 0xAD, 0xC3, 0xF8, 0x7C, 0xFE, 0x84, 0xD7,
+ 0x08, 0xF3, 0xBE, 0x3D, 0x60, 0x1E, 0x95, 0x8D,
+ 0x44, 0x5B, 0x65, 0x7E, 0xC1, 0x30, 0xC3, 0x84,
+ 0xC0, 0xB0, 0xFE, 0xBF, 0x28, 0x54, 0x1E, 0xC4
+};
+
+static const br_rsa_public_key RSA_PK = {
+ (void *)RSA_N, sizeof RSA_N,
+ (void *)RSA_E, sizeof RSA_E
+};
+
+static const br_rsa_private_key RSA_SK = {
+ 2048,
+ (void *)RSA_P, sizeof RSA_P,
+ (void *)RSA_Q, sizeof RSA_Q,
+ (void *)RSA_DP, sizeof RSA_DP,
+ (void *)RSA_DQ, sizeof RSA_DQ,
+ (void *)RSA_IQ, sizeof RSA_IQ
+};
+
+static void
+test_speed_rsa_inner(char *name,
+ br_rsa_public fpub, br_rsa_private fpriv, br_rsa_keygen kgen)
+{
+ unsigned char tmp[sizeof RSA_N];
+ int i;
+ long num;
+ /*
+ br_hmac_drbg_context rng;
+ */
+ br_aesctr_drbg_context rng;
+ const br_block_ctr_class *ictr;
+
+ memset(tmp, 'R', sizeof tmp);
+ tmp[0] = 0;
+ for (i = 0; i < 10; i ++) {
+ if (!fpriv(tmp, &RSA_SK)) {
+ abort();
+ }
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ fpriv(tmp, &RSA_SK);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f priv/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+ for (i = 0; i < 10; i ++) {
+ if (!fpub(tmp, sizeof tmp, &RSA_PK)) {
+ abort();
+ }
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ fpub(tmp, sizeof tmp, &RSA_PK);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f pub/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+
+ if (kgen == 0) {
+ printf("%-30s KEYGEN UNAVAILABLE\n", name);
+ fflush(stdout);
+ return;
+ }
+ /*
+ br_hmac_drbg_init(&rng, &br_sha256_vtable, "RSA keygen seed", 15);
+ */
+ ictr = br_aes_x86ni_ctr_get_vtable();
+ if (ictr == NULL) {
+ ictr = br_aes_pwr8_ctr_get_vtable();
+ if (ictr == NULL) {
+#if BR_64
+ ictr = &br_aes_ct64_ctr_vtable;
+#else
+ ictr = &br_aes_ct_ctr_vtable;
+#endif
+ }
+ }
+ br_aesctr_drbg_init(&rng, ictr, "RSA keygen seed", 15);
+
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_rsa_private_key sk;
+ unsigned char kbuf[BR_RSA_KBUF_PRIV_SIZE(1024)];
+
+ kgen(&rng.vtable, &sk, kbuf, NULL, NULL, 1024, 0);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 10.0) {
+ printf("%-30s %8.2f kgen[1024]/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_rsa_private_key sk;
+ unsigned char kbuf[BR_RSA_KBUF_PRIV_SIZE(2048)];
+
+ kgen(&rng.vtable, &sk, kbuf, NULL, NULL, 2048, 0);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 10.0) {
+ printf("%-30s %8.2f kgen[2048]/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_rsa_i15(void)
+{
+ test_speed_rsa_inner("RSA i15",
+ &br_rsa_i15_public, &br_rsa_i15_private, &br_rsa_i15_keygen);
+}
+
+static void
+test_speed_rsa_i31(void)
+{
+ test_speed_rsa_inner("RSA i31",
+ &br_rsa_i31_public, &br_rsa_i31_private, &br_rsa_i31_keygen);
+}
+
+static void
+test_speed_rsa_i32(void)
+{
+ test_speed_rsa_inner("RSA i32",
+ &br_rsa_i32_public, &br_rsa_i32_private, 0);
+}
+
+static void
+test_speed_rsa_i62(void)
+{
+ br_rsa_public pub;
+ br_rsa_private priv;
+ br_rsa_keygen kgen;
+
+ pub = br_rsa_i62_public_get();
+ priv = br_rsa_i62_private_get();
+ kgen = br_rsa_i62_keygen_get();
+ if (pub) {
+ test_speed_rsa_inner("RSA i62", pub, priv, kgen);
+ } else {
+ printf("%-30s UNAVAILABLE\n", "RSA i62");
+ }
+}
+
+static void
+test_speed_ec_inner_1(const char *name,
+ const br_ec_impl *impl, const br_ec_curve_def *cd)
+{
+ unsigned char bx[80], U[160];
+ uint32_t x[22], n[22];
+ size_t nlen, ulen;
+ int i;
+ long num;
+
+ nlen = cd->order_len;
+ br_i31_decode(n, cd->order, nlen);
+ memset(bx, 'T', sizeof bx);
+ br_i31_decode_reduce(x, bx, sizeof bx, n);
+ br_i31_encode(bx, nlen, x);
+ ulen = cd->generator_len;
+ memcpy(U, cd->generator, ulen);
+ for (i = 0; i < 10; i ++) {
+ impl->mul(U, ulen, bx, nlen, cd->curve);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ impl->mul(U, ulen, bx, nlen, cd->curve);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f mul/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_ec_inner_2(const char *name,
+ const br_ec_impl *impl, const br_ec_curve_def *cd)
+{
+ unsigned char bx[80], U[160];
+ uint32_t x[22], n[22];
+ size_t nlen;
+ int i;
+ long num;
+
+ nlen = cd->order_len;
+ br_i31_decode(n, cd->order, nlen);
+ memset(bx, 'T', sizeof bx);
+ br_i31_decode_reduce(x, bx, sizeof bx, n);
+ br_i31_encode(bx, nlen, x);
+ for (i = 0; i < 10; i ++) {
+ impl->mulgen(U, bx, nlen, cd->curve);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ impl->mulgen(U, bx, nlen, cd->curve);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f mul/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_ec_inner(const char *name,
+ const br_ec_impl *impl, const br_ec_curve_def *cd)
+{
+ char tmp[50];
+
+ test_speed_ec_inner_1(name, impl, cd);
+ sprintf(tmp, "%s (FP)", name);
+ test_speed_ec_inner_2(tmp, impl, cd);
+}
+
+static void
+test_speed_ec_p256_m15(void)
+{
+ test_speed_ec_inner("EC p256_m15",
+ &br_ec_p256_m15, &br_secp256r1);
+}
+
+static void
+test_speed_ec_p256_m31(void)
+{
+ test_speed_ec_inner("EC p256_m31",
+ &br_ec_p256_m31, &br_secp256r1);
+}
+
+static void
+test_speed_ec_p256_m62(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_p256_m62_get();
+ if (ec != NULL) {
+ test_speed_ec_inner("EC p256_m62", ec, &br_secp256r1);
+ } else {
+ printf("%-30s UNAVAILABLE\n", "EC p256_m62");
+ }
+}
+
+static void
+test_speed_ec_p256_m64(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_p256_m64_get();
+ if (ec != NULL) {
+ test_speed_ec_inner("EC p256_m64", ec, &br_secp256r1);
+ } else {
+ printf("%-30s UNAVAILABLE\n", "EC p256_m64");
+ }
+}
+
+static void
+test_speed_ec_prime_i15(void)
+{
+ test_speed_ec_inner("EC prime_i15 P-256",
+ &br_ec_prime_i15, &br_secp256r1);
+ test_speed_ec_inner("EC prime_i15 P-384",
+ &br_ec_prime_i15, &br_secp384r1);
+ test_speed_ec_inner("EC prime_i15 P-521",
+ &br_ec_prime_i15, &br_secp521r1);
+}
+
+static void
+test_speed_ec_prime_i31(void)
+{
+ test_speed_ec_inner("EC prime_i31 P-256",
+ &br_ec_prime_i31, &br_secp256r1);
+ test_speed_ec_inner("EC prime_i31 P-384",
+ &br_ec_prime_i31, &br_secp384r1);
+ test_speed_ec_inner("EC prime_i31 P-521",
+ &br_ec_prime_i31, &br_secp521r1);
+}
+
+static void
+test_speed_ec_c25519_i15(void)
+{
+ test_speed_ec_inner("EC c25519_i15",
+ &br_ec_c25519_i15, &br_curve25519);
+}
+
+static void
+test_speed_ec_c25519_i31(void)
+{
+ test_speed_ec_inner("EC c25519_i31",
+ &br_ec_c25519_i31, &br_curve25519);
+}
+
+static void
+test_speed_ec_c25519_m15(void)
+{
+ test_speed_ec_inner("EC c25519_m15",
+ &br_ec_c25519_m15, &br_curve25519);
+}
+
+static void
+test_speed_ec_c25519_m31(void)
+{
+ test_speed_ec_inner("EC c25519_m31",
+ &br_ec_c25519_m31, &br_curve25519);
+}
+
+static void
+test_speed_ec_c25519_m62(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_c25519_m62_get();
+ if (ec != NULL) {
+ test_speed_ec_inner("EC c25519_m62", ec, &br_curve25519);
+ } else {
+ printf("%-30s UNAVAILABLE\n", "EC c25519_m62");
+ }
+}
+
+static void
+test_speed_ec_c25519_m64(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_c25519_m64_get();
+ if (ec != NULL) {
+ test_speed_ec_inner("EC c25519_m64", ec, &br_curve25519);
+ } else {
+ printf("%-30s UNAVAILABLE\n", "EC c25519_m64");
+ }
+}
+
+static void
+test_speed_ecdsa_inner(const char *name,
+ const br_ec_impl *impl, const br_ec_curve_def *cd,
+ br_ecdsa_sign sign, br_ecdsa_vrfy vrfy)
+{
+ unsigned char bx[80], U[160], hv[32], sig[160];
+ uint32_t x[22], n[22];
+ size_t nlen, ulen, sig_len;
+ int i;
+ long num;
+ br_ec_private_key sk;
+ br_ec_public_key pk;
+
+ nlen = cd->order_len;
+ br_i31_decode(n, cd->order, nlen);
+ memset(bx, 'T', sizeof bx);
+ br_i31_decode_reduce(x, bx, sizeof bx, n);
+ br_i31_encode(bx, nlen, x);
+ ulen = cd->generator_len;
+ memcpy(U, cd->generator, ulen);
+ impl->mul(U, ulen, bx, nlen, cd->curve);
+ sk.curve = cd->curve;
+ sk.x = bx;
+ sk.xlen = nlen;
+ pk.curve = cd->curve;
+ pk.q = U;
+ pk.qlen = ulen;
+
+ memset(hv, 'H', sizeof hv);
+ sig_len = sign(impl, &br_sha256_vtable, hv, &sk, sig);
+ if (vrfy(impl, hv, sizeof hv, &pk, sig, sig_len) != 1) {
+ fprintf(stderr, "self-test sign/verify failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (i = 0; i < 10; i ++) {
+ hv[1] ++;
+ sign(impl, &br_sha256_vtable, hv, &sk, sig);
+ vrfy(impl, hv, sizeof hv, &pk, sig, sig_len);
+ }
+
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ hv[1] ++;
+ sig_len = sign(impl, &br_sha256_vtable, hv, &sk, sig);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f sign/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ vrfy(impl, hv, sizeof hv, &pk, sig, sig_len);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f verify/s\n", name,
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_ecdsa_p256_m15(void)
+{
+ test_speed_ecdsa_inner("ECDSA m15 P-256",
+ &br_ec_p256_m15, &br_secp256r1,
+ &br_ecdsa_i15_sign_asn1,
+ &br_ecdsa_i15_vrfy_asn1);
+}
+
+static void
+test_speed_ecdsa_p256_m31(void)
+{
+ test_speed_ecdsa_inner("ECDSA m31 P-256",
+ &br_ec_p256_m31, &br_secp256r1,
+ &br_ecdsa_i31_sign_asn1,
+ &br_ecdsa_i31_vrfy_asn1);
+}
+
+static void
+test_speed_ecdsa_p256_m62(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_p256_m62_get();
+ if (ec != NULL) {
+ test_speed_ecdsa_inner("ECDSA m62 P-256",
+ ec, &br_secp256r1,
+ &br_ecdsa_i31_sign_asn1,
+ &br_ecdsa_i31_vrfy_asn1);
+ } else {
+ printf("%-30s UNAVAILABLE\n", "ECDSA m62 P-256");
+ }
+}
+
+static void
+test_speed_ecdsa_p256_m64(void)
+{
+ const br_ec_impl *ec;
+
+ ec = br_ec_p256_m64_get();
+ if (ec != NULL) {
+ test_speed_ecdsa_inner("ECDSA m64 P-256",
+ ec, &br_secp256r1,
+ &br_ecdsa_i31_sign_asn1,
+ &br_ecdsa_i31_vrfy_asn1);
+ } else {
+ printf("%-30s UNAVAILABLE\n", "ECDSA m64 P-256");
+ }
+}
+
+static void
+test_speed_ecdsa_i15(void)
+{
+ test_speed_ecdsa_inner("ECDSA i15 P-256",
+ &br_ec_prime_i15, &br_secp256r1,
+ &br_ecdsa_i15_sign_asn1,
+ &br_ecdsa_i15_vrfy_asn1);
+ test_speed_ecdsa_inner("ECDSA i15 P-384",
+ &br_ec_prime_i15, &br_secp384r1,
+ &br_ecdsa_i15_sign_asn1,
+ &br_ecdsa_i15_vrfy_asn1);
+ test_speed_ecdsa_inner("ECDSA i15 P-521",
+ &br_ec_prime_i15, &br_secp521r1,
+ &br_ecdsa_i15_sign_asn1,
+ &br_ecdsa_i15_vrfy_asn1);
+}
+
+static void
+test_speed_ecdsa_i31(void)
+{
+ test_speed_ecdsa_inner("ECDSA i31 P-256",
+ &br_ec_prime_i31, &br_secp256r1,
+ &br_ecdsa_i31_sign_asn1,
+ &br_ecdsa_i31_vrfy_asn1);
+ test_speed_ecdsa_inner("ECDSA i31 P-384",
+ &br_ec_prime_i31, &br_secp384r1,
+ &br_ecdsa_i31_sign_asn1,
+ &br_ecdsa_i31_vrfy_asn1);
+ test_speed_ecdsa_inner("ECDSA i31 P-521",
+ &br_ec_prime_i31, &br_secp521r1,
+ &br_ecdsa_i31_sign_asn1,
+ &br_ecdsa_i31_vrfy_asn1);
+}
+
+static void
+test_speed_i31(void)
+{
+ static const unsigned char bp[] = {
+ /* A 521-bit prime integer (order of the P-521 curve). */
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
+ 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
+ 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
+ 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
+ 0x64, 0x09
+ };
+
+ unsigned char tmp[60 + sizeof bp];
+ uint32_t p[20], x[20], y[20], z[20], uu[60], p0i;
+ int i;
+ long num;
+
+ br_i31_decode(p, bp, sizeof bp);
+ p0i = br_i31_ninv31(p[1]);
+ memset(tmp, 'T', sizeof tmp);
+ br_i31_decode_reduce(x, tmp, sizeof tmp, p);
+ memset(tmp, 'U', sizeof tmp);
+ br_i31_decode_reduce(y, tmp, sizeof tmp, p);
+
+ for (i = 0; i < 10; i ++) {
+ br_i31_to_monty(x, p);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_i31_to_monty(x, p);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f ops/s\n", "i31 to_monty",
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+
+ for (i = 0; i < 10; i ++) {
+ br_i31_from_monty(x, p, p0i);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_i31_from_monty(x, p, p0i);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f ops/s\n", "i31 from_monty",
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+
+ for (i = 0; i < 10; i ++) {
+ br_i31_montymul(z, x, y, p, p0i);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_i31_montymul(z, x, y, p, p0i);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f ops/s\n", "i31 montymul",
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+
+ for (i = 0; i < 10; i ++) {
+ br_i31_moddiv(x, y, p, p0i, uu);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_i31_moddiv(x, y, p, p0i, uu);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f ops/s\n", "i31 moddiv",
+ (double)num / tt);
+ fflush(stdout);
+ break;
+ }
+ num <<= 1;
+ }
+}
+
+#if 0
+
+static unsigned char P2048[] = {
+ 0xFD, 0xB6, 0xE0, 0x3E, 0x00, 0x49, 0x4C, 0xF0, 0x69, 0x3A, 0xDD, 0x7D,
+ 0xF8, 0xA2, 0x41, 0xB0, 0x6C, 0x67, 0xC5, 0xBA, 0xB8, 0x46, 0x80, 0xF5,
+ 0xBF, 0xAB, 0x98, 0xFC, 0x84, 0x73, 0xA5, 0x63, 0xC9, 0x52, 0x12, 0xDA,
+ 0x4C, 0xC1, 0x5B, 0x9D, 0x8D, 0xDF, 0xCD, 0xFE, 0xC5, 0xAD, 0x5A, 0x6F,
+ 0xDD, 0x02, 0xD9, 0xEC, 0x71, 0xEF, 0xEB, 0xB6, 0x95, 0xED, 0x94, 0x25,
+ 0x0E, 0x63, 0xDD, 0x6A, 0x52, 0xC7, 0x93, 0xAF, 0x85, 0x9D, 0x2C, 0xBE,
+ 0x5C, 0xBE, 0x35, 0xD8, 0xDD, 0x39, 0xEF, 0x1B, 0xB1, 0x49, 0x67, 0xB2,
+ 0x33, 0xC9, 0x7C, 0xE1, 0x51, 0x79, 0x51, 0x59, 0xCA, 0x6E, 0x2A, 0xDF,
+ 0x0D, 0x76, 0x1C, 0xE7, 0xA5, 0xC0, 0x1E, 0x6C, 0x56, 0x3A, 0x32, 0xE5,
+ 0xB5, 0xC5, 0xD4, 0xDB, 0xFE, 0xFF, 0xF8, 0xF2, 0x96, 0xA9, 0xC9, 0x65,
+ 0x59, 0x9E, 0x01, 0x79, 0x9D, 0x38, 0x68, 0x0F, 0xAD, 0x43, 0x3A, 0xD6,
+ 0x84, 0x0A, 0xE2, 0xEF, 0x96, 0xC1, 0x6D, 0x89, 0x74, 0x19, 0x63, 0x82,
+ 0x3B, 0xA0, 0x9C, 0xBA, 0x78, 0xDE, 0xDC, 0xC2, 0xE7, 0xD4, 0xFA, 0xD6,
+ 0x19, 0x21, 0x29, 0xAE, 0x5E, 0xF4, 0x38, 0x81, 0xC6, 0x9E, 0x0E, 0x3C,
+ 0xCD, 0xC0, 0xDC, 0x93, 0x5D, 0xFD, 0x9A, 0x5C, 0xAB, 0x54, 0x1F, 0xFF,
+ 0x9C, 0x12, 0x1B, 0x4C, 0xDF, 0x2D, 0x9C, 0x85, 0xF9, 0x68, 0x15, 0x89,
+ 0x42, 0x9B, 0x6C, 0x45, 0x89, 0x3A, 0xBC, 0xE9, 0x19, 0x91, 0xBE, 0x0C,
+ 0xEF, 0x90, 0xCC, 0xF6, 0xD6, 0xF0, 0x3D, 0x5C, 0xF5, 0xE5, 0x0F, 0x2F,
+ 0x02, 0x8A, 0x83, 0x4B, 0x93, 0x2F, 0x14, 0x12, 0x1F, 0x56, 0x9A, 0x12,
+ 0x58, 0x88, 0xAE, 0x60, 0xB8, 0x5A, 0xE4, 0xA1, 0xBF, 0x4A, 0x81, 0x84,
+ 0xAB, 0xBB, 0xE4, 0xD0, 0x1D, 0x41, 0xD9, 0x0A, 0xAB, 0x1E, 0x47, 0x5B,
+ 0x31, 0xAC, 0x2B, 0x73
+};
+
+static unsigned char G2048[] = {
+ 0x02
+};
+
+static void
+test_speed_modpow(void)
+{
+ uint32_t mx[65], mp[65], me[65], t1[65], t2[65], len;
+ unsigned char e[64];
+ int i;
+ long num;
+
+ len = br_int_decode(mp, sizeof mp / sizeof mp[0],
+ P2048, sizeof P2048);
+ if (len != 65) {
+ abort();
+ }
+ memset(e, 'P', sizeof e);
+ if (!br_int_decode(me, sizeof me / sizeof me[0], e, sizeof e)) {
+ abort();
+ }
+ if (!br_modint_decode(mx, mp, G2048, sizeof G2048)) {
+ abort();
+ }
+ for (i = 0; i < 10; i ++) {
+ br_modint_to_monty(mx, mp);
+ br_modint_montypow(mx, me, mp, t1, t2);
+ br_modint_from_monty(mx, mp);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_modint_to_monty(mx, mp);
+ br_modint_montypow(mx, me, mp, t1, t2);
+ br_modint_from_monty(mx, mp);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f exp/s\n", "pow[2048:256]",
+ (double)num / tt);
+ fflush(stdout);
+ return;
+ }
+ num <<= 1;
+ }
+}
+
+static void
+test_speed_moddiv(void)
+{
+ uint32_t mx[65], my[65], mp[65], t1[65], t2[65], t3[65], len;
+ unsigned char x[255], y[255];
+ int i;
+ long num;
+
+ len = br_int_decode(mp, sizeof mp / sizeof mp[0],
+ P2048, sizeof P2048);
+ if (len != 65) {
+ abort();
+ }
+ memset(x, 'T', sizeof x);
+ memset(y, 'P', sizeof y);
+ if (!br_modint_decode(mx, mp, x, sizeof x)) {
+ abort();
+ }
+ if (!br_modint_decode(my, mp, y, sizeof y)) {
+ abort();
+ }
+ for (i = 0; i < 10; i ++) {
+ br_modint_div(mx, my, mp, t1, t2, t3);
+ }
+ num = 10;
+ for (;;) {
+ clock_t begin, end;
+ double tt;
+ long k;
+
+ begin = clock();
+ for (k = num; k > 0; k --) {
+ br_modint_div(mx, my, mp, t1, t2, t3);
+ }
+ end = clock();
+ tt = (double)(end - begin) / CLOCKS_PER_SEC;
+ if (tt >= 2.0) {
+ printf("%-30s %8.2f div/s\n", "div[2048]",
+ (double)num / tt);
+ fflush(stdout);
+ return;
+ }
+ num <<= 1;
+ }
+}
+#endif
+
+#define STU(x) { test_speed_ ## x, #x }
+
+static const struct {
+ void (*fn)(void);
+ char *name;
+} tfns[] = {
+ STU(md5),
+ STU(sha1),
+ STU(sha256),
+ STU(sha512),
+
+ STU(aes128_big_cbcenc),
+ STU(aes128_big_cbcdec),
+ STU(aes192_big_cbcenc),
+ STU(aes192_big_cbcdec),
+ STU(aes256_big_cbcenc),
+ STU(aes256_big_cbcdec),
+ STU(aes128_big_ctr),
+ STU(aes192_big_ctr),
+ STU(aes256_big_ctr),
+
+ STU(aes128_small_cbcenc),
+ STU(aes128_small_cbcdec),
+ STU(aes192_small_cbcenc),
+ STU(aes192_small_cbcdec),
+ STU(aes256_small_cbcenc),
+ STU(aes256_small_cbcdec),
+ STU(aes128_small_ctr),
+ STU(aes192_small_ctr),
+ STU(aes256_small_ctr),
+
+ STU(aes128_ct_cbcenc),
+ STU(aes128_ct_cbcdec),
+ STU(aes192_ct_cbcenc),
+ STU(aes192_ct_cbcdec),
+ STU(aes256_ct_cbcenc),
+ STU(aes256_ct_cbcdec),
+ STU(aes128_ct_ctr),
+ STU(aes192_ct_ctr),
+ STU(aes256_ct_ctr),
+
+ STU(aes128_ct64_cbcenc),
+ STU(aes128_ct64_cbcdec),
+ STU(aes192_ct64_cbcenc),
+ STU(aes192_ct64_cbcdec),
+ STU(aes256_ct64_cbcenc),
+ STU(aes256_ct64_cbcdec),
+ STU(aes128_ct64_ctr),
+ STU(aes192_ct64_ctr),
+ STU(aes256_ct64_ctr),
+
+ STU(aes128_x86ni_cbcenc),
+ STU(aes128_x86ni_cbcdec),
+ STU(aes192_x86ni_cbcenc),
+ STU(aes192_x86ni_cbcdec),
+ STU(aes256_x86ni_cbcenc),
+ STU(aes256_x86ni_cbcdec),
+ STU(aes128_x86ni_ctr),
+ STU(aes192_x86ni_ctr),
+ STU(aes256_x86ni_ctr),
+
+ STU(aes128_pwr8_cbcenc),
+ STU(aes128_pwr8_cbcdec),
+ STU(aes192_pwr8_cbcenc),
+ STU(aes192_pwr8_cbcdec),
+ STU(aes256_pwr8_cbcenc),
+ STU(aes256_pwr8_cbcdec),
+ STU(aes128_pwr8_ctr),
+ STU(aes192_pwr8_ctr),
+ STU(aes256_pwr8_ctr),
+
+ STU(des_tab_cbcenc),
+ STU(des_tab_cbcdec),
+ STU(3des_tab_cbcenc),
+ STU(3des_tab_cbcdec),
+
+ STU(des_ct_cbcenc),
+ STU(des_ct_cbcdec),
+ STU(3des_ct_cbcenc),
+ STU(3des_ct_cbcdec),
+
+ STU(chacha20_ct),
+ STU(chacha20_sse2),
+
+ STU(ghash_ctmul),
+ STU(ghash_ctmul32),
+ STU(ghash_ctmul64),
+ STU(ghash_pclmul),
+ STU(ghash_pwr8),
+
+ STU(poly1305_ctmul),
+ STU(poly1305_ctmul32),
+ STU(poly1305_ctmulq),
+ STU(poly1305_i15),
+
+ STU(eax_aes128_big),
+ STU(eax_aes192_big),
+ STU(eax_aes256_big),
+ STU(eax_aes128_small),
+ STU(eax_aes192_small),
+ STU(eax_aes256_small),
+ STU(eax_aes128_ct),
+ STU(eax_aes192_ct),
+ STU(eax_aes256_ct),
+ STU(eax_aes128_ct64),
+ STU(eax_aes192_ct64),
+ STU(eax_aes256_ct64),
+ STU(eax_aes128_x86ni),
+ STU(eax_aes192_x86ni),
+ STU(eax_aes256_x86ni),
+ STU(eax_aes128_pwr8),
+ STU(eax_aes192_pwr8),
+ STU(eax_aes256_pwr8),
+
+ STU(shake128),
+ STU(shake256),
+
+ STU(rsa_i15),
+ STU(rsa_i31),
+ STU(rsa_i32),
+ STU(rsa_i62),
+ STU(ec_prime_i15),
+ STU(ec_prime_i31),
+ STU(ec_p256_m15),
+ STU(ec_p256_m31),
+ STU(ec_p256_m62),
+ STU(ec_p256_m64),
+ STU(ec_c25519_i15),
+ STU(ec_c25519_i31),
+ STU(ec_c25519_m15),
+ STU(ec_c25519_m31),
+ STU(ec_c25519_m62),
+ STU(ec_c25519_m64),
+ STU(ecdsa_p256_m15),
+ STU(ecdsa_p256_m31),
+ STU(ecdsa_p256_m62),
+ STU(ecdsa_p256_m64),
+ STU(ecdsa_i15),
+ STU(ecdsa_i31),
+
+ STU(i31)
+};
+
+static int
+eq_name(const char *s1, const char *s2)
+{
+ for (;;) {
+ int c1, c2;
+
+ for (;;) {
+ c1 = *s1 ++;
+ if (c1 >= 'A' && c1 <= 'Z') {
+ c1 += 'a' - 'A';
+ } else {
+ switch (c1) {
+ case '-': case '_': case '.': case ' ':
+ continue;
+ }
+ }
+ break;
+ }
+ for (;;) {
+ c2 = *s2 ++;
+ if (c2 >= 'A' && c2 <= 'Z') {
+ c2 += 'a' - 'A';
+ } else {
+ switch (c2) {
+ case '-': case '_': case '.': case ' ':
+ continue;
+ }
+ }
+ break;
+ }
+ if (c1 != c2) {
+ return 0;
+ }
+ if (c1 == 0) {
+ return 1;
+ }
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ size_t u;
+
+ if (argc <= 1) {
+ printf("usage: testspeed all | name...\n");
+ printf("individual test names:\n");
+ for (u = 0; u < (sizeof tfns) / (sizeof tfns[0]); u ++) {
+ printf(" %s\n", tfns[u].name);
+ }
+ } else {
+ for (u = 0; u < (sizeof tfns) / (sizeof tfns[0]); u ++) {
+ int i;
+
+ for (i = 1; i < argc; i ++) {
+ if (eq_name(argv[i], tfns[u].name)
+ || eq_name(argv[i], "all"))
+ {
+ tfns[u].fn();
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+}
Property changes on: stable/12/contrib/bearssl/test/test_speed.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/test_x509.c
===================================================================
--- stable/12/contrib/bearssl/test/test_x509.c (nonexistent)
+++ stable/12/contrib/bearssl/test/test_x509.c (revision 346145)
@@ -0,0 +1,2058 @@
+/*
+ * 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>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "bearssl.h"
+
+#define STR(x) STR_(x)
+#define STR_(x) #x
+#ifdef SRCDIRNAME
+#define DIRNAME STR(SRCDIRNAME) "/test/x509"
+#else
+#define DIRNAME "test/x509"
+#endif
+#define CONFFILE DIRNAME "/alltests.txt"
+#define DEFAULT_TIME "2016-08-30T18:00:00Z"
+
+static void *
+xmalloc(size_t len)
+{
+ void *buf;
+
+ if (len == 0) {
+ return NULL;
+ }
+ buf = malloc(len);
+ if (buf == NULL) {
+ fprintf(stderr, "error: cannot allocate %lu byte(s)\n",
+ (unsigned long)len);
+ exit(EXIT_FAILURE);
+ }
+ return buf;
+}
+
+static void
+xfree(void *buf)
+{
+ if (buf != NULL) {
+ free(buf);
+ }
+}
+
+static char *
+xstrdup(const char *name)
+{
+ size_t n;
+ char *s;
+
+ if (name == NULL) {
+ return NULL;
+ }
+ n = strlen(name) + 1;
+ s = xmalloc(n);
+ memcpy(s, name, n);
+ return s;
+}
+
+typedef struct {
+ char *buf;
+ size_t ptr, len;
+} string_builder;
+
+static string_builder *
+SB_new(void)
+{
+ string_builder *sb;
+
+ sb = xmalloc(sizeof *sb);
+ sb->len = 8;
+ sb->buf = xmalloc(sb->len);
+ sb->ptr = 0;
+ return sb;
+}
+
+static void
+SB_expand(string_builder *sb, size_t extra_len)
+{
+ size_t nlen;
+ char *nbuf;
+
+ if (extra_len < (sb->len - sb->ptr)) {
+ return;
+ }
+ nlen = sb->len << 1;
+ if (extra_len > (nlen - sb->ptr)) {
+ nlen = sb->ptr + extra_len;
+ }
+ nbuf = xmalloc(nlen);
+ memcpy(nbuf, sb->buf, sb->ptr);
+ xfree(sb->buf);
+ sb->buf = nbuf;
+ sb->len = nlen;
+}
+
+static void
+SB_append_char(string_builder *sb, int c)
+{
+ SB_expand(sb, 1);
+ sb->buf[sb->ptr ++] = c;
+}
+
+/* unused
+static void
+SB_append_string(string_builder *sb, const char *s)
+{
+ size_t n;
+
+ n = strlen(s);
+ SB_expand(sb, n);
+ memcpy(sb->buf + sb->ptr, s, n);
+ sb->ptr += n;
+}
+*/
+
+/* unused
+static char *
+SB_to_string(string_builder *sb)
+{
+ char *s;
+
+ s = xmalloc(sb->ptr + 1);
+ memcpy(s, sb->buf, sb->ptr);
+ s[sb->ptr] = 0;
+ return s;
+}
+*/
+
+static char *
+SB_contents(string_builder *sb)
+{
+ return sb->buf;
+}
+
+static size_t
+SB_length(string_builder *sb)
+{
+ return sb->ptr;
+}
+
+static void
+SB_set_length(string_builder *sb, size_t len)
+{
+ if (sb->ptr < len) {
+ SB_expand(sb, len - sb->ptr);
+ memset(sb->buf + sb->ptr, ' ', len - sb->ptr);
+ }
+ sb->ptr = len;
+}
+
+static void
+SB_reset(string_builder *sb)
+{
+ SB_set_length(sb, 0);
+}
+
+static void
+SB_free(string_builder *sb)
+{
+ xfree(sb->buf);
+ xfree(sb);
+}
+
+typedef struct ht_elt_ {
+ char *name;
+ void *value;
+ struct ht_elt_ *next;
+} ht_elt;
+
+typedef struct {
+ size_t size;
+ ht_elt **buckets;
+ size_t num_buckets;
+} HT;
+
+static HT *
+HT_new(void)
+{
+ HT *ht;
+ size_t u;
+
+ ht = xmalloc(sizeof *ht);
+ ht->size = 0;
+ ht->num_buckets = 8;
+ ht->buckets = xmalloc(ht->num_buckets * sizeof(ht_elt *));
+ for (u = 0; u < ht->num_buckets; u ++) {
+ ht->buckets[u] = NULL;
+ }
+ return ht;
+}
+
+static uint32_t
+hash_string(const char *name)
+{
+ uint32_t hc;
+
+ hc = 0;
+ while (*name) {
+ int x;
+
+ hc = (hc << 5) - hc;
+ x = *(const unsigned char *)name;
+ if (x >= 'A' && x <= 'Z') {
+ x += 'a' - 'A';
+ }
+ hc += (uint32_t)x;
+ name ++;
+ }
+ return hc;
+}
+
+static int
+eqstring(const char *s1, const char *s2)
+{
+ while (*s1 && *s2) {
+ int x1, x2;
+
+ x1 = *(const unsigned char *)s1;
+ x2 = *(const unsigned char *)s2;
+ if (x1 >= 'A' && x1 <= 'Z') {
+ x1 += 'a' - 'A';
+ }
+ if (x2 >= 'A' && x2 <= 'Z') {
+ x2 += 'a' - 'A';
+ }
+ if (x1 != x2) {
+ return 0;
+ }
+ s1 ++;
+ s2 ++;
+ }
+ return !(*s1 || *s2);
+}
+
+static void
+HT_expand(HT *ht)
+{
+ size_t n, n2, u;
+ ht_elt **new_buckets;
+
+ n = ht->num_buckets;
+ n2 = n << 1;
+ new_buckets = xmalloc(n2 * sizeof *new_buckets);
+ for (u = 0; u < n2; u ++) {
+ new_buckets[u] = NULL;
+ }
+ for (u = 0; u < n; u ++) {
+ ht_elt *e, *f;
+
+ f = NULL;
+ for (e = ht->buckets[u]; e != NULL; e = f) {
+ uint32_t hc;
+ size_t v;
+
+ hc = hash_string(e->name);
+ v = (size_t)(hc & ((uint32_t)n2 - 1));
+ f = e->next;
+ e->next = new_buckets[v];
+ new_buckets[v] = e;
+ }
+ }
+ xfree(ht->buckets);
+ ht->buckets = new_buckets;
+ ht->num_buckets = n2;
+}
+
+static void *
+HT_put(HT *ht, const char *name, void *value)
+{
+ uint32_t hc;
+ size_t k;
+ ht_elt *e, **prev;
+
+ hc = hash_string(name);
+ k = (size_t)(hc & ((uint32_t)ht->num_buckets - 1));
+ prev = &ht->buckets[k];
+ e = *prev;
+ while (e != NULL) {
+ if (eqstring(name, e->name)) {
+ void *old_value;
+
+ old_value = e->value;
+ if (value == NULL) {
+ *prev = e->next;
+ xfree(e->name);
+ xfree(e);
+ ht->size --;
+ } else {
+ e->value = value;
+ }
+ return old_value;
+ }
+ prev = &e->next;
+ e = *prev;
+ }
+ if (value != NULL) {
+ e = xmalloc(sizeof *e);
+ e->name = xstrdup(name);
+ e->value = value;
+ e->next = ht->buckets[k];
+ ht->buckets[k] = e;
+ ht->size ++;
+ if (ht->size > ht->num_buckets) {
+ HT_expand(ht);
+ }
+ }
+ return NULL;
+}
+
+/* unused
+static void *
+HT_remove(HT *ht, const char *name)
+{
+ return HT_put(ht, name, NULL);
+}
+*/
+
+static void *
+HT_get(const HT *ht, const char *name)
+{
+ uint32_t hc;
+ size_t k;
+ ht_elt *e;
+
+ hc = hash_string(name);
+ k = (size_t)(hc & ((uint32_t)ht->num_buckets - 1));
+ for (e = ht->buckets[k]; e != NULL; e = e->next) {
+ if (eqstring(name, e->name)) {
+ return e->value;
+ }
+ }
+ return NULL;
+}
+
+static void
+HT_clear(HT *ht, void (*free_value)(void *value))
+{
+ size_t u;
+
+ for (u = 0; u < ht->num_buckets; u ++) {
+ ht_elt *e, *f;
+
+ f = NULL;
+ for (e = ht->buckets[u]; e != NULL; e = f) {
+ f = e->next;
+ xfree(e->name);
+ if (free_value != 0) {
+ free_value(e->value);
+ }
+ xfree(e);
+ }
+ ht->buckets[u] = NULL;
+ }
+ ht->size = 0;
+}
+
+static void
+HT_free(HT *ht, void (*free_value)(void *value))
+{
+ HT_clear(ht, free_value);
+ xfree(ht->buckets);
+ xfree(ht);
+}
+
+/* unused
+static size_t
+HT_size(HT *ht)
+{
+ return ht->size;
+}
+*/
+
+static unsigned char *
+read_all(FILE *f, size_t *len)
+{
+ unsigned char *buf;
+ size_t ptr, blen;
+
+ blen = 1024;
+ buf = xmalloc(blen);
+ ptr = 0;
+ for (;;) {
+ size_t rlen;
+
+ if (ptr == blen) {
+ unsigned char *buf2;
+
+ blen <<= 1;
+ buf2 = xmalloc(blen);
+ memcpy(buf2, buf, ptr);
+ xfree(buf);
+ buf = buf2;
+ }
+ rlen = fread(buf + ptr, 1, blen - ptr, f);
+ if (rlen == 0) {
+ unsigned char *buf3;
+
+ buf3 = xmalloc(ptr);
+ memcpy(buf3, buf, ptr);
+ xfree(buf);
+ *len = ptr;
+ return buf3;
+ }
+ ptr += rlen;
+ }
+}
+
+static unsigned char *
+read_file(const char *name, size_t *len)
+{
+ FILE *f;
+ unsigned char *buf;
+
+#ifdef DIRNAME
+ char *dname;
+
+ dname = xmalloc(strlen(DIRNAME) + strlen(name) + 2);
+ sprintf(dname, "%s/%s", DIRNAME, name);
+ name = dname;
+#endif
+ f = fopen(name, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "could not open file '%s'\n", name);
+ exit(EXIT_FAILURE);
+ }
+ buf = read_all(f, len);
+ if (ferror(f)) {
+ fprintf(stderr, "read error on file '%s'\n", name);
+ exit(EXIT_FAILURE);
+ }
+ fclose(f);
+#ifdef DIRNAME
+ xfree(dname);
+#endif
+ return buf;
+}
+
+static int
+parse_dec(const char *s, unsigned len, int *val)
+{
+ int acc;
+
+ acc = 0;
+ while (len -- > 0) {
+ int c;
+
+ c = *s ++;
+ if (c >= '0' && c <= '9') {
+ acc = (acc * 10) + (c - '0');
+ } else {
+ return -1;
+ }
+ }
+ *val = acc;
+ return 0;
+}
+
+static int
+parse_choice(const char *s, const char *acceptable)
+{
+ int c;
+
+ c = *s;
+ while (*acceptable) {
+ if (c == *acceptable ++) {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int
+month_length(int year, int month)
+{
+ static const int base_month_length[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+
+ int x;
+
+ x = base_month_length[month - 1];
+ if (month == 2 && year % 4 == 0
+ && (year % 100 != 0 || year % 400 == 0))
+ {
+ x ++;
+ }
+ return x;
+}
+
+/*
+ * Convert a time string to a days+seconds count. Returned value is 0
+ * on success, -1 on error.
+ */
+static int
+string_to_time(const char *s, uint32_t *days, uint32_t *seconds)
+{
+ int year, month, day, hour, minute, second;
+ int day_of_year, leaps, i;
+
+ if (parse_dec(s, 4, &year) < 0) {
+ return -1;
+ }
+ s += 4;
+ if (parse_choice(s ++, "-:/ ") < 0) {
+ return -1;
+ }
+ if (parse_dec(s, 2, &month) < 0) {
+ return -1;
+ }
+ s += 2;
+ if (parse_choice(s ++, "-:/ ") < 0) {
+ return -1;
+ }
+ if (parse_dec(s, 2, &day) < 0) {
+ return -1;
+ }
+ s += 2;
+ if (parse_choice(s ++, " T") < 0) {
+ return -1;
+ }
+ if (parse_dec(s, 2, &hour) < 0) {
+ return -1;
+ }
+ s += 2;
+ if (parse_choice(s ++, "-:/ ") < 0) {
+ return -1;
+ }
+ if (parse_dec(s, 2, &minute) < 0) {
+ return -1;
+ }
+ s += 2;
+ if (parse_choice(s ++, "-:/ ") < 0) {
+ return -1;
+ }
+ if (parse_dec(s, 2, &second) < 0) {
+ return -1;
+ }
+ s += 2;
+ if (*s == '.') {
+ while (*s && *s >= '0' && *s <= '9') {
+ s ++;
+ }
+ }
+ if (*s) {
+ if (*s ++ != 'Z') {
+ return -1;
+ }
+ if (*s) {
+ return -1;
+ }
+ }
+
+ if (month < 1 || month > 12) {
+ return -1;
+ }
+ day_of_year = 0;
+ for (i = 1; i < month; i ++) {
+ day_of_year += month_length(year, i);
+ }
+ if (day < 1 || day > month_length(year, month)) {
+ return -1;
+ }
+ day_of_year += (day - 1);
+ leaps = (year + 3) / 4 - (year + 99) / 100 + (year + 399) / 400;
+
+ if (hour > 23 || minute > 59 || second > 60) {
+ return -1;
+ }
+ *days = (uint32_t)year * 365 + (uint32_t)leaps + day_of_year;
+ *seconds = (uint32_t)hour * 3600 + minute * 60 + second;
+ return 0;
+}
+
+static FILE *conf;
+static int conf_delayed_char;
+static long conf_linenum;
+static string_builder *line_builder;
+static long current_linenum;
+
+static void
+conf_init(const char *fname)
+{
+ conf = fopen(fname, "r");
+ if (conf == NULL) {
+ fprintf(stderr, "could not open file '%s'\n", fname);
+ exit(EXIT_FAILURE);
+ }
+ conf_delayed_char = -1;
+ conf_linenum = 1;
+ line_builder = SB_new();
+}
+
+static void
+conf_close(void)
+{
+ if (conf != NULL) {
+ if (ferror(conf)) {
+ fprintf(stderr, "read error on configuration file\n");
+ exit(EXIT_FAILURE);
+ }
+ fclose(conf);
+ conf = NULL;
+ }
+ if (line_builder != NULL) {
+ SB_free(line_builder);
+ line_builder = NULL;
+ }
+}
+
+/*
+ * Get next character from the config file.
+ */
+static int
+conf_next_low(void)
+{
+ int x;
+
+ x = conf_delayed_char;
+ if (x >= 0) {
+ conf_delayed_char = -1;
+ } else {
+ x = fgetc(conf);
+ if (x == EOF) {
+ x = -1;
+ }
+ }
+ if (x == '\r') {
+ x = fgetc(conf);
+ if (x == EOF) {
+ x = -1;
+ }
+ if (x != '\n') {
+ conf_delayed_char = x;
+ x = '\n';
+ }
+ }
+ if (x == '\n') {
+ conf_linenum ++;
+ }
+ return x;
+}
+
+static int
+is_ws(int x)
+{
+ return x <= 32;
+}
+
+static int
+is_name_char(int c)
+{
+ return (c >= 'A' && c <= 'Z')
+ || (c >= 'a' && c <= 'z')
+ || (c >= '0' && c <= '9')
+ || (c == '_' || c == '-' || c == '.');
+}
+
+/*
+ * Read a complete line. This handles line continuation; empty lines and
+ * comment lines are skipped; leading and trailing whitespace is removed.
+ * Returned value is 0 (line read) or -1 (no line, EOF reached). The line
+ * contents are accumulated in the line_builder.
+ */
+static int
+conf_next_line(void)
+{
+ for (;;) {
+ int c;
+ int lcwb;
+
+ SB_reset(line_builder);
+
+ /*
+ * Get first non-whitespace character. This skips empty
+ * lines. Comment lines (first non-whitespace character
+ * is a semicolon) are also skipped.
+ */
+ for (;;) {
+ c = conf_next_low();
+ if (c < 0) {
+ return -1;
+ }
+ if (is_ws(c)) {
+ continue;
+ }
+ if (c == ';') {
+ for (;;) {
+ c = conf_next_low();
+ if (c < 0) {
+ return -1;
+ }
+ if (c == '\n') {
+ break;
+ }
+ }
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Read up the remaining of the line. The line continuation
+ * sequence (final backslash) is detected and processed.
+ */
+ current_linenum = conf_linenum;
+ lcwb = (c == '\\');
+ SB_append_char(line_builder, c);
+ for (;;) {
+ c = conf_next_low();
+ if (c < 0) {
+ break;
+ }
+ if (lcwb) {
+ if (c == '\n') {
+ SB_set_length(line_builder,
+ SB_length(line_builder) - 1);
+ }
+ lcwb = 0;
+ continue;
+ }
+ if (c == '\n') {
+ break;
+ } else if (c == '\\') {
+ lcwb = 1;
+ }
+ SB_append_char(line_builder, c);
+ }
+
+ /*
+ * Remove trailing whitespace (if any).
+ */
+ for (;;) {
+ size_t u;
+
+ u = SB_length(line_builder);
+ if (u == 0 || !is_ws(
+ SB_contents(line_builder)[u - 1]))
+ {
+ break;
+ }
+ SB_set_length(line_builder, u - 1);
+ }
+
+ /*
+ * We might end up with a totally empty line (in case there
+ * was a line continuation but nothing else), in which case
+ * we must loop.
+ */
+ if (SB_length(line_builder) > 0) {
+ return 0;
+ }
+ }
+}
+
+/*
+ * Test whether the current line is a section header. If yes, then the
+ * header name is extracted, and returned as a newly allocated string.
+ * Otherwise, NULL is returned.
+ */
+static char *
+parse_header_name(void)
+{
+ char *buf, *name;
+ size_t u, v, w, len;
+
+ buf = SB_contents(line_builder);
+ len = SB_length(line_builder);
+ if (len < 2 || buf[0] != '[' || buf[len - 1] != ']') {
+ return NULL;
+ }
+ u = 1;
+ v = len - 1;
+ while (u < v && is_ws(buf[u])) {
+ u ++;
+ }
+ while (u < v && is_ws(buf[v - 1])) {
+ v --;
+ }
+ if (u == v) {
+ return NULL;
+ }
+ for (w = u; w < v; w ++) {
+ if (!is_name_char(buf[w])) {
+ return NULL;
+ }
+ }
+ len = v - u;
+ name = xmalloc(len + 1);
+ memcpy(name, buf + u, len);
+ name[len] = 0;
+ return name;
+}
+
+/*
+ * Parse the current line as a 'name = value' pair. The pair is pushed into
+ * the provided hash table. On error (including a duplicate key name),
+ * this function returns -1; otherwise, it returns 0.
+ */
+static int
+parse_keyvalue(HT *d)
+{
+ char *buf, *name, *value;
+ size_t u, len;
+
+ buf = SB_contents(line_builder);
+ len = SB_length(line_builder);
+ for (u = 0; u < len; u ++) {
+ if (!is_name_char(buf[u])) {
+ break;
+ }
+ }
+ if (u == 0) {
+ return -1;
+ }
+ name = xmalloc(u + 1);
+ memcpy(name, buf, u);
+ name[u] = 0;
+ if (HT_get(d, name) != NULL) {
+ xfree(name);
+ return -1;
+ }
+ while (u < len && is_ws(buf[u])) {
+ u ++;
+ }
+ if (u >= len || buf[u] != '=') {
+ xfree(name);
+ return -1;
+ }
+ u ++;
+ while (u < len && is_ws(buf[u])) {
+ u ++;
+ }
+ value = xmalloc(len - u + 1);
+ memcpy(value, buf + u, len - u);
+ value[len - u] = 0;
+ HT_put(d, name, value);
+ xfree(name);
+ return 0;
+}
+
+/*
+ * Public keys, indexed by name. Elements are pointers to br_x509_pkey
+ * structures.
+ */
+static HT *keys;
+
+/*
+ * Trust anchors, indexed by name. Elements are pointers to
+ * test_trust_anchor structures.
+ */
+static HT *trust_anchors;
+
+typedef struct {
+ unsigned char *dn;
+ size_t dn_len;
+ unsigned flags;
+ char *key_name;
+} test_trust_anchor;
+
+/*
+ * Test case: trust anchors, certificates (file names), key type and
+ * usage, expected status and EE public key.
+ */
+typedef struct {
+ char *name;
+ char **ta_names;
+ char **cert_names;
+ char *servername;
+ unsigned key_type_usage;
+ unsigned status;
+ char *ee_key_name;
+ unsigned hashes;
+ uint32_t days, seconds;
+} test_case;
+
+static test_case *all_chains;
+static size_t all_chains_ptr, all_chains_len;
+
+static void
+free_key(void *value)
+{
+ br_x509_pkey *pk;
+
+ pk = value;
+ switch (pk->key_type) {
+ case BR_KEYTYPE_RSA:
+ xfree((void *)pk->key.rsa.n);
+ xfree((void *)pk->key.rsa.e);
+ break;
+ case BR_KEYTYPE_EC:
+ xfree((void *)pk->key.ec.q);
+ break;
+ default:
+ fprintf(stderr, "unknown key type: %d\n", pk->key_type);
+ exit(EXIT_FAILURE);
+ break;
+ }
+ xfree(pk);
+}
+
+static void
+free_trust_anchor(void *value)
+{
+ test_trust_anchor *ttc;
+
+ ttc = value;
+ xfree(ttc->dn);
+ xfree(ttc->key_name);
+ xfree(ttc);
+}
+
+static void
+free_test_case_contents(test_case *tc)
+{
+ size_t u;
+
+ xfree(tc->name);
+ for (u = 0; tc->ta_names[u]; u ++) {
+ xfree(tc->ta_names[u]);
+ }
+ xfree(tc->ta_names);
+ for (u = 0; tc->cert_names[u]; u ++) {
+ xfree(tc->cert_names[u]);
+ }
+ xfree(tc->cert_names);
+ xfree(tc->servername);
+ xfree(tc->ee_key_name);
+}
+
+static char *
+get_value(char *objtype, HT *objdata, long linenum, char *name)
+{
+ char *value;
+
+ value = HT_get(objdata, name);
+ if (value == NULL) {
+ fprintf(stderr,
+ "missing property '%s' in section '%s' (line %ld)\n",
+ name, objtype, linenum);
+ exit(EXIT_FAILURE);
+ }
+ return value;
+}
+
+static unsigned char *
+parse_hex(const char *name, long linenum, const char *value, size_t *len)
+{
+ unsigned char *buf;
+
+ buf = NULL;
+ for (;;) {
+ size_t u, ptr;
+ int acc, z;
+
+ ptr = 0;
+ acc = 0;
+ z = 0;
+ for (u = 0; value[u]; u ++) {
+ int c;
+
+ c = value[u];
+ if (c >= '0' && c <= '9') {
+ c -= '0';
+ } else if (c >= 'A' && c <= 'F') {
+ c -= 'A' - 10;
+ } else if (c >= 'a' && c <= 'f') {
+ c -= 'a' - 10;
+ } else if (c == ' ' || c == ':') {
+ continue;
+ } else {
+ fprintf(stderr, "invalid hexadecimal character"
+ " in '%s' (line %ld)\n",
+ name, linenum);
+ exit(EXIT_FAILURE);
+ }
+ if (z) {
+ if (buf != NULL) {
+ buf[ptr] = (acc << 4) + c;
+ }
+ ptr ++;
+ } else {
+ acc = c;
+ }
+ z = !z;
+ }
+ if (z) {
+ fprintf(stderr, "invalid hexadecimal value (partial"
+ " byte) in '%s' (line %ld)\n",
+ name, linenum);
+ exit(EXIT_FAILURE);
+ }
+ if (buf == NULL) {
+ buf = xmalloc(ptr);
+ } else {
+ *len = ptr;
+ return buf;
+ }
+ }
+}
+
+static char **
+split_names(const char *value)
+{
+ char **names;
+ size_t len;
+
+ names = NULL;
+ len = strlen(value);
+ for (;;) {
+ size_t u, ptr;
+
+ ptr = 0;
+ u = 0;
+ while (u < len) {
+ size_t v;
+
+ while (u < len && is_ws(value[u])) {
+ u ++;
+ }
+ v = u;
+ while (v < len && !is_ws(value[v])) {
+ v ++;
+ }
+ if (v > u) {
+ if (names != NULL) {
+ char *name;
+
+ name = xmalloc(v - u + 1);
+ memcpy(name, value + u, v - u);
+ name[v - u] = 0;
+ names[ptr] = name;
+ }
+ ptr ++;
+ }
+ u = v;
+ }
+ if (names == NULL) {
+ names = xmalloc((ptr + 1) * sizeof *names);
+ } else {
+ names[ptr] = NULL;
+ return names;
+ }
+ }
+}
+
+static int
+string_to_hash(const char *name)
+{
+ char tmp[20];
+ size_t u, v;
+
+ for (u = 0, v = 0; name[u]; u ++) {
+ int c;
+
+ c = name[u];
+ if ((c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= 'a' && c <= 'z'))
+ {
+ tmp[v ++] = c;
+ if (v == sizeof tmp) {
+ return -1;
+ }
+ }
+ }
+ tmp[v] = 0;
+ if (eqstring(tmp, "md5")) {
+ return br_md5_ID;
+ } else if (eqstring(tmp, "sha1")) {
+ return br_sha1_ID;
+ } else if (eqstring(tmp, "sha224")) {
+ return br_sha224_ID;
+ } else if (eqstring(tmp, "sha256")) {
+ return br_sha256_ID;
+ } else if (eqstring(tmp, "sha384")) {
+ return br_sha384_ID;
+ } else if (eqstring(tmp, "sha512")) {
+ return br_sha512_ID;
+ } else {
+ return -1;
+ }
+}
+
+static int
+string_to_curve(const char *name)
+{
+ char tmp[20];
+ size_t u, v;
+
+ for (u = 0, v = 0; name[u]; u ++) {
+ int c;
+
+ c = name[u];
+ if ((c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= 'a' && c <= 'z'))
+ {
+ tmp[v ++] = c;
+ if (v == sizeof tmp) {
+ return -1;
+ }
+ }
+ }
+ tmp[v] = 0;
+ if (eqstring(tmp, "p256") || eqstring(tmp, "secp256r1")) {
+ return BR_EC_secp256r1;
+ } else if (eqstring(tmp, "p384") || eqstring(tmp, "secp384r1")) {
+ return BR_EC_secp384r1;
+ } else if (eqstring(tmp, "p521") || eqstring(tmp, "secp521r1")) {
+ return BR_EC_secp521r1;
+ } else {
+ return -1;
+ }
+}
+
+static void
+parse_object(char *objtype, HT *objdata, long linenum)
+{
+ char *name;
+
+ name = get_value(objtype, objdata, linenum, "name");
+ if (eqstring(objtype, "key")) {
+ char *stype;
+ br_x509_pkey *pk;
+
+ stype = get_value(objtype, objdata, linenum, "type");
+ pk = xmalloc(sizeof *pk);
+ if (eqstring(stype, "RSA")) {
+ char *sn, *se;
+
+ sn = get_value(objtype, objdata, linenum, "n");
+ se = get_value(objtype, objdata, linenum, "e");
+ pk->key_type = BR_KEYTYPE_RSA;
+ pk->key.rsa.n = parse_hex("modulus", linenum,
+ sn, &pk->key.rsa.nlen);
+ pk->key.rsa.e = parse_hex("exponent", linenum,
+ se, &pk->key.rsa.elen);
+ } else if (eqstring(stype, "EC")) {
+ char *sc, *sq;
+ int curve;
+
+ sc = get_value(objtype, objdata, linenum, "curve");
+ sq = get_value(objtype, objdata, linenum, "q");
+ curve = string_to_curve(sc);
+ if (curve < 0) {
+ fprintf(stderr, "unknown curve name: '%s'"
+ " (line %ld)\n", sc, linenum);
+ exit(EXIT_FAILURE);
+ }
+ pk->key_type = BR_KEYTYPE_EC;
+ pk->key.ec.curve = curve;
+ pk->key.ec.q = parse_hex("public point", linenum,
+ sq, &pk->key.ec.qlen);
+ } else {
+ fprintf(stderr, "unknown key type '%s' (line %ld)\n",
+ stype, linenum);
+ exit(EXIT_FAILURE);
+ }
+ if (HT_put(keys, name, pk) != NULL) {
+ fprintf(stderr, "duplicate key: '%s' (line %ld)\n",
+ name, linenum);
+ exit(EXIT_FAILURE);
+ }
+ } else if (eqstring(objtype, "anchor")) {
+ char *dnfile, *kname, *tatype;
+ test_trust_anchor *tta;
+
+ dnfile = get_value(objtype, objdata, linenum, "DN_file");
+ kname = get_value(objtype, objdata, linenum, "key");
+ tatype = get_value(objtype, objdata, linenum, "type");
+ tta = xmalloc(sizeof *tta);
+ tta->dn = read_file(dnfile, &tta->dn_len);
+ tta->key_name = xstrdup(kname);
+ if (eqstring(tatype, "CA")) {
+ tta->flags = BR_X509_TA_CA;
+ } else if (eqstring(tatype, "EE")) {
+ tta->flags = 0;
+ } else {
+ fprintf(stderr,
+ "unknown trust anchor type: '%s' (line %ld)\n",
+ tatype, linenum);
+ }
+ if (HT_put(trust_anchors, name, tta) != NULL) {
+ fprintf(stderr,
+ "duplicate trust anchor: '%s' (line %ld)\n",
+ name, linenum);
+ exit(EXIT_FAILURE);
+ }
+ } else if (eqstring(objtype, "chain")) {
+ test_case tc;
+ char *ktype, *kusage, *sstatus, *shashes, *stime;
+
+ ktype = get_value(objtype, objdata, linenum, "keytype");
+ kusage = get_value(objtype, objdata, linenum, "keyusage");
+ sstatus = get_value(objtype, objdata, linenum, "status");
+ tc.name = xstrdup(name);
+ tc.ta_names = split_names(
+ get_value(objtype, objdata, linenum, "anchors"));
+ tc.cert_names = split_names(
+ get_value(objtype, objdata, linenum, "chain"));
+ tc.servername = xstrdup(HT_get(objdata, "servername"));
+ if (eqstring(ktype, "RSA")) {
+ tc.key_type_usage = BR_KEYTYPE_RSA;
+ } else if (eqstring(ktype, "EC")) {
+ tc.key_type_usage = BR_KEYTYPE_EC;
+ } else {
+ fprintf(stderr,
+ "unknown key type: '%s' (line %ld)\n",
+ ktype, linenum);
+ exit(EXIT_FAILURE);
+ }
+ if (eqstring(kusage, "KEYX")) {
+ tc.key_type_usage |= BR_KEYTYPE_KEYX;
+ } else if (eqstring(kusage, "SIGN")) {
+ tc.key_type_usage |= BR_KEYTYPE_SIGN;
+ } else {
+ fprintf(stderr,
+ "unknown key usage: '%s' (line %ld)\n",
+ kusage, linenum);
+ exit(EXIT_FAILURE);
+ }
+ tc.status = (unsigned)atoi(sstatus);
+ if (tc.status == 0) {
+ tc.ee_key_name = xstrdup(
+ get_value(objtype, objdata, linenum, "eekey"));
+ } else {
+ tc.ee_key_name = NULL;
+ }
+ shashes = HT_get(objdata, "hashes");
+ if (shashes == NULL) {
+ tc.hashes = (unsigned)-1;
+ } else {
+ char **hns;
+ size_t u;
+
+ tc.hashes = 0;
+ hns = split_names(shashes);
+ for (u = 0;; u ++) {
+ char *hn;
+ int id;
+
+ hn = hns[u];
+ if (hn == NULL) {
+ break;
+ }
+ id = string_to_hash(hn);
+ if (id < 0) {
+ fprintf(stderr,
+ "unknown hash function '%s'"
+ " (line %ld)\n", hn, linenum);
+ exit(EXIT_FAILURE);
+ }
+ tc.hashes |= (unsigned)1 << id;
+ xfree(hn);
+ }
+ xfree(hns);
+ }
+ stime = HT_get(objdata, "time");
+ if (stime == NULL) {
+ stime = DEFAULT_TIME;
+ }
+ if (string_to_time(stime, &tc.days, &tc.seconds) < 0) {
+ fprintf(stderr, "invalid time string '%s' (line %ld)\n",
+ stime, linenum);
+ exit(EXIT_FAILURE);
+ }
+ if (all_chains_ptr == all_chains_len) {
+ if (all_chains_len == 0) {
+ all_chains_len = 8;
+ all_chains = xmalloc(
+ all_chains_len * sizeof *all_chains);
+ } else {
+ test_case *ntc;
+ size_t nlen;
+
+ nlen = all_chains_len << 1;
+ ntc = xmalloc(nlen * sizeof *ntc);
+ memcpy(ntc, all_chains,
+ all_chains_len * sizeof *all_chains);
+ xfree(all_chains);
+ all_chains = ntc;
+ all_chains_len = nlen;
+ }
+ }
+ all_chains[all_chains_ptr ++] = tc;
+ } else {
+ fprintf(stderr, "unknown section type '%s' (line %ld)\n",
+ objtype, linenum);
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void
+process_conf_file(const char *fname)
+{
+ char *objtype;
+ HT *objdata;
+ long objlinenum;
+
+ keys = HT_new();
+ trust_anchors = HT_new();
+ all_chains = NULL;
+ all_chains_ptr = 0;
+ all_chains_len = 0;
+ conf_init(fname);
+ objtype = NULL;
+ objdata = HT_new();
+ objlinenum = 0;
+ for (;;) {
+ char *hname;
+
+ if (conf_next_line() < 0) {
+ break;
+ }
+ hname = parse_header_name();
+ if (hname != NULL) {
+ if (objtype != NULL) {
+ parse_object(objtype, objdata, objlinenum);
+ HT_clear(objdata, xfree);
+ xfree(objtype);
+ }
+ objtype = hname;
+ objlinenum = current_linenum;
+ continue;
+ }
+ if (objtype == NULL) {
+ fprintf(stderr, "no current section (line %ld)\n",
+ current_linenum);
+ exit(EXIT_FAILURE);
+ }
+ if (parse_keyvalue(objdata) < 0) {
+ fprintf(stderr, "wrong configuration, line %ld\n",
+ current_linenum);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (objtype != NULL) {
+ parse_object(objtype, objdata, objlinenum);
+ xfree(objtype);
+ }
+ HT_free(objdata, xfree);
+ conf_close();
+}
+
+static const struct {
+ int id;
+ const br_hash_class *impl;
+} hash_impls[] = {
+ { br_md5_ID, &br_md5_vtable },
+ { br_sha1_ID, &br_sha1_vtable },
+ { br_sha224_ID, &br_sha224_vtable },
+ { br_sha256_ID, &br_sha256_vtable },
+ { br_sha384_ID, &br_sha384_vtable },
+ { br_sha512_ID, &br_sha512_vtable },
+ { 0, NULL }
+};
+
+typedef struct {
+ unsigned char *data;
+ size_t len;
+} blob;
+
+static int
+eqbigint(const unsigned char *b1, size_t b1_len,
+ const unsigned char *b2, size_t b2_len)
+{
+ while (b1_len > 0 && *b1 == 0) {
+ b1 ++;
+ b1_len --;
+ }
+ while (b2_len > 0 && *b2 == 0) {
+ b2 ++;
+ b2_len --;
+ }
+ return b1_len == b2_len && memcmp(b1, b2, b1_len) == 0;
+}
+
+static int
+eqpkey(const br_x509_pkey *pk1, const br_x509_pkey *pk2)
+{
+ if (pk1 == pk2) {
+ return 1;
+ }
+ if (pk1 == NULL || pk2 == NULL) {
+ return 0;
+ }
+ if (pk1->key_type != pk2->key_type) {
+ return 0;
+ }
+ switch (pk1->key_type) {
+ case BR_KEYTYPE_RSA:
+ return eqbigint(pk1->key.rsa.n, pk1->key.rsa.nlen,
+ pk2->key.rsa.n, pk2->key.rsa.nlen)
+ && eqbigint(pk1->key.rsa.e, pk1->key.rsa.elen,
+ pk2->key.rsa.e, pk2->key.rsa.elen);
+ case BR_KEYTYPE_EC:
+ return pk1->key.ec.curve == pk2->key.ec.curve
+ && pk1->key.ec.qlen == pk2->key.ec.qlen
+ && memcmp(pk1->key.ec.q,
+ pk2->key.ec.q, pk1->key.ec.qlen) == 0;
+ default:
+ fprintf(stderr, "unknown key type: %d\n", pk1->key_type);
+ exit(EXIT_FAILURE);
+ break;
+ }
+ return 0;
+}
+
+static size_t max_dp_usage;
+static size_t max_rp_usage;
+
+static void
+run_test_case(test_case *tc)
+{
+ br_x509_minimal_context ctx;
+ br_x509_trust_anchor *anchors;
+ size_t num_anchors;
+ size_t u;
+ const br_hash_class *dnhash;
+ size_t num_certs;
+ blob *certs;
+ br_x509_pkey *ee_pkey_ref;
+ const br_x509_pkey *ee_pkey;
+ unsigned usages;
+ unsigned status;
+
+ printf("%s: ", tc->name);
+ fflush(stdout);
+
+ /*
+ * Get the hash function to use for hashing DN. We can use just
+ * any supported hash function, but for the elegance of things,
+ * we will use one of the hash function implementations
+ * supported for this test case (with SHA-1 as fallback).
+ */
+ dnhash = &br_sha1_vtable;
+ for (u = 0; hash_impls[u].id; u ++) {
+ if ((tc->hashes & ((unsigned)1 << (hash_impls[u].id))) != 0) {
+ dnhash = hash_impls[u].impl;
+ }
+ }
+
+ /*
+ * Get trust anchors.
+ */
+ for (num_anchors = 0; tc->ta_names[num_anchors]; num_anchors ++);
+ anchors = xmalloc(num_anchors * sizeof *anchors);
+ for (u = 0; tc->ta_names[u]; u ++) {
+ test_trust_anchor *tta;
+ br_x509_pkey *tak;
+
+ tta = HT_get(trust_anchors, tc->ta_names[u]);
+ if (tta == NULL) {
+ fprintf(stderr, "no such trust anchor: '%s'\n",
+ tc->ta_names[u]);
+ exit(EXIT_FAILURE);
+ }
+ tak = HT_get(keys, tta->key_name);
+ if (tak == NULL) {
+ fprintf(stderr, "no such public key: '%s'\n",
+ tta->key_name);
+ exit(EXIT_FAILURE);
+ }
+ anchors[u].dn.data = tta->dn;
+ anchors[u].dn.len = tta->dn_len;
+ anchors[u].flags = tta->flags;
+ anchors[u].pkey = *tak;
+ }
+
+ /*
+ * Read all relevant certificates.
+ */
+ for (num_certs = 0; tc->cert_names[num_certs]; num_certs ++);
+ certs = xmalloc(num_certs * sizeof *certs);
+ for (u = 0; u < num_certs; u ++) {
+ certs[u].data = read_file(tc->cert_names[u], &certs[u].len);
+ }
+
+ /*
+ * Get expected EE public key (if any).
+ */
+ if (tc->ee_key_name == NULL) {
+ ee_pkey_ref = NULL;
+ } else {
+ ee_pkey_ref = HT_get(keys, tc->ee_key_name);
+ if (ee_pkey_ref == NULL) {
+ fprintf(stderr, "no such public key: '%s'\n",
+ tc->ee_key_name);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * Initialise the engine.
+ */
+ br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors);
+ for (u = 0; hash_impls[u].id; u ++) {
+ int id;
+
+ id = hash_impls[u].id;
+ if ((tc->hashes & ((unsigned)1 << id)) != 0) {
+ br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
+ }
+ }
+ br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
+ br_x509_minimal_set_ecdsa(&ctx,
+ br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
+
+ /*
+ * Set the validation date.
+ */
+ br_x509_minimal_set_time(&ctx, tc->days, tc->seconds);
+
+ /*
+ * Put "canaries" to detect actual stack usage.
+ */
+ for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
+ ctx.dp_stack[u] = 0xA7C083FE;
+ }
+ for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
+ ctx.rp_stack[u] = 0xA7C083FE;
+ }
+
+ /*
+ * Run the engine. We inject certificates by chunks of 100 bytes
+ * in order to exercise the coroutine API.
+ */
+ ctx.vtable->start_chain(&ctx.vtable, tc->servername);
+ for (u = 0; u < num_certs; u ++) {
+ size_t v;
+
+ ctx.vtable->start_cert(&ctx.vtable, certs[u].len);
+ v = 0;
+ while (v < certs[u].len) {
+ size_t w;
+
+ w = certs[u].len - v;
+ if (w > 100) {
+ w = 100;
+ }
+ ctx.vtable->append(&ctx.vtable, certs[u].data + v, w);
+ v += w;
+ }
+ ctx.vtable->end_cert(&ctx.vtable);
+ }
+ status = ctx.vtable->end_chain(&ctx.vtable);
+ ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
+
+ /*
+ * Check key type and usage.
+ */
+ if (ee_pkey != NULL) {
+ unsigned ktu;
+
+ ktu = ee_pkey->key_type | usages;
+ if (tc->key_type_usage != (ktu & tc->key_type_usage)) {
+ fprintf(stderr, "wrong key type + usage"
+ " (expected 0x%02X, got 0x%02X)\n",
+ tc->key_type_usage, ktu);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /*
+ * Check results. Note that we may still get a public key if
+ * the path is "not trusted" (but otherwise fine).
+ */
+ if (status != tc->status) {
+ fprintf(stderr, "wrong status (got %d, expected %d)\n",
+ status, tc->status);
+ exit(EXIT_FAILURE);
+ }
+ if (status == BR_ERR_X509_NOT_TRUSTED) {
+ ee_pkey = NULL;
+ }
+ if (!eqpkey(ee_pkey, ee_pkey_ref)) {
+ fprintf(stderr, "wrong EE public key\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Check stack usage.
+ */
+ for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
+ if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
+ if (max_dp_usage < u) {
+ max_dp_usage = u;
+ }
+ break;
+ }
+ }
+ for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
+ if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
+ if (max_rp_usage < u) {
+ max_rp_usage = u;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Release everything.
+ */
+ for (u = 0; u < num_certs; u ++) {
+ xfree(certs[u].data);
+ }
+ xfree(certs);
+ xfree(anchors);
+ printf("OK\n");
+}
+
+/*
+ * A custom structure for tests, synchronised with the test certificate
+ * names.crt.
+ *
+ * If num is 1 or more, then this is a DN element with OID '1.1.1.1.num'.
+ * If num is -1 or less, then this is a SAN element of type -num.
+ * If num is 0, then this is a SAN element of type OtherName with
+ * OID 1.3.6.1.4.1.311.20.2.3 (Microsoft UPN).
+ */
+typedef struct {
+ int num;
+ int status;
+ const char *expected;
+} name_element_test;
+
+static name_element_test names_ref[] = {
+ /* === DN tests === */
+ {
+ /* [12] 66:6f:6f */
+ 1, 1, "foo"
+ },
+ {
+ /* [12] 62:61:72 */
+ 1, 1, "bar"
+ },
+ {
+ /* [18] 31:32:33:34 */
+ 2, 1, "1234"
+ },
+ {
+ /* [19] 66:6f:6f */
+ 3, 1, "foo"
+ },
+ {
+ /* [20] 66:6f:6f */
+ 4, 1, "foo"
+ },
+ {
+ /* [22] 66:6f:6f */
+ 5, 1, "foo"
+ },
+ {
+ /* [30] 00:66:00:6f:00:6f */
+ 6, 1, "foo"
+ },
+ {
+ /* [30] fe:ff:00:66:00:6f:00:6f */
+ 7, 1, "foo"
+ },
+ {
+ /* [30] ff:fe:66:00:6f:00:6f:00 */
+ 8, 1, "foo"
+ },
+ {
+ /* [20] 63:61:66:e9 */
+ 9, 1, "caf\xC3\xA9"
+ },
+ {
+ /* [12] 63:61:66:c3:a9 */
+ 10, 1, "caf\xC3\xA9"
+ },
+ {
+ /* [12] 63:61:66:e0:83:a9 */
+ 11, -1, NULL
+ },
+ {
+ /* [12] 63:61:66:e3:90:8c */
+ 12, 1, "caf\xE3\x90\x8C"
+ },
+ {
+ /* [30] 00:63:00:61:00:66:34:0c */
+ 13, 1, "caf\xE3\x90\x8C"
+ },
+ {
+ /* [12] 63:61:66:c3 */
+ 14, -1, NULL
+ },
+ {
+ /* [30] d8:42:df:f4:00:67:00:6f */
+ 15, 1, "\xF0\xA0\xAF\xB4go"
+ },
+ {
+ /* [30] 00:66:d8:42 */
+ 16, -1, NULL
+ },
+ {
+ /* [30] d8:42:00:66 */
+ 17, -1, NULL
+ },
+ {
+ /* [30] df:f4:00:66 */
+ 18, -1, NULL
+ },
+ {
+ /* [12] 66:00:6f */
+ 19, -1, NULL
+ },
+ {
+ /* [30] 00:00:34:0c */
+ 20, -1, NULL
+ },
+ {
+ /* [30] 34:0c:00:00:00:66 */
+ 21, -1, NULL
+ },
+ {
+ /* [12] ef:bb:bf:66:6f:6f */
+ 22, 1, "foo"
+ },
+ {
+ /* [30] 00:66:ff:fe:00:6f */
+ 23, -1, NULL
+ },
+ {
+ /* [30] 00:66:ff:fd:00:6f */
+ 24, 1, "f\xEF\xBF\xBDo"
+ },
+
+ /* === Value not found in the DN === */
+ {
+ 127, 0, NULL
+ },
+
+ /* === SAN tests === */
+ {
+ /* SAN OtherName (Microsoft UPN) */
+ 0, 1, "foo@bar.com"
+ },
+ {
+ /* SAN rfc822Name */
+ -1, 1, "bar@foo.com"
+ },
+ {
+ /* SAN dNSName */
+ -2, 1, "example.com"
+ },
+ {
+ /* SAN dNSName */
+ -2, 1, "www.example.com"
+ },
+ {
+ /* uniformResourceIdentifier */
+ -6, 1, "http://www.example.com/"
+ }
+};
+
+static void
+free_name_elements(br_name_element *elts, size_t num)
+{
+ size_t u;
+
+ for (u = 0; u < num; u ++) {
+ xfree((void *)elts[u].oid);
+ xfree(elts[u].buf);
+ }
+ xfree(elts);
+}
+
+static void
+test_name_extraction(void)
+{
+ unsigned char *data;
+ size_t len;
+ br_x509_minimal_context ctx;
+ uint32_t days, seconds;
+ size_t u;
+ unsigned status;
+ br_name_element *names;
+ size_t num_names;
+ int good;
+
+ printf("Name extraction: ");
+ fflush(stdout);
+ data = read_file("names.crt", &len);
+ br_x509_minimal_init(&ctx, &br_sha256_vtable, NULL, 0);
+ for (u = 0; hash_impls[u].id; u ++) {
+ int id;
+
+ id = hash_impls[u].id;
+ br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
+ }
+ br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
+ br_x509_minimal_set_ecdsa(&ctx,
+ br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
+ string_to_time(DEFAULT_TIME, &days, &seconds);
+ br_x509_minimal_set_time(&ctx, days, seconds);
+
+ num_names = (sizeof names_ref) / (sizeof names_ref[0]);
+ names = xmalloc(num_names * sizeof *names);
+ for (u = 0; u < num_names; u ++) {
+ int num;
+ unsigned char *oid;
+
+ num = names_ref[u].num;
+ if (num > 0) {
+ oid = xmalloc(5);
+ oid[0] = 4;
+ oid[1] = 0x29;
+ oid[2] = 0x01;
+ oid[3] = 0x01;
+ oid[4] = num;
+ } else if (num == 0) {
+ oid = xmalloc(13);
+ oid[0] = 0x00;
+ oid[1] = 0x00;
+ oid[2] = 0x0A;
+ oid[3] = 0x2B;
+ oid[4] = 0x06;
+ oid[5] = 0x01;
+ oid[6] = 0x04;
+ oid[7] = 0x01;
+ oid[8] = 0x82;
+ oid[9] = 0x37;
+ oid[10] = 0x14;
+ oid[11] = 0x02;
+ oid[12] = 0x03;
+ } else {
+ oid = xmalloc(2);
+ oid[0] = 0x00;
+ oid[1] = -num;
+ }
+ names[u].oid = oid;
+ names[u].buf = xmalloc(256);
+ names[u].len = 256;
+ }
+ br_x509_minimal_set_name_elements(&ctx, names, num_names);
+
+ /*
+ * Put "canaries" to detect actual stack usage.
+ */
+ for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
+ ctx.dp_stack[u] = 0xA7C083FE;
+ }
+ for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
+ ctx.rp_stack[u] = 0xA7C083FE;
+ }
+
+ /*
+ * Run the engine. Since we set no trust anchor, we expect a status
+ * of "not trusted".
+ */
+ ctx.vtable->start_chain(&ctx.vtable, NULL);
+ ctx.vtable->start_cert(&ctx.vtable, len);
+ ctx.vtable->append(&ctx.vtable, data, len);
+ ctx.vtable->end_cert(&ctx.vtable);
+ status = ctx.vtable->end_chain(&ctx.vtable);
+ if (status != BR_ERR_X509_NOT_TRUSTED) {
+ fprintf(stderr, "wrong status: %u\n", status);
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Check stack usage.
+ */
+ for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
+ if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
+ if (max_dp_usage < u) {
+ max_dp_usage = u;
+ }
+ break;
+ }
+ }
+ for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
+ if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
+ if (max_rp_usage < u) {
+ max_rp_usage = u;
+ }
+ break;
+ }
+ }
+
+ good = 1;
+ for (u = 0; u < num_names; u ++) {
+ if (names[u].status != names_ref[u].status) {
+ printf("ERR: name %u (id=%d): status=%d, expected=%d\n",
+ (unsigned)u, names_ref[u].num,
+ names[u].status, names_ref[u].status);
+ if (names[u].status > 0) {
+ unsigned char *p;
+
+ printf(" obtained:");
+ p = (unsigned char *)names[u].buf;
+ while (*p) {
+ printf(" %02X", *p ++);
+ }
+ printf("\n");
+ }
+ good = 0;
+ continue;
+ }
+ if (names_ref[u].expected == NULL) {
+ if (names[u].buf[0] != 0) {
+ printf("ERR: name %u not zero-terminated\n",
+ (unsigned)u);
+ good = 0;
+ continue;
+ }
+ } else {
+ if (strcmp(names[u].buf, names_ref[u].expected) != 0) {
+ unsigned char *p;
+
+ printf("ERR: name %u (id=%d): wrong value\n",
+ (unsigned)u, names_ref[u].num);
+ printf(" expected:");
+ p = (unsigned char *)names_ref[u].expected;
+ while (*p) {
+ printf(" %02X", *p ++);
+ }
+ printf("\n");
+ printf(" obtained:");
+ p = (unsigned char *)names[u].buf;
+ while (*p) {
+ printf(" %02X", *p ++);
+ }
+ printf("\n");
+ good = 0;
+ continue;
+ }
+ }
+ }
+ if (!good) {
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ for (u = 0; u < num_names; u ++) {
+ printf("%u: (%d)", (unsigned)u, names[u].status);
+ if (names[u].status > 0) {
+ size_t v;
+
+ for (v = 0; names[u].buf[v]; v ++) {
+ printf(" %02x", names[u].buf[v]);
+ }
+ }
+ printf("\n");
+ }
+ */
+
+ xfree(data);
+ free_name_elements(names, num_names);
+ printf("OK\n");
+}
+
+int
+main(int argc, const char *argv[])
+{
+ size_t u;
+
+#ifdef SRCDIRNAME
+ /*
+ * We want to change the current directory to that of the
+ * executable, so that test files are reliably located. We
+ * do that only if SRCDIRNAME is defined (old Makefile would
+ * not do that).
+ */
+ if (argc >= 1) {
+ const char *arg, *c;
+
+ arg = argv[0];
+ for (c = arg + strlen(arg);; c --) {
+ int sep, r;
+
+#ifdef _WIN32
+ sep = (*c == '/') || (*c == '\\');
+#else
+ sep = (*c == '/');
+#endif
+ if (sep) {
+ size_t len;
+ char *dn;
+
+ len = 1 + (c - arg);
+ dn = xmalloc(len + 1);
+ memcpy(dn, arg, len);
+ dn[len] = 0;
+#ifdef _WIN32
+ r = _chdir(dn);
+#else
+ r = chdir(dn);
+#endif
+ if (r != 0) {
+ fprintf(stderr, "warning: could not"
+ " set directory to '%s'\n", dn);
+ }
+ xfree(dn);
+ break;
+ }
+ if (c == arg) {
+ break;
+ }
+ }
+ }
+#else
+ (void)argc;
+ (void)argv;
+#endif
+
+ process_conf_file(CONFFILE);
+
+ max_dp_usage = 0;
+ max_rp_usage = 0;
+ for (u = 0; u < all_chains_ptr; u ++) {
+ run_test_case(&all_chains[u]);
+ }
+ test_name_extraction();
+
+ printf("Maximum data stack usage: %u\n", (unsigned)max_dp_usage);
+ printf("Maximum return stack usage: %u\n", (unsigned)max_rp_usage);
+
+ HT_free(keys, free_key);
+ HT_free(trust_anchors, free_trust_anchor);
+ for (u = 0; u < all_chains_ptr; u ++) {
+ free_test_case_contents(&all_chains[u]);
+ }
+ xfree(all_chains);
+
+ return 0;
+}
Property changes on: stable/12/contrib/bearssl/test/test_x509.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/alltests.txt
===================================================================
--- stable/12/contrib/bearssl/test/x509/alltests.txt (nonexistent)
+++ stable/12/contrib/bearssl/test/x509/alltests.txt (revision 346145)
@@ -0,0 +1,722 @@
+; Most/all of these test chains use the same structure:
+; root -> ica1 -> ica2 -> ee
+; "ica1" is "Intermediate CA 1"
+; "ee" is "end-entity", i.e. the client or server certificate itself
+;
+; In SSL/TLS order, the EE comes first. The root may or may not be included
+; as a self-signed certificate.
+
+[key]
+name = root-rsa2048
+type = RSA
+n = B6D934D450FDB3AF7A73F1CE38BF5D6F45E1FD4EB198C6608326D217D1C5B79AA3C1DE6339979CF05E5CC81C17B988196DF0B62E3050A1546E93C0DBCF30CB9F1E2779F1C3995235AA3DB6DFB0AD7CCB49CDC0EDE766102AE9CE281F2150FA774C2DDAEF3C58EB4EBFCEE9FB1ADAA383A3CDA3CA9380DCDAF317CC7AAB33809CB2D47F463FC53CDC6194B727296E2ABC5B0936D4C63B0DEBBECEDB1D1CBC106A7171B3F2CA289A77F28AEC42EFB14A8EE2F21A322ACDC0A6462C9AC28537917F46A19381A17466DFBAB339209193FA1DA1A885E7E4F907F610F6A82701B67F12C340C3C9E2B0AB49183A64B659B795B59636DF2269AA726A544E2729A30E9715
+e = 010001
+
+[key]
+name = root-p256
+type = EC
+curve = P-256
+q = 047174BAABB9302E81D5E557F9F320680C9CF964DBB4200D6DEA40D04A6E42FDB69A682544F6DF7BC4FCDEDD7BBBC5DB7C763F4166406EDBA787C2E5D8C5F37F8D
+
+[key]
+name = root-p384
+type = EC
+curve = P-384
+q = 040ED28B3F7F0A38A6DB72CB4DAC8198C3D595BFABEE2E4A3CC6797F1A272C57AD715F96B5FDA29C4DD87B75B1438B6A92C4FD0282A3080A857F28AB31FF8B49F805470A01EE551F7F27C914E7E780AE474558D6F5539BAE806626514FE560478B
+
+[key]
+name = root-p521
+type = EC
+curve = P-521
+q = 040168E669615D1B20F2E753D2C86312F51094D3E5C6CF49E8D73418278CD769FE40A84AD4F34865D59D94D5685B389E0CFD0450754CAE81ED1D4A91D0773F7A002ED701DEF2DBDEFC7554E74CD600693DBDE1A7E09CD9044774C744C7CE575BF8B645FF79FCCE06116F61D44FDAE62D3046F4EB41DECB8219B279A5B8CE2A47F3DF0D463B
+
+[key]
+name = root-new
+type = EC
+curve = P-256
+q = 0465D02336D3ACEB9A000B33A6EECA9745EFD72A0F7C0B138FAAA564E705A3269A479BB5A041DC1D244EA1D2BB9639C79187D3D63CEF79EDD1DC65E80027E75997
+
+[key]
+name = ica1-rsa2048
+type = RSA
+n = B3E86BAF9C1652E3810C50AB25CECC0DC7F21F7F50DF2C5C35D6622E632741A7E453A84B27FA1391A3FA094A2F3B5ECF77B38AC1CD49959C750D6474EFE4D74BB9A19B68D2307148EAF74B14DF3F47A9D8BBEC8F28CCFADFB41F947C96FC080528F9E8F42F2FEE629C8A3AE0855860B60F2D30B4C04154914C1F5FADF119F0C022A67DD83F793459427B5BB541C4647F52CF3C3722A12F7925942441C23FFAC775FB48B50D18A7F454F32E6ED84358C4AB50E805AD91B61E0175B3549CDEA09915FBACF15C974951CCEF58126F736BB33414010F5A9DFAAAD693D3E2EAC3ABBC4EEDCC51A1B8F894B6B42CA8862B1FF6514329525E1389B36A78604E4EC01BA5
+e = 010001
+
+[key]
+name = ica2-rsa2048
+type = RSA
+n = AE15F7CBEEE3961BCA63D22681B2D8163423735684FCFDB2E98E9DD0D9D0D706A191EF8D4F604E16BDE6529EE557867B7A7FFCBC34AD86EC9150ADD5C7D18D83E95ABA2FDB0DB92131FAA2FD91EC37836261809C6A82253309DF8F7893EACFDB93B0A2687CEA873E369C4B379A71E52084C3789A2BA42C7E76D561A9131272F14B411BC6A555BA9D8965C06699C0F17C9B61B24E6601B0A9C4FDC8C1D0C789BE2746DE6271BA27F52A850F436026BC2A9D07AAD608DC26D86956A1D308DED858936B0EC2AF783E2574D49F001820BFD7158DB9D13D8900A01264E186C0D580F124B2D2FB4C677CAE3DC9BF47026DE47C0D4490518CCD026237F86FB96701C695
+e = 010001
+
+[key]
+name = ee-rsa2048
+type = RSA
+n = D47A1D27BA2B3A67B2916AFBE78344CAED1C75ADDD4D8362D6AA6895B224217B15AE2A996815ED66F0B858E7D3F52EC6D92A5EE70E2EE7FC6759C0C8617D4BA46FDD9FD9C8858764C7BA1A0F29D496A8789A6B6220A932D0EEA98C286147A2502A63F621DEDAD8D5F07FC5008270E6A3BF5C89274F51927703C3B0CC2E3BEC23F22F5341AF8993FFD280B14397DED619A092127A3D6679E1C1BCE17770A28B3D4684533FE44E424137921E1FFD38B3F7EF873980D356CFF4E013DE64B072A40384C441ED6FFA3EE2CA0420D2D7DC2C822B7AE26DA11C48DBCF894F34973D28A853DAE7C1E17315A330767F8F2342143D5134D25AAD3C9BCBC8FE7F6E8E40F3BD
+e = 010001
+
+[key]
+name = ee-p256
+type = EC
+curve = P-256
+q = 045F389DA7FF4D8AAFF63439461AFC3ADFF423AAA9EAFBC508DE008EBE79A537584C6DDD01CAAB47DF89B6C7171F38FC1D2014DD45C0E08F934E380BFCE999A149
+
+[key]
+name = ee-p384
+type = EC
+curve = P-384
+q = 0415A488877F3D14830E29A1C2F2C0745CE8CF5E684304D1668972389BA615B34E9648D5A7861E49DFFFBFFFEAD7FC6AF11BC4516C3557332DD86DDFDE2A236CCEA844EBD594CCD3ED5B7AE0061BD6595737B59FE754BCDAB6FE38D34D93DBBF30
+
+[key]
+name = ee-p521
+type = EC
+curve = P-521
+q = 040060547ACA9D520FB3272833236CBF8E71AC286A3001FBB1E2C3FD8BAB0817DDE4E4FA53550F120D678F4D55AE4FF36C7C8EAE9E32A08A44FC66F45331E08946077A0139B87FE54B986012A94838C8006034941CD0512E596436D2E8E61CA93585D5C06EAD5094585B5B2A3E013803B3E6AAA1D4156EF09E8352029BB70AC6BF338F918B
+
+; Trust anchor: the root.
+[anchor]
+name = root
+DN_file = dn-root.der
+key = root-rsa2048
+type = CA
+
+; Trust anchor: root with an ECDSA key (in P-256 curve)
+[anchor]
+name = root-p256
+DN_file = dn-root.der
+key = root-p256
+type = CA
+
+; Trust anchor: root with an ECDSA key (in P-384 curve)
+[anchor]
+name = root-p384
+DN_file = dn-root.der
+key = root-p384
+type = CA
+
+; Trust anchor: root with an ECDSA key (in P-521 curve)
+[anchor]
+name = root-p521
+DN_file = dn-root.der
+key = root-p521
+type = CA
+
+; Trust anchor: another root with an ECDSA key (in P-256 curve)
+[anchor]
+name = root-new
+DN_file = dn-root-new.der
+key = root-new
+type = CA
+
+; Intermediate CA 1 as trust anchor.
+[anchor]
+name = ica1
+DN_file = dn-ica1.der
+key = ica1-rsa2048
+type = CA
+
+; Intermediate CA 2 as trust anchor.
+[anchor]
+name = ica2
+DN_file = dn-ica2.der
+key = ica2-rsa2048
+type = CA
+
+; EE certificate as trust anchor (direct trust only).
+[anchor]
+name = ee
+DN_file = dn-ee.der
+key = ee-rsa2048
+type = EE
+
+; Base valid chain.
+[chain]
+name = base
+anchors = root
+chain = ee.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Valid chain except that no trust anchor is provided; this should fail
+; with BR_ERR_X509_NOT_TRUSTED.
+[chain]
+name = noTA
+anchors =
+chain = ee.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 62
+
+; Use of intermediate CA 1 as anchor (extra certificates are ignored).
+[chain]
+name = anchorICA1
+anchors = ica1
+chain = ee.crt ica2.crt junk.crt junk.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Use of intermediate CA 2 as anchor (extra certificates are ignored).
+[chain]
+name = anchorICA2
+anchors = ica2
+chain = ee.crt junk.crt junk.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Direct trust of EE.
+[chain]
+name = directTrust
+anchors = ee
+chain = ee.crt junk.crt junk.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Server name check: name does not match the SAN nor the CN.
+[chain]
+name = wrongName1
+anchors = root
+chain = ee.crt ica2.crt ica1.crt
+servername = foo.example.com
+keytype = RSA
+keyusage = KEYX
+status = 56
+
+; Server name check: name matches the CN but not the SAN, and there is
+; a SAN so the CN is ignored.
+[chain]
+name = wrongName2
+anchors = root
+chain = ee-names.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 56
+
+; Server name check: name does not match CN, but matches the first SAN
+; name.
+[chain]
+name = goodName1
+anchors = root
+chain = ee-names.crt ica2.crt ica1.crt
+servername = foo.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Server name check: name does not match CN, but matches the second SAN
+; name.
+[chain]
+name = goodName2
+anchors = root
+chain = ee-names.crt ica2.crt ica1.crt
+servername = barqux.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Server name check: no SAN, but the CN matches the server name.
+[chain]
+name = goodName3
+anchors = root
+chain = ee-names2.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Server name check: no SAN, and the CN does not match the server name.
+[chain]
+name = wrongName3
+anchors = root
+chain = ee-names2.crt ica2.crt ica1.crt
+servername = foo.example.com
+keytype = RSA
+keyusage = KEYX
+status = 56
+
+; Server name check: no SAN, and the CN does not match the server name,
+; although its byte contents seem to match (but with BMPString encoding).
+[chain]
+name = wrongName4
+anchors = root
+chain = ee-names3.crt ica2.crt ica1.crt
+servername = www1.example.com
+keytype = RSA
+keyusage = KEYX
+status = 56
+
+; Server name check: no SAN, and the CN uses BMPString encoding, but we
+; do not actually request a server name check, so this should pass.
+[chain]
+name = ignoreName1
+anchors = root
+chain = ee-names3.crt ica2.crt ica1.crt
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Wildcard processing: the name 'localhost' should not match because
+; the engine recognises the wildcard only in a '*.' starting sequence,
+; so the lone '*' in a SAN will not be accepted.
+[chain]
+name = wildcard1
+anchors = root
+chain = ee-names4.crt ica2.crt ica1.crt
+servername = localhost
+keytype = RSA
+keyusage = KEYX
+status = 56
+
+; Wildcard processing: the name 'example.com' will be matched by '*.com'.
+[chain]
+name = wildcard2
+anchors = root
+chain = ee-names4.crt ica2.crt ica1.crt
+servername = example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Wildcard processing: the name 'www.example.com' will be matched by
+; '*.example.com'.
+[chain]
+name = wildcard3
+anchors = root
+chain = ee-names4.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Wildcard processing: the name 'foo.foo.example.com' will not be matched by
+; 'foo.*.example.com' because we accept the wildcard only in the first name
+; component.
+[chain]
+name = wildcard4
+anchors = root
+chain = ee-names4.crt ica2.crt ica1.crt
+servername = foo.foo.example.com
+keytype = RSA
+keyusage = KEYX
+status = 56
+
+; Wildcard processing: the name 'foo.bar.example.com' will not be matched by
+; 'foo.*.example.com', but '*.bar.example.com' will fit.
+[chain]
+name = wildcard5
+anchors = root
+chain = ee-names4.crt ica2.crt ica1.crt
+servername = foo.bar.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Wildcard processing: the name 'foo.bar.example.foobar' will not be matched by
+; '*.*.example.foobar' because we support only a single level of wildcard.
+[chain]
+name = wildcard6
+anchors = root
+chain = ee-names4.crt ica2.crt ica1.crt
+servername = foo.bar.example.foobar
+keytype = RSA
+keyusage = KEYX
+status = 56
+
+; Wildcard processing: the name 'foo.*.example.foobar' will be matched
+; by '*.*.example.foobar' because the '*' in the provided server name matches
+; the second '*' in '*.*.example.foobar'. This is a corner case with no
+; practical impact because expected server names are usually extracted from
+; URL and cannot have embedded '*' in them.
+[chain]
+name = wildcard7
+anchors = root
+chain = ee-names4.crt ica2.crt ica1.crt
+servername = foo.*.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Hash function support: the chain uses only SHA-256.
+[chain]
+name = hashSHA256Only
+anchors = root
+chain = ee.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+hashes = sha256
+eekey = ee-rsa2048
+status = 0
+
+; Hash function support: the chain uses only SHA-256.
+[chain]
+name = hashSHA256Unsupported
+anchors = root
+chain = ee.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+hashes = md5 sha1 sha224 sha384 sha512
+status = 49
+
+; Hash function support: signature on EE uses SHA-1.
+[chain]
+name = hashSHA1
+anchors = root
+chain = ee-sha1.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Hash function support: signature on EE uses SHA-224.
+[chain]
+name = hashSHA224
+anchors = root
+chain = ee-sha224.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Hash function support: signature on EE uses SHA-384.
+[chain]
+name = hashSHA384
+anchors = root
+chain = ee-sha384.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Hash function support: signature on EE uses SHA-512.
+[chain]
+name = hashSHA512
+anchors = root
+chain = ee-sha512.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Hash function support: signature on EE uses MD5. This is rejected by
+; the engine (even though MD5 is supported as a hash function).
+[chain]
+name = hashMD5
+anchors = root
+chain = ee-md5.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 49
+
+; EE certificate has trailing garbage (an extra byte), which should be
+; rejected.
+[chain]
+name = trailingGarbage
+anchors = root
+chain = ee-trailing.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 40
+
+; Signature on EE certificate is incorrect (one byte modified in signature).
+[chain]
+name = badSignature1
+anchors = root
+chain = ee-badsig1.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 52
+
+; Signature on EE certificate is incorrect (one byte modified in serial
+; number).
+[chain]
+name = badSignature2
+anchors = root
+chain = ee-badsig2.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 52
+
+; Signature on EE certificate is incorrect but this is ignored because we
+; use a direct trust model here.
+[chain]
+name = ignoredSignature1
+anchors = ee
+chain = ee-badsig1.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Signature on EE certificate is incorrect but this is ignored because we
+; use a direct trust model here.
+[chain]
+name = ignoredSignature2
+anchors = ee
+chain = ee-badsig2.crt ica2.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Intermediate CA 1 has a 1016-bit RSA key, which should be rejected
+; with BR_ERR_X509_WEAK_PUBLIC_KEY.
+[chain]
+name = rsa1016
+anchors = root
+chain = ee.crt ica2-1016.crt ica1-1016.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 60
+
+; Intermediate CA 1 has a 1017-bit RSA key, which should be accepted
+; (because that's 128 bytes, which is the lower limit).
+[chain]
+name = rsa1017
+anchors = root
+chain = ee.crt ica2-1017.crt ica1-1017.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; Intermediate CA 1 has a 4096-bit RSA key, which should be supported.
+[chain]
+name = rsa4096
+anchors = root
+chain = ee.crt ica2-4096.crt ica1-4096.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; EE is valid from 2010/02/17 11:40:35 to 2098/07/20 15:11:08. The
+; start date is in UTCTime, the end date is in GeneralizedTime.
+[chain]
+name = date1
+anchors = ica2
+chain = ee-dates.crt ica2.crt ica1.crt
+time = 2010-02-17 11:40:34Z
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 54
+
+; EE is valid from 2010/02/17 11:40:35 to 2098/07/20 15:11:08. The
+; start date is in UTCTime, the end date is in GeneralizedTime.
+[chain]
+name = date2
+anchors = ica2
+chain = ee-dates.crt ica2.crt ica1.crt
+time = 2010-02-17 11:40:36Z
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; EE is valid from 2010/02/17 11:40:35 to 2098/07/20 15:11:08. The
+; start date is in UTCTime, the end date is in GeneralizedTime.
+[chain]
+name = date3
+anchors = ica2
+chain = ee-dates.crt ica2.crt ica1.crt
+time = 2098-07-20 15:11:07Z
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; EE is valid from 2010/02/17 11:40:35 to 2098/07/20 15:11:08. The
+; start date is in UTCTime, the end date is in GeneralizedTime.
+[chain]
+name = date4
+anchors = ica2
+chain = ee-dates.crt ica2.crt ica1.crt
+time = 2098-07-20 15:11:09Z
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 54
+
+; Intermediate CA 2 certificate is not a CA.
+[chain]
+name = notCA
+anchors = root
+chain = ee-dates.crt ica2-notCA.crt ica1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+status = 58
+
+; A chain using ECDSA with P-256.
+[chain]
+name = secp256r1
+anchors = root-p256
+chain = ee-p256.crt ica2-p256.crt ica1-p256.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p256
+status = 0
+
+; A chain using ECDSA with P-384.
+[chain]
+name = secp384r1
+anchors = root-p384
+chain = ee-p384.crt ica2-p384.crt ica1-p384.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p384
+status = 0
+
+; A chain using ECDSA with P-521.
+[chain]
+name = secp521r1
+anchors = root-p521
+chain = ee-p521.crt ica2-p521.crt ica1-p521.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p521
+status = 0
+
+; A chain using ECDSA with P-256, signature on EE uses SHA-1.
+[chain]
+name = secp256r1-sha1
+anchors = root-p256
+chain = ee-p256-sha1.crt ica2-p256.crt ica1-p256.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p256
+status = 0
+
+; A chain using ECDSA with P-256, signature on EE uses SHA-224.
+[chain]
+name = secp256r1-sha224
+anchors = root-p256
+chain = ee-p256-sha224.crt ica2-p256.crt ica1-p256.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p256
+status = 0
+
+; A chain using ECDSA with P-256, signature on EE uses SHA-256.
+[chain]
+name = secp256r1-sha256
+anchors = root-p256
+chain = ee-p256-sha256.crt ica2-p256.crt ica1-p256.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p256
+status = 0
+
+; A chain using ECDSA with P-256, signature on EE uses SHA-384.
+[chain]
+name = secp256r1-sha384
+anchors = root-p256
+chain = ee-p256-sha384.crt ica2-p256.crt ica1-p256.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p256
+status = 0
+
+; A chain using ECDSA with P-256, signature on EE uses SHA-512.
+[chain]
+name = secp256r1-sha512
+anchors = root-p256
+chain = ee-p256-sha512.crt ica2-p256.crt ica1-p256.crt
+servername = www.example.com
+keytype = EC
+keyusage = SIGN
+eekey = ee-p256
+status = 0
+
+; EE certificate has a Certificate Policies extension, but it is not
+; critical.
+[chain]
+name = certpol-noncrit
+anchors = root-new
+chain = ee-cp1.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; EE certificate has a critical Certificate Policies extension, but it
+; contains no policy qualifier.
+[chain]
+name = certpol-noqual
+anchors = root-new
+chain = ee-cp2.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; EE certificate has a critical Certificate Policies extension, and it
+; contains some qualifiers, but they are all id-qt-cps.
+[chain]
+name = certpol-qualcps
+anchors = root-new
+chain = ee-cp3.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 0
+
+; EE certificate has a critical Certificate Policies extension, and it
+; contains a qualifier distinct from id-qt-cps. This implies rejection
+; of the path.
+[chain]
+name = certpol-qualother
+anchors = root-new
+chain = ee-cp4.crt
+servername = www.example.com
+keytype = RSA
+keyusage = KEYX
+eekey = ee-rsa2048
+status = 57
Property changes on: stable/12/contrib/bearssl/test/x509/alltests.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/dn-ee.der
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/dn-ee.der
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/dn-ica1.der
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/dn-ica1.der
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/dn-ica2.der
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/dn-ica2.der
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/dn-root-new.der
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/dn-root-new.der
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/dn-root.der
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/dn-root.der
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-badsig1.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-badsig1.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-badsig2.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-badsig2.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-cp1.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-cp1.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-cp2.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-cp2.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-cp3.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-cp3.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-cp4.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-cp4.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-dates.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-dates.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-md5.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-md5.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-names.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-names.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-names2.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-names2.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-names3.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-names3.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-names4.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-names4.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p256-sha1.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p256-sha1.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p256-sha224.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p256-sha224.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p256-sha256.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p256-sha256.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p256-sha384.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p256-sha384.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p256-sha512.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p256-sha512.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p256.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p256.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p384.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p384.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-p521.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-p521.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-sha1.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-sha1.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-sha224.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-sha224.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-sha384.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-sha384.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-sha512.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-sha512.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee-trailing.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee-trailing.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ee.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ee.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica1-1016.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica1-1016.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica1-1017.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica1-1017.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica1-4096.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica1-4096.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica1-p256.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica1-p256.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica1-p384.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica1-p384.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica1-p521.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica1-p521.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica1.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica1.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2-1016.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2-1016.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2-1017.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2-1017.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2-4096.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2-4096.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2-notCA.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2-notCA.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2-p256.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2-p256.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2-p384.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2-p384.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2-p521.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2-p521.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/ica2.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/ica2.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/junk.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/junk.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/names.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/names.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/root-p256.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/root-p256.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/root-p384.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/root-p384.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/root-p521.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/root-p521.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/contrib/bearssl/test/x509/root.crt
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: stable/12/contrib/bearssl/test/x509/root.crt
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: stable/12/etc/mtree/BSD.include.dist
===================================================================
--- stable/12/etc/mtree/BSD.include.dist (revision 346144)
+++ stable/12/etc/mtree/BSD.include.dist (revision 346145)
@@ -1,376 +1,380 @@
# $FreeBSD$
#
# Please see the file src/etc/mtree/README before making changes to this file.
#
/set type=dir uname=root gname=wheel mode=0755
.
arpa
..
atf-c
..
atf-c++
..
bsm
..
bsnmp
..
c++
4.2
backward
..
bits
..
debug
..
ext
pb_ds
detail
basic_tree_policy
..
bin_search_tree_
..
binary_heap_
..
binomial_heap_
..
binomial_heap_base_
..
cc_hash_table_map_
..
eq_fn
..
gp_hash_table_map_
..
hash_fn
..
left_child_next_sibling_heap_
..
list_update_map_
..
list_update_policy
..
ov_tree_map_
..
pairing_heap_
..
pat_trie_
..
rb_tree_map_
..
rc_binomial_heap_
..
resize_policy
..
splay_tree_
..
thin_heap_
..
tree_policy
..
trie_policy
..
unordered_iterator
..
..
..
..
tr1
..
..
v1
experimental
..
ext
..
tr1
..
..
..
cam
ata
..
mmc
..
nvme
..
scsi
..
..
casper
..
crypto
..
dev
acpica
..
agp
..
an
..
bktr
..
ciss
..
evdev
..
filemon
..
firewire
..
hwpmc
..
hyperv
..
ic
..
iicbus
..
io
..
mfi
..
mlx5
..
mmc
..
mpt
mpilib
..
..
nand
..
nvme
..
ofw
..
pbio
..
pci
..
powermac_nvram
..
ppbus
..
smbus
..
speaker
..
tcp_log
..
usb
..
+ veriexec
+ ..
vkbd
..
wi
..
..
devdctl
..
edit
readline
..
..
fs
cuse
..
devfs
..
fdescfs
..
msdosfs
..
nandfs
..
nfs
..
nullfs
..
procfs
..
smbfs
..
udf
..
unionfs
..
..
gcc
4.2
..
..
geom
cache
..
concat
..
eli
..
gate
..
journal
..
label
..
mirror
..
mountver
..
multipath
..
nop
..
raid
..
raid3
..
shsec
..
stripe
..
virstor
..
..
gnu
posix
..
..
gssapi
..
infiniband
complib
..
iba
..
opensm
..
vendor
..
..
isofs
cd9660
..
..
kadm5
..
krb5
..
lib80211
..
libipt
..
libmilter
..
libxo
..
lzma
..
machine
pc
..
..
net
altq
..
..
net80211
..
netgraph
atm
..
bluetooth
include
..
..
netflow
..
..
netinet
cc
..
netdump
..
..
netinet6
..
netipsec
..
netnatm
api
..
msg
..
saal
..
sig
..
..
netpfil
pf
..
..
netsmb
..
nfs
..
nfsclient
..
nfsserver
..
opencsd
c_api
..
etmv3
..
etmv4
..
ptm
..
stm
..
..
openssl
..
pcap
..
protocols
..
rdma
..
rpc
..
rpcsvc
..
security
audit
..
mac_biba
..
mac_bsdextended
..
mac_lomac
..
mac_mls
..
mac_partition
+ ..
+ mac_veriexec
..
..
ssp
..
sys
disk
..
..
teken
..
ufs
ffs
..
ufs
..
..
vm
..
xlocale
..
..
Index: stable/12/include/Makefile
===================================================================
--- stable/12/include/Makefile (revision 346144)
+++ stable/12/include/Makefile (revision 346145)
@@ -1,409 +1,418 @@
# @(#)Makefile 8.2 (Berkeley) 1/4/94
# $FreeBSD$
#
# Doing a "make install" builds /usr/include.
.include <src.opts.mk>
PACKAGE=runtime
TAGS+= development
CLEANFILES= osreldate.h version
SUBDIR= arpa protocols rpcsvc rpc xlocale
SUBDIR_PARALLEL=
INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h _ctype.h ctype.h \
db.h \
dirent.h dlfcn.h elf.h elf-hints.h err.h fmtmsg.h fnmatch.h fstab.h \
fts.h ftw.h getopt.h glob.h grp.h \
ieeefp.h ifaddrs.h \
inttypes.h iso646.h kenv.h langinfo.h libgen.h limits.h link.h \
locale.h malloc.h malloc_np.h memory.h monetary.h mpool.h mqueue.h \
ndbm.h netconfig.h \
netdb.h nl_types.h nlist.h nss.h nsswitch.h paths.h \
printf.h proc_service.h pthread.h \
pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h \
res_update.h resolv.h runetype.h search.h semaphore.h setjmp.h \
signal.h spawn.h stab.h stdalign.h stdbool.h stddef.h \
stdnoreturn.h stdio.h stdlib.h string.h stringlist.h \
strings.h sysexits.h tar.h termios.h tgmath.h \
time.h timeconv.h timers.h ttyent.h \
uchar.h ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h \
wchar.h wctype.h wordexp.h xlocale.h
.PATH: ${SRCTOP}/contrib/libc-vis
INCS+= vis.h
MHDRS= float.h floatingpoint.h stdarg.h
PHDRS= sched.h _semaphore.h
LHDRS= aio.h errno.h fcntl.h linker_set.h poll.h stdatomic.h stdint.h \
syslog.h ucontext.h
LDIRS= bsm cam geom net net80211 netgraph netinet netinet6 \
netipsec netsmb nfs nfsclient nfsserver sys vm
LSUBDIRS= cam/ata cam/mmc cam/nvme cam/scsi \
dev/acpica dev/agp dev/an dev/bktr dev/ciss dev/filemon dev/firewire \
dev/hwpmc dev/hyperv \
dev/ic dev/iicbus dev/io dev/mfi dev/mmc dev/nvme \
dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/smbus \
- dev/speaker dev/tcp_log dev/vkbd dev/wi \
+ dev/speaker dev/tcp_log dev/veriexec dev/vkbd dev/wi \
fs/devfs fs/fdescfs fs/msdosfs fs/nandfs fs/nfs fs/nullfs \
fs/procfs fs/smbfs fs/udf fs/unionfs \
geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \
geom/mirror geom/mountver geom/multipath geom/nop \
geom/raid geom/raid3 geom/shsec geom/stripe geom/virstor \
net/altq \
netgraph/atm netgraph/netflow \
netinet/cc \
netinet/netdump \
security/audit \
security/mac_biba security/mac_bsdextended security/mac_lomac \
security/mac_mls security/mac_partition \
+ security/mac_veriexec \
sys/disk \
ufs/ffs ufs/ufs
LSUBSUBDIRS= dev/mpt/mpilib
.if ${MK_BLUETOOTH} != "no"
LSUBSUBDIRS+= netgraph/bluetooth/include
.endif
.if ${MK_CUSE} != "no"
LSUBDIRS+= fs/cuse
.endif
.if ${MK_GSSAPI} != "no"
SUBDIR+= gssapi
INCS+= gssapi.h
.endif
.if ${MK_HESIOD} != "no"
INCS+= hesiod.h
.endif
# Handle the #define aliases for libiconv
.if ${MK_ICONV} == "yes"
INCS+= iconv.h
.endif
.if ${MK_USB} != "no"
LSUBDIRS+= dev/usb
.endif
.if ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64"
_dev_powermac_nvram= dev/powermac_nvram
.endif
# Define SHARED to indicate whether you want symbolic links to the system
# source (``symlinks''), or a separate copy (``copies''). ``symlinks'' is
# probably only useful for developers and should be avoided if you do not
# wish to tie your /usr/include and /usr/src together.
#SHARED= symlinks
SHARED?= copies
INCS+= osreldate.h
SYSDIR= ${SRCTOP}/sys
NEWVERS_SH= ${SYSDIR}/conf/newvers.sh
PARAM_H= ${SYSDIR}/sys/param.h
MK_OSRELDATE_SH= ${.CURDIR}/mk-osreldate.sh
SYMLINKS+= ${LIBDIR:C,[^/]+,..,g:C,^/,,}${INCLUDEDIR} ${LIBDIR}/include
osreldate.h: ${NEWVERS_SH} ${PARAM_H} ${MK_OSRELDATE_SH}
env NEWVERS_SH=${NEWVERS_SH} PARAMFILE=${PARAM_H} SYSDIR=${SYSDIR} \
sh ${MK_OSRELDATE_SH}
.for i in ${LHDRS}
INCSLINKS+= sys/$i ${INCLUDEDIR}/$i
.endfor
.for i in ${MHDRS}
INCSLINKS+= machine/$i ${INCLUDEDIR}/$i
.endfor
.for i in ${PHDRS}
INCSLINKS+= sys/$i ${INCLUDEDIR}/$i
.endfor
.if ${MACHINE} != ${MACHINE_CPUARCH}
_MARCHS= ${MACHINE_CPUARCH}
.endif
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
_MARCHS+= x86
.endif
META_TARGETS+= compat
stage_includes: ${SHARED}
SDESTDIR= ${SYSROOT:U${DESTDIR}}
# Take care of stale directory-level symlinks.
compat:
.for i in ${LDIRS} ${LSUBDIRS} machine ${_MARCHS} crypto
if [ -L ${SDESTDIR}${INCLUDEDIR}/$i ]; then \
rm -f ${SDESTDIR}${INCLUDEDIR}/$i; \
fi
.endfor
mtree -deU ${NO_ROOT:D-W} ${MTREE_FOLLOWS_SYMLINKS} \
-f ${SRCTOP}/etc/mtree/BSD.include.dist \
-p ${SDESTDIR}${INCLUDEDIR} > /dev/null
copies: .PHONY .META
.for i in ${LDIRS} ${LSUBDIRS} ${LSUBSUBDIRS} crypto machine machine/pc \
${_MARCHS}
if [ -d ${SDESTDIR}${INCLUDEDIR}/$i ]; then \
cd ${SDESTDIR}${INCLUDEDIR}/$i; \
for h in *.h; do \
if [ -L $$h ]; then rm -f $$h; fi; \
done; \
fi
.endfor
-.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS}
+.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec} ${LSUBSUBDIRS}
cd ${SRCTOP}/sys; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \
${SDESTDIR}${INCLUDEDIR}/$i
.endfor
cd ${SRCTOP}/sys/dev/acpica; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 acpiio.h \
${SDESTDIR}${INCLUDEDIR}/dev/acpica; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 acpi_hpet.h \
${SDESTDIR}${INCLUDEDIR}/dev/acpica
cd ${SRCTOP}/sys/dev/agp; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 agpreg.h \
${SDESTDIR}${INCLUDEDIR}/dev/agp
cd ${SRCTOP}/sys/dev/bktr; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 ioctl_*.h \
${SDESTDIR}${INCLUDEDIR}/dev/bktr
.if ${MK_NAND} != "no"
cd ${SRCTOP}/sys/dev/nand; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nandsim.h \
${SDESTDIR}${INCLUDEDIR}/dev/nand; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nand_dev.h \
${SDESTDIR}${INCLUDEDIR}/dev/nand
.endif
cd ${SRCTOP}/sys/dev/evdev; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 input.h \
${SDESTDIR}${INCLUDEDIR}/dev/evdev; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 input-event-codes.h \
${SDESTDIR}${INCLUDEDIR}/dev/evdev; \
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 uinput.h \
${SDESTDIR}${INCLUDEDIR}/dev/evdev
cd ${SRCTOP}/sys/dev/hyperv/include; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 hyperv.h \
${SDESTDIR}${INCLUDEDIR}/dev/hyperv
cd ${SRCTOP}/sys/dev/hyperv/utilities; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 hv_snapshot.h \
${SDESTDIR}${INCLUDEDIR}/dev/hyperv
cd ${SRCTOP}/sys/dev/pci; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 pcireg.h \
${SDESTDIR}${INCLUDEDIR}/dev/pci
+ cd ${SRCTOP}/sys/dev/veriexec; \
+ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 veriexec_ioctl.h \
+ ${SDESTDIR}${INCLUDEDIR}/dev/veriexec
cd ${SRCTOP}/sys/fs/cd9660/; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/isofs/cd9660
.if ${MK_IPFILTER} != "no"
cd ${SRCTOP}/sys/contrib/ipfilter/netinet; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/netinet
.endif
.if ${MK_PF} != "no"
cd ${SRCTOP}/sys/netpfil/pf; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/netpfil/pf
.endif
cd ${SRCTOP}/sys/crypto; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 rijndael/rijndael.h \
${SDESTDIR}${INCLUDEDIR}/crypto
cd ${SRCTOP}/sys/opencrypto; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/crypto
cd ${SRCTOP}/sys/${MACHINE}/include; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/machine
.if exists(${SRCTOP}/sys/${MACHINE}/include/pc)
cd ${SRCTOP}/sys/${MACHINE}/include/pc; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/machine/pc
.endif
.for _MARCH in ${_MARCHS}
.if exists(${SRCTOP}/sys/${_MARCH}/include)
${INSTALL} -d ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 755 \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}; \
cd ${SRCTOP}/sys/${_MARCH}/include; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}
.if exists(${SRCTOP}/sys/${_MARCH}/include/pc)
${INSTALL} -d ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 755 \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \
cd ${SRCTOP}/sys/${_MARCH}/include/pc; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}/pc
.endif
.endif
.endfor
cd ${SRCTOP}/sys/rpc; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 types.h \
${SDESTDIR}${INCLUDEDIR}/rpc
cd ${SRCTOP}/sys/teken; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 teken.h \
${SDESTDIR}${INCLUDEDIR}/teken
.if ${MK_CDDL} != "no"
cd ${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/sys; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nvpair.h \
${SDESTDIR}${INCLUDEDIR}/sys
.endif
.if ${MK_MLX5TOOL} != "no"
cd ${SRCTOP}/sys/dev/mlx5; \
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 mlx5io.h \
${SDESTDIR}${INCLUDEDIR}/dev/mlx5
.endif
symlinks: .PHONY .META
@${ECHO} "Setting up symlinks to kernel source tree..."
.for i in ${LDIRS}
cd ${SRCTOP}/sys/$i; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \
done
.endfor
-.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci}
+.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec}
cd ${SRCTOP}/sys/$i; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \
done
.endfor
cd ${SRCTOP}/sys/dev/acpica; \
for h in acpiio.h acpi_hpet.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/acpica/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/acpica; \
done
cd ${SRCTOP}/sys/dev/agp; \
for h in agpreg.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/agp/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/agp; \
done
cd ${SRCTOP}/sys/dev/bktr; \
for h in ioctl_*.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/bktr/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/bktr; \
done
.if ${MK_NAND} != "no"
cd ${SRCTOP}/sys/dev/nand; \
for h in nandsim.h nand_dev.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/nand/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/nand; \
done
.endif
cd ${SRCTOP}/sys/dev/evdev; \
for h in input.h input-event-codes.h uinput.h; do \
ln -fs ../../../../sys/dev/evdev/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/evdev; \
done
cd ${SRCTOP}/sys/dev/hyperv/include; \
for h in hyperv.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/hyperv/include/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/hyperv; \
done
cd ${SRCTOP}/sys/dev/hyperv/utilities; \
for h in hv_snapshot.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/hyperv/utilities/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/hyperv; \
done
cd ${SRCTOP}/sys/dev/pci; \
for h in pcireg.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/pci/$$h \
${SDESTDIR}${INCLUDEDIR}/dev/pci; \
+ done
+ cd ${SRCTOP}/sys/dev/veriexec; \
+ for h in veriexec_ioctl.h; do \
+ ln -fs ../../../../sys/dev/veriexec/$$h \
+ ${SDESTDIR}${INCLUDEDIR}/dev/veriexec; \
done
.for i in ${LSUBSUBDIRS}
cd ${SRCTOP}/sys/$i; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \
done
.endfor
.if ${MK_IPFILTER} != "no"
cd ${SRCTOP}/sys/contrib/ipfilter/netinet; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/contrib/ipfilter/netinet/$$h \
${SDESTDIR}${INCLUDEDIR}/netinet; \
done
.endif
.if ${MK_PF} != "no"
cd ${SRCTOP}/sys/netpfil/pf; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/netpfil/pf/$$h \
${SDESTDIR}${INCLUDEDIR}/netpfil/pf; \
done
.endif
cd ${SRCTOP}/sys/crypto; \
for h in rijndael/rijndael.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/crypto/$$h \
${SDESTDIR}${INCLUDEDIR}/crypto; \
done
cd ${SRCTOP}/sys/opencrypto; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/opencrypto/$$h \
${SDESTDIR}${INCLUDEDIR}/crypto; \
done
cd ${SRCTOP}/sys/${MACHINE}/include; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/${MACHINE}/include/$$h \
${SDESTDIR}${INCLUDEDIR}/machine; \
done
.if exists(${SRCTOP}/sys/${MACHINE}/include/pc)
cd ${SRCTOP}/sys/${MACHINE}/include/pc; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/${MACHINE}/include/pc/$$h \
${SDESTDIR}${INCLUDEDIR}/machine/pc; \
done
.endif
.for _MARCH in ${_MARCHS}
.if exists(${SRCTOP}/sys/${_MARCH}/include)
${INSTALL} -d ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 755 \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}; \
cd ${SRCTOP}/sys/${_MARCH}/include; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/${_MARCH}/include/$$h \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}; \
done
.if exists(${SRCTOP}/sys/${_MARCH}/include/pc)
${INSTALL} -d ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 755 \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \
cd ${SRCTOP}/sys/${_MARCH}/include/pc; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/${_MARCH}/include/pc/$$h \
${SDESTDIR}${INCLUDEDIR}/${_MARCH}/pc; \
done
.endif
.endif
.endfor
cd ${SRCTOP}/sys/fs/cd9660; \
for h in *.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/fs/cd9660/$$h \
${SDESTDIR}${INCLUDEDIR}/isofs/cd9660; \
done
cd ${SRCTOP}/sys/rpc; \
for h in types.h; do \
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/rpc/$$h \
${SDESTDIR}${INCLUDEDIR}/rpc; \
done
.if ${MK_CDDL} != "no"
${INSTALL_SYMLINK} ${TAG_ARGS} \
../../../sys/cddl/contrib/opensolaris/uts/common/sys/nvpair.h \
${SDESTDIR}${INCLUDEDIR}/sys
.endif
.if ${MK_MLX5TOOL} != "no"
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/mlx5/mlx5io.h \
${SDESTDIR}${INCLUDEDIR}/dev/mlx5
.endif
.include <bsd.prog.mk>
installincludes: ${SHARED}
${SHARED}: compat
.if ${MACHINE} == "host" && !defined(_SKIP_BUILD)
# we're here because we are building a sysroot...
# we need MACHINE et al set correctly
HOST_MACHINE!= uname -m
HOST_MACHINE_ARCH!= uname -p
MACHINE:= ${HOST_MACHINE}
MACHINE_ARCH:= ${HOST_MACHINE_ARCH}
.endif
Index: stable/12/lib/Makefile
===================================================================
--- stable/12/lib/Makefile (revision 346144)
+++ stable/12/lib/Makefile (revision 346145)
@@ -1,217 +1,219 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
# $FreeBSD$
.include <src.opts.mk>
# The SUBDIR_BOOTSTRAP list is a small set of libraries which are used by many
# of the other libraries. These are built first with a .WAIT between them
# and the main list to avoid needing a SUBDIR_DEPEND line on every library
# naming just these few items.
SUBDIR_BOOTSTRAP= \
csu \
.WAIT \
libc \
libc_nonshared \
libcompiler_rt \
${_libclang_rt} \
${_libcplusplus} \
${_libcxxrt} \
libelf \
msun
# The main list; please keep these sorted alphabetically.
SUBDIR= ${SUBDIR_BOOTSTRAP} \
.WAIT \
geom \
libalias \
libarchive \
libauditd \
libbegemot \
libblocksruntime \
libbsdstat \
libbsm \
libbz2 \
libcalendar \
libcam \
libcapsicum \
libcasper \
libcompat \
libcrypt \
libdevctl \
libdevinfo \
libdevstat \
${_libdl} \
libdwarf \
libedit \
libelftc \
libevent \
libexecinfo \
libexpat \
libfetch \
libfigpar \
libgeom \
libifconfig \
libipsec \
libjail \
libkiconv \
libkvm \
liblzma \
libmemstat \
libmd \
libmt \
lib80211 \
libnetbsd \
libnv \
libopenbsd \
libopie \
libpam \
libpathconv \
libpcap \
libpjdlog \
${_libproc} \
libprocstat \
libregex \
librpcsvc \
librss \
librt \
${_librtld_db} \
libsbuf \
libsmb \
libsqlite3 \
libstdbuf \
libstdthreads \
libsysdecode \
libtacplus \
libthread_db \
libucl \
libufs \
libugidfw \
libulog \
libutil \
${_libvgl} \
libwrap \
libxo \
liby \
libz \
libzstd \
ncurses
# Inter-library dependencies. When the makefile for a library contains LDADD
# libraries, those libraries should be listed as build order dependencies here.
SUBDIR_DEPEND_geom= libufs
SUBDIR_DEPEND_libarchive= libz libbz2 libexpat liblzma libmd
SUBDIR_DEPEND_libauditdm= libbsm
SUBDIR_DEPEND_libbsnmp= ${_libnetgraph}
SUBDIR_DEPEND_libc++:= libcxxrt
SUBDIR_DEPEND_libc= libcompiler_rt
SUBDIR_DEPEND_libcam= libsbuf
SUBDIR_DEPEND_libcasper= libnv
SUBDIR_DEPEND_libdevstat= libkvm
SUBDIR_DEPEND_libdpv= libfigpar ncurses libutil
SUBDIR_DEPEND_libedit= ncurses
SUBDIR_DEPEND_libgeom= libexpat libsbuf
SUBDIR_DEPEND_librpcsec_gss= libgssapi
SUBDIR_DEPEND_libmagic= libz
SUBDIR_DEPEND_libmemstat= libkvm
SUBDIR_DEPEND_libopie= libmd
SUBDIR_DEPEND_libpam= libcrypt libopie ${_libradius} librpcsvc libtacplus libutil ${_libypclnt} ${_libcom_err}
SUBDIR_DEPEND_libpjdlog= libutil
SUBDIR_DEPEND_libprocstat= libkvm libutil
SUBDIR_DEPEND_libradius= libmd
SUBDIR_DEPEND_libsmb= libkiconv
SUBDIR_DEPEND_libtacplus= libmd
SUBDIR_DEPEND_libulog= libmd
SUBDIR_DEPEND_libunbound= ${_libldns}
SUBDIR_DEPEND_liblzma= ${_libthr}
.if ${MK_OFED} != "no"
SUBDIR_DEPEND_libpcap= ofed
.endif
# NB: keep these sorted by MK_* knobs
SUBDIR.${MK_ATM}+= libngatm
+SUBDIR.${MK_BEARSSL}+= libbearssl libsecureboot
SUBDIR.${MK_BLACKLIST}+=libblacklist
SUBDIR.${MK_BLUETOOTH}+=libbluetooth libsdp
SUBDIR.${MK_BSNMP}+= libbsnmp
.if !defined(COMPAT_32BIT) && !defined(COMPAT_SOFTFP)
SUBDIR.${MK_CLANG}+= clang
.endif
SUBDIR.${MK_CUSE}+= libcuse
SUBDIR.${MK_CXX}+= libdevdctl
SUBDIR.${MK_TOOLCHAIN}+=libpe
SUBDIR.${MK_DIALOG}+= libdpv
SUBDIR.${MK_FILE}+= libmagic
SUBDIR.${MK_GPIO}+= libgpio
SUBDIR.${MK_GSSAPI}+= libgssapi librpcsec_gss
SUBDIR.${MK_ICONV}+= libiconv_modules
SUBDIR.${MK_KERBEROS_SUPPORT}+= libcom_err
SUBDIR.${MK_LDNS}+= libldns
# The libraries under libclang_rt can only be built by clang, and only make
# sense to build when clang is enabled at all. Furthermore, they can only be
# built for certain architectures.
.if ${MK_CLANG} != "no" && ${COMPILER_TYPE} == "clang" && \
(${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \
${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "i386")
_libclang_rt= libclang_rt
.endif
.if ${MK_LIBCPLUSPLUS} != "no"
_libcxxrt= libcxxrt
_libcplusplus= libc++
_libcplusplus+= libc++experimental
_libcplusplus+= libc++fs
.endif
SUBDIR.${MK_EFI}+= libefivar
SUBDIR.${MK_LIBTHR}+= libthr
SUBDIR.${MK_LLVM_LIBUNWIND}+= libgcc_eh
SUBDIR.${MK_LLVM_LIBUNWIND}+= libgcc_s
SUBDIR.${MK_NAND}+= libnandfs
SUBDIR.${MK_NETGRAPH}+= libnetgraph
SUBDIR.${MK_NIS}+= libypclnt
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
_libvgl= libvgl
.endif
.if ${MACHINE_CPUARCH} == "aarch64"
SUBDIR.${MK_PMC}+= libopencsd
.endif
.if ${MACHINE_CPUARCH} == "amd64"
SUBDIR.${MK_PMC}+= libipt
SUBDIR.${MK_BHYVE}+= libvmmapi
.endif
.if ${MACHINE_CPUARCH} != "sparc64"
_libproc= libproc
_librtld_db= librtld_db
.endif
.if defined(LINKER_FEATURES) && ${LINKER_FEATURES:Mfilter}
_libdl= libdl
.endif
SUBDIR.${MK_OPENSSL}+= libmp
SUBDIR.${MK_PMC}+= libpmc libpmcstat
SUBDIR.${MK_RADIUS_SUPPORT}+= libradius
SUBDIR.${MK_SENDMAIL}+= libmilter libsm libsmdb libsmutil
SUBDIR.${MK_TELNET}+= libtelnet
SUBDIR.${MK_TESTS_SUPPORT}+= atf
SUBDIR.${MK_TESTS}+= tests
SUBDIR.${MK_UNBOUND}+= libunbound
SUBDIR.${MK_USB}+= libusbhid libusb
SUBDIR.${MK_OFED}+= ofed
+SUBDIR.${MK_VERIEXEC}+= libveriexec
SUBDIR.${MK_ZFS}+= libbe
.if !make(install)
SUBDIR_PARALLEL=
.endif
.include <bsd.subdir.mk>
Index: stable/12/lib/libbearssl/Makefile
===================================================================
--- stable/12/lib/libbearssl/Makefile (nonexistent)
+++ stable/12/lib/libbearssl/Makefile (revision 346145)
@@ -0,0 +1,277 @@
+# $FreeBSD$
+
+# This is a reach over build of BearSSL (www.BearSSL.org)
+
+.include <src.opts.mk>
+
+LIB= bearssl
+
+# pick up SRCS used by libsa
+.include "Makefile.libsa.inc"
+
+SRCS+= \
+ codec/dec16be.c \
+ codec/dec16le.c \
+ codec/dec32le.c \
+ codec/dec64le.c \
+ codec/enc16be.c \
+ codec/enc16le.c \
+ codec/enc32le.c \
+ codec/enc64le.c \
+ codec/pemenc.c \
+ ec/ec_all_m15.c \
+ ec/ec_c25519_i15.c \
+ ec/ec_c25519_i31.c \
+ ec/ec_c25519_m15.c \
+ ec/ec_curve25519.c \
+ ec/ec_keygen.c \
+ ec/ec_p256_m15.c \
+ ec/ec_prime_i15.c \
+ ec/ecdsa_default_sign_asn1.c \
+ ec/ecdsa_default_sign_raw.c \
+ ec/ecdsa_default_vrfy_raw.c \
+ ec/ecdsa_i15_bits.c \
+ ec/ecdsa_i15_sign_asn1.c \
+ ec/ecdsa_i15_sign_raw.c \
+ ec/ecdsa_i15_vrfy_asn1.c \
+ ec/ecdsa_i15_vrfy_raw.c \
+ ec/ecdsa_i31_sign_asn1.c \
+ ec/ecdsa_i31_sign_raw.c \
+ ec/ecdsa_rta.c \
+ hash/dig_oid.c \
+ hash/dig_size.c \
+ hash/ghash_ctmul.c \
+ hash/ghash_ctmul32.c \
+ hash/ghash_ctmul64.c \
+ hash/ghash_pwr8.c \
+ hash/md5.c \
+ hash/md5sha1.c \
+
+
+# this one does not compile for amd64
+# we do not need it
+# hash/ghash_pclmul.c \
+
+SRCS+= \
+ int/i15_add.c \
+ int/i15_bitlen.c \
+ int/i15_decmod.c \
+ int/i15_decode.c \
+ int/i15_decred.c \
+ int/i15_encode.c \
+ int/i15_fmont.c \
+ int/i15_iszero.c \
+ int/i15_moddiv.c \
+ int/i15_modpow.c \
+ int/i15_modpow2.c \
+ int/i15_montmul.c \
+ int/i15_mulacc.c \
+ int/i15_muladd.c \
+ int/i15_ninv15.c \
+ int/i15_reduce.c \
+ int/i15_rshift.c \
+ int/i15_sub.c \
+ int/i15_tmont.c \
+ int/i31_decred.c \
+ int/i31_mulacc.c \
+ int/i31_reduce.c \
+ int/i32_add.c \
+ int/i32_bitlen.c \
+ int/i32_decmod.c \
+ int/i32_decode.c \
+ int/i32_decred.c \
+ int/i32_encode.c \
+ int/i32_fmont.c \
+ int/i32_iszero.c \
+ int/i32_modpow.c \
+ int/i32_montmul.c \
+ int/i32_mulacc.c \
+ int/i32_muladd.c \
+ int/i32_ninv32.c \
+ int/i32_reduce.c \
+ int/i32_sub.c \
+ int/i32_tmont.c \
+
+SRCS+= \
+ kdf/hkdf.c \
+ kdf/shake.c \
+
+SRCS+= \
+ rsa/rsa_default_keygen.c \
+ rsa/rsa_default_modulus.c \
+ rsa/rsa_default_pkcs1_sign.c \
+ rsa/rsa_default_priv.c \
+ rsa/rsa_default_privexp.c \
+ rsa/rsa_default_pss_sign.c \
+ rsa/rsa_default_pss_vrfy.c \
+ rsa/rsa_default_pub.c \
+ rsa/rsa_default_pubexp.c \
+ rsa/rsa_i15_keygen.c \
+ rsa/rsa_i15_modulus.c \
+ rsa/rsa_i15_pkcs1_sign.c \
+ rsa/rsa_i15_pkcs1_vrfy.c \
+ rsa/rsa_i15_priv.c \
+ rsa/rsa_i15_privexp.c \
+ rsa/rsa_i15_pss_sign.c \
+ rsa/rsa_i15_pss_vrfy.c \
+ rsa/rsa_i15_pub.c \
+ rsa/rsa_i15_pubexp.c \
+ rsa/rsa_i31_keygen.c \
+ rsa/rsa_i31_keygen_inner.c \
+ rsa/rsa_i31_modulus.c \
+ rsa/rsa_i31_pkcs1_sign.c \
+ rsa/rsa_i31_priv.c \
+ rsa/rsa_i31_privexp.c \
+ rsa/rsa_i31_pss_sign.c \
+ rsa/rsa_i31_pss_vrfy.c \
+ rsa/rsa_i31_pubexp.c \
+ rsa/rsa_i32_pkcs1_sign.c \
+ rsa/rsa_i32_pkcs1_vrfy.c \
+ rsa/rsa_i32_priv.c \
+ rsa/rsa_i32_pss_sign.c \
+ rsa/rsa_i32_pss_vrfy.c \
+ rsa/rsa_i32_pub.c \
+ rsa/rsa_i62_keygen.c \
+ rsa/rsa_i62_pkcs1_sign.c \
+ rsa/rsa_i62_priv.c \
+ rsa/rsa_i62_pss_sign.c \
+ rsa/rsa_i62_pss_vrfy.c \
+ rsa/rsa_pkcs1_sig_pad.c \
+ rsa/rsa_pss_sig_pad.c \
+ rsa/rsa_pss_sig_unpad.c \
+ rsa/rsa_ssl_decrypt.c \
+
+SRCS+= \
+ x509/encode_ec_pk8der.c \
+ x509/encode_ec_rawder.c \
+ x509/encode_rsa_pk8der.c \
+ x509/encode_rsa_rawder.c \
+ x509/skey_decoder.c \
+ x509/x509_knownkey.c \
+ x509/x509_minimal_full.c \
+
+INCS= \
+ 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 \
+
+INCS:= ${INCS:S,^,${BEARSSL}/,}
+
+
+.if ${MK_BEARSSL_SSL:Uno} == "yes"
+SRCS+= \
+ mac/hmac.c \
+ mac/hmac_ct.c \
+ rand/hmac_drbg.c \
+ ssl/prf.c \
+ ssl/prf_md5sha1.c \
+ ssl/prf_sha256.c \
+ ssl/prf_sha384.c \
+ ssl/ssl_ccert_single_ec.c \
+ ssl/ssl_ccert_single_rsa.c \
+ ssl/ssl_client.c \
+ ssl/ssl_client_default_rsapub.c \
+ ssl/ssl_client_full.c \
+ ssl/ssl_engine.c \
+ ssl/ssl_engine_default_aescbc.c \
+ ssl/ssl_engine_default_aesccm.c \
+ ssl/ssl_engine_default_aesgcm.c \
+ ssl/ssl_engine_default_chapol.c \
+ ssl/ssl_engine_default_descbc.c \
+ ssl/ssl_engine_default_ec.c \
+ ssl/ssl_engine_default_ecdsa.c \
+ ssl/ssl_engine_default_rsavrfy.c \
+ ssl/ssl_hashes.c \
+ ssl/ssl_hs_client.c \
+ ssl/ssl_hs_server.c \
+ ssl/ssl_io.c \
+ ssl/ssl_lru.c \
+ ssl/ssl_rec_cbc.c \
+ ssl/ssl_rec_ccm.c \
+ ssl/ssl_rec_chapol.c \
+ ssl/ssl_rec_gcm.c \
+ ssl/ssl_scert_single_ec.c \
+ ssl/ssl_scert_single_rsa.c \
+ ssl/ssl_server.c \
+ ssl/ssl_server_full_ec.c \
+ ssl/ssl_server_full_rsa.c \
+ ssl/ssl_server_mine2c.c \
+ ssl/ssl_server_mine2g.c \
+ ssl/ssl_server_minf2c.c \
+ ssl/ssl_server_minf2g.c \
+ ssl/ssl_server_minr2g.c \
+ ssl/ssl_server_minu2g.c \
+ ssl/ssl_server_minv2g.c \
+
+SRCS+= \
+ symcipher/aes_big_cbcdec.c \
+ symcipher/aes_big_cbcenc.c \
+ symcipher/aes_big_ctr.c \
+ symcipher/aes_big_dec.c \
+ symcipher/aes_big_enc.c \
+ symcipher/aes_common.c \
+ symcipher/aes_ct.c \
+ symcipher/aes_ct64.c \
+ symcipher/aes_ct64_cbcdec.c \
+ symcipher/aes_ct64_cbcenc.c \
+ symcipher/aes_ct64_ctr.c \
+ symcipher/aes_ct64_dec.c \
+ symcipher/aes_ct64_enc.c \
+ symcipher/aes_ct_cbcdec.c \
+ symcipher/aes_ct_cbcenc.c \
+ symcipher/aes_ct_ctr.c \
+ symcipher/aes_ct_dec.c \
+ symcipher/aes_ct_enc.c \
+ symcipher/aes_pwr8.c \
+ symcipher/aes_pwr8_cbcdec.c \
+ symcipher/aes_pwr8_cbcenc.c \
+ symcipher/aes_pwr8_ctr.c \
+ symcipher/aes_pwr8_ctrcbc.c \
+ symcipher/aes_small_cbcdec.c \
+ symcipher/aes_small_cbcenc.c \
+ symcipher/aes_small_ctr.c \
+ symcipher/aes_small_dec.c \
+ symcipher/aes_small_enc.c \
+ symcipher/aes_x86ni.c \
+ symcipher/aes_x86ni_cbcdec.c \
+ symcipher/aes_x86ni_cbcenc.c \
+ symcipher/aes_x86ni_ctr.c \
+ symcipher/chacha20_ct.c \
+ symcipher/des_ct.c \
+ symcipher/des_ct_cbcdec.c \
+ symcipher/des_ct_cbcenc.c \
+ symcipher/des_support.c \
+ symcipher/des_tab.c \
+ symcipher/des_tab_cbcdec.c \
+ symcipher/des_tab_cbcenc.c \
+ symcipher/poly1305_ctmul.c \
+ symcipher/poly1305_ctmul32.c \
+ symcipher/poly1305_ctmulq.c \
+ symcipher/poly1305_i15.c \
+
+.endif
+
+.include <bsd.lib.mk>
+
+.if ${MACHINE} == "host"
+CWARNFLAGS+= -Wno-error
+.endif
+XCFLAGS.gcc.rsa_i62_keygen+= -Wno-error
+XCFLAGS.i15_moddiv+= -Wno-shadow
+XCFLAGS.i31_moddiv+= -Wno-shadow
+XCFLAGS.i62_modpow2+= -Wno-cast-align
+XCFLAGS.x509_minimal+= -Wno-cast-qual
+
+CFLAGS+= ${XCFLAGS.${.TARGET:T:R}:U} \
+ ${XCFLAGS.${COMPILER_TYPE}.${.TARGET:T:R}:U}
+
Property changes on: stable/12/lib/libbearssl/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libbearssl/Makefile.depend
===================================================================
--- stable/12/lib/libbearssl/Makefile.depend (nonexistent)
+++ stable/12/lib/libbearssl/Makefile.depend (revision 346145)
@@ -0,0 +1,17 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
Property changes on: stable/12/lib/libbearssl/Makefile.depend
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libbearssl/Makefile.inc
===================================================================
--- stable/12/lib/libbearssl/Makefile.inc (nonexistent)
+++ stable/12/lib/libbearssl/Makefile.inc (revision 346145)
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+BEARSSL?= ${SRCTOP}/contrib/bearssl
+BEARSSL_SRC= ${BEARSSL}/src
+
+CFLAGS+= -I${BEARSSL}/inc
+
Property changes on: stable/12/lib/libbearssl/Makefile.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libbearssl/Makefile.libsa.inc
===================================================================
--- stable/12/lib/libbearssl/Makefile.libsa.inc (nonexistent)
+++ stable/12/lib/libbearssl/Makefile.libsa.inc (revision 346145)
@@ -0,0 +1,86 @@
+# $FreeBSD$
+
+# This file is included by libsa
+# It contains SRCS needed for loader
+
+.PATH: ${.PARSEDIR}
+
+.include "Makefile.inc"
+
+.PATH: ${BEARSSL_SRC}
+
+CFLAGS+= -I${BEARSSL_SRC}
+
+# we do not need/want nested objdirs
+OBJS_SRCS_FILTER = T R
+
+# we list only the srcs the loader(s) actually needs
+SRCS+= \
+ codec/ccopy.c \
+ codec/dec32be.c \
+ codec/dec64be.c \
+ codec/enc32be.c \
+ codec/enc64be.c \
+ codec/pemdec.c \
+
+SRCS+= \
+ ec/ec_all_m31.c \
+ ec/ec_c25519_m31.c \
+ ec/ec_c25519_m62.c \
+ ec/ec_c25519_m64.c \
+ ec/ec_default.c \
+ ec/ec_p256_m31.c \
+ ec/ec_p256_m62.c \
+ ec/ec_p256_m64.c \
+ ec/ec_prime_i31.c \
+ ec/ec_pubkey.c \
+ ec/ec_secp256r1.c \
+ ec/ec_secp384r1.c \
+ ec/ec_secp521r1.c \
+ ec/ecdsa_atr.c \
+ ec/ecdsa_default_vrfy_asn1.c \
+ ec/ecdsa_i31_bits.c \
+ ec/ecdsa_i31_vrfy_asn1.c \
+ ec/ecdsa_i31_vrfy_raw.c \
+
+# Note: sha1 is needed for OpenPGP (keyId)
+SRCS+= \
+ hash/multihash.c \
+ hash/sha1.c \
+ hash/sha2big.c \
+ hash/sha2small.c \
+
+SRCS+= \
+ int/i31_add.c \
+ int/i31_bitlen.c \
+ int/i31_decmod.c \
+ int/i31_decode.c \
+ int/i31_encode.c \
+ int/i31_fmont.c \
+ int/i31_iszero.c \
+ int/i31_moddiv.c \
+ int/i31_modpow.c \
+ int/i31_modpow2.c \
+ int/i31_montmul.c \
+ int/i31_muladd.c \
+ int/i31_ninv31.c \
+ int/i31_rshift.c \
+ int/i31_sub.c \
+ int/i31_tmont.c \
+ int/i32_div32.c \
+ int/i62_modpow2.c \
+
+SRCS+= \
+ rsa/rsa_default_pkcs1_vrfy.c \
+ rsa/rsa_i31_pkcs1_vrfy.c \
+ rsa/rsa_i31_pub.c \
+ rsa/rsa_i62_pkcs1_vrfy.c \
+ rsa/rsa_i62_pub.c \
+ rsa/rsa_pkcs1_sig_unpad.c \
+
+
+SRCS+= \
+ x509/asn1enc.c \
+ x509/x509_decoder.c \
+ x509/x509_minimal.c \
+
Property changes on: stable/12/lib/libbearssl/Makefile.libsa.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/Makefile.inc
===================================================================
--- stable/12/lib/libsecureboot/Makefile.inc (nonexistent)
+++ stable/12/lib/libsecureboot/Makefile.inc (revision 346145)
@@ -0,0 +1,144 @@
+# $FreeBSD$
+
+.if empty(BEARSSL)
+.include "../libbearssl/Makefile.inc"
+.endif
+
+.if !target(_${__this}_)
+_${__this}_:
+
+libsecureboot_src:= ${.PARSEDIR}
+
+CFLAGS+= -I${libsecureboot_src}/h
+
+.PATH: ${.PARSEDIR}
+
+SRCS+= \
+ readfile.c \
+ brf.c \
+ vesigned.c \
+ vets.c
+
+.if ${.CURDIR:M*libsecureboot*} != ""
+SRCS+= veta.c
+.endif
+
+CFLAGS+= ${XCFLAGS.${.TARGET:T:R}:U}
+
+# we use a couple of files from ${BEARSSL}/tools
+BRSSL_CFLAGS+= -I${BEARSSL}/tools
+BRSSL_SRCS+= \
+ ${BEARSSL}/tools/xmem.c \
+ ${BEARSSL}/tools/vector.c
+
+# we do not need/want nested objdirs
+OBJS_SRCS_FILTER = T R
+
+SRCS+= ${BRSSL_SRCS}
+
+
+# extract the last cert from a chain (should be rootCA)
+_LAST_PEM_USE: .USE
+ sed "1,`grep -n .-END ${.ALLSRC:M*.pem} | tail -2 | head -1 | sed 's,:.*,,'`d" ${.ALLSRC:M*.pem} > ${.TARGET}
+
+# extract 2nd last cert from chain - we use this for self-test
+_2ndLAST_PEM_USE: .USE
+ sed -n "`grep -n .-BEGIN ${.ALLSRC:M*.pem} | tail -2 | \
+ sed 's,:.*,,' | xargs | (read a b; echo $$a,$$(($$b - 1)))`p" ${.ALLSRC:M*.pem} > ${.TARGET}
+
+# list of hashes we support
+VE_HASH_LIST?= SHA256
+
+# list of signatures we support
+# some people don't trust ECDSA
+VE_SIGNATURE_LIST?= RSA
+
+# this list controls our search for signatures so will not be sorted
+# note: for X509 signatures we assume we can replace the trailing
+# "sig" with "certs" to find the certificate chain
+# eg. for manifest.esig we use manifest.ecerts
+VE_SIGNATURE_EXT_LIST?= sig
+
+# needs to be yes for FIPS 140-2 compliance
+VE_SELF_TESTS?= no
+
+# rules to populate the [tv]*.pem files we use to generate ta.h
+# and can add/alter VE_*_LIST as desired.
+.-include "local.trust.mk"
+
+# this is what we use as our trust anchor
+CFLAGS+= -I. -DTRUST_ANCHOR_STR=ta_PEM
+
+.if ${VE_SELF_TESTS} != "no"
+XCFLAGS.vets+= -DVERIFY_CERTS_STR=vc_PEM
+.endif
+
+# clean these up
+VE_HASH_LIST:= ${VE_HASH_LIST:tu:O:u}
+VE_SIGNATURE_LIST:= ${VE_SIGNATURE_LIST:tu:O:u}
+
+# define what we are supporting
+CFLAGS+= ${VE_HASH_LIST:@H@-DVE_$H_SUPPORT@} \
+ ${VE_SIGNATURE_LIST:@S@-DVE_$S_SUPPORT@}
+
+.if ${VE_SIGNATURE_LIST:MOPENPGP} != ""
+.include "openpgp/Makefile.inc"
+.endif
+
+.if ${VE_SELF_TESTS} != "no"
+# The input used for hash KATs
+VE_HASH_KAT_STR?= vc_PEM
+
+XCFLAGS.vets+= -DVE_HASH_KAT_STR=${VE_HASH_KAT_STR}
+.endif
+
+# this should be updated occassionally this is 2019-01-01Z
+SOURCE_DATE_EPOCH?= 1546329600
+.if ${MK_REPRODUCIBLE_BUILD} == "yes"
+BUILD_UTC?= ${SOURCE_DATE_EPOCH}
+.endif
+# BUILD_UTC provides a basis for the loader's notion of time
+# By default we use the mtime of BUILD_UTC_FILE
+.if empty(BUILD_UTC_FILE)
+BUILD_UTC_FILE:= ${.PARSEDIR:tA}/${.PARSEFILE}
+.endif
+# you can of course set BUILD_UTC to any value you like
+BUILD_UTC?= ${${STAT:Ustat} -f %m ${BUILD_UTC_FILE}:L:sh}
+
+# Generate ta.h containing one or more PEM encoded trust anchors in ta_PEM.
+#
+# If we are doing self-tests, we define another arrary vc_PEM
+# containing certificates that we can verify for each trust anchor.
+# This is typically a subordinate CA cert.
+# Finally we generate a hash of vc_PEM using each supported hash method
+# to use as a Known Answer Test (needed for FIPS 140-2)
+#
+vets.o vets.po vets.pico: ta.h
+ta.h: ${.ALLTARGETS:M[tv]*pem:O:u}
+ @( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
+ cat ${.ALLSRC:N*crl*:Mt*.pem} /dev/null | \
+ file2c -sx 'static const char ta_PEM[] = {' '};'; \
+ echo "${.newline}${VE_HASH_LIST:@H@static char vh_$H[] = \"`cat ${.ALLSRC:N*crl*:Mv*.pem} | ${$H:U${H:tl}}`\";${.newline}@}"; ) > ${.TARGET}
+.if ${VE_SELF_TESTS} != "no"
+ ( cat ${.ALLSRC:N*crl*:Mv*.pem} /dev/null | \
+ file2c -sx 'static const char vc_PEM[] = {' '};'; echo ) >> ${.TARGET}
+.endif
+ echo '#define BUILD_UTC ${BUILD_UTC}' >> ${.TARGET} ${.OODATE:MNOMETA_CMP}
+
+# This header records our preference for signature extensions.
+vesigned.o vesigned.po vesigned.pico: vse.h
+vse.h:
+ @( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
+ echo "static const char *signature_exts[] = {"; \
+ echo '${VE_SIGNATURE_EXT_LIST:@e@"$e",${.newline}@}'; \
+ echo 'NULL };' ) > ${.TARGET}
+
+
+.for s in ${BRSSL_SRCS} brf.c vets.c veta.c
+.ifdef BRSSL_SED
+$s: brssl.h
+.endif
+XCFLAGS.${s:R}+= ${BRSSL_CFLAGS}
+.endfor
+
+.endif
Property changes on: stable/12/lib/libsecureboot/Makefile.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/tests/Makefile
===================================================================
--- stable/12/lib/libsecureboot/tests/Makefile (nonexistent)
+++ stable/12/lib/libsecureboot/tests/Makefile (revision 346145)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+PROG= tvo
+
+SRCS+= tvo.c
+CFLAGS+= -DUNIT_TEST -g -O0
+
+LIBADD+= bearssl
+MAN=
+NO_SHARED=
+
+# we want to test verify_file api too
+# which requires a kludge or two
+.include "../Makefile.libsa.inc"
+BRSSL_CFLAGS := ${BRSSL_CFLAGS:N-DNO_STDIO}
+XCFLAGS.verify_file += -DSOPEN_MAX=64
+
+.include <bsd.prog.mk>
Property changes on: stable/12/lib/libsecureboot/tests/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/tests/Makefile.depend.host
===================================================================
--- stable/12/lib/libsecureboot/tests/Makefile.depend.host (nonexistent)
+++ stable/12/lib/libsecureboot/tests/Makefile.depend.host (revision 346145)
@@ -0,0 +1,12 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/libbearssl \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
Property changes on: stable/12/lib/libsecureboot/tests/Makefile.depend.host
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/tests/tvo.c
===================================================================
--- stable/12/lib/libsecureboot/tests/tvo.c (nonexistent)
+++ stable/12/lib/libsecureboot/tests/tvo.c (revision 346145)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "../libsecureboot-priv.h"
+
+#include <unistd.h>
+#include <err.h>
+#include <verify_file.h>
+
+char *Skip;
+
+int
+main(int argc, char *argv[])
+{
+ int n;
+ int fd;
+ int c;
+ int Vflag;
+ char *cp;
+ char *prefix;
+
+ prefix = NULL;
+ Skip = NULL;
+
+ n = ve_trust_init();
+ printf("Trust %d\n", n);
+ Vflag = 0;
+
+ while ((c = getopt(argc, argv, "dp:s:T:V")) != -1) {
+ switch (c) {
+ case 'd':
+ DebugVe++;
+ break;
+ case 'p':
+ prefix = optarg;
+ break;
+ case 's':
+ Skip = optarg;
+ break;
+ case 'T':
+ n = ve_trust_add(optarg);
+ printf("Local trust %s: %d\n", optarg, n);
+ break;
+ case 'V':
+ Vflag = 1;
+ break;
+ default:
+ errx(1, "unknown option: -%c", c);
+ break;
+ }
+ }
+
+ ve_self_tests();
+
+ for ( ; optind < argc; optind++) {
+ if (Vflag) {
+ /*
+ * Simulate what loader does.
+ * verify_file should "just work"
+ */
+ fd = open(argv[optind], O_RDONLY);
+ if (fd > 0) {
+ /*
+ * See if verify_file is happy
+ */
+ int x;
+
+ x = verify_file(fd, argv[optind], 0, VE_GUESS);
+ printf("verify_file(%s) = %d\n", argv[optind], x);
+ close(fd);
+ }
+ continue;
+ }
+#ifdef VE_OPENPGP_SUPPORT
+ if (strstr(argv[optind], "asc")) {
+ cp = (char *)verify_asc(argv[optind], 1);
+ if (cp) {
+ printf("Verified: %s: %.28s...\n",
+ argv[optind], cp);
+ fingerprint_info_add(argv[optind],
+ prefix, Skip, cp, NULL);
+ } else {
+ fprintf(stderr, "%s: %s\n",
+ argv[optind], ve_error_get());
+ }
+ } else
+#endif
+ if (strstr(argv[optind], "sig")) {
+ cp = (char *)verify_sig(argv[optind], 1);
+ if (cp) {
+ printf("Verified: %s: %.28s...\n",
+ argv[optind], cp);
+ fingerprint_info_add(argv[optind],
+ prefix, Skip, cp, NULL);
+ } else {
+ fprintf(stderr, "%s: %s\n",
+ argv[optind], ve_error_get());
+ }
+ } else if (strstr(argv[optind], "manifest")) {
+ cp = (char *)read_file(argv[optind], NULL);
+ if (cp) {
+ fingerprint_info_add(argv[optind],
+ prefix, Skip, cp, NULL);
+ }
+ } else {
+ fd = verify_open(argv[optind], O_RDONLY);
+ printf("verify_open(%s) = %d %s\n", argv[optind], fd,
+ (fd < 0) ? ve_error_get() : "");
+ if (fd > 0) {
+ /*
+ * Check that vectx_* can also verify the file.
+ */
+ void *vp;
+ char buf[BUFSIZ];
+ struct stat st;
+ int error;
+ size_t off, n;
+
+ fstat(fd, &st);
+ lseek(fd, 0, SEEK_SET);
+ off = st.st_size % 512;
+ vp = vectx_open(fd, argv[optind], off,
+ &st, &error);
+ if (!vp) {
+ printf("vectx_open(%s) failed: %d %s\n",
+ argv[optind], error,
+ ve_error_get());
+ } else {
+ off = vectx_lseek(vp,
+ (st.st_size % 1024), SEEK_SET);
+
+ if (off < st.st_size) {
+ n = vectx_read(vp, buf,
+ sizeof(buf));
+ if (n > 0)
+ off += n;
+ }
+ off = vectx_lseek(vp, 0, SEEK_END);
+ /* repeating that should be harmless */
+ off = vectx_lseek(vp, 0, SEEK_END);
+ error = vectx_close(vp);
+ if (error) {
+ printf("vectx_close(%s) == %d %s\n",
+ argv[optind], error,
+ ve_error_get());
+ } else {
+ printf("vectx_close: Verified: %s\n",
+ argv[optind]);
+ }
+ }
+ close(fd);
+ }
+ }
+ }
+ return (0);
+}
+
Property changes on: stable/12/lib/libsecureboot/tests/tvo.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/verify_file.c
===================================================================
--- stable/12/lib/libsecureboot/verify_file.c (nonexistent)
+++ stable/12/lib/libsecureboot/verify_file.c (revision 346145)
@@ -0,0 +1,421 @@
+/*-
+ * Copyright (c) 2017-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Routines to verify files loaded.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include "libsecureboot.h"
+#include <verify_file.h>
+#include <manifests.h>
+
+#define VE_NOT_CHECKED -42
+
+#ifdef UNIT_TEST
+# include <err.h>
+# define panic warn
+/*
+ * define MANIFEST_SKIP to Skip - in tests/tvo.c so that
+ * tvo can control the value we use in find_manifest()
+ */
+extern char *Skip;
+# undef MANIFEST_SKIP
+# define MANIFEST_SKIP Skip
+# undef VE_DEBUG_LEVEL
+#endif
+
+/*
+ * We sometimes need to know if input is verified or not.
+ * The extra slot is for tracking most recently opened.
+ */
+static int ve_status[SOPEN_MAX+1];
+static int ve_status_state;
+struct verify_status;
+struct verify_status *verified_files = NULL;
+static int loaded_manifests = 0; /* have we loaded anything? */
+
+#define VE_STATUS_NONE 1
+#define VE_STATUS_VALID 2
+
+/**
+ * @brief set ve status for fd
+ */
+static void
+ve_status_set(int fd, int ves)
+{
+ if (fd >= 0 && fd < SOPEN_MAX) {
+ ve_status[fd] = ves;
+ ve_status_state = VE_STATUS_VALID;
+ }
+ ve_status[SOPEN_MAX] = ves;
+}
+
+/**
+ * @brief get ve status of fd
+ *
+ * What we return depends on ve_status_state.
+ *
+ * @return
+ * @li ve_status[fd] if ve_status_state is valid
+ * @li ve_status[SOPEN_MAX] if ve_status_state is none
+ * @li VE_NOT_CHECKED if ve_status_state uninitialized
+ */
+int
+ve_status_get(int fd)
+{
+ if (!ve_status_state) {
+ return (VE_NOT_CHECKED);
+ }
+ if (ve_status_state == VE_STATUS_VALID &&
+ fd >= 0 && fd < SOPEN_MAX)
+ return (ve_status[fd]);
+ return (ve_status[SOPEN_MAX]); /* most recent */
+}
+
+/**
+ * @brief track verify status
+ *
+ * occasionally loader will make multiple calls
+ * for the same file, we need only check it once.
+ */
+struct verify_status {
+ dev_t vs_dev;
+ ino_t vs_ino;
+ int vs_status;
+ struct verify_status *vs_next;
+};
+
+static int
+is_verified(struct stat *stp)
+{
+ struct verify_status *vsp;
+
+ for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) {
+ if (stp->st_dev == vsp->vs_dev &&
+ stp->st_ino == vsp->vs_ino)
+ return (vsp->vs_status);
+ }
+ return (VE_NOT_CHECKED);
+}
+
+/* most recent first, since most likely to see repeated calls. */
+static void
+add_verify_status(struct stat *stp, int status)
+{
+ struct verify_status *vsp;
+
+ vsp = malloc(sizeof(struct verify_status));
+ vsp->vs_next = verified_files;
+ vsp->vs_dev = stp->st_dev;
+ vsp->vs_ino = stp->st_ino;
+ vsp->vs_status = status;
+ verified_files = vsp;
+}
+
+
+/**
+ * @brief
+ * load specified manifest if verified
+ */
+int
+load_manifest(const char *name, const char *prefix,
+ const char *skip, struct stat *stp)
+{
+ struct stat st;
+ size_t n;
+ int rc;
+ char *content;
+
+ rc = VE_FINGERPRINT_NONE;
+ n = strlen(name);
+ if (n > 4) {
+ if (!stp) {
+ stp = &st;
+ if (stat(name, &st) < 0 || !S_ISREG(st.st_mode))
+ return (rc);
+ }
+ rc = is_verified(stp);
+ if (rc != VE_NOT_CHECKED) {
+ return (rc);
+ }
+ /* loader has no sense of time */
+ ve_utc_set(stp->st_mtime);
+ content = (char *)verify_signed(name, VEF_VERBOSE);
+ if (content) {
+ fingerprint_info_add(name, prefix, skip, content, stp);
+ add_verify_status(stp, VE_VERIFIED);
+ loaded_manifests = 1; /* we are verifying! */
+ DEBUG_PRINTF(3, ("loaded: %s %s %s\n",
+ name, prefix, skip));
+ rc = 0;
+ } else {
+ rc = VE_FINGERPRINT_WRONG;
+ add_verify_status(stp, rc); /* remember */
+ }
+ }
+ return (rc);
+}
+
+static int
+find_manifest(const char *name)
+{
+ struct stat st;
+ char buf[MAXPATHLEN];
+ char *prefix;
+ char *skip;
+ const char **tp;
+ int rc;
+
+ strncpy(buf, name, MAXPATHLEN - 1);
+ if (!(prefix = strrchr(buf, '/')))
+ return (-1);
+ *prefix = '\0';
+ prefix = strdup(buf);
+ rc = VE_FINGERPRINT_NONE;
+ for (tp = manifest_names; *tp; tp++) {
+ snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp);
+ DEBUG_PRINTF(5, ("looking for %s\n", buf));
+ if (stat(buf, &st) == 0 && st.st_size > 0) {
+#ifdef MANIFEST_SKIP_ALWAYS /* very unlikely */
+ skip = MANIFEST_SKIP_ALWAYS;
+#else
+#ifdef MANIFEST_SKIP /* rare */
+ if (*tp[0] == '.') {
+ skip = MANIFEST_SKIP;
+ } else
+#endif
+ skip = NULL;
+#endif
+ rc = load_manifest(buf, skip ? prefix : NULL,
+ skip, &st);
+ break;
+ }
+ }
+ free(prefix);
+ return (rc);
+}
+
+
+#ifdef LOADER_VERIEXEC_TESTING
+# define ACCEPT_NO_FP_DEFAULT VE_MUST + 1
+#else
+# define ACCEPT_NO_FP_DEFAULT VE_MUST
+#endif
+#ifndef VE_VERBOSE_DEFAULT
+# define VE_VERBOSE_DEFAULT 0
+#endif
+
+static int
+severity_guess(const char *filename)
+{
+ const char *cp;
+
+ /* Some files like *.conf and *.hints may be unsigned */
+ if ((cp = strrchr(filename, '.'))) {
+ if (strcmp(cp, ".conf") == 0 ||
+ strcmp(cp, ".cookie") == 0 ||
+ strcmp(cp, ".hints") == 0)
+ return (VE_TRY);
+ }
+ return (VE_WANT);
+}
+
+static void
+verify_tweak(char *tweak, int *accept_no_fp, int *verbose, int *verifying)
+{
+ if (strcmp(tweak, "off") == 0) {
+ *verifying = 0;
+ } else if (strcmp(tweak, "strict") == 0) {
+ /* anything caller wants verified must be */
+ *accept_no_fp = VE_WANT;
+ *verbose = 1; /* warn of anything unverified */
+ /* treat self test failure as fatal */
+ if (!ve_self_tests()) {
+ panic("verify self tests failed");
+ }
+ } else if (strcmp(tweak, "modules") == 0) {
+ /* modules/kernel must be verified */
+ *accept_no_fp = VE_MUST;
+ } else if (strcmp(tweak, "try") == 0) {
+ /* best effort: always accept no fp */
+ *accept_no_fp = VE_MUST + 1;
+ } else if (strcmp(tweak, "verbose") == 0) {
+ *verbose = 1;
+ } else if (strcmp(tweak, "quiet") == 0) {
+ *verbose = 0;
+ }
+}
+
+/**
+ * @brief verify an open file
+ *
+ * @param[in] fd
+ * open descriptor
+ *
+ * @param[in] filename
+ * path we opened and will use to lookup fingerprint
+ *
+ * @param[in] off
+ * current offset in fd, must be restored on return
+ *
+ * @param[in] severity
+ * indicator of how to handle case of missing fingerprint
+ *
+ * We look for a signed manifest relative to the filename
+ * just opened and verify/load it if needed.
+ *
+ * We then use verify_fd() in libve to actually verify that hash for
+ * open file. If it returns < 0 we look at the severity arg to decide
+ * what to do about it.
+ *
+ * If verify_fd() returns VE_FINGERPRINT_NONE we accept it if severity
+ * is < accept_no_fp.
+ *
+ * @return >= 0 on success < 0 on failure
+ */
+int
+verify_file(int fd, const char *filename, off_t off, int severity)
+{
+ static int verifying = -1;
+ static int accept_no_fp = ACCEPT_NO_FP_DEFAULT;
+ static int verbose = VE_VERBOSE_DEFAULT;
+ struct stat st;
+ char *cp;
+ int rc;
+
+ if (verifying < 0) {
+ verifying = ve_trust_init();
+#ifdef VE_DEBUG_LEVEL
+ ve_debug_set(VE_DEBUG_LEVEL);
+#endif
+ /* initialize ve_status with default result */
+ rc = verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING;
+ ve_status_set(0, rc);
+ ve_status_state = VE_STATUS_NONE;
+ if (verifying)
+ ve_self_tests();
+ }
+ if (!verifying)
+ return (0);
+
+ if (fd < 0 || fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
+ return (0);
+
+ DEBUG_PRINTF(3, ("fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n",
+ fd, filename, (long long)off, (long long)st.st_dev,
+ (long long)st.st_ino));
+
+
+ rc = is_verified(&st);
+ if (rc != VE_NOT_CHECKED) {
+ ve_status_set(fd, rc);
+ return (rc);
+ }
+ rc = find_manifest(filename);
+ if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
+ if (severity <= VE_GUESS)
+ severity = severity_guess(filename);
+ if ((rc = verify_fd(fd, filename, off, &st)) >= 0) {
+ if (verbose || severity > VE_WANT) {
+#if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0
+ printf("Verified %s %llu,%llu\n", filename,
+ st.st_dev, st.st_ino);
+#else
+ printf("Verified %s\n", filename);
+#endif
+ }
+ if (severity < VE_MUST) { /* not a kernel or module */
+
+ if ((cp = strrchr(filename, '/'))) {
+ cp++;
+ if (strncmp(cp, "loader.ve.", 10) == 0) {
+ cp += 10;
+ verify_tweak(cp,
+ &accept_no_fp, &verbose,
+ &verifying);
+ }
+ }
+ }
+ add_verify_status(&st, rc);
+ ve_status_set(fd, rc);
+ return (rc);
+ }
+
+ if (severity || verbose || rc == VE_FINGERPRINT_WRONG)
+ printf("Unverified: %s\n", ve_error_get());
+ if (rc == VE_FINGERPRINT_UNKNOWN && severity < VE_MUST)
+ rc = VE_UNVERIFIED_OK;
+ else if (rc == VE_FINGERPRINT_NONE && severity < accept_no_fp)
+ rc = VE_UNVERIFIED_OK;
+
+ add_verify_status(&st, rc);
+ }
+#ifdef LOADER_VERIEXEC_TESTING
+ else if (rc != VE_FINGERPRINT_WRONG) {
+ /*
+ * We have not loaded any manifest and
+ * not because of verication failure.
+ * Most likely reason is we have none.
+ * Allow boot to proceed if we are just testing.
+ */
+ return (VE_UNVERIFIED_OK);
+ }
+#endif
+ if (rc == VE_FINGERPRINT_WRONG && severity > accept_no_fp)
+ panic("cannot continue");
+ ve_status_set(fd, rc);
+ return (rc);
+}
+
+/**
+ * @brief get hex string for pcr value and export
+ *
+ * In case we are doing measured boot, provide
+ * value of the "pcr" data we have accumulated.
+ */
+void
+verify_pcr_export(void)
+{
+#ifdef VE_PCR_SUPPORT
+ char hexbuf[br_sha256_SIZE * 2 + 2];
+ unsigned char hbuf[br_sha256_SIZE];
+ char *hex;
+ ssize_t hlen;
+
+ hlen = ve_pcr_get(hbuf, sizeof(hbuf));
+ if (hlen > 0) {
+ hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
+ if (hex) {
+ hex[hlen*2] = '\0'; /* clobber newline */
+ setenv("loader.ve.pcr", hex, 1);
+ }
+ }
+#endif
+}
Property changes on: stable/12/lib/libsecureboot/verify_file.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/Makefile
===================================================================
--- stable/12/lib/libsecureboot/Makefile (nonexistent)
+++ stable/12/lib/libsecureboot/Makefile (revision 346145)
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+LIB= secureboot
+
+.include "Makefile.inc"
+
+INCS= h/libsecureboot.h
+
+.include <bsd.lib.mk>
Property changes on: stable/12/lib/libsecureboot/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/Makefile.depend
===================================================================
--- stable/12/lib/libsecureboot/Makefile.depend (nonexistent)
+++ stable/12/lib/libsecureboot/Makefile.depend (revision 346145)
@@ -0,0 +1,17 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
Property changes on: stable/12/lib/libsecureboot/Makefile.depend
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/Makefile.depend.host
===================================================================
--- stable/12/lib/libsecureboot/Makefile.depend.host (nonexistent)
+++ stable/12/lib/libsecureboot/Makefile.depend.host (revision 346145)
@@ -0,0 +1,12 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/libstand \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
Property changes on: stable/12/lib/libsecureboot/Makefile.depend.host
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/Makefile.libsa.inc
===================================================================
--- stable/12/lib/libsecureboot/Makefile.libsa.inc (nonexistent)
+++ stable/12/lib/libsecureboot/Makefile.libsa.inc (revision 346145)
@@ -0,0 +1,40 @@
+# $FreeBSD$
+
+BRSSL_CFLAGS+= -DNO_STDIO
+
+.include "Makefile.inc"
+
+# for "measured boot"
+# loader puts the equivalent of TPM's PCR register into kenv
+# this is not as good but *way* simpler than talking to TPM
+CFLAGS+= -DVE_PCR_SUPPORT
+
+# sources that only apply to libsa
+SRCS+= \
+ vectx.c \
+ veopen.c \
+ vepcr.c \
+ verify_file.c \
+
+# this is the list of paths (relative to a file
+# that we need to verify) used to find a signed manifest.
+# the signature extensions in VE_SIGNATURE_EXT_LIST
+# will be applied to each.
+VE_MANIFEST_LIST?= manifest ../manifest
+
+verify_file.o: manifests.h
+manifests.h:
+ @( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
+ echo "static const char *manifest_names[] = {"; \
+ echo '${VE_MANIFEST_LIST:@m@"$m",${.newline}@}'; \
+ echo 'NULL };' ) > ${.TARGET}
+
+XCFLAGS.verify_file+= \
+ -DVE_DEBUG_LEVEL=${VE_DEBUG_LEVEL:U0} \
+ -DVE_VERBOSE_DEFAULT=${VE_VERBOSE_DEFAULT:U0} \
+
+.if !empty(MANIFEST_SKIP_ALWAYS)
+XCFLAGS.verify_file+= -DMANIFEST_SKIP_ALWAYS=\"${MANIFEST_SKIP_ALWAYS}\"
+.elif !empty(MANIFEST_SKIP)
+XCFLAGS.verify_file+= -DMANIFEST_SKIP=\"${MANIFEST_SKIP}\"
+.endif
Property changes on: stable/12/lib/libsecureboot/Makefile.libsa.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/README.rst
===================================================================
--- stable/12/lib/libsecureboot/README.rst (nonexistent)
+++ stable/12/lib/libsecureboot/README.rst (revision 346145)
@@ -0,0 +1,134 @@
+libsecureboot
+*************
+
+This library depends one way or another on verifying digital signatures.
+To do that, the necessary trust anchors need to be available.
+
+The simplest (and most attractive for an embedded system) is to
+capture them in this library.
+
+The makefile ``local.trust.mk`` is responsible for doing that.
+The file provided is just an example and depends on the environment
+here at Juniper.
+
+Within Juniper we use signing servers, which apart from signing things
+provide access to the necessary trust anchors.
+That signing server is freely available - see
+http://www.crufty.net/sjg/docs/signing-server.htm
+
+X.509 certificates chains offer a lot of flexibility over time and are
+a great solution for an embedded vendor like Juniper or even
+FreeBSD.org, but are probably overkill for personal or small site use.
+
+Setting up a CA for this is rather involved so I'll just provide a
+link below to suitable tutorial below.
+
+Using OpenPGP is much simpler.
+
+
+OpenPGP
+========
+
+This is very simple to setup and use.
+
+An RSA key pair can be generated with::
+
+ GNUPGHOME=$PWD/.gnupg gpg --openpgp \
+ --quick-generate-key --batch --passphrase '' "keyname" RSA
+
+The use of ``GNUPGHOME=$PWD/.gnupg`` just avoids messing with personal
+keyrings.
+We can list the resulting key::
+
+ GNUPGHOME=$PWD/.gnupg gpg --openpgp --list-keys
+
+ gpg: WARNING: unsafe permissions on homedir
+ '/h/sjg/openpgp/.gnupg'
+ gpg: Warning: using insecure memory!
+ /h/sjg/openpgp/.gnupg/pubring.kbx
+ ---------------------------------
+ pub rsa2048 2018-03-26 [SC] [expires: 2020-03-25]
+ AB39B111E40DD019E0E7C171ACA72B4719FD2523
+ uid [ultimate] OpenPGPtest
+
+The ``keyID`` we want later will be the last 8 octets
+(``ACA72B4719FD2523``)
+This is what we will use for looking up the key.
+
+We can then export the private and public keys::
+
+ GNUPGHOME=$PWD/.gnupg gpg --openpgp \
+ --export --armor > ACA72B4719FD2523.pub.asc
+ GNUPGHOME=$PWD/.gnupg gpg --openpgp \
+ --export-secret-keys --armor > ACA72B4719FD2523.sec.asc
+
+The public key ``ACA72B4719FD2523.pub.asc`` is what we want to
+embed in this library.
+If you look at the ``ta_asc.h`` target in ``openpgp/Makefile.inc``
+we want the trust anchor in a file named ``t*.asc``
+eg. ``ta_openpgp.asc``.
+
+The ``ta_asc.h`` target will capture all such ``t*.asc`` into that
+header.
+
+Signatures
+----------
+
+We expect ascii armored (``.asc``) detached signatures.
+Eg. signature for ``manifest`` would be in ``manifest.asc``
+
+We only support version 4 signatures using RSA (the default for ``gpg``).
+
+
+OpenSSL
+========
+
+The basic idea here is to setup a private CA.
+
+There are lots of good tutorials on available on this topic;
+just google *setup openssl ca*.
+A good example is https://jamielinux.com/docs/openssl-certificate-authority/
+
+All we need for this library is a copy of the PEM encoded root CA
+certificate (trust anchor). This is expected to be in a file named
+``t*.pem`` eg. ``ta_rsa.pem``.
+
+The ``ta.h`` target in ``Makefile.inc`` will combine all such
+``t*.pem`` files into that header.
+
+Signatures
+----------
+
+For Junos we currently use EC DSA signatures with file extension
+``.esig`` so the signature for ``manifest`` would be ``manifest.esig``
+
+This was the first signature method we used with the remote signing
+servers and it ends up being a signature of a hash.
+Ie. client sends a hash which during signing gets hashed again.
+So for Junos we define VE_ECDSA_HASH_AGAIN which causes ``verify_ec``
+to hash again.
+
+Otherwise our EC DSA and RSA signatures are the default used by
+OpenSSL - an original design goal was that a customer could verify our
+signatures using nothing but an ``openssl`` binary.
+
+
+Self tests
+==========
+
+If you want the ``loader`` to perform self-test of a given signature
+verification method on startup (a must for FIPS 140-2 certification)
+you need to provide a suitable file signed by each supported trust
+anchor.
+
+These should be stored in files with names that start with ``v`` and
+have the same extension as the corresponding trust anchor.
+Eg. for ``ta_openpgp.asc`` we use ``vc_openpgp.asc``
+and for ``ta_rsa.pem`` we use ``vc_rsa.pem``.
+
+Note for the X.509 case we simply extract the 2nd last certificate
+from the relevant chain - which is sure to be a valid certificate
+signed by the corresponding trust anchor.
+
+--------------------
+$FreeBSD$
Property changes on: stable/12/lib/libsecureboot/README.rst
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Index: stable/12/lib/libsecureboot/brf.c
===================================================================
--- stable/12/lib/libsecureboot/brf.c (nonexistent)
+++ stable/12/lib/libsecureboot/brf.c (revision 346145)
@@ -0,0 +1,403 @@
+// The functions here are derrived from BearSSL/tools/*.c
+// When that is refactored suitably we can use them directly.
+/*
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define NEED_BRSSL_H
+#include "libsecureboot-priv.h"
+#include <brssl.h>
+
+
+static int
+is_ign(int c)
+{
+ if (c == 0) {
+ return (0);
+ }
+ if (c <= 32 || c == '-' || c == '_' || c == '.'
+ || c == '/' || c == '+' || c == ':')
+ {
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Get next non-ignored character, normalised:
+ * ASCII letters are converted to lowercase
+ * control characters, space, '-', '_', '.', '/', '+' and ':' are ignored
+ * A terminating zero is returned as 0.
+ */
+static int
+next_char(const char **ps, const char *limit)
+{
+ for (;;) {
+ int c;
+
+ if (*ps == limit) {
+ return (0);
+ }
+ c = *(*ps) ++;
+ if (c == 0) {
+ return (0);
+ }
+ if (c >= 'A' && c <= 'Z') {
+ c += 'a' - 'A';
+ }
+ if (!is_ign(c)) {
+ return (c);
+ }
+ }
+}
+
+/*
+ * Partial string equality comparison, with normalisation.
+ */
+static int
+eqstr_chunk(const char *s1, size_t s1_len, const char *s2, size_t s2_len)
+{
+ const char *lim1, *lim2;
+
+ lim1 = s1 + s1_len;
+ lim2 = s2 + s2_len;
+ for (;;) {
+ int c1, c2;
+
+ c1 = next_char(&s1, lim1);
+ c2 = next_char(&s2, lim2);
+ if (c1 != c2) {
+ return (0);
+ }
+ if (c1 == 0) {
+ return (1);
+ }
+ }
+}
+
+/* see brssl.h */
+int
+eqstr(const char *s1, const char *s2)
+{
+ return (eqstr_chunk(s1, strlen(s1), s2, strlen(s2)));
+}
+
+int
+looks_like_DER(const unsigned char *buf, size_t len)
+{
+ int fb;
+ size_t dlen;
+
+ if (len < 2) {
+ return (0);
+ }
+ if (*buf ++ != 0x30) {
+ return (0);
+ }
+ fb = *buf ++;
+ len -= 2;
+ if (fb < 0x80) {
+ return ((size_t)fb == len);
+ } else if (fb == 0x80) {
+ return (0);
+ } else {
+ fb -= 0x80;
+ if (len < (size_t)fb + 2) {
+ return (0);
+ }
+ len -= (size_t)fb;
+ dlen = 0;
+ while (fb -- > 0) {
+ if (dlen > (len >> 8)) {
+ return (0);
+ }
+ dlen = (dlen << 8) + (size_t)*buf ++;
+ }
+ return (dlen == len);
+ }
+}
+
+static void
+vblob_append(void *cc, const void *data, size_t len)
+{
+ bvector *bv;
+
+ bv = cc;
+ VEC_ADDMANY(*bv, data, len);
+}
+
+void
+free_pem_object_contents(pem_object *po)
+{
+ if (po != NULL) {
+ xfree(po->name);
+ xfree(po->data);
+ }
+}
+
+pem_object *
+decode_pem(const void *src, size_t len, size_t *num)
+{
+ VECTOR(pem_object) pem_list = VEC_INIT;
+ br_pem_decoder_context pc;
+ pem_object po, *pos;
+ const unsigned char *buf;
+ bvector bv = VEC_INIT;
+ int inobj;
+ int extra_nl;
+
+ *num = 0;
+ br_pem_decoder_init(&pc);
+ buf = src;
+ inobj = 0;
+ po.name = NULL;
+ po.data = NULL;
+ po.data_len = 0;
+ extra_nl = 1;
+ while (len > 0) {
+ size_t tlen;
+
+ tlen = br_pem_decoder_push(&pc, buf, len);
+ buf += tlen;
+ len -= tlen;
+ switch (br_pem_decoder_event(&pc)) {
+
+ case BR_PEM_BEGIN_OBJ:
+ po.name = xstrdup(br_pem_decoder_name(&pc));
+ br_pem_decoder_setdest(&pc, vblob_append, &bv);
+ inobj = 1;
+ break;
+
+ case BR_PEM_END_OBJ:
+ if (inobj) {
+ po.data = VEC_TOARRAY(bv);
+ po.data_len = VEC_LEN(bv);
+ VEC_ADD(pem_list, po);
+ VEC_CLEAR(bv);
+ po.name = NULL;
+ po.data = NULL;
+ po.data_len = 0;
+ inobj = 0;
+ }
+ break;
+
+ case BR_PEM_ERROR:
+ xfree(po.name);
+ VEC_CLEAR(bv);
+ ve_error_set("ERROR: invalid PEM encoding");
+ VEC_CLEAREXT(pem_list, &free_pem_object_contents);
+ return (NULL);
+ }
+
+ /*
+ * We add an extra newline at the end, in order to
+ * support PEM files that lack the newline on their last
+ * line (this is somwehat invalid, but PEM format is not
+ * standardised and such files do exist in the wild, so
+ * we'd better accept them).
+ */
+ if (len == 0 && extra_nl) {
+ extra_nl = 0;
+ buf = (const unsigned char *)"\n";
+ len = 1;
+ }
+ }
+ if (inobj) {
+ ve_error_set("ERROR: unfinished PEM object");
+ xfree(po.name);
+ VEC_CLEAR(bv);
+ VEC_CLEAREXT(pem_list, &free_pem_object_contents);
+ return (NULL);
+ }
+
+ *num = VEC_LEN(pem_list);
+ VEC_ADD(pem_list, po);
+ pos = VEC_TOARRAY(pem_list);
+ VEC_CLEAR(pem_list);
+ return (pos);
+}
+
+br_x509_certificate *
+parse_certificates(unsigned char *buf, size_t len, size_t *num)
+{
+ VECTOR(br_x509_certificate) cert_list = VEC_INIT;
+ pem_object *pos;
+ size_t u, num_pos;
+ br_x509_certificate *xcs;
+ br_x509_certificate dummy;
+
+ *num = 0;
+
+ /*
+ * Check for a DER-encoded certificate.
+ */
+ if (looks_like_DER(buf, len)) {
+ xcs = xmalloc(2 * sizeof *xcs);
+ xcs[0].data = buf;
+ xcs[0].data_len = len;
+ xcs[1].data = NULL;
+ xcs[1].data_len = 0;
+ *num = 1;
+ return (xcs);
+ }
+
+ pos = decode_pem(buf, len, &num_pos);
+ if (pos == NULL) {
+ return (NULL);
+ }
+ for (u = 0; u < num_pos; u ++) {
+ if (eqstr(pos[u].name, "CERTIFICATE")
+ || eqstr(pos[u].name, "X509 CERTIFICATE"))
+ {
+ br_x509_certificate xc;
+
+ xc.data = pos[u].data;
+ xc.data_len = pos[u].data_len;
+ pos[u].data = NULL;
+ VEC_ADD(cert_list, xc);
+ }
+ }
+ for (u = 0; u < num_pos; u ++) {
+ free_pem_object_contents(&pos[u]);
+ }
+ xfree(pos);
+
+ if (VEC_LEN(cert_list) == 0) {
+ return (NULL);
+ }
+ *num = VEC_LEN(cert_list);
+ dummy.data = NULL;
+ dummy.data_len = 0;
+ VEC_ADD(cert_list, dummy);
+ xcs = VEC_TOARRAY(cert_list);
+ VEC_CLEAR(cert_list);
+ return (xcs);
+}
+
+br_x509_certificate *
+read_certificates(const char *fname, size_t *num)
+{
+ br_x509_certificate *xcs;
+ unsigned char *buf;
+ size_t len;
+
+ *num = 0;
+
+ /*
+ * TODO: reading the whole file is crude; we could parse them
+ * in a streamed fashion. But it does not matter much in practice.
+ */
+ buf = read_file(fname, &len);
+ if (buf == NULL) {
+ return (NULL);
+ }
+ xcs = parse_certificates(buf, len, num);
+ if (xcs == NULL) {
+ ve_error_set("ERROR: no certificate in file '%s'\n", fname);
+ }
+ xfree(buf);
+ return (xcs);
+}
+
+/* see brssl.h */
+void
+free_certificates(br_x509_certificate *certs, size_t num)
+{
+ size_t u;
+
+ for (u = 0; u < num; u ++) {
+ xfree(certs[u].data);
+ }
+ xfree(certs);
+}
+
+
+static void
+dn_append(void *ctx, const void *buf, size_t len)
+{
+ VEC_ADDMANY(*(bvector *)ctx, buf, len);
+}
+
+int
+certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,
+ br_x509_certificate *xc)
+{
+ br_x509_decoder_context dc;
+ bvector vdn = VEC_INIT;
+ br_x509_pkey *pk;
+
+ br_x509_decoder_init(&dc, dn_append, &vdn);
+ br_x509_decoder_push(&dc, xc->data, xc->data_len);
+ pk = br_x509_decoder_get_pkey(&dc);
+ if (pk == NULL) {
+ ve_error_set("ERROR: CA decoding failed with error %d\n",
+ br_x509_decoder_last_error(&dc));
+ VEC_CLEAR(vdn);
+ return (-1);
+ }
+ ta->dn.data = VEC_TOARRAY(vdn);
+ ta->dn.len = VEC_LEN(vdn);
+ VEC_CLEAR(vdn);
+ ta->flags = 0;
+ if (br_x509_decoder_isCA(&dc)) {
+ ta->flags |= BR_X509_TA_CA;
+ }
+ switch (pk->key_type) {
+ case BR_KEYTYPE_RSA:
+ ta->pkey.key_type = BR_KEYTYPE_RSA;
+ ta->pkey.key.rsa.n = xblobdup(pk->key.rsa.n, pk->key.rsa.nlen);
+ ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
+ ta->pkey.key.rsa.e = xblobdup(pk->key.rsa.e, pk->key.rsa.elen);
+ ta->pkey.key.rsa.elen = pk->key.rsa.elen;
+ break;
+ case BR_KEYTYPE_EC:
+ ta->pkey.key_type = BR_KEYTYPE_EC;
+ ta->pkey.key.ec.curve = pk->key.ec.curve;
+ ta->pkey.key.ec.q = xblobdup(pk->key.ec.q, pk->key.ec.qlen);
+ ta->pkey.key.ec.qlen = pk->key.ec.qlen;
+ break;
+ default:
+ ve_error_set("ERROR: unsupported public key type in CA\n");
+ xfree(ta->dn.data);
+ return (-1);
+ }
+ return (0);
+}
+
+/* see brssl.h */
+void
+free_ta_contents(br_x509_trust_anchor *ta)
+{
+ xfree(ta->dn.data);
+ switch (ta->pkey.key_type) {
+ case BR_KEYTYPE_RSA:
+ xfree(ta->pkey.key.rsa.n);
+ xfree(ta->pkey.key.rsa.e);
+ break;
+ case BR_KEYTYPE_EC:
+ xfree(ta->pkey.key.ec.q);
+ break;
+ }
+}
Property changes on: stable/12/lib/libsecureboot/brf.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/h/libsecureboot.h
===================================================================
--- stable/12/lib/libsecureboot/h/libsecureboot.h (nonexistent)
+++ stable/12/lib/libsecureboot/h/libsecureboot.h (revision 346145)
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2017-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * $FreeBSD$
+ */
+#ifndef _LIBSECUREBOOT_H_
+#define _LIBSECUREBOOT_H_
+
+#include <sys/param.h>
+#ifdef _STANDALONE
+#include <stand.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#endif
+
+#include <bearssl.h>
+
+#ifndef NEED_BRSSL_H
+unsigned char * read_file(const char *, size_t *);
+#endif
+
+extern int DebugVe;
+
+#define DEBUG_PRINTF(n, x) if (DebugVe >= n) printf x
+
+int ve_trust_init(void);
+int ve_trust_add(const char *);
+void ve_debug_set(int);
+void ve_utc_set(time_t utc);
+char *ve_error_get(void);
+int ve_error_set(const char *, ...) __printflike(1,2);
+int ve_self_tests(void);
+
+void fingerprint_info_add(const char *, const char *, const char *,
+ const char *, struct stat *);
+
+int ve_check_hash(br_hash_compat_context *, const br_hash_class *,
+ const char *, const char *, size_t);
+
+struct vectx;
+struct vectx* vectx_open(int, const char *, off_t, struct stat *, int *);
+ssize_t vectx_read(struct vectx *, void *, size_t);
+off_t vectx_lseek(struct vectx *, off_t, int);
+int vectx_close(struct vectx *);
+
+char * hexdigest(char *, size_t, unsigned char *, size_t);
+int verify_fd(int, const char *, off_t, struct stat *);
+int verify_open(const char *, int);
+
+unsigned char *verify_signed(const char *, int);
+unsigned char *verify_sig(const char *, int);
+unsigned char *verify_asc(const char *, int); /* OpenPGP */
+
+void ve_pcr_init(void);
+void ve_pcr_update(unsigned char *, size_t);
+ssize_t ve_pcr_get(unsigned char *, size_t);
+
+/* flags for verify_{asc,sig,signed} */
+#define VEF_VERBOSE 1
+
+#define VE_FINGERPRINT_OK 1
+/* errors from verify_fd */
+#define VE_FINGERPRINT_NONE -2
+#define VE_FINGERPRINT_WRONG -3
+#define VE_FINGERPRINT_UNKNOWN -4 /* may not be an error */
+
+#endif /* _LIBSECUREBOOT_H_ */
Property changes on: stable/12/lib/libsecureboot/h/libsecureboot.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/h/verify_file.h
===================================================================
--- stable/12/lib/libsecureboot/h/verify_file.h (nonexistent)
+++ stable/12/lib/libsecureboot/h/verify_file.h (revision 346145)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2017-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _VERIFY_FILE_H_
+#define _VERIFY_FILE_H_
+
+#define VE_GUESS -1 /* let verify_file work it out */
+#define VE_TRY 0 /* we don't mind if unverified */
+#define VE_WANT 1 /* we want this verified */
+#define VE_MUST 2 /* this must be verified */
+
+#define VE_VERIFIED 1 /* all good */
+#define VE_UNVERIFIED_OK 0 /* not verified but that's ok */
+#define VE_NOT_VERIFYING 2 /* we are not verifying */
+
+struct stat;
+
+void ve_debug_set(int);
+int ve_status_get(int);
+int load_manifest(const char *, const char *, const char *, struct stat *);
+int verify_file(int, const char *, off_t, int);
+void verify_pcr_export(void);
+
+#endif /* _VERIFY_FILE_H_ */
Property changes on: stable/12/lib/libsecureboot/h/verify_file.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/libsecureboot-priv.h
===================================================================
--- stable/12/lib/libsecureboot/libsecureboot-priv.h (nonexistent)
+++ stable/12/lib/libsecureboot/libsecureboot-priv.h (revision 346145)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2017, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * $FreeBSD$
+ */
+#ifndef _LIBSECUREBOOT_PRIV_H_
+#define _LIBSECUREBOOT_PRIV_H_
+
+/* public api */
+#include "libsecureboot.h"
+
+size_t ve_trust_anchors_add(br_x509_certificate *, size_t);
+char *fingerprint_info_lookup(int, const char *);
+
+br_x509_certificate * parse_certificates(unsigned char *, size_t, size_t *);
+int certificate_to_trust_anchor_inner(br_x509_trust_anchor *,
+ br_x509_certificate *);
+
+int verify_rsa_digest(br_rsa_public_key *pkey,
+ const unsigned char *hash_oid,
+ unsigned char *mdata, size_t mlen,
+ unsigned char *sdata, size_t slen);
+
+int openpgp_self_tests(void);
+
+#endif /* _LIBSECUREBOOT_PRIV_H_ */
Property changes on: stable/12/lib/libsecureboot/libsecureboot-priv.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/local.trust.mk
===================================================================
--- stable/12/lib/libsecureboot/local.trust.mk (nonexistent)
+++ stable/12/lib/libsecureboot/local.trust.mk (revision 346145)
@@ -0,0 +1,114 @@
+# $FreeBSD$
+
+# Consider this file an example.
+#
+# For Junos this is how we obtain trust anchor .pems
+# the signing server (http://www.crufty.net/sjg/blog/signing-server.htm)
+# for each key will provide the appropriate certificate chain on request
+
+# force these for Junos
+MANIFEST_SKIP_ALWAYS= boot
+VE_HASH_LIST= \
+ SHA1 \
+ SHA256 \
+ SHA384
+
+VE_SIGNATURE_LIST= \
+ ECDSA
+
+VE_SIGNATURE_EXT_LIST= \
+ esig
+
+VE_SELF_TESTS= yes
+
+.if ${MACHINE} == "host" && ${.CURDIR:T} == "tests"
+# for testing
+VE_HASH_LIST+= \
+ SHA512
+
+VE_SIGNATURE_LIST+= \
+ RSA \
+ DEPRECATED_RSA_SHA1
+
+VE_SIGNATURE_EXT_LIST+= \
+ sig
+.endif
+
+SIGNER ?= ${SB_TOOLS_PATH:U/volume/buildtools/bin}/sign.py
+
+.if exists(${SIGNER})
+SIGN_HOST ?= ${SB_SITE:Usvl}-junos-signer.juniper.net
+ECDSA_PORT:= ${133%y:L:gmtime}
+SIGN_ECDSA= ${PYTHON} ${SIGNER} -u ${SIGN_HOST}:${ECDSA_PORT} -h sha256
+RSA2_PORT:= ${163%y:L:gmtime}
+SIGN_RSA2= ${PYTHON} ${SIGNER} -u ${SIGN_HOST}:${RSA2_PORT} -h sha256
+
+.if !empty(OPENPGP_SIGN_URL)
+VE_SIGNATURE_LIST+= OPENPGP
+VE_SIGNATURE_EXT_LIST+= asc
+
+SIGN_OPENPGP= ${PYTHON} ${SIGNER:H}/openpgp-sign.py -a -u ${OPENPGP_SIGN_URL}
+
+ta_openpgp.asc:
+ ${SIGN_OPENPGP} -C ${.TARGET}
+
+ta.h: ta_openpgp.asc
+
+.if ${VE_SELF_TESTS} != "no"
+# for self test
+vc_openpgp.asc: ta_openpgp.asc
+ ${SIGN_OPENPGP} ${.ALLSRC:M*.asc}
+ mv ta_openpgp.asc.asc ${.TARGET}
+
+ta.h: vc_openpgp.asc
+.endif
+.endif
+
+rcerts.pem:
+ ${SIGN_RSA2} -C ${.TARGET}
+
+ecerts.pem:
+ ${SIGN_ECDSA} -C ${.TARGET}
+
+.if ${VE_SIGNATURE_LIST:tu:MECDSA} != ""
+# the last cert in the chain is the one we want
+ta_ec.pem: ecerts.pem _LAST_PEM_USE
+
+.if ${VE_SELF_TESTS} != "no"
+# these are for verification self test
+vc_ec.pem: ecerts.pem _2ndLAST_PEM_USE
+.endif
+.endif
+
+.if ${VE_SIGNATURE_LIST:tu:MRSA} != ""
+ta_rsa.pem: rcerts.pem _LAST_PEM_USE
+.if ${VE_SELF_TESTS} != "no"
+vc_rsa.pem: rcerts.pem _2ndLAST_PEM_USE
+.endif
+.endif
+
+# we take the mtime of this as our baseline time
+BUILD_UTC_FILE= ecerts.pem
+#VE_DEBUG_LEVEL=3
+#VE_VERBOSE_DEFAULT=1
+
+.else
+# you need to provide t*.pem or t*.asc files for each trust anchor
+.if empty(TRUST_ANCHORS)
+TRUST_ANCHORS!= cd ${.CURDIR} && 'ls' -1 *.pem t*.asc 2> /dev/null
+.endif
+.if empty(TRUST_ANCHORS)
+.error Need TRUST_ANCHORS see ${.CURDIR}/README.rst
+.endif
+.if ${TRUST_ANCHORS:T:Mt*.pem} != ""
+ta.h: ${TRUST_ANCHORS:M*.pem}
+.endif
+.if ${TRUST_ANCHORS:T:Mt*.asc} != ""
+VE_SIGNATURE_LIST+= OPENPGP
+VE_SIGNATURE_EXT_LIST+= asc
+ta_asc.h: ${TRUST_ANCHORS:M*.asc}
+.endif
+# we take the mtime of this as our baseline time
+BUILD_UTC_FILE?= ${TRUST_ANCHORS:[1]}
+.endif
+
Property changes on: stable/12/lib/libsecureboot/local.trust.mk
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/openpgp/Makefile.inc
===================================================================
--- stable/12/lib/libsecureboot/openpgp/Makefile.inc (nonexistent)
+++ stable/12/lib/libsecureboot/openpgp/Makefile.inc (revision 346145)
@@ -0,0 +1,48 @@
+# $FreeBSD$
+
+# decode OpenPGP signatures per rfc4880
+.PATH: ${.PARSEDIR}
+
+CFLAGS+= -DUSE_BEARSSL
+
+BRSSL_SRCS+= dearmor.c
+SRCS+= \
+ decode.c \
+ opgp_key.c \
+ opgp_sig.c
+
+opgp_key.o opgp_key.po opgp_key.pico: ta_asc.h
+
+# Generate ta_asc.h containing one or more OpenPGP trust anchors.
+#
+# Since each trust anchor must be processed individually,
+# we create ta_ASC as a list of pointers to them.
+#
+# If we are doing self-tests, we define another arrary vc_ASC
+# containing pointers to a signature of each trust anchor.
+# It is assumed that these v*.asc files are named similarly to
+# the appropriate t*.asc so that the relative order of vc_ASC
+# entries matches ta_ASC.
+#
+ta_asc.h: ${.ALLTARGETS:M[tv]*.asc:O:u}
+.if ${VE_SIGNATURE_LIST:MOPENPGP} != ""
+ @( echo '/* Autogenerated - DO NOT EDIT!!! */'; echo; \
+ echo "#define HAVE_TA_ASC 1"; \
+ set -- ${.ALLSRC:Mt*.asc:@f@$f ${f:T:R}@}; \
+ while test $$# -ge 2; do \
+ file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
+ shift 2; \
+ done; \
+ echo 'static const char *ta_ASC[] = { ${.ALLSRC:Mt*.asc:T:R:ts,}, NULL };'; \
+ echo; ) > ${.TARGET}
+.if ${VE_SELF_TESTS} != "no"
+ @( echo "#define HAVE_VC_ASC 1"; \
+ set -- ${.ALLSRC:Mv*.asc:@f@$f ${f:T:R}@}; \
+ while test $$# -ge 2; do \
+ file2c -sx "static const char $$2[] = {" ', 0x00 };' < $$1; \
+ shift 2; \
+ done; \
+ echo 'static const char *vc_ASC[] = { ${.ALLSRC:Mv*.asc:T:R:ts,}, NULL };'; \
+ echo; ) >> ${.TARGET}
+.endif
+.endif
Property changes on: stable/12/lib/libsecureboot/openpgp/Makefile.inc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/openpgp/dearmor.c
===================================================================
--- stable/12/lib/libsecureboot/openpgp/dearmor.c (nonexistent)
+++ stable/12/lib/libsecureboot/openpgp/dearmor.c (revision 346145)
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define NEED_BRSSL_H
+#include <libsecureboot.h>
+#include <brssl.h>
+
+#include "decode.h"
+
+/**
+ * @brief decode ascii armor
+ *
+ * once we get rid of the trailing checksum
+ * we can treat as PEM.
+ *
+ * @sa rfc4880:6.2
+ */
+unsigned char *
+dearmor(char *pem, size_t nbytes, size_t *len)
+{
+#ifdef USE_BEARSSL
+ pem_object *po;
+ size_t npo;
+#else
+ BIO *bp;
+ char *name = NULL;
+ char *header = NULL;
+#endif
+ unsigned char *data = NULL;
+ char *cp;
+ char *ep;
+
+ /* we need to remove the Armor tail */
+ if ((cp = strstr((char *)pem, "\n=")) &&
+ (ep = strstr(cp, "\n---"))) {
+ memmove(cp, ep, nbytes - (size_t)(ep - pem));
+ nbytes -= (size_t)(ep - cp);
+ pem[nbytes] = '\0';
+ }
+#ifdef USE_BEARSSL
+ /* we also need to remove any headers */
+ if ((cp = strstr((char *)pem, "---\n")) &&
+ (ep = strstr(cp, "\n\n"))) {
+ cp += 4;
+ ep += 2;
+ memmove(cp, ep, nbytes - (size_t)(ep - pem));
+ nbytes -= (size_t)(ep - cp);
+ pem[nbytes] = '\0';
+ }
+ if ((po = decode_pem(pem, nbytes, &npo))) {
+ data = po->data;
+ *len = po->data_len;
+ }
+#else
+ if ((bp = BIO_new_mem_buf(pem, (int)nbytes))) {
+ long llen = (long)nbytes;
+
+ if (!PEM_read_bio(bp, &name, &header, &data, &llen))
+ data = NULL;
+ BIO_free(bp);
+ *len = (size_t)llen;
+ }
+#endif
+ return (data);
+}
+
+#ifdef MAIN_DEARMOR
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+
+/*
+ * Mostly a unit test.
+ */
+int
+main(int argc, char *argv[])
+{
+ const char *infile, *outfile;
+ unsigned char *data;
+ size_t n, x;
+ int fd;
+ int o;
+
+ infile = outfile = NULL;
+ while ((o = getopt(argc, argv, "i:o:")) != -1) {
+ switch (o) {
+ case 'i':
+ infile = optarg;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ default:
+ errx(1, "unknown option: -%c", o);
+ }
+ }
+ if (!infile)
+ errx(1, "need -i infile");
+ if (outfile) {
+ if ((fd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC)) < 0)
+ err(1, "cannot open %s", outfile);
+ } else {
+ fd = 1; /* stdout */
+ }
+ data = read_file(infile, &n);
+ if (!(data[0] & OPENPGP_TAG_ISTAG))
+ data = dearmor(data, n, &n);
+ for (x = 0; x < n; ) {
+ o = write(fd, &data[x], (n - x));
+ if (o < 0)
+ err(1, "cannot write");
+ x += o;
+ }
+ if (fd != 1)
+ close(fd);
+ free(data);
+ return (0);
+}
+#endif
Property changes on: stable/12/lib/libsecureboot/openpgp/dearmor.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/openpgp/decode.c
===================================================================
--- stable/12/lib/libsecureboot/openpgp/decode.c (nonexistent)
+++ stable/12/lib/libsecureboot/openpgp/decode.c (revision 346145)
@@ -0,0 +1,304 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <libsecureboot.h>
+
+#include "decode.h"
+
+char *
+octets2hex(unsigned char *ptr, size_t n)
+{
+ char *hex;
+ char *cp;
+ size_t i;
+
+ hex = malloc(2 * n + 1);
+ if (hex != NULL) {
+ for (i = 0, cp = hex; i < n; i++) {
+ snprintf(&cp[i*2], 3, "%02X", ptr[i]);
+ }
+ }
+ return (hex);
+}
+
+unsigned char *
+i2octets(int n, size_t i)
+{
+ static unsigned char o[16];
+ int x, j;
+
+ if (n > 15)
+ return (NULL);
+ for (j = 0, x = n - 1; x >= 0; x--, j++) {
+ o[j] = (unsigned char)((i & (0xff << x * 8)) >> x * 8);
+ }
+ return (o);
+}
+
+int
+octets2i(unsigned char *ptr, size_t n)
+{
+ size_t i;
+ int val;
+
+ for (val = i = 0; i < n; i++) {
+ val |= (*ptr++ << ((n - i - 1) * 8));
+ }
+ return (val);
+}
+
+/**
+ * @brief decode packet tag
+ *
+ * Also indicate if new/old and in the later case
+ * the length type
+ *
+ * @sa rfc4880:4.2
+ */
+int
+decode_tag(unsigned char *ptr, int *isnew, int *ltype)
+{
+ int tag;
+
+ if (!ptr || !isnew || !ltype)
+ return (-1);
+ tag = *ptr;
+
+ if (!(tag & OPENPGP_TAG_ISTAG))
+ return (-1); /* we are lost! */
+ *isnew = tag & OPENPGP_TAG_ISNEW;
+ if (*isnew) {
+ *ltype = -1; /* irrelevant */
+ tag &= OPENPGP_TAG_NEW_MASK;
+ } else {
+ *ltype = tag & OPENPGP_TAG_OLD_TYPE;
+ tag = (tag & OPENPGP_TAG_OLD_MASK) >> 2;
+ }
+ return (tag);
+}
+
+/**
+ * @brief return packet length
+ *
+ * @sa rfc4880:4.2.2
+ */
+static int
+decode_new_len(unsigned char **pptr)
+{
+ unsigned char *ptr;
+ int len = -1;
+
+ if (pptr == NULL)
+ return (-1);
+ ptr = *pptr;
+
+ if (!(*ptr < 224 || *ptr == 255))
+ return (-1); /* not supported */
+
+ if (*ptr < 192)
+ len = *ptr++;
+ else if (*ptr < 224) {
+ len = ((*ptr - 192) << 8) + *(ptr+1) + 192;
+ ptr++;
+ } else if (*ptr == 255) {
+ len = (*ptr++ << 24);
+ len |= (*ptr++ << 16);
+ len |= (*ptr++ < 8);
+ len |= *ptr++;
+ }
+
+ *pptr = ptr;
+ return (len);
+}
+
+/**
+ * @brief return packet length
+ *
+ * @sa rfc4880:4.2.1
+ */
+static int
+decode_len(unsigned char **pptr, int ltype)
+{
+ unsigned char *ptr;
+ int len;
+
+ if (ltype < 0)
+ return (decode_new_len(pptr));
+
+ if (pptr == NULL)
+ return (-1);
+
+ ptr = *pptr;
+
+ switch (ltype) {
+ case 0:
+ len = *ptr++;
+ break;
+ case 1:
+ len = (*ptr++ << 8);
+ len |= *ptr++;
+ break;
+ case 2:
+ len = *ptr++ << 24;
+ len |= *ptr++ << 16;
+ len |= *ptr++ << 8;
+ len |= *ptr++;
+ break;
+ case 3:
+ default:
+ /* Not supported */
+ len = -1;
+ }
+
+ *pptr = ptr;
+ return (len);
+}
+
+/**
+ * @brief return pointer and length of an mpi
+ *
+ * @sa rfc4880:3.2
+ */
+unsigned char *
+decode_mpi(unsigned char **pptr, size_t *sz)
+{
+ unsigned char *data;
+ unsigned char *ptr;
+ size_t mlen;
+
+ if (pptr == NULL || sz == NULL)
+ return (NULL);
+
+ ptr = *pptr;
+
+ mlen = (size_t)(*ptr++ << 8);
+ mlen |= (size_t)*ptr++; /* number of bits */
+ mlen = (mlen + 7) / 8; /* number of bytes */
+ *sz = mlen;
+ data = ptr;
+ ptr += mlen;
+ *pptr = ptr;
+ return (data);
+}
+
+/**
+ * @brief return an OpenSSL BIGNUM from mpi
+ *
+ * @sa rfc4880:3.2
+ */
+#ifdef USE_BEARSSL
+unsigned char *
+mpi2bn(unsigned char **pptr, size_t *sz)
+{
+ return (decode_mpi(pptr, sz));
+}
+#else
+BIGNUM *
+mpi2bn(unsigned char **pptr)
+{
+ BIGNUM *bn = NULL;
+ unsigned char *ptr;
+ int mlen;
+
+ if (pptr == NULL)
+ return (NULL);
+
+ ptr = *pptr;
+
+ mlen = (*ptr++ << 8);
+ mlen |= *ptr++; /* number of bits */
+ mlen = (mlen + 7) / 8; /* number of bytes */
+ bn = BN_bin2bn(ptr, mlen, NULL);
+ ptr += mlen;
+ *pptr = ptr;
+
+ return (bn);
+}
+#endif
+
+/**
+ * @brief decode a packet
+ *
+ * If want is set, check that the packet tag matches
+ * if all good, call the provided decoder with its arg
+ *
+ * @return count of unconsumed data
+ *
+ * @sa rfc4880:4.2
+ */
+int
+decode_packet(int want, unsigned char **pptr, size_t nbytes,
+ decoder_t decoder, void *decoder_arg)
+{
+ int tag;
+ unsigned char *ptr;
+ unsigned char *nptr;
+ int isnew, ltype;
+ int len;
+ int hlen;
+ int rc = 0;
+
+ nptr = ptr = *pptr;
+
+ tag = decode_tag(ptr, &isnew, &ltype);
+
+ if (want > 0 && tag != want)
+ return (-1);
+ ptr++;
+
+ len = rc = decode_len(&ptr, ltype);
+ hlen = (int)(ptr - nptr);
+ nptr = ptr + len; /* consume it */
+
+ if (decoder)
+ rc = decoder(tag, &ptr, len, decoder_arg);
+ *pptr = nptr;
+ nbytes -= (size_t)(hlen + len);
+ if (rc < 0)
+ return (rc); /* error */
+ return ((int)nbytes); /* unconsumed data */
+}
+
+/**
+ * @brief decode a sub packet
+ *
+ * @sa rfc4880:5.2.3.1
+ */
+unsigned char *
+decode_subpacket(unsigned char **pptr, int *stag, int *sz)
+{
+ unsigned char *ptr;
+ int len;
+
+ ptr = *pptr;
+ len = decode_len(&ptr, -1);
+ *sz = (int)(len + ptr - *pptr);
+ *pptr = ptr + len;
+ *stag = *ptr++;
+ return (ptr);
+}
Property changes on: stable/12/lib/libsecureboot/openpgp/decode.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/openpgp/decode.h
===================================================================
--- stable/12/lib/libsecureboot/openpgp/decode.h (nonexistent)
+++ stable/12/lib/libsecureboot/openpgp/decode.h (revision 346145)
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * $FreeBSD$
+ */
+
+#ifdef USE_BEARSSL
+unsigned char * mpi2bn(unsigned char **pptr, size_t *sz);
+#else
+# include <openssl/bn.h>
+# include <openssl/rsa.h>
+# include <openssl/evp.h>
+
+BIGNUM * mpi2bn(unsigned char **pptr);
+#endif
+
+#define NEW(x) calloc(1,sizeof(x))
+
+#define OPENPGP_TAG_ISTAG 0200
+#define OPENPGP_TAG_ISNEW 0100
+#define OPENPGP_TAG_NEW_MASK 0077
+#define OPENPGP_TAG_OLD_MASK 0074
+#define OPENPGP_TAG_OLD_TYPE 0003
+
+typedef int (*decoder_t)(int, unsigned char **, int, void *);
+
+unsigned char * i2octets(int n, size_t i);
+int octets2i(unsigned char *ptr, size_t n);
+char * octets2hex(unsigned char *ptr, size_t n);
+int decode_tag(unsigned char *ptr, int *isnew, int *ltype);
+unsigned char * decode_mpi(unsigned char **pptr, size_t *sz);
+unsigned char * dearmor(char *pem, size_t nbytes, size_t *len);
+int decode_packet(int want, unsigned char **pptr, size_t nbytes,
+ decoder_t decoder, void *decoder_arg);
+unsigned char * decode_subpacket(unsigned char **pptr, int *stag, int *sz);
Property changes on: stable/12/lib/libsecureboot/openpgp/decode.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/openpgp/opgp_key.c
===================================================================
--- stable/12/lib/libsecureboot/openpgp/opgp_key.c (nonexistent)
+++ stable/12/lib/libsecureboot/openpgp/opgp_key.c (revision 346145)
@@ -0,0 +1,352 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "../libsecureboot-priv.h"
+
+#include "decode.h"
+#include "packet.h"
+
+/**
+ * @brief decode user-id packet
+ *
+ * This is trivial
+ *
+ * @sa rfc4880:5.11
+ */
+ssize_t
+decode_user(int tag, unsigned char **pptr, size_t len, OpenPGP_user *user)
+{
+ char *cp;
+
+ if (tag == 13) {
+ user->id = malloc(len + 1);
+ strncpy(user->id, (char *)*pptr, len);
+ user->id[len] = '\0';
+ user->name = user->id;
+ cp = strchr(user->id, '<');
+ if (cp > user->id) {
+ user->id = strdup(user->id);
+ cp[-1] = '\0';
+ }
+ }
+ *pptr += len;
+ return ((ssize_t)len);
+}
+
+/**
+ * @brief decode a key packet
+ *
+ * We only really support v4 and RSA
+ *
+ * @sa rfc4880:5.5.1.1
+ */
+ssize_t
+decode_key(int tag, unsigned char **pptr, size_t len, OpenPGP_key *key)
+{
+ unsigned char *ptr;
+ int version;
+#ifdef USE_BEARSSL
+ br_sha1_context mctx;
+ unsigned char mdata[br_sha512_SIZE];
+ size_t mlen;
+#else
+ RSA *rsa = NULL;
+ const EVP_MD *md = NULL;
+ EVP_MD_CTX mctx;
+ unsigned char mdata[EVP_MAX_MD_SIZE];
+ unsigned int mlen;
+#endif
+
+ if (tag != 6)
+ return (-1);
+
+ key->key = NULL;
+ ptr = *pptr;
+ version = *ptr;
+ if (version == 4) { /* all we support really */
+ /* comput key fingerprint and id @sa rfc4880:12.2 */
+ mdata[0] = 0x99; /* rfc4880: 12.2.a.1 */
+ mdata[1] = (len >> 8) & 0xff;
+ mdata[2] = len & 0xff;
+
+#ifdef USE_BEARSSL
+ br_sha1_init(&mctx);
+ br_sha1_update(&mctx, mdata, 3);
+ br_sha1_update(&mctx, ptr, len);
+ br_sha1_out(&mctx, mdata);
+ mlen = br_sha1_SIZE;
+#else
+ md = EVP_get_digestbyname("sha1");
+ EVP_DigestInit(&mctx, md);
+ EVP_DigestUpdate(&mctx, mdata, 3);
+ EVP_DigestUpdate(&mctx, ptr, len);
+ mlen = (unsigned int)sizeof(mdata);
+ EVP_DigestFinal(&mctx, mdata, &mlen);
+#endif
+ key->id = octets2hex(&mdata[mlen - 8], 8);
+ }
+ ptr += 1; /* done with version */
+ ptr += 4; /* skip ctime */
+ if (version == 3)
+ ptr += 2; /* valid days */
+ key->sig_alg = *ptr++;
+ if (key->sig_alg == 1) { /* RSA */
+#ifdef USE_BEARSSL
+ key->key = NEW(br_rsa_public_key);
+ if (!key->key)
+ goto oops;
+ key->key->n = mpi2bn(&ptr, &key->key->nlen);
+ key->key->e = mpi2bn(&ptr, &key->key->elen);
+#else
+ rsa = RSA_new();
+ if (!rsa)
+ goto oops;
+ rsa->n = mpi2bn(&ptr);
+ rsa->e = mpi2bn(&ptr);
+ key->key = EVP_PKEY_new();
+ if (!key->key || !rsa->n || !rsa->e) {
+ goto oops;
+ }
+ if (!EVP_PKEY_set1_RSA(key->key, rsa))
+ goto oops;
+#endif
+ }
+ /* we are done */
+ return ((ssize_t)len);
+oops:
+#ifdef USE_BEARSSL
+ free(key->key);
+ key->key = NULL;
+#else
+ if (rsa)
+ RSA_free(rsa);
+ if (key->key) {
+ EVP_PKEY_free(key->key);
+ key->key = NULL;
+ }
+#endif
+ return (-1);
+}
+
+static OpenPGP_key *
+load_key_buf(unsigned char *buf, size_t nbytes)
+{
+ unsigned char *data = NULL;
+ unsigned char *ptr;
+ ssize_t rc;
+ int tag;
+ OpenPGP_key *key;
+
+ if (!buf)
+ return (NULL);
+
+ initialize();
+
+ if (!(buf[0] & OPENPGP_TAG_ISTAG)) {
+ data = dearmor((char *)buf, nbytes, &nbytes);
+ ptr = data;
+ } else
+ ptr = buf;
+ key = NEW(OpenPGP_key);
+ if (key) {
+ rc = decode_packet(0, &ptr, nbytes, (decoder_t)decode_key,
+ key);
+ if (rc < 0) {
+ free(key);
+ key = NULL;
+ } else if (rc > 8) {
+ int isnew, ltype;
+
+ tag = decode_tag(ptr, &isnew, &ltype);
+ if (tag == 13) {
+ key->user = NEW(OpenPGP_user);
+ rc = decode_packet(0, &ptr, (size_t)rc,
+ (decoder_t)decode_user, key->user);
+ }
+ }
+ }
+ free(data);
+ return (key);
+}
+
+static LIST_HEAD(, OpenPGP_key_) trust_list;
+
+/**
+ * @brief add a key to our list
+ */
+void
+openpgp_trust_add(OpenPGP_key *key)
+{
+ static int once = 0;
+
+ if (!once) {
+ once = 1;
+
+ LIST_INIT(&trust_list);
+ }
+ if (key)
+ LIST_INSERT_HEAD(&trust_list, key, entries);
+}
+
+/**
+ * @brief if keyID is in our list return the key
+ *
+ * @return key or NULL
+ */
+OpenPGP_key *
+openpgp_trust_get(const char *keyID)
+{
+ OpenPGP_key *key;
+
+ openpgp_trust_add(NULL); /* initialize if needed */
+
+ LIST_FOREACH(key, &trust_list, entries) {
+ if (strcmp(key->id, keyID) == 0)
+ return (key);
+ }
+ return (NULL);
+}
+
+/**
+ * @brief load a key from file
+ */
+OpenPGP_key *
+load_key_file(const char *kfile)
+{
+ unsigned char *data = NULL;
+ size_t n;
+ OpenPGP_key *key;
+
+ data = read_file(kfile, &n);
+ key = load_key_buf(data, n);
+ free(data);
+ openpgp_trust_add(key);
+ return (key);
+}
+
+#include <ta_asc.h>
+
+#ifndef _STANDALONE
+/* we can lookup keyID in filesystem */
+
+static const char *trust_store[] = {
+ "/var/db/trust",
+ "/etc/db/trust",
+ NULL,
+};
+
+/**
+ * @brief lookup key id in trust store
+ *
+ */
+static OpenPGP_key *
+load_trusted_key_id(const char *keyID)
+{
+ char kfile[MAXPATHLEN];
+ const char **tp;
+ size_t n;
+
+ for (tp = trust_store; *tp; tp++) {
+ n = (size_t)snprintf(kfile, sizeof(kfile), "%s/%s", *tp, keyID);
+ if (n >= sizeof(kfile))
+ return (NULL);
+ if (access(kfile, R_OK) == 0) {
+ return (load_key_file(kfile));
+ }
+ }
+ return (NULL);
+}
+#endif
+
+/**
+ * @brief return key if trusted
+ */
+OpenPGP_key *
+load_key_id(const char *keyID)
+{
+ static int once = 0;
+ OpenPGP_key *key;
+
+ if (!once) {
+#ifdef HAVE_TA_ASC
+ const char **tp;
+ char *cp;
+ size_t n;
+
+ for (tp = ta_ASC; *tp; tp++) {
+ if ((cp = strdup(*tp))) {
+ n = strlen(cp);
+ key = load_key_buf((unsigned char *)cp, n);
+ free(cp);
+ openpgp_trust_add(key);
+ }
+ }
+#endif
+ once = 1;
+ }
+ key = openpgp_trust_get(keyID);
+#ifndef _STANDALONE
+ if (!key)
+ key = load_trusted_key_id(keyID);
+#endif
+ return (key);
+}
+
+/**
+ * @brief test that we can verify a signature
+ *
+ * Unlike X.509 certificates, we only support RSA keys
+ * so we stop after first successful signature verification
+ * (which should also be the first attempt ;-)
+ */
+int
+openpgp_self_tests(void)
+{
+ static int rc = -1; /* remember result */
+#ifdef HAVE_VC_ASC
+ const char **vp, **tp;
+ char *fdata, *sdata = NULL;
+ size_t fbytes, sbytes;
+
+ for (tp = ta_ASC, vp = vc_ASC; *tp && *vp && rc; tp++, vp++) {
+ if ((fdata = strdup(*tp)) &&
+ (sdata = strdup(*vp))) {
+ fbytes = strlen(fdata);
+ sbytes = strlen(sdata);
+ rc = openpgp_verify("ta_ASC",
+ (unsigned char *)fdata, fbytes,
+ (unsigned char *)sdata, sbytes, 0);
+ printf("Testing verify OpenPGP signature:\t\t%s\n",
+ rc ? "Failed" : "Passed");
+ }
+ free(fdata);
+ free(sdata);
+ }
+#endif
+ return (rc);
+}
Property changes on: stable/12/lib/libsecureboot/openpgp/opgp_key.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/openpgp/opgp_sig.c
===================================================================
--- stable/12/lib/libsecureboot/openpgp/opgp_sig.c (nonexistent)
+++ stable/12/lib/libsecureboot/openpgp/opgp_sig.c (revision 346145)
@@ -0,0 +1,484 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * RCSid:
+ * from: signer.c,v 1.10 2018/03/23 01:14:30 sjg
+ *
+ * @(#) Copyright (c) 2012 Simon J. Gerraty
+ *
+ * This file is provided in the hope that it will
+ * be of use. There is absolutely NO WARRANTY.
+ * Permission to copy, redistribute or otherwise
+ * use this file is hereby granted provided that
+ * the above copyright notice and this notice are
+ * left intact.
+ *
+ * Please send copies of changes and bug-fixes to:
+ * sjg@crufty.net
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "../libsecureboot-priv.h"
+#ifdef _STANDALONE
+#define warnx printf
+#else
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#endif
+
+#include "decode.h"
+#include "packet.h"
+
+#ifdef USE_BEARSSL
+
+#define get_error_string ve_error_get
+
+void
+initialize (void)
+{
+#ifdef _STANDALONE
+ ve_trust_init();
+#endif
+}
+
+#else
+
+#include <openssl/err.h>
+
+/**
+ * @brief intialize OpenSSL
+ */
+void
+initialize(void)
+{
+ static int once;
+
+ if (once)
+ return);
+ once = 1;
+ //CRYPTO_malloc_init();
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+}
+
+/**
+ * @brief
+ * last error from OpenSSL as a string
+ */
+char *
+get_error_string(void)
+{
+ initialize();
+ return (ERR_error_string(ERR_get_error(), NULL));
+}
+#endif
+
+/**
+ * @brief decode a signature packet
+ *
+ * We only support RSA
+ *
+ * @sa rfc4880:5.2
+ */
+ssize_t
+decode_sig(int tag, unsigned char **pptr, size_t len, OpenPGP_sig *sig)
+{
+ unsigned char *ptr;
+ unsigned char *pgpbytes;
+ unsigned char *sp;
+ int version;
+ int hcount = 0;
+ int ucount = 0;
+ int stag = 0;
+ int n;
+
+ n = tag; /* avoid unused */
+
+ /*
+ * We need to keep a reference to the packet bytes
+ * as these form part of the signature data.
+ *
+ * @sa rfc4880:5.2.4
+ */
+ pgpbytes = ptr = *pptr;
+ version = *ptr++;
+ if (version == 3) {
+ ptr++;
+ sig->pgpbytes = malloc(5);
+ if (!sig->pgpbytes)
+ return (-1);
+ memcpy(sig->pgpbytes, ptr, 5);
+ sig->pgpbytes_len = 5;
+ sig->sig_type = *ptr++;
+ ptr += 4;
+ sig->key_id = octets2hex(ptr, 8);
+ ptr += 8;
+ sig->sig_alg = *ptr++;
+ sig->hash_alg = *ptr++;
+ } else if (version == 4) {
+ sig->sig_type = *ptr++;
+ sig->sig_alg = *ptr++;
+ sig->hash_alg = *ptr++;
+ hcount = octets2i(ptr, 2);
+ ptr += 2;
+ sig->pgpbytes_len = (size_t)hcount + 6;
+ sig->pgpbytes = malloc(sig->pgpbytes_len + 6);
+ if (!sig->pgpbytes)
+ return (-1);
+ memcpy(sig->pgpbytes, pgpbytes, sig->pgpbytes_len);
+ sp = &sig->pgpbytes[sig->pgpbytes_len];
+ *sp++ = 4;
+ *sp++ = 255;
+ memcpy(sp, i2octets(4, (int)sig->pgpbytes_len), 4);
+ sig->pgpbytes_len += 6;
+
+ while (hcount > 0) {
+ sp = decode_subpacket(&ptr, &stag, &n);
+ hcount -= n;
+ /* can check stag to see if we care */
+ }
+ ucount = octets2i(ptr, 2);
+ ptr += 2;
+ while (ucount > 0) {
+ sp = decode_subpacket(&ptr, &stag, &n);
+ ucount -= n;
+ /* can check stag to see if we care */
+ if (stag == 16) {
+ free(sig->key_id);
+ sig->key_id = octets2hex(sp, 8);
+ }
+ }
+ } else
+ return (-1);
+ ptr += 2; /* skip hash16 */
+ if (sig->sig_alg == 1) { /* RSA */
+ sig->sig = decode_mpi(&ptr, &sig->sig_len);
+ }
+ /* we are done */
+ return ((ssize_t)len);
+}
+
+/**
+ * @brief map OpenPGP hash algorithm id's to name
+ *
+ * @sa rfc4880:9.4
+ */
+static struct hash_alg_map {
+ int halg;
+ const char *hname;
+} hash_algs[] = {
+ {1, "md5"},
+ {2, "sha1"},
+ {8, "sha256"},
+ {9, "sha384"},
+ {10, "sha512"},
+ {11, "sha224"},
+ {0, NULL},
+};
+
+static const char *
+get_hname(int hash_alg)
+{
+ struct hash_alg_map *hmp;
+
+ for (hmp = hash_algs; hmp->halg > 0; hmp++) {
+ if (hmp->halg == hash_alg)
+ return (hmp->hname);
+ }
+ return (NULL);
+}
+
+/* lifted from signer.c */
+/**
+ * @brief verify a digest
+ *
+ * The public key, digest name, file and signature data.
+ *
+ * @return 1 on success 0 on failure, -1 on error
+ */
+#ifndef USE_BEARSSL
+static int
+verify_digest (EVP_PKEY *pkey,
+ const char *digest,
+ unsigned char *mdata, size_t mlen,
+ unsigned char *sdata, size_t slen)
+{
+ EVP_MD_CTX ctx;
+ const EVP_MD *md = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ int rc = 0;
+ int i = -1;
+
+ initialize();
+ md = EVP_get_digestbyname(digest);
+ EVP_DigestInit(&ctx, md);
+
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (!pctx)
+ goto fail;
+ if (EVP_PKEY_verify_init(pctx) <= 0)
+ goto fail;
+ if (EVP_PKEY_CTX_set_signature_md(pctx, ctx.digest) <= 0)
+ goto fail;
+ i = EVP_PKEY_verify(pctx, sdata, slen, mdata, mlen);
+ if (i >= 0)
+ rc = i;
+fail:
+ EVP_PKEY_CTX_free(pctx);
+ return (rc);
+}
+#endif
+
+
+/**
+ * @brief verify OpenPGP signed file
+ *
+ *
+ * @param[in] filename
+ * used to determine the signature name
+ *
+ * @param[in] fdata
+ * content of filename
+ *
+ * @param[in] fbytes
+ * of fdata
+ *
+ * @param[in] sdata
+ * content of signature
+ *
+ * @param[in] sbytes
+ * of sdata
+ *
+ * @param[in] flags
+ *
+ * @return 0 on success
+ */
+int
+openpgp_verify(const char *filename,
+ unsigned char *fdata, size_t fbytes,
+ unsigned char *sdata, size_t sbytes,
+ int flags)
+{
+ OpenPGP_key *key;
+ OpenPGP_sig *sig;
+#ifdef USE_BEARSSL
+ const br_hash_class *md;
+ br_hash_compat_context mctx;
+ const unsigned char *hash_oid;
+#else
+ const EVP_MD *md = NULL;
+ EVP_MD_CTX mctx;
+#endif
+ unsigned char mdata[64];
+ unsigned char *ptr;
+ unsigned char *ddata = NULL;
+ const char *hname;
+ size_t mlen;
+ int rc = -1;
+
+ initialize();
+
+ sig = NEW(OpenPGP_sig);
+ if (!sdata || !sig) {
+ warnx("cannot verify %s", filename);
+ goto oops;
+ }
+ if (!(sdata[0] & OPENPGP_TAG_ISTAG))
+ sdata = ddata = dearmor((char *)sdata, sbytes, &sbytes);
+ ptr = sdata;
+ rc = decode_packet(2, &ptr, sbytes, (decoder_t)decode_sig, sig);
+ if (rc == 0 && sig->key_id) {
+ key = load_key_id(sig->key_id);
+ if (!key) {
+ warnx("cannot find key-id: %s", sig->key_id);
+ rc = -1;
+ } else if (!(hname = get_hname(sig->hash_alg))) {
+ warnx("unsupported hash algorithm: %d", sig->hash_alg);
+ rc = -1;
+ } else {
+ /*
+ * Hash fdata according to the OpenPGP recipe
+ *
+ * @sa rfc4880:5.2.4
+ */
+#ifdef USE_BEARSSL
+ switch (sig->hash_alg) { /* see hash_algs above */
+ case 2: /* sha1 */
+ md = &br_sha1_vtable;
+ mlen = br_sha1_SIZE;
+ hash_oid = BR_HASH_OID_SHA1;
+ break;
+ case 8: /* sha256 */
+ md = &br_sha256_vtable;
+ mlen = br_sha256_SIZE;
+ hash_oid = BR_HASH_OID_SHA256;
+ break;
+ default:
+ warnx("unsupported hash algorithm: %s", hname);
+ goto oops;
+ }
+ md->init(&mctx.vtable);
+ md->update(&mctx.vtable, fdata, fbytes);
+ md->update(&mctx.vtable, sig->pgpbytes,
+ sig->pgpbytes_len);
+ md->out(&mctx.vtable, mdata);
+
+ rc = verify_rsa_digest(key->key, hash_oid,
+ mdata, mlen, sig->sig, sig->sig_len);
+#else
+ md = EVP_get_digestbyname(hname);
+ EVP_DigestInit(&mctx, md);
+ EVP_DigestUpdate(&mctx, fdata, fbytes);
+ EVP_DigestUpdate(&mctx, sig->pgpbytes,
+ sig->pgpbytes_len);
+ mlen = sizeof(mdata);
+ EVP_DigestFinal(&mctx,mdata,(unsigned int *)&mlen);
+
+ rc = verify_digest(key->key, hname, mdata, mlen,
+ sig->sig, sig->sig_len);
+#endif
+
+ if (rc > 0) {
+ if ((flags & 1))
+ printf("Verified %s signed by %s\n",
+ filename,
+ key->user ? key->user->name : "someone");
+ rc = 0; /* success */
+ } else if (rc == 0) {
+ printf("Unverified %s: %s\n",
+ filename, get_error_string());
+ rc = 1;
+ } else {
+ printf("Unverified %s\n", filename);
+ }
+ }
+ } else {
+ warnx("cannot decode signature for %s", filename);
+ rc = -1;
+ }
+oops:
+ free(ddata);
+ free(sig);
+ return (rc);
+}
+
+#ifndef _STANDALONE
+/**
+ * @brief list of extensions we handle
+ *
+ * ".asc" is preferred as it works seamlessly with openpgp
+ */
+static const char *sig_exts[] = {
+ ".asc",
+ ".pgp",
+ ".psig",
+ NULL,
+};
+
+/**
+ * @brief verify OpenPGP signed file
+ *
+ *
+ * @param[in] filename
+ * used to determine the signature name
+ *
+ * @param[in] fdata
+ * content of filename
+ *
+ * @param[in] nbytes
+ * of fdata
+ *
+ * @return
+ */
+
+int
+openpgp_verify_file(const char *filename, unsigned char *fdata, size_t nbytes)
+{
+ char pbuf[MAXPATHLEN];
+ unsigned char *sdata;
+ const char *sname = NULL;
+ const char **ep;
+ size_t sz;
+ int n;
+
+ for (ep = sig_exts; *ep; ep++) {
+ n = snprintf(pbuf, sizeof(pbuf), "%s%s", filename, *ep);
+ if (n >= (int)sizeof(pbuf)) {
+ warnx("cannot form signature name for %s", filename);
+ return (-1);
+ }
+ if (access(pbuf, R_OK) == 0) {
+ sname = pbuf;
+ break;
+ }
+ }
+ if (!sname) {
+ warnx("cannot find signature for %s", filename);
+ return (-1);
+ }
+ sdata = read_file(sname, &sz);
+ return (openpgp_verify(filename, fdata, nbytes, sdata, sz, 1));
+}
+#endif
+
+/**
+ * @brief verify OpenPGP signature
+ *
+ * @return content of signed file
+ */
+unsigned char *
+verify_asc(const char *sigfile, int flags)
+{
+ char pbuf[MAXPATHLEN];
+ char *cp;
+ size_t n;
+ unsigned char *fdata, *sdata;
+ size_t fbytes, sbytes;
+
+ if ((sdata = read_file(sigfile, &sbytes))) {
+ n = strlcpy(pbuf, sigfile, sizeof(pbuf));
+ if ((cp = strrchr(pbuf, '.')))
+ *cp = '\0';
+ if ((fdata = read_file(pbuf, &fbytes))) {
+ if (openpgp_verify(pbuf, fdata, fbytes, sdata,
+ sbytes, flags)) {
+ free(fdata);
+ fdata = NULL;
+ }
+ }
+ } else
+ fdata = NULL;
+ free(sdata);
+ return (fdata);
+}
Property changes on: stable/12/lib/libsecureboot/openpgp/opgp_sig.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/openpgp/packet.h
===================================================================
--- stable/12/lib/libsecureboot/openpgp/packet.h (nonexistent)
+++ stable/12/lib/libsecureboot/openpgp/packet.h (revision 346145)
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * $FreeBSD$
+ */
+
+#include <sys/queue.h>
+
+/*
+ * Structs to represent what we need
+ */
+
+typedef struct OpenPGP_user {
+ char *id;
+ char *name;
+} OpenPGP_user;
+
+struct OpenPGP_key_ {
+ char *id;
+ int sig_alg;
+ OpenPGP_user *user;
+#ifdef USE_BEARSSL
+ br_rsa_public_key *key;
+#else
+ EVP_PKEY *key;
+#endif
+ LIST_ENTRY(OpenPGP_key_) entries;
+};
+
+typedef struct OpenPGP_key_ OpenPGP_key;
+
+typedef struct OpenPGP_sig {
+ char *key_id;
+ int sig_type;
+ int sig_alg;
+ int hash_alg;
+ unsigned char *pgpbytes;
+ size_t pgpbytes_len;
+ unsigned char *sig;
+ size_t sig_len;
+} OpenPGP_sig;
+
+void openpgp_trust_add(OpenPGP_key *key);
+OpenPGP_key * openpgp_trust_get(const char *keyID);
+OpenPGP_key * load_key_file(const char *kfile);
+OpenPGP_key * load_key_id(const char *keyID);
+void initialize(void);
+char * get_error_string(void);
+int openpgp_verify(const char *filename, unsigned char *fdata, size_t fbytes,
+ unsigned char *sdata, size_t sbytes, int flags);
+int openpgp_verify_file(const char *filename, unsigned char *fdata,
+ size_t nbytes);
+
+/* packet decoders */
+#define DECODER_DECL(x) \
+ ssize_t decode_##x(int, unsigned char **, size_t, OpenPGP_##x *)
+
+DECODER_DECL(user);
+DECODER_DECL(key);
+DECODER_DECL(sig);
Property changes on: stable/12/lib/libsecureboot/openpgp/packet.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/readfile.c
===================================================================
--- stable/12/lib/libsecureboot/readfile.c (nonexistent)
+++ stable/12/lib/libsecureboot/readfile.c (revision 346145)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2017-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <libsecureboot.h>
+
+unsigned char *
+read_file(const char *path, size_t *len)
+{
+ int fd, m, n, x;
+ struct stat st;
+ unsigned char *buf;
+
+ if (len)
+ *len = 0;
+ if ((fd = open(path, O_RDONLY)) < 0)
+ return (NULL);
+ fstat(fd, &st);
+ if (len)
+ *len = st.st_size;
+ buf = malloc(st.st_size + 1);
+ for (x = 0, m = st.st_size; m > 0; ) {
+ n = read(fd, &buf[x], m);
+ if (n < 0)
+ break;
+ if (n > 0) {
+ m -= n;
+ x += n;
+ }
+ }
+ close(fd);
+ if (m == 0) {
+ buf[st.st_size] = '\0';
+ return (buf);
+ }
+ free(buf);
+ return (NULL);
+}
Property changes on: stable/12/lib/libsecureboot/readfile.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/vectx.c
===================================================================
--- stable/12/lib/libsecureboot/vectx.c (nonexistent)
+++ stable/12/lib/libsecureboot/vectx.c (revision 346145)
@@ -0,0 +1,291 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _STANDALONE
+/* Avoid unwanted userlandish components */
+#define _KERNEL
+#include <sys/errno.h>
+#undef _KERNEL
+#endif
+
+#include "libsecureboot-priv.h"
+
+/**
+ * @file vectx.c
+ * @brief api to verify file while reading
+ *
+ * This API allows the hash of a file to be computed as it is read.
+ * Key to this is seeking by reading.
+ *
+ * On close an indication of the verification result is returned.
+ */
+
+struct vectx {
+ br_hash_compat_context vec_ctx; /* hash ctx */
+ const br_hash_class *vec_md; /* hash method */
+ const char *vec_path; /* path we are verifying */
+ const char *vec_want; /* hash value we want */
+ off_t vec_off; /* current offset */
+ size_t vec_size; /* size of path */
+ size_t vec_hashsz; /* size of hash */
+ int vec_fd; /* file descriptor */
+ int vec_status; /* verification status */
+};
+
+/**
+ * @brief
+ * verify an open file as we read it
+ *
+ * If the file has no fingerprint to match, we will still return a
+ * verification context containing little more than the file
+ * descriptor, and an error code in @c error.
+ *
+ * @param[in] fd
+ * open descriptor
+ *
+ * @param[in] path
+ * pathname to open
+ *
+ * @param[in] off
+ * current offset
+ *
+ * @param[in] stp
+ * pointer to struct stat
+ *
+ * @param[out] error
+ * @li 0 all is good
+ * @li ENOMEM out of memory
+ * @li VE_FINGERPRINT_NONE no entry found
+ * @li VE_FINGERPRINT_UNKNOWN no fingerprint in entry
+ *
+ * @return ctx or NULL on error.
+ * NULL is only returned for non-files or out-of-memory.
+ */
+struct vectx *
+vectx_open(int fd, const char *path, off_t off, struct stat *stp, int *error)
+{
+ struct vectx *ctx;
+ struct stat st;
+ size_t hashsz;
+ char *cp;
+
+ if (!stp) {
+ if (fstat(fd, &st) == 0)
+ stp = &st;
+ }
+
+ /* we *should* only get called for files */
+ if (stp && !S_ISREG(stp->st_mode)) {
+ *error = 0;
+ return (NULL);
+ }
+
+ ctx = malloc(sizeof(struct vectx));
+ if (!ctx)
+ goto enomem;
+ ctx->vec_fd = fd;
+ ctx->vec_path = path;
+ ctx->vec_size = stp->st_size;
+ ctx->vec_off = 0;
+ ctx->vec_want = NULL;
+ ctx->vec_status = 0;
+ hashsz = 0;
+
+ cp = fingerprint_info_lookup(fd, path);
+ if (!cp) {
+ ctx->vec_status = VE_FINGERPRINT_NONE;
+ ve_error_set("%s: no entry", path);
+ } else {
+ if (strncmp(cp, "sha256=", 7) == 0) {
+ ctx->vec_md = &br_sha256_vtable;
+ hashsz = br_sha256_SIZE;
+ cp += 7;
+#ifdef VE_SHA1_SUPPORT
+ } else if (strncmp(cp, "sha1=", 5) == 0) {
+ ctx->vec_md = &br_sha1_vtable;
+ hashsz = br_sha1_SIZE;
+ cp += 5;
+#endif
+#ifdef VE_SHA384_SUPPORT
+ } else if (strncmp(cp, "sha384=", 7) == 0) {
+ ctx->vec_md = &br_sha384_vtable;
+ hashsz = br_sha384_SIZE;
+ cp += 7;
+#endif
+#ifdef VE_SHA512_SUPPORT
+ } else if (strncmp(cp, "sha512=", 7) == 0) {
+ ctx->vec_md = &br_sha512_vtable;
+ hashsz = br_sha512_SIZE;
+ cp += 7;
+#endif
+ } else {
+ ctx->vec_status = VE_FINGERPRINT_UNKNOWN;
+ ve_error_set("%s: no supported fingerprint", path);
+ }
+ }
+ *error = ctx->vec_status;
+ ctx->vec_hashsz = hashsz;
+ ctx->vec_want = cp;
+ ctx->vec_md->init(&ctx->vec_ctx.vtable);
+
+ if (hashsz > 0 && off > 0) {
+ lseek(fd, 0, SEEK_SET);
+ vectx_lseek(ctx, off, SEEK_SET);
+ }
+ return (ctx);
+
+enomem: /* unlikely */
+ *error = ENOMEM;
+ free(ctx);
+ return (NULL);
+}
+
+/**
+ * @brief
+ * read bytes from file and update hash
+ *
+ * It is critical that all file I/O comes through here.
+ * We keep track of current offset.
+ *
+ * @param[in] pctx
+ * pointer to ctx
+ *
+ * @param[in] buf
+ *
+ * @param[in] nbytes
+ *
+ * @return bytes read or error.
+ */
+ssize_t
+vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
+{
+ unsigned char *bp = buf;
+ int n;
+ size_t off;
+
+ if (ctx->vec_hashsz == 0) /* nothing to do */
+ return (read(ctx->vec_fd, buf, nbytes));
+
+ off = 0;
+ do {
+ n = read(ctx->vec_fd, &bp[off], nbytes - off);
+ if (n < 0)
+ return (n);
+ if (n > 0) {
+ ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], n);
+ off += n;
+ ctx->vec_off += n;
+ }
+ } while (n > 0 && off < nbytes);
+ return (off);
+}
+
+/**
+ * @brief
+ * vectx equivalent of lseek
+ *
+ * We do not actually, seek, but call vectx_read
+ * to reach the desired offset.
+ *
+ * We do not support seeking backwards.
+ *
+ * @param[in] pctx
+ * pointer to ctx
+ *
+ * @param[in] off
+ * desired offset
+ *
+ * @param[in] whence
+ *
+ * @return offset or error.
+ */
+off_t
+vectx_lseek(struct vectx *ctx, off_t off, int whence)
+{
+ unsigned char buf[PAGE_SIZE];
+ size_t delta;
+ ssize_t n;
+
+ if (ctx->vec_hashsz == 0) /* nothing to do */
+ return (lseek(ctx->vec_fd, off, whence));
+
+ /*
+ * Try to convert whence to SEEK_SET
+ * but we cannot support seeking backwards!
+ * Nor beyond end of file.
+ */
+ if (whence == SEEK_END && off <= 0) {
+ whence = SEEK_SET;
+ off += ctx->vec_size;
+ } else if (whence == SEEK_CUR && off >= 0) {
+ whence = SEEK_SET;
+ off += ctx->vec_off;
+ }
+ if (whence != SEEK_SET || off < ctx->vec_off ||
+ (size_t)off > ctx->vec_size) {
+ printf("ERROR: %s: unsupported operation\n", __func__);
+ return (-1);
+ }
+ n = 0;
+ do {
+ delta = off - ctx->vec_off;
+ if (delta > 0) {
+ delta = MIN(PAGE_SIZE, delta);
+ n = vectx_read(ctx, buf, delta);
+ if (n < 0)
+ return (n);
+ }
+ } while (ctx->vec_off < off && n > 0);
+ return (ctx->vec_off);
+}
+
+/**
+ * @brief
+ * check that hashes match and cleanup
+ *
+ * We have finished reading file, compare the hash with what
+ * we wanted.
+ *
+ * @param[in] pctx
+ * pointer to ctx
+ *
+ * @return 0 or an error.
+ */
+int
+vectx_close(struct vectx *ctx)
+{
+ int rc;
+
+ if (ctx->vec_hashsz == 0) {
+ rc = ctx->vec_status;
+ } else {
+ rc = ve_check_hash(&ctx->vec_ctx, ctx->vec_md,
+ ctx->vec_path, ctx->vec_want, ctx->vec_hashsz);
+ }
+ free(ctx);
+ return ((rc < 0) ? rc : 0);
+}
Property changes on: stable/12/lib/libsecureboot/vectx.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/veopen.c
===================================================================
--- stable/12/lib/libsecureboot/veopen.c (nonexistent)
+++ stable/12/lib/libsecureboot/veopen.c (revision 346145)
@@ -0,0 +1,458 @@
+/*-
+ * Copyright (c) 2017-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/queue.h>
+
+#include "libsecureboot-priv.h"
+
+
+struct fingerprint_info {
+ char *fi_prefix; /**< manifest entries relative to */
+ char *fi_skip; /**< manifest entries prefixed with */
+ const char *fi_data; /**< manifest data */
+ size_t fi_prefix_len; /**< length of prefix */
+ size_t fi_skip_len; /**< length of skip */
+ dev_t fi_dev; /**< device id */
+ LIST_ENTRY(fingerprint_info) entries;
+};
+
+static LIST_HEAD(, fingerprint_info) fi_list;
+
+static void
+fingerprint_info_init(void)
+{
+ static int once;
+
+ if (once)
+ return;
+ LIST_INIT(&fi_list);
+ once = 1;
+}
+
+/**
+ * @brief
+ * add manifest data to list
+ *
+ * list is kept sorted by longest prefix.
+ *
+ * @param[in] prefix
+ * path that all manifest entries are resolved via
+ *
+ * @param[in] skip
+ * optional prefix within manifest entries which should be skipped
+ *
+ * @param[in] data
+ * manifest data
+ */
+void
+fingerprint_info_add(const char *filename, const char *prefix,
+ const char *skip, const char *data, struct stat *stp)
+{
+ struct fingerprint_info *fip, *nfip, *lfip;
+ char *cp;
+ int n;
+
+ fingerprint_info_init();
+ nfip = malloc(sizeof(struct fingerprint_info));
+ if (prefix) {
+ nfip->fi_prefix = strdup(prefix);
+ } else {
+ if (!filename) {
+ free(nfip);
+ return;
+ }
+ nfip->fi_prefix = strdup(filename);
+ cp = strrchr(nfip->fi_prefix, '/');
+ if (cp)
+ *cp = '\0';
+ else {
+ free(nfip->fi_prefix);
+ free(nfip);
+ return;
+ }
+ }
+ /* collapse any trailing ..[/] */
+ n = 0;
+ while ((cp = strrchr(nfip->fi_prefix, '/')) != NULL) {
+ if (cp[1] == '\0') { /* trailing "/" */
+ *cp = '\0';
+ continue;
+ }
+ if (strcmp(&cp[1], "..") == 0) {
+ n++;
+ *cp = '\0';
+ continue;
+ }
+ if (n > 0) {
+ n--;
+ *cp = '\0';
+ }
+ if (n == 0)
+ break;
+ }
+#ifdef UNIT_TEST
+ nfip->fi_dev = 0;
+#else
+ nfip->fi_dev = stp->st_dev;
+#endif
+ nfip->fi_data = data;
+ nfip->fi_prefix_len = strlen(nfip->fi_prefix);
+ if (skip) {
+ nfip->fi_skip_len = strlen(skip);
+ if (nfip->fi_skip_len)
+ nfip->fi_skip = strdup(skip);
+ else
+ nfip->fi_skip = NULL;
+ } else {
+ nfip->fi_skip = NULL;
+ nfip->fi_skip_len = 0;
+ }
+
+ if (LIST_EMPTY(&fi_list)) {
+ LIST_INSERT_HEAD(&fi_list, nfip, entries);
+ DEBUG_PRINTF(4, ("inserted %zu %s at head\n",
+ nfip->fi_prefix_len, nfip->fi_prefix));
+ return;
+ }
+ LIST_FOREACH(fip, &fi_list, entries) {
+ if (nfip->fi_prefix_len >= fip->fi_prefix_len) {
+ LIST_INSERT_BEFORE(fip, nfip, entries);
+ DEBUG_PRINTF(4, ("inserted %zu %s before %zu %s\n",
+ nfip->fi_prefix_len, nfip->fi_prefix,
+ fip->fi_prefix_len, fip->fi_prefix));
+ return;
+ }
+ lfip = fip;
+ }
+ LIST_INSERT_AFTER(lfip, nfip, entries);
+ DEBUG_PRINTF(4, ("inserted %zu %s after %zu %s\n",
+ nfip->fi_prefix_len, nfip->fi_prefix,
+ lfip->fi_prefix_len, lfip->fi_prefix));
+}
+
+#ifdef MANIFEST_SKIP_MAYBE
+/*
+ * Deal with old incompatible boot/manifest
+ * if fp[-1] is '/' and start of entry matches
+ * MANIFEST_SKIP_MAYBE, we want it.
+ */
+static char *
+maybe_skip(char *fp, struct fingerprint_info *fip, size_t *nplenp)
+{
+ char *tp;
+
+ tp = fp - sizeof(MANIFEST_SKIP_MAYBE);
+
+ if (tp >= fip->fi_data) {
+ DEBUG_PRINTF(3, ("maybe: %.48s\n", tp));
+ if ((tp == fip->fi_data || tp[-1] == '\n') &&
+ strncmp(tp, MANIFEST_SKIP_MAYBE,
+ sizeof(MANIFEST_SKIP_MAYBE) - 1) == 0) {
+ fp = tp;
+ *nplenp += sizeof(MANIFEST_SKIP_MAYBE);
+ }
+ }
+ return (fp);
+}
+#endif
+
+char *
+fingerprint_info_lookup(int fd, const char *path)
+{
+ char pbuf[MAXPATHLEN+1];
+ char nbuf[MAXPATHLEN+1];
+ struct stat st;
+ struct fingerprint_info *fip;
+ char *cp, *ep, *fp, *np;
+ const char *prefix;
+ size_t n, plen, nlen, nplen;
+ dev_t dev = 0;
+
+ fingerprint_info_init();
+
+ n = strlcpy(pbuf, path, sizeof(pbuf));
+ if (n >= sizeof(pbuf))
+ return (NULL);
+#ifndef UNIT_TEST
+ if (fstat(fd, &st) == 0)
+ dev = st.st_dev;
+#endif
+ /*
+ * get the first entry - it will have longest prefix
+ * so we can can work out how to initially split path
+ */
+ fip = LIST_FIRST(&fi_list);
+ if (!fip)
+ return (NULL);
+ prefix = pbuf;
+ ep = NULL;
+ cp = &pbuf[fip->fi_prefix_len];
+ do {
+ if (ep) {
+ *ep = '/';
+ cp -= 2;
+ if (cp < pbuf)
+ break;
+ }
+ nlen = plen = 0; /* keep gcc quiet */
+ if (cp > pbuf) {
+ for ( ; cp >= pbuf && *cp != '/'; cp--)
+ ; /* nothing */
+ if (cp > pbuf) {
+ ep = cp++;
+ *ep = '\0';
+ } else {
+ cp = pbuf;
+ }
+ if (ep) {
+ plen = ep - pbuf;
+ nlen = n - plen - 1;
+ }
+ }
+ if (cp == pbuf) {
+ prefix = "/";
+ plen = 1;
+ if (*cp == '/') {
+ nlen = n - 1;
+ cp++;
+ } else
+ nlen = n;
+ ep = NULL;
+ }
+
+ DEBUG_PRINTF(2, ("looking for %s %zu %s\n", prefix, plen, cp));
+
+ LIST_FOREACH(fip, &fi_list, entries) {
+ DEBUG_PRINTF(4, ("at %zu %s\n",
+ fip->fi_prefix_len, fip->fi_prefix));
+
+ if (fip->fi_prefix_len < plen) {
+ DEBUG_PRINTF(3, ("skipping prefix=%s %zu %zu\n",
+ fip->fi_prefix, fip->fi_prefix_len,
+ plen));
+ break;
+ }
+ if (fip->fi_prefix_len == plen) {
+ if (fip->fi_dev != 0 && fip->fi_dev != dev) {
+ DEBUG_PRINTF(3, (
+ "skipping dev=%ld != %ld\n",
+ (long)fip->fi_dev,
+ (long)dev));
+ continue;
+ }
+ if (strcmp(prefix, fip->fi_prefix)) {
+ DEBUG_PRINTF(3, (
+ "skipping prefix=%s\n",
+ fip->fi_prefix));
+ continue;
+ }
+ DEBUG_PRINTF(3, ("checking prefix=%s\n",
+ fip->fi_prefix));
+ if (fip->fi_skip_len) {
+ np = nbuf;
+ nplen = snprintf(nbuf, sizeof(nbuf),
+ "%s/%s",
+ fip->fi_skip, cp);
+ nplen = MIN(nplen, sizeof(nbuf) - 1);
+ } else {
+ np = cp;
+ nplen = nlen;
+ }
+ DEBUG_PRINTF(3, ("lookup: '%s'\n", np));
+ if (!(fp = strstr(fip->fi_data, np)))
+ continue;
+#ifdef MANIFEST_SKIP_MAYBE
+ if (fip->fi_skip_len == 0 &&
+ fp > fip->fi_data && fp[-1] == '/') {
+ fp = maybe_skip(fp, fip, &nplen);
+ }
+#endif
+ /*
+ * when we find a match:
+ * fp[nplen] will be space and
+ * fp will be fip->fi_data or
+ * fp[-1] will be \n
+ */
+ if (!((fp == fip->fi_data || fp[-1] == '\n') &&
+ fp[nplen] == ' ')) {
+ do {
+ fp++;
+ fp = strstr(fp, np);
+ if (fp) {
+#ifdef MANIFEST_SKIP_MAYBE
+ if (fip->fi_skip_len == 0 &&
+ fp > fip->fi_data &&
+ fp[-1] == '/') {
+ fp = maybe_skip(fp, fip, &nplen);
+ }
+#endif
+ DEBUG_PRINTF(3,
+ ("fp[-1]=%#x fp[%zu]=%#x fp=%.78s\n",
+ fp[-1], nplen,
+ fp[nplen],
+ fp));
+ }
+ } while (fp != NULL &&
+ !(fp[-1] == '\n' &&
+ fp[nplen] == ' '));
+ if (!fp)
+ continue;
+ }
+ DEBUG_PRINTF(2, ("found %.78s\n", fp));
+ /* we have a match! */
+ for (cp = &fp[nplen]; *cp == ' '; cp++)
+ ; /* nothing */
+ return (cp);
+ } else {
+ DEBUG_PRINTF(3,
+ ("Ignoring prefix=%s\n", fip->fi_prefix));
+ }
+ }
+ } while (cp > &pbuf[1]);
+
+ return (NULL);
+}
+
+static int
+verify_fingerprint(int fd, const char *path, const char *cp, off_t off)
+{
+ unsigned char buf[PAGE_SIZE];
+ const br_hash_class *md;
+ br_hash_compat_context mctx;
+ size_t hlen;
+ int n;
+
+ if (strncmp(cp, "sha256=", 7) == 0) {
+ md = &br_sha256_vtable;
+ hlen = br_sha256_SIZE;
+ cp += 7;
+#ifdef VE_SHA1_SUPPORT
+ } else if (strncmp(cp, "sha1=", 5) == 0) {
+ md = &br_sha1_vtable;
+ hlen = br_sha1_SIZE;
+ cp += 5;
+#endif
+#ifdef VE_SHA384_SUPPORT
+ } else if (strncmp(cp, "sha384=", 7) == 0) {
+ md = &br_sha384_vtable;
+ hlen = br_sha384_SIZE;
+ cp += 7;
+#endif
+#ifdef VE_SHA512_SUPPORT
+ } else if (strncmp(cp, "sha512=", 7) == 0) {
+ md = &br_sha512_vtable;
+ hlen = br_sha512_SIZE;
+ cp += 7;
+#endif
+ } else {
+ ve_error_set("%s: no supported fingerprint", path);
+ return (VE_FINGERPRINT_UNKNOWN);
+ }
+
+ md->init(&mctx.vtable);
+ if (off)
+ lseek(fd, 0, SEEK_SET);
+ do {
+ n = read(fd, buf, sizeof(buf));
+ if (n < 0)
+ return (n);
+ if (n > 0)
+ md->update(&mctx.vtable, buf, n);
+ } while (n > 0);
+ lseek(fd, off, SEEK_SET);
+ return (ve_check_hash(&mctx, md, path, cp, hlen));
+}
+
+
+/**
+ * @brief
+ * verify an open file
+ *
+ * @param[in] fd
+ * open descriptor
+ *
+ * @param[in] path
+ * pathname to open
+ *
+ * @param[in] off
+ * current offset
+ *
+ * @return 0, VE_FINGERPRINT_OK or VE_FINGERPRINT_NONE, VE_FINGERPRINT_WRONG
+ */
+int
+verify_fd(int fd, const char *path, off_t off, struct stat *stp)
+{
+ struct stat st;
+ char *cp;
+ int rc;
+
+ if (!stp) {
+ if (fstat(fd, &st) == 0)
+ stp = &st;
+ }
+ if (stp && !S_ISREG(stp->st_mode))
+ return (0); /* not relevant */
+ cp = fingerprint_info_lookup(fd, path);
+ if (!cp) {
+ ve_error_set("%s: no entry", path);
+ return (VE_FINGERPRINT_NONE);
+ }
+ rc = verify_fingerprint(fd, path, cp, off);
+ switch (rc) {
+ case VE_FINGERPRINT_OK:
+ case VE_FINGERPRINT_UNKNOWN:
+ return (rc);
+ default:
+ return (VE_FINGERPRINT_WRONG);
+ }
+}
+
+/**
+ * @brief
+ * open a file if it can be verified
+ *
+ * @param[in] path
+ * pathname to open
+ *
+ * @param[in] flags
+ * flags for open
+ *
+ * @return fd or VE_FINGERPRINT_NONE, VE_FINGERPRINT_WRONG
+ */
+int
+verify_open(const char *path, int flags)
+{
+ int fd;
+ int rc;
+
+ if ((fd = open(path, flags)) >= 0) {
+ if ((rc = verify_fd(fd, path, 0, NULL)) < 0) {
+ close(fd);
+ fd = rc;
+ }
+ }
+ return (fd);
+}
Property changes on: stable/12/lib/libsecureboot/veopen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/vepcr.c
===================================================================
--- stable/12/lib/libsecureboot/vepcr.c (nonexistent)
+++ stable/12/lib/libsecureboot/vepcr.c (revision 346145)
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "libsecureboot-priv.h"
+
+/*
+ * To support measured boot without putting a ton
+ * of extra code in the loader, we just maintain
+ * a hash of all the hashes we (attempt to) verify.
+ * The loader can export this for kernel or rc script
+ * to feed to a TPM pcr register - hence the name ve_pcr.
+ *
+ * NOTE: in the current standard the TPM pcr register size is for SHA1,
+ * the fact that we provide a SHA256 hash should not matter
+ * as long as we are consistent - it can be truncated or hashed
+ * before feeding to TPM.
+ */
+
+static const br_hash_class *pcr_md = NULL;
+static br_hash_compat_context pcr_ctx;
+static size_t pcr_hlen = 0;
+
+/**
+ * @brief initialize pcr context
+ *
+ * Real TPM registers only hold a SHA1 hash
+ * but we use SHA256
+ */
+void
+ve_pcr_init(void)
+{
+ pcr_hlen = br_sha256_SIZE;
+ pcr_md = &br_sha256_vtable;
+ pcr_md->init(&pcr_ctx.vtable);
+}
+
+/**
+ * @brief update pcr context
+ */
+void
+ve_pcr_update(unsigned char *data, size_t dlen)
+{
+ if (pcr_md)
+ pcr_md->update(&pcr_ctx.vtable, data, dlen);
+}
+
+/**
+ * @brief get pcr result
+ */
+ssize_t
+ve_pcr_get(unsigned char *buf, size_t sz)
+{
+ if (!pcr_md)
+ return (-1);
+ if (sz < pcr_hlen)
+ return (-1);
+ pcr_md->out(&pcr_ctx.vtable, buf);
+ return (pcr_hlen);
+}
+
Property changes on: stable/12/lib/libsecureboot/vepcr.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/vesigned.c
===================================================================
--- stable/12/lib/libsecureboot/vesigned.c (nonexistent)
+++ stable/12/lib/libsecureboot/vesigned.c (revision 346145)
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <libsecureboot.h>
+
+#include <vse.h>
+
+/**
+ * @brief
+ * verify signed file
+ *
+ * We look for a signature using the extensions
+ * recorded in signature_exts.
+ * If we find a match we pass it to a suitable verify method.
+ *
+ * @return content of verified file or NULL on error.
+ */
+unsigned char *
+verify_signed(const char *filename, int flags)
+{
+ struct stat st;
+ char buf[MAXPATHLEN];
+ const char **se;
+
+ for (se = signature_exts; *se; se++) {
+ snprintf(buf, sizeof(buf), "%s.%s", filename, *se);
+ if (stat(buf, &st) < 0 || !S_ISREG(st.st_mode))
+ continue;
+ DEBUG_PRINTF(5, ("verify_signed: %s\n", buf));
+#ifdef VE_OPENPGP_SUPPORT
+ if (strncmp(*se, "asc", 3) == 0)
+ return (verify_asc(buf, flags));
+#endif
+ return (verify_sig(buf, flags));
+ }
+ return (NULL);
+}
Property changes on: stable/12/lib/libsecureboot/vesigned.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/veta.c
===================================================================
--- stable/12/lib/libsecureboot/veta.c (nonexistent)
+++ stable/12/lib/libsecureboot/veta.c (revision 346145)
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file veta.c - add to trust anchors
+ *
+ */
+
+#define NEED_BRSSL_H
+#include "libsecureboot-priv.h"
+#include <brssl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#ifdef VE_OPENPGP_SUPPORT
+#include "openpgp/packet.h"
+#endif
+
+/**
+ * @brief add trust anchors from a file
+ *
+ * The file might contain X.509 certs
+ * or OpenPGP public key
+ */
+static size_t
+trust_file_add(const char *trust)
+{
+ br_x509_certificate *xcs;
+ size_t num;
+
+ xcs = read_certificates(trust, &num);
+ if (xcs) {
+ num = ve_trust_anchors_add(xcs, num);
+ }
+#ifdef VE_OPENPGP_SUPPORT
+ else if (load_key_file(trust)) {
+ num = 1;
+ }
+#endif
+ return (num);
+}
+
+/**
+ * @brief add trust anchors from a directory
+ *
+ * Pass each file in directory to trust_file_add
+ */
+static size_t
+trust_dir_add(const char *trust)
+{
+ char fbuf[MAXPATHLEN];
+ DIR *dh;
+ struct dirent *de;
+ struct stat st;
+ ssize_t sz;
+ size_t num;
+
+ if (!(dh = opendir(trust)))
+ return (0);
+ for (num = 0, de = readdir(dh); de; de = readdir(dh)) {
+ if (de->d_name[0] == '.')
+ continue;
+ sz = snprintf(fbuf, sizeof(fbuf), "%s/%s", trust, de->d_name);
+ if (sz >= (ssize_t)sizeof(fbuf))
+ continue;
+ if (stat(fbuf, &st) < 0 || S_ISDIR(st.st_mode))
+ continue;
+ num += trust_file_add(fbuf);
+ }
+ closedir(dh);
+ return (num);
+}
+
+/**
+ * @brief add trust anchors
+ */
+int
+ve_trust_add(const char *trust)
+{
+ struct stat st;
+
+ if (stat(trust, &st) < 0)
+ return (-1);
+ if (S_ISDIR(st.st_mode))
+ return (trust_dir_add(trust));
+ return (trust_file_add(trust));
+}
Property changes on: stable/12/lib/libsecureboot/veta.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/lib/libsecureboot/vets.c
===================================================================
--- stable/12/lib/libsecureboot/vets.c (nonexistent)
+++ stable/12/lib/libsecureboot/vets.c (revision 346145)
@@ -0,0 +1,700 @@
+/*-
+ * Copyright (c) 2017-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file vets.c - trust store
+ * @brief verify signatures
+ *
+ * We leverage code from BearSSL www.bearssl.org
+ */
+
+#include <sys/time.h>
+#include <stdarg.h>
+#define NEED_BRSSL_H
+#include "libsecureboot-priv.h"
+#include <brssl.h>
+#include <ta.h>
+
+#ifndef TRUST_ANCHOR_STR
+# define TRUST_ANCHOR_STR ta_PEM
+#endif
+
+#define SECONDS_PER_DAY 86400
+#define X509_DAYS_TO_UTC0 719528
+
+int DebugVe = 0;
+
+typedef VECTOR(br_x509_certificate) cert_list;
+
+static anchor_list trust_anchors = VEC_INIT;
+
+void
+ve_debug_set(int n)
+{
+ DebugVe = n;
+}
+
+static char ebuf[512];
+
+char *
+ve_error_get(void)
+{
+ return (ebuf);
+}
+
+int
+ve_error_set(const char *fmt, ...)
+{
+ int rc;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ebuf[0] = '\0';
+ rc = 0;
+ if (fmt) {
+#ifdef STAND_H
+ vsprintf(ebuf, fmt, ap); /* no vsnprintf in libstand */
+ ebuf[sizeof(ebuf) - 1] = '\0';
+ rc = strlen(ebuf);
+#else
+ rc = vsnprintf(ebuf, sizeof(ebuf), fmt, ap);
+#endif
+ }
+ va_end(ap);
+ return (rc);
+}
+
+/* this is the time we use for verifying certs */
+static time_t ve_utc = 0;
+
+/**
+ * @brief
+ * set ve_utc used for certificate verification
+ *
+ * @param[in] utc
+ * time - ignored unless greater than current value.
+ */
+void
+ve_utc_set(time_t utc)
+{
+ if (utc > ve_utc) {
+ DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc));
+ ve_utc = utc;
+ }
+}
+
+static void
+free_cert_contents(br_x509_certificate *xc)
+{
+ xfree(xc->data);
+}
+
+/**
+ * @brief
+ * add certs to our trust store
+ */
+size_t
+ve_trust_anchors_add(br_x509_certificate *xcs, size_t num)
+{
+ br_x509_trust_anchor ta;
+ size_t u;
+
+ for (u = 0; u < num; u++) {
+ if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
+ break;
+ }
+ VEC_ADD(trust_anchors, ta);
+ }
+ return (u);
+}
+
+/**
+ * @brief
+ * initialize our trust_anchors from ta_PEM
+ */
+int
+ve_trust_init(void)
+{
+ br_x509_certificate *xcs;
+ static int once = -1;
+ size_t num;
+
+ if (once >= 0)
+ return (once);
+ once = 0;
+
+ ve_utc_set(time(NULL));
+#ifdef BUILD_UTC
+ ve_utc_set(BUILD_UTC); /* just in case */
+#endif
+ ve_error_set(NULL); /* make sure it is empty */
+#ifdef VE_PCR_SUPPORT
+ ve_pcr_init();
+#endif
+
+#ifdef TRUST_ANCHOR_STR
+ xcs = parse_certificates(__DECONST(unsigned char *, TRUST_ANCHOR_STR),
+ sizeof(TRUST_ANCHOR_STR), &num);
+ if (xcs == NULL)
+ return (0);
+ num = ve_trust_anchors_add(xcs, num);
+ once = (int) num;
+#else
+ num = 0;
+#endif
+ return (num);
+}
+
+/**
+ * if we can verify the certificate chain in "certs",
+ * return the public key and if "xcp" is !NULL the associated
+ * certificate
+ */
+static br_x509_pkey *
+verify_signer_xcs(br_x509_certificate *xcs,
+ size_t num,
+ br_name_element *elts, size_t num_elts)
+{
+ br_x509_minimal_context mc;
+ br_x509_certificate *xc;
+ size_t u;
+ cert_list chain = VEC_INIT;
+ const br_x509_pkey *tpk;
+ br_x509_pkey *pk;
+ unsigned int usages;
+ int err;
+
+ DEBUG_PRINTF(5, ("verify_signer: %zu certs in chain\n", num));
+ VEC_ADDMANY(chain, xcs, num);
+ if (VEC_LEN(chain) == 0) {
+ ve_error_set("ERROR: no/invalid certificate chain\n");
+ return (NULL);
+ }
+
+ DEBUG_PRINTF(5, ("verify_signer: %zu trust anchors\n",
+ VEC_LEN(trust_anchors)));
+
+ br_x509_minimal_init(&mc, &br_sha256_vtable,
+ &VEC_ELT(trust_anchors, 0),
+ VEC_LEN(trust_anchors));
+#ifdef VE_ECDSA_SUPPORT
+ br_x509_minimal_set_ecdsa(&mc,
+ &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
+#endif
+#ifdef VE_RSA_SUPPORT
+ br_x509_minimal_set_rsa(&mc, &br_rsa_i31_pkcs1_vrfy);
+#endif
+#if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
+ /* This is deprecated! do not enable unless you absoultely have to */
+ br_x509_minimal_set_hash(&mc, br_sha1_ID, &br_sha1_vtable);
+#endif
+ br_x509_minimal_set_hash(&mc, br_sha256_ID, &br_sha256_vtable);
+#ifdef VE_SHA384_SUPPORT
+ br_x509_minimal_set_hash(&mc, br_sha384_ID, &br_sha384_vtable);
+#endif
+#ifdef VE_SHA512_SUPPORT
+ br_x509_minimal_set_hash(&mc, br_sha512_ID, &br_sha512_vtable);
+#endif
+ br_x509_minimal_set_name_elements(&mc, elts, num_elts);
+
+#ifdef _STANDALONE
+ /*
+ * Clock is probably bogus so we use ve_utc.
+ */
+ mc.days = (ve_utc / SECONDS_PER_DAY) + X509_DAYS_TO_UTC0;
+ mc.seconds = (ve_utc % SECONDS_PER_DAY);
+#endif
+
+ mc.vtable->start_chain(&mc.vtable, NULL);
+ for (u = 0; u < VEC_LEN(chain); u ++) {
+ xc = &VEC_ELT(chain, u);
+ mc.vtable->start_cert(&mc.vtable, xc->data_len);
+ mc.vtable->append(&mc.vtable, xc->data, xc->data_len);
+ mc.vtable->end_cert(&mc.vtable);
+ switch (mc.err) {
+ case 0:
+ case BR_ERR_X509_OK:
+ case BR_ERR_X509_EXPIRED:
+ break;
+ default:
+ printf("u=%zu mc.err=%d\n", u, mc.err);
+ break;
+ }
+ }
+ err = mc.vtable->end_chain(&mc.vtable);
+ pk = NULL;
+ if (err) {
+ ve_error_set("Validation failed, err = %d", err);
+ } else {
+ tpk = mc.vtable->get_pkey(&mc.vtable, &usages);
+ if (tpk != NULL) {
+ pk = xpkeydup(tpk);
+ }
+ }
+ VEC_CLEAREXT(chain, &free_cert_contents);
+ return (pk);
+}
+
+static br_x509_pkey *
+verify_signer(const char *certs,
+ br_name_element *elts, size_t num_elts)
+{
+ br_x509_certificate *xcs;
+ br_x509_pkey *pk;
+ size_t num;
+
+ ve_trust_init();
+ xcs = read_certificates(certs, &num);
+ if (xcs == NULL) {
+ ve_error_set("cannot read certificates\n");
+ return (NULL);
+ }
+ pk = verify_signer_xcs(xcs, num, elts, num_elts);
+ xfree(xcs);
+ return (pk);
+}
+
+/**
+ * we need a hex digest including trailing newline below
+ */
+char *
+hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len)
+{
+ char const hex2ascii[] = "0123456789abcdef";
+ size_t i;
+
+ /* every binary byte is 2 chars in hex + newline + null */
+ if (bufsz < (2 * foo_len) + 2)
+ return (NULL);
+
+ for (i = 0; i < foo_len; i++) {
+ buf[i * 2] = hex2ascii[foo[i] >> 4];
+ buf[i * 2 + 1] = hex2ascii[foo[i] & 0x0f];
+ }
+
+ buf[i * 2] = 0x0A; /* we also want a newline */
+ buf[i * 2 + 1] = '\0';
+
+ return (buf);
+}
+
+/**
+ * @brief
+ * verify file against sigfile using pk
+ *
+ * When we generated the signature in sigfile,
+ * we hashed (sha256) file, and sent that to signing server
+ * which hashed (sha256) that hash.
+ *
+ * To verify we need to replicate that result.
+ *
+ * @param[in] pk
+ * br_x509_pkey
+ *
+ * @paramp[in] file
+ * file to be verified
+ *
+ * @param[in] sigfile
+ * signature (PEM encoded)
+ *
+ * @return NULL on error, otherwise content of file.
+ */
+#ifdef VE_ECDSA_SUPPORT
+static unsigned char *
+verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile)
+{
+ char hexbuf[br_sha512_SIZE * 2 + 2];
+ unsigned char rhbuf[br_sha512_SIZE];
+ char *hex;
+ br_sha256_context ctx;
+ unsigned char *fcp, *scp;
+ size_t flen, slen, plen;
+ pem_object *po;
+ const br_ec_impl *ec;
+ br_ecdsa_vrfy vrfy;
+
+ if ((fcp = read_file(file, &flen)) == NULL)
+ return (NULL);
+ if ((scp = read_file(sigfile, &slen)) == NULL) {
+ free(fcp);
+ return (NULL);
+ }
+ if ((po = decode_pem(scp, slen, &plen)) == NULL) {
+ free(fcp);
+ free(scp);
+ return (NULL);
+ }
+ br_sha256_init(&ctx);
+ br_sha256_update(&ctx, fcp, flen);
+ br_sha256_out(&ctx, rhbuf);
+ hex = hexdigest(hexbuf, sizeof(hexbuf), rhbuf, br_sha256_SIZE);
+ /* now hash that */
+ if (hex) {
+ br_sha256_init(&ctx);
+ br_sha256_update(&ctx, hex, strlen(hex));
+ br_sha256_out(&ctx, rhbuf);
+ }
+ ec = br_ec_get_default();
+ vrfy = br_ecdsa_vrfy_asn1_get_default();
+ if (!vrfy(ec, rhbuf, br_sha256_SIZE, &pk->key.ec, po->data,
+ po->data_len)) {
+ free(fcp);
+ fcp = NULL;
+ }
+ free(scp);
+ return (fcp);
+}
+#endif
+
+#if defined(VE_RSA_SUPPORT) || defined(VE_OPENPGP_SUPPORT)
+/**
+ * @brief verify an rsa digest
+ *
+ * @return 0 on failure
+ */
+int
+verify_rsa_digest (br_rsa_public_key *pkey,
+ const unsigned char *hash_oid,
+ unsigned char *mdata, size_t mlen,
+ unsigned char *sdata, size_t slen)
+{
+ br_rsa_pkcs1_vrfy vrfy;
+ unsigned char vhbuf[br_sha512_SIZE];
+
+ vrfy = br_rsa_pkcs1_vrfy_get_default();
+
+ if (!vrfy(sdata, slen, hash_oid, mlen, pkey, vhbuf) ||
+ memcmp(vhbuf, mdata, mlen) != 0) {
+ return (0); /* fail */
+ }
+ return (1); /* ok */
+}
+#endif
+
+/**
+ * @brief
+ * verify file against sigfile using pk
+ *
+ * When we generated the signature in sigfile,
+ * we hashed (sha256) file, and sent that to signing server
+ * which hashed (sha256) that hash.
+ *
+ * Or (deprecated) we simply used sha1 hash directly.
+ *
+ * To verify we need to replicate that result.
+ *
+ * @param[in] pk
+ * br_x509_pkey
+ *
+ * @paramp[in] file
+ * file to be verified
+ *
+ * @param[in] sigfile
+ * signature (PEM encoded)
+ *
+ * @return NULL on error, otherwise content of file.
+ */
+#ifdef VE_RSA_SUPPORT
+static unsigned char *
+verify_rsa(br_x509_pkey *pk, const char *file, const char *sigfile)
+{
+ unsigned char rhbuf[br_sha512_SIZE];
+ const unsigned char *hash_oid;
+ const br_hash_class *md;
+ br_hash_compat_context mctx;
+ unsigned char *fcp, *scp;
+ size_t flen, slen, plen, hlen;
+ pem_object *po;
+
+ if ((fcp = read_file(file, &flen)) == NULL)
+ return (NULL);
+ if ((scp = read_file(sigfile, &slen)) == NULL) {
+ free(fcp);
+ return (NULL);
+ }
+ if ((po = decode_pem(scp, slen, &plen)) == NULL) {
+ free(fcp);
+ free(scp);
+ return (NULL);
+ }
+
+ switch (po->data_len) {
+#if defined(UNIT_TEST) && defined(VE_DEPRECATED_RSA_SHA1_SUPPORT)
+ case 256:
+ // this is our old deprecated sig method
+ md = &br_sha1_vtable;
+ hlen = br_sha1_SIZE;
+ hash_oid = BR_HASH_OID_SHA1;
+ break;
+#endif
+ default:
+ md = &br_sha256_vtable;
+ hlen = br_sha256_SIZE;
+ hash_oid = BR_HASH_OID_SHA256;
+ break;
+ }
+ md->init(&mctx.vtable);
+ md->update(&mctx.vtable, fcp, flen);
+ md->out(&mctx.vtable, rhbuf);
+ if (!verify_rsa_digest(&pk->key.rsa, hash_oid,
+ rhbuf, hlen, po->data, po->data_len)) {
+ free(fcp);
+ fcp = NULL;
+ }
+ free(scp);
+ return (fcp);
+}
+#endif
+
+/**
+ * @brief
+ * verify a signature and return content of signed file
+ *
+ * @param[in] sigfile
+ * file containing signature
+ * we derrive path of signed file and certificate change from
+ * this.
+ *
+ * @param[in] flags
+ * only bit 1 significant so far
+ *
+ * @return NULL on error otherwise content of signed file
+ */
+unsigned char *
+verify_sig(const char *sigfile, int flags)
+{
+ br_x509_pkey *pk;
+ br_name_element cn;
+ char cn_buf[80];
+ unsigned char cn_oid[4];
+ char pbuf[MAXPATHLEN];
+ char *cp;
+ unsigned char *ucp;
+ size_t n;
+
+ DEBUG_PRINTF(5, ("verify_sig: %s\n", sigfile));
+ n = strlcpy(pbuf, sigfile, sizeof(pbuf));
+ if (n > (sizeof(pbuf) - 5) || strcmp(&sigfile[n - 3], "sig") != 0)
+ return (NULL);
+ cp = strcpy(&pbuf[n - 3], "certs");
+ /*
+ * We want the commonName field
+ * the OID we want is 2,5,4,3 - but DER encoded
+ */
+ cn_oid[0] = 3;
+ cn_oid[1] = 0x55;
+ cn_oid[2] = 4;
+ cn_oid[3] = 3;
+ cn.oid = cn_oid;
+ cn.buf = cn_buf;
+ cn.len = sizeof(cn_buf);
+
+ pk = verify_signer(pbuf, &cn, 1);
+ if (!pk) {
+ printf("cannot verify: %s: %s\n", pbuf, ve_error_get());
+ return (NULL);
+ }
+ for (; cp > pbuf; cp--) {
+ if (*cp == '.') {
+ *cp = '\0';
+ break;
+ }
+ }
+ switch (pk->key_type) {
+#ifdef VE_ECDSA_SUPPORT
+ case BR_KEYTYPE_EC:
+ ucp = verify_ec(pk, pbuf, sigfile);
+ break;
+#endif
+#ifdef VE_RSA_SUPPORT
+ case BR_KEYTYPE_RSA:
+ ucp = verify_rsa(pk, pbuf, sigfile);
+ break;
+#endif
+ default:
+ ucp = NULL; /* not supported */
+ }
+ xfreepkey(pk);
+ if (!ucp) {
+ printf("Unverified %s (%s)\n", pbuf,
+ cn.status ? cn_buf : "unknown");
+ } else if ((flags & 1) != 0) {
+ printf("Verified %s signed by %s\n", pbuf,
+ cn.status ? cn_buf : "someone we trust");
+ }
+ return (ucp);
+}
+
+
+/**
+ * @brief verify hash matches
+ *
+ * We have finished hashing a file,
+ * see if we got the desired result.
+ *
+ * @param[in] ctx
+ * pointer to hash context
+ *
+ * @param[in] md
+ * pointer to hash class
+ *
+ * @param[in] path
+ * name of the file we are checking
+ *
+ * @param[in] want
+ * the expected result
+ *
+ * @param[in] hlen
+ * size of hash output
+ *
+ * @return 0 on success
+ */
+int
+ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md,
+ const char *path, const char *want, size_t hlen)
+{
+ char hexbuf[br_sha512_SIZE * 2 + 2];
+ unsigned char hbuf[br_sha512_SIZE];
+ char *hex;
+ int rc;
+ int n;
+
+ md->out(&ctx->vtable, hbuf);
+#ifdef VE_PCR_SUPPORT
+ ve_pcr_update(hbuf, hlen);
+#endif
+ hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen);
+ if (!hex)
+ return (VE_FINGERPRINT_WRONG);
+ n = 2*hlen;
+ if ((rc = strncmp(hex, want, n))) {
+ ve_error_set("%s: %.*s != %.*s", path, n, hex, n, want);
+ rc = VE_FINGERPRINT_WRONG;
+ }
+ return (rc ? rc : VE_FINGERPRINT_OK);
+}
+
+#ifdef VE_HASH_KAT_STR
+static int
+test_hash(const br_hash_class *md, size_t hlen,
+ const char *hname, const char *s, size_t slen, const char *want)
+{
+ br_hash_compat_context mctx;
+
+ md->init(&mctx.vtable);
+ md->update(&mctx.vtable, s, slen);
+ return (ve_check_hash(&mctx, md, hname, want, hlen) != VE_FINGERPRINT_OK);
+}
+
+#endif
+
+#define ve_test_hash(n, N) \
+ printf("Testing hash: " #n "\t\t\t\t%s\n", \
+ test_hash(&br_ ## n ## _vtable, br_ ## n ## _SIZE, #n, \
+ VE_HASH_KAT_STR, sizeof(VE_HASH_KAT_STR), \
+ vh_ ## N) ? "Failed" : "Passed")
+
+/**
+ * @brief
+ * run self tests on hash and signature verification
+ *
+ * Test that the hash methods (SHA1 and SHA256) work.
+ * Test that we can verify a certificate for each supported
+ * Root CA.
+ *
+ * @return cached result.
+ */
+int
+ve_self_tests(void)
+{
+ static int once = -1;
+#ifdef VERIFY_CERTS_STR
+ br_x509_certificate *xcs;
+ br_x509_pkey *pk;
+ br_name_element cn;
+ char cn_buf[80];
+ unsigned char cn_oid[4];
+ size_t num;
+ size_t u;
+#endif
+
+ if (once >= 0)
+ return (once);
+ once = 0;
+
+ DEBUG_PRINTF(5, ("Self tests...\n"));
+#ifdef VE_HASH_KAT_STR
+#ifdef VE_SHA1_SUPPORT
+ ve_test_hash(sha1, SHA1);
+#endif
+#ifdef VE_SHA256_SUPPORT
+ ve_test_hash(sha256, SHA256);
+#endif
+#ifdef VE_SHA384_SUPPORT
+ ve_test_hash(sha384, SHA384);
+#endif
+#ifdef VE_SHA512_SUPPORT
+ ve_test_hash(sha512, SHA512);
+#endif
+#endif
+#ifdef VERIFY_CERTS_STR
+ xcs = parse_certificates(__DECONST(unsigned char *, VERIFY_CERTS_STR),
+ sizeof(VERIFY_CERTS_STR), &num);
+ if (xcs == NULL)
+ return (0);
+ /*
+ * We want the commonName field
+ * the OID we want is 2,5,4,3 - but DER encoded
+ */
+ cn_oid[0] = 3;
+ cn_oid[1] = 0x55;
+ cn_oid[2] = 4;
+ cn_oid[3] = 3;
+ cn.oid = cn_oid;
+ cn.buf = cn_buf;
+
+ for (u = 0; u < num; u ++) {
+ cn.len = sizeof(cn_buf);
+ if ((pk = verify_signer_xcs(&xcs[u], 1, &cn, 1)) != NULL) {
+ once++;
+ printf("Testing verify certificate: %s\tPassed\n",
+ cn.status ? cn_buf : "");
+ xfreepkey(pk);
+ }
+ }
+ if (!once)
+ printf("Testing verify certificate:\t\t\tFailed\n");
+ xfree(xcs);
+#else
+ printf("No X.509 self tests\n");
+#endif /* VERIFY_CERTS_STR */
+#ifdef VE_OPENPGP_SUPPORT
+ if (!openpgp_self_tests())
+ once++;
+#endif
+ return (once);
+}
Property changes on: stable/12/lib/libsecureboot/vets.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/sbin/Makefile
===================================================================
--- stable/12/sbin/Makefile (revision 346144)
+++ stable/12/sbin/Makefile (revision 346145)
@@ -1,98 +1,99 @@
# @(#)Makefile 8.5 (Berkeley) 3/31/94
# $FreeBSD$
.include <src.opts.mk>
SUBDIR=adjkerntz \
camcontrol \
clri \
comcontrol \
conscontrol \
ddb \
devfs \
devmatch \
dhclient \
dmesg \
dump \
dumpfs \
dumpon \
etherswitchcfg \
ffsinfo \
fsck \
fsck_ffs \
fsck_msdosfs \
fsdb \
fsirand \
gbde \
geom \
ggate \
growfs \
gvinum \
ifconfig \
init \
kldconfig \
kldload \
kldstat \
kldunload \
ldconfig \
md5 \
mdconfig \
mdmfs \
mknod \
mksnap_ffs \
mount \
mount_cd9660 \
mount_fusefs \
mount_msdosfs \
mount_nfs \
mount_nullfs \
mount_udf \
mount_unionfs \
newfs \
newfs_msdos \
nfsiod \
nos-tun \
ping \
rcorder \
reboot \
recoverdisk \
resolvconf \
restore \
route \
savecore \
setkey \
shutdown \
spppcontrol \
swapon \
sysctl \
tunefs \
umount
SUBDIR.${MK_CCD}+= ccdconfig
SUBDIR.${MK_CXX}+= devd
SUBDIR.${MK_HAST}+= hastctl
SUBDIR.${MK_HAST}+= hastd
SUBDIR.${MK_INET6}+= ping6
SUBDIR.${MK_INET6}+= rtsol
SUBDIR.${MK_IPFILTER}+= ipf
SUBDIR.${MK_IPFW}+= ipfw
SUBDIR.${MK_IPFW}+= natd
SUBDIR.${MK_ISCSI}+= iscontrol
SUBDIR.${MK_NAND}+= nandfs
SUBDIR.${MK_NAND}+= newfs_nandfs
SUBDIR.${MK_NVME}+= nvmecontrol
SUBDIR.${MK_OPENSSL}+= decryptcore
SUBDIR.${MK_PF}+= pfctl
SUBDIR.${MK_PF}+= pflogd
SUBDIR.${MK_QUOTAS}+= quotacheck
SUBDIR.${MK_ROUTED}+= routed
+SUBDIR.${MK_VERIEXEC}+= veriexec
SUBDIR.${MK_ZFS}+= bectl
SUBDIR.${MK_ZFS}+= zfsbootcfg
SUBDIR.${MK_TESTS}+= tests
.include <bsd.arch.inc.mk>
SUBDIR_PARALLEL=
.include <bsd.subdir.mk>
Index: stable/12/sbin/veriexec/Makefile
===================================================================
--- stable/12/sbin/veriexec/Makefile (nonexistent)
+++ stable/12/sbin/veriexec/Makefile (revision 346145)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+PROG= veriexec
+MAN= veriexec.8
+SRCS= \
+ veriexec.c \
+ manifest_parser.y \
+ manifest_lexer.l
+
+LIBADD+= veriexec secureboot bearssl
+
+NO_SHARED=
+
+.include <bsd.prog.mk>
+
+CFLAGS+= -I${.CURDIR} ${XCFLAGS.${.TARGET:T:R}:U}
+
+XCFLAGS.manifest_lexer+= -Wno-missing-variable-declarations \
+ -Wno-unneeded-internal-declaration
+XCFLAGS.manifest_parser+= -Wno-missing-variable-declarations
Property changes on: stable/12/sbin/veriexec/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/sbin/veriexec/Makefile.depend
===================================================================
--- stable/12/sbin/veriexec/Makefile.depend (nonexistent)
+++ stable/12/sbin/veriexec/Makefile.depend (revision 346145)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbearssl \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsecureboot \
+ lib/libveriexec \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
Property changes on: stable/12/sbin/veriexec/Makefile.depend
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/sbin/veriexec/manifest_lexer.l
===================================================================
--- stable/12/sbin/veriexec/manifest_lexer.l (nonexistent)
+++ stable/12/sbin/veriexec/manifest_lexer.l (revision 346145)
@@ -0,0 +1,151 @@
+%{
+/*-
+ * Copyright (c) 2004-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "veriexec.h"
+#include "manifest_parser.h"
+
+#define YY_NO_UNPUT
+
+int lineno = 1;
+int bol = 1;
+extern int parser_version;
+
+void yyerror(const char *message);
+void warning(const char *message);
+int yylex(void);
+
+%}
+
+%%
+
+\n {
+ lineno++;
+ bol=1;
+ return EOL;
+}
+
+[/a-zA-Z0-9\.][^ \t\n=]* {
+ yylval.string = strdup(yytext);
+ if (bol) {
+ bol=0;
+ return PATH;
+ } else
+ return STRING;
+}
+
+= {
+ return EQ;
+}
+
+
+[ \t\r] ; /* eat white ones */
+
+#>[0-9]+ {
+ /*
+ * If we are older than the specified version
+ * ignore rest of line, otherwise just discard this token.
+ */
+ int skip = atoi(&yytext[2]);
+
+ VERBOSE(3, ("%s: skip if %d <= %d\n", yytext, parser_version, skip));
+ if (parser_version <= skip) {
+ /* treat as a comment, yyless() is cheaper than yyunput() */
+ yytext[yyleng - 1] = '#';
+ yyless(2);
+ }
+}
+
+#[^>\n].* ; /* comment */
+
+. yyerror("invalid character");
+
+%%
+
+static char *manifest_file = NULL;
+
+struct string_buf {
+ const char *buf;
+ size_t pos, size;
+};
+
+static int
+read_string_buf (void *token, char *dest, int count)
+{
+ struct string_buf *str_buf_p = (struct string_buf *)token;
+ ssize_t n;
+
+ if (count < 0)
+ return 0;
+
+ n = str_buf_p->size - str_buf_p->pos;
+ if (count < n)
+ n = count;
+
+ memcpy(dest, str_buf_p->buf + str_buf_p->pos, n);
+ str_buf_p->pos += n;
+
+ return n;
+}
+
+FILE *
+manifest_open (const char *file, const char *file_content)
+{
+ static struct string_buf str_buf;
+
+ if (manifest_file) {
+ free(manifest_file);
+ fclose(yyin);
+ }
+
+ str_buf.buf = file_content;
+ str_buf.pos = 0;
+ str_buf.size = strlen(file_content);
+ yyin = fropen(&str_buf, read_string_buf);
+ if (yyin) {
+ manifest_file = strdup(file);
+ lineno = 1;
+ manifest_parser_init();
+ } else
+ manifest_file = NULL;
+ return yyin;
+}
+
+void
+yyerror(const char *string)
+{
+ fprintf(stderr, "%s: %d: %s at %s\n",
+ manifest_file, lineno, string, yytext);
+}
+
+int
+yywrap(void)
+{
+ return (1);
+}
Property changes on: stable/12/sbin/veriexec/manifest_lexer.l
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Index: stable/12/sbin/veriexec/manifest_parser.y
===================================================================
--- stable/12/sbin/veriexec/manifest_parser.y (nonexistent)
+++ stable/12/sbin/veriexec/manifest_parser.y (revision 346145)
@@ -0,0 +1,301 @@
+%{
+/*-
+ * Copyright (c) 2004-2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <err.h>
+#include <sysexits.h>
+#include <libsecureboot.h>
+
+#include "veriexec.h"
+
+int yylex(void);
+void yyerror(const char *);
+
+/* function prototypes */
+static int convert(char *fp, unsigned int count, unsigned char *out);
+static void do_ioctl(void);
+static int get_fingerprint_type(const char *fp_type);
+
+/* ioctl parameter struct */
+#ifdef MAXLABELLEN
+static struct verified_exec_label_params lparams;
+static struct verified_exec_params *params = &lparams.params;
+#else
+static struct verified_exec_params oparams;
+static struct verified_exec_params *params = &oparams;
+#endif
+
+#ifndef SHA256_DIGEST_LENGTH
+# define SHA_DIGEST_LENGTH br_sha1_SIZE
+# define SHA256_DIGEST_LENGTH br_sha256_SIZE
+# define SHA384_DIGEST_LENGTH br_sha384_SIZE
+#endif
+
+static int fmode;
+
+extern int lineno;
+extern int dev_fd;
+
+struct fingerprint_type {
+ const char *fp_type;
+ int fp_size;
+};
+
+/* static globals */
+static const struct fingerprint_type fingerprint_table[] = {
+ { "sha1", SHA_DIGEST_LENGTH },
+ { "sha256", SHA256_DIGEST_LENGTH },
+#if MAXFINGERPRINTLEN > 32
+ { "sha384", SHA384_DIGEST_LENGTH },
+#endif
+ { NULL, 0 }
+};
+
+/*
+ * Indicate to lexer our version.
+ * A token #>NUMBER will be consumed (and discared)
+ * by lexer if parser_version > NUMBER
+ * Otherwise the rest of the line will be discared
+ * as for a comment.
+ */
+int parser_version = 1;
+
+%}
+
+%union {
+ char *string;
+ int intval;
+}
+
+%token EOL
+%token <string> EQ
+%token <string> PATH
+%token <string> STRING
+
+%%
+
+statement: /* empty */
+ | statement path attributes eol
+ | statement error eol {
+ yyclearin; /* discard lookahead */
+ yyerrok; /* no more error */
+ fprintf(stderr,
+ "skipping to next fingerprint\n");
+ }
+ ;
+
+attributes: /* empty */
+ | attributes flag
+ | attributes attr
+ ;
+
+attr: STRING EQ STRING
+{
+ int fptype;
+
+ fptype = get_fingerprint_type($1);
+
+ /*
+ * There's only one attribute we care about
+ */
+ if (fingerprint_table[fptype].fp_size) {
+ strlcpy(params->fp_type, $1, sizeof(params->fp_type));
+ if (convert($3, fingerprint_table[fptype].fp_size,
+ params->fingerprint) < 0) {
+ yyerror("bad fingerprint");
+ YYERROR;
+ }
+ } else if (strcmp($1, "label") == 0) {
+ static int warned_labels = 0;
+
+#ifdef VERIEXEC_LABEL
+ strlcpy(lparams.label, $3, sizeof(lparams.label));
+ VERBOSE(3, ("version=%d label=%s\n", VeriexecVersion,
+ lparams.label));
+ if (VeriexecVersion > 1) {
+ params->flags |= VERIEXEC_LABEL;
+ } else
+#endif
+ if (!warned_labels) {
+ warnx("ignoring labels");
+ warned_labels = 1;
+ }
+ } else if (strcmp($1, "mode") == 0) {
+ fmode = (int)strtol($3, NULL, 8);
+ }
+};
+
+flag: STRING
+{
+ /*
+ * indirect only matters if the interpreter itself is not
+ * executable.
+ */
+ if (!strcmp($1, "indirect")) {
+ params->flags |= VERIEXEC_INDIRECT;
+ } else if (!strcmp($1, "no_ptrace")) {
+ params->flags |= VERIEXEC_NOTRACE;
+ } else if (!strcmp($1, "trusted")) {
+ params->flags |= VERIEXEC_TRUSTED;
+ } else if (!strcmp($1, "no_fips")) {
+#ifdef VERIEXEC_NOFIPS
+ params->flags |= VERIEXEC_NOFIPS;
+#endif
+ }
+}
+;
+
+path: PATH
+{
+ if (strlen($1) >= MAXPATHLEN) {
+ yyerror("Path >= MAXPATHLEN");
+ YYERROR;
+ }
+ /*
+ * The majority of files in the manifest are relative
+ * to the package mount point, but we want absolute paths.
+ * Prepending '/' is actually all we need.
+ */
+ if (snprintf(params->file, sizeof(params->file), "%s%s%s",
+ Cdir ? Cdir : "",
+ ($1[0] == '/') ? "" : "/",
+ $1) >= (int)sizeof(params->file)) {
+ errx(EX_DATAERR, "cannot form pathname");
+ }
+ params->flags = 0;
+ fmode = -1; /* unknown */
+};
+
+eol: EOL
+{
+ if (!YYRECOVERING()) { /* Don't do the ioctl if we saw an error */
+ do_ioctl();
+ }
+ params->fp_type[0] = '\0'; /* invalidate it */
+};
+
+%%
+
+void
+manifest_parser_init(void)
+{
+ params->fp_type[0] = '\0'; /* invalidate it */
+}
+
+int
+get_fingerprint_type(const char *fp_type)
+{
+ int i;
+
+ for (i = 0; fingerprint_table[i].fp_type; i++)
+ if (!strcmp(fp_type, fingerprint_table[i].fp_type))
+ break;
+
+ return (i);
+}
+
+/*
+ * Convert: takes the hexadecimal string pointed to by fp and converts
+ * it to a "count" byte binary number which is stored in the array pointed to
+ * by out. Returns -1 if the conversion fails.
+ */
+static int
+convert(char *fp, unsigned int count, unsigned char *out)
+{
+ unsigned int i;
+ int value;
+
+ for (i = 0; i < count; i++) {
+ value = 0;
+ if (isdigit(fp[i * 2]))
+ value += fp[i * 2] - '0';
+ else if (isxdigit(fp[i * 2]))
+ value += 10 + tolower(fp[i * 2]) - 'a';
+ else
+ return (-1);
+ value <<= 4;
+ if (isdigit(fp[i * 2 + 1]))
+ value += fp[i * 2 + 1] - '0';
+ else if (isxdigit(fp[i * 2 + 1]))
+ value += 10 + tolower(fp[i * 2 + 1]) - 'a';
+ else
+ return (-1);
+ out[i] = value;
+ }
+
+ return (i);
+}
+
+/*
+ * Perform the load of the fingerprint. Assumes that the fingerprint
+ * pseudo-device is opened and the file handle is in fd.
+ */
+static void
+do_ioctl(void)
+{
+ struct stat st;
+
+ if (params->fp_type[0] == '\0') {
+ VERBOSE(1,("skipping %s\n", params->file));
+ return;
+ }
+
+ /*
+ * See if the path is executable, if not put it on the FILE list.
+ */
+ if (fmode > 0) {
+ if (!(fmode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+ params->flags |= VERIEXEC_FILE;
+ }
+ } else if (stat(params->file, &st) == 0) {
+ if (!(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+ params->flags |= VERIEXEC_FILE;
+ }
+ }
+ /*
+ * We may be forcing some flags...
+ */
+ params->flags |= ForceFlags;
+ VERBOSE(1, ("loading %s for %s %s flags=%#x\n",
+ params->fp_type,
+ (params->flags == VERIEXEC_FILE) ? "file" : "executable",
+ params->file, params->flags));
+
+#ifdef VERIEXEC_LABEL
+ if (params->flags & VERIEXEC_LABEL) {
+ if (ioctl(dev_fd, VERIEXEC_LABEL_LOAD, &lparams) < 0)
+ warn("cannot update veriexec label for %s",
+ params->file);
+ } else
+#endif
+ if (ioctl(dev_fd, VERIEXEC_SIGNED_LOAD, params) < 0)
+ warn("cannot update veriexec for %s", params->file);
+ params->fp_type[0] = '\0';
+}
Property changes on: stable/12/sbin/veriexec/manifest_parser.y
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Index: stable/12/sbin/veriexec/veriexec.8
===================================================================
--- stable/12/sbin/veriexec/veriexec.8 (nonexistent)
+++ stable/12/sbin/veriexec/veriexec.8 (revision 346145)
@@ -0,0 +1,146 @@
+.\"-
+.\" Copyright (c) 2018, Juniper Networks, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 4, 2018
+.Dt VERIEXEC 8
+.Os
+.Sh NAME
+.Nm veriexec
+.Nd manipulate state of mac_veriexec
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Op Fl C Ar directory
+.Pa manifest
+.Nm
+.Fl z Ar state
+.Nm
+.Fl i Ar state
+.Nm
+.Fl x
+.Ar file ...
+.Sh DESCRIPTION
+.Nm
+is a utility to query or manipulate the state of
+.Xr mac_veriexec 4 .
+.Pp
+The first form is for loading a
+.Pa manifest .
+.Nm
+first verifies a digital signature of the
+.Ar manifest
+and if successful, parses it and feeds its content to kernel.
+.Pp
+The second form with
+.Fl z
+is used to modify the
+.Ar state ,
+and with
+.Fl i
+to query the current
+.Ar state .
+.Pp
+The final form with
+.Fl x
+is used to test whether
+.Ar file
+is verified or not.
+This requires
+.Xr mac_veriexec 4
+to be in the
+.Ql active
+or
+.Ql enforce
+state.
+.Pp
+The possible states
+are:
+.Bl -tag -width enforce
+.It Ar loaded
+set automatically when first
+.Pa manifest
+has been loaded.
+.It Ar active
+.Xr mac_veriexec 4
+will begin checking files.
+This state can only be entered from the
+.Ar loaded
+state.
+.It Ar enforce
+.Xr mac_veriexec 4
+will fail attempts to
+.Xr exec 2
+or
+.Xr open 2
+files with
+.Dv O_VERIFY
+unless verified.
+.It Ar locked
+prevent loading of any more manifests.
+.El
+.Sh MANIFESTS
+The manifest contains a mapping of relative pathnames to fingerprints
+with optional flags.
+For example:
+.Bd -literal -offset indent
+sbin/veriexec sha256=f22136...c0ff71 no_ptrace
+usr/bin/python sha256=5944d9...876525 indirect
+sbin/somedaemon sha256=77fc2f...63f5687 label=mod1/val1,mod2/val2
+.Ed
+The supported flags are:
+.Bl -tag -width indirect
+.It Ql indirect
+the executable cannot be run directly,
+but can be used as an interpreter for example via:
+.Bd -literal -offset indent
+#!/usr/bin/python
+.Ed
+.It Ql no_ptrace
+do not allow running executable under a debugger.
+Useful for any application critical to the security state of system.
+.El
+.Pp
+The
+.Ql label
+argument allows associating a
+.Xr maclabel 7
+with the executable.
+Neither
+.Nm
+nor
+.Xr mac_veriexec 4
+(if it supports labels)
+pay any attention to the content of the label
+they are provided for the use of other
+.Xr mac 4
+modules.
+.Sh HISTORY
+The Verified Exec system first appeared in NetBSD.
+This utility derrives from the one found in Junos.
+The key difference is the requirement that manifest files
+be digitally signed.
+
+
Property changes on: stable/12/sbin/veriexec/veriexec.8
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/sbin/veriexec/veriexec.c
===================================================================
--- stable/12/sbin/veriexec/veriexec.c (nonexistent)
+++ stable/12/sbin/veriexec/veriexec.c (revision 346145)
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <paths.h>
+#include <err.h>
+#include <syslog.h>
+#include <libsecureboot.h>
+#include <libveriexec.h>
+
+#include "veriexec.h"
+
+int dev_fd = -1;
+int ForceFlags = 0;
+int Verbose = 0;
+int VeriexecVersion = 0;
+
+const char *Cdir = NULL;
+
+static int
+veriexec_load(const char *manifest)
+{
+ unsigned char *content;
+ int rc;
+
+ content = verify_signed(manifest, VEF_VERBOSE);
+ if (!content)
+ errx(EX_USAGE, "cannot verify %s", manifest);
+ if (manifest_open(manifest, content)) {
+ rc = yyparse();
+ } else {
+ err(EX_NOINPUT, "cannot load %s", manifest);
+ }
+ free(content);
+ return (rc);
+}
+
+int
+main(int argc, char *argv[])
+{
+ unsigned long ctl;
+ int c;
+ int x;
+
+ dev_fd = open(_PATH_DEV_VERIEXEC, O_WRONLY, 0);
+
+ while ((c = getopt(argc, argv, "C:i:x:vz:")) != -1) {
+ switch (c) {
+ case 'C':
+ Cdir = optarg;
+ break;
+ case 'i':
+ if (dev_fd < 0) {
+ err(EX_UNAVAILABLE, "cannot open veriexec");
+ }
+ if (ioctl(dev_fd, VERIEXEC_GETSTATE, &x)) {
+ err(EX_UNAVAILABLE,
+ "Cannot get veriexec state");
+ }
+ switch (optarg[0]) {
+ case 'a': /* active */
+ ctl = VERIEXEC_STATE_ACTIVE;
+ break;
+ case 'e': /* enforce */
+ ctl = VERIEXEC_STATE_ENFORCE;
+ break;
+ case 'l': /* loaded/locked */
+ ctl = (strncmp(optarg, "lock", 4)) ?
+ VERIEXEC_STATE_LOCKED :
+ VERIEXEC_STATE_LOADED;
+ break;
+ default:
+ errx(EX_USAGE, "unknown state %s", optarg);
+ break;
+ }
+ exit((x & ctl) == 0);
+ break;
+ case 'v':
+ Verbose++;
+ break;
+ case 'x':
+ /*
+ * -x says all other args are paths to check.
+ */
+ for (x = 0; optind < argc; optind++) {
+ if (veriexec_check_path(argv[optind])) {
+ warn("%s", argv[optind]);
+ x = 2;
+ }
+ }
+ exit(x);
+ break;
+ case 'z':
+ switch (optarg[0]) {
+ case 'a': /* active */
+ ctl = VERIEXEC_ACTIVE;
+ break;
+ case 'd': /* debug* */
+ ctl = (strstr(optarg, "off")) ?
+ VERIEXEC_DEBUG_OFF : VERIEXEC_DEBUG_ON;
+ if (optind < argc && ctl == VERIEXEC_DEBUG_ON) {
+ x = atoi(argv[optind]);
+ if (x == 0)
+ ctl = VERIEXEC_DEBUG_OFF;
+ }
+ break;
+ case 'e': /* enforce */
+ ctl = VERIEXEC_ENFORCE;
+ break;
+ case 'g':
+ ctl = VERIEXEC_GETSTATE; /* get state */
+ break;
+ case 'l': /* lock */
+ ctl = VERIEXEC_LOCK;
+ break;
+ default:
+ errx(EX_USAGE, "unknown command %s", optarg);
+ break;
+ }
+ if (dev_fd < 0) {
+ err(EX_UNAVAILABLE, "cannot open veriexec");
+ }
+ if (ioctl(dev_fd, ctl, &x)) {
+ err(EX_UNAVAILABLE, "cannot %s veriexec", optarg);
+ }
+ if (ctl == VERIEXEC_DEBUG_ON ||
+ ctl == VERIEXEC_DEBUG_OFF) {
+ printf("debug is: %d\n", x);
+ } else if (ctl == VERIEXEC_GETSTATE) {
+ printf("%#o\n", x);
+ }
+ exit(EX_OK);
+ break;
+ }
+ }
+ openlog(getprogname(), LOG_PID, LOG_AUTH);
+ if (ve_trust_init() < 1)
+ errx(EX_OSFILE, "cannot initialize trust store");
+#ifdef VERIEXEC_GETVERSION
+ if (ioctl(dev_fd, VERIEXEC_GETVERSION, &VeriexecVersion)) {
+ VeriexecVersion = 0; /* unknown */
+ }
+#endif
+
+ for (; optind < argc; optind++) {
+ if (veriexec_load(argv[optind])) {
+ err(EX_DATAERR, "cannot load %s", argv[optind]);
+ }
+ }
+ exit(EX_OK);
+}
Property changes on: stable/12/sbin/veriexec/veriexec.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/sbin/veriexec/veriexec.h
===================================================================
--- stable/12/sbin/veriexec/veriexec.h (nonexistent)
+++ stable/12/sbin/veriexec/veriexec.h (revision 346145)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __VERIEXEC_H__
+#define __VERIEXEC_H__
+
+#include <sys/ioctl.h>
+#include <dev/veriexec/veriexec_ioctl.h>
+
+extern int dev_fd;
+extern int parser_version;
+extern int ForceFlags;
+extern int Verbose;
+extern int VeriexecVersion;
+extern const char *Cdir;
+
+#define VERBOSE(n, x) if (Verbose > n) printf x
+
+FILE * manifest_open (const char *file, const char *file_content);
+void manifest_parser_init(void);
+int yyparse(void);
+extern FILE *yyin;
+
+#endif
Property changes on: stable/12/sbin/veriexec/veriexec.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/share/mk/src.libnames.mk
===================================================================
--- stable/12/share/mk/src.libnames.mk (revision 346144)
+++ stable/12/share/mk/src.libnames.mk (revision 346145)
@@ -1,603 +1,618 @@
# $FreeBSD$
#
# The include file <src.libnames.mk> define library names suitable
# for INTERNALLIB and PRIVATELIB definition
.if !target(__<bsd.init.mk>__)
.error src.libnames.mk cannot be included directly.
.endif
.if !target(__<src.libnames.mk>__)
__<src.libnames.mk>__:
.include <src.opts.mk>
_PRIVATELIBS= \
atf_c \
atf_cxx \
bsdstat \
devdctl \
event \
heimipcc \
heimipcs \
ifconfig \
ldns \
sqlite3 \
ssh \
ucl \
unbound \
zstd
_INTERNALLIBS= \
amu \
bsnmptools \
c_nossp_pic \
cron \
elftc \
fifolog \
ipf \
lpr \
netbsd \
ntp \
ntpevent \
openbsd \
opts \
parse \
pe \
pmcstat \
sl \
sm \
smdb \
smutil \
telnet \
vers
_LIBRARIES= \
${_PRIVATELIBS} \
${_INTERNALLIBS} \
${LOCAL_LIBRARIES} \
80211 \
alias \
archive \
asn1 \
auditd \
avl \
be \
begemot \
bluetooth \
bsdxml \
bsm \
bsnmp \
bz2 \
c \
c_pic \
calendar \
cam \
casper \
cap_dns \
cap_grp \
cap_pwd \
cap_random \
cap_sysctl \
cap_syslog \
com_err \
compiler_rt \
crypt \
crypto \
ctf \
cuse \
cxxrt \
devctl \
devdctl \
devinfo \
devstat \
dialog \
dl \
dpv \
dtrace \
dwarf \
edit \
efivar \
elf \
execinfo \
fetch \
figpar \
geom \
gnuregex \
gpio \
gssapi \
gssapi_krb5 \
hdb \
heimbase \
heimntlm \
heimsqlite \
hx509 \
ipsec \
ipt \
jail \
kadm5clnt \
kadm5srv \
kafs5 \
kdc \
kiconv \
krb5 \
kvm \
l \
lzma \
m \
magic \
md \
memstat \
mp \
mt \
nandfs \
ncurses \
ncursesw \
netgraph \
ngatm \
nv \
nvpair \
opencsd \
opie \
pam \
panel \
panelw \
pcap \
pcsclite \
pjdlog \
pmc \
proc \
procstat \
pthread \
radius \
regex \
roken \
rpcsec_gss \
rpcsvc \
rt \
rtld_db \
sbuf \
sdp \
sm \
smb \
ssl \
ssp_nonshared \
stdthreads \
supcplusplus \
sysdecode \
tacplus \
termcap \
termcapw \
ufs \
ugidfw \
ulog \
umem \
usb \
usbhid \
util \
uutil \
vmmapi \
wind \
wrap \
xo \
y \
ypclnt \
z \
zfs_core \
zfs \
zpool \
.if ${MK_BLACKLIST} != "no"
_LIBRARIES+= \
blacklist \
.endif
.if ${MK_OFED} != "no"
_LIBRARIES+= \
cxgb4 \
ibcm \
ibmad \
ibnetdisc \
ibumad \
ibverbs \
mlx4 \
mlx5 \
rdmacm \
osmcomp \
opensm \
osmvendor
.endif
+.if ${MK_BEARSSL} == "yes"
+_INTERNALLIBS+= \
+ bearssl \
+ secureboot \
+
+LIBBEARSSL?= ${LIBBEARSSLDIR}/libbearssl${PIE_SUFFIX}.a
+LIBSECUREBOOT?= ${LIBSECUREBOOTDIR}/libsecureboot${PIE_SUFFIX}.a
+.endif
+
+.if ${MK_VERIEXEC} == "yes"
+_INTERNALLIBS+= veriexec
+
+LIBVERIEXEC?= ${LIBVERIEXECDIR}/libveriexec${PIE_SUFFIX}.a
+.endif
+
# Each library's LIBADD needs to be duplicated here for static linkage of
# 2nd+ order consumers. Auto-generating this would be better.
_DP_80211= sbuf bsdxml
_DP_archive= z bz2 lzma bsdxml
_DP_zstd= pthread
.if ${MK_BLACKLIST} != "no"
_DP_blacklist+= pthread
.endif
_DP_crypto= pthread
.if ${MK_OPENSSL} != "no"
_DP_archive+= crypto
.else
_DP_archive+= md
.endif
_DP_sqlite3= pthread
_DP_ssl= crypto
_DP_ssh= crypto crypt z
.if ${MK_LDNS} != "no"
_DP_ssh+= ldns
.endif
_DP_edit= ncursesw
.if ${MK_OPENSSL} != "no"
_DP_bsnmp= crypto
.endif
_DP_geom= bsdxml sbuf
_DP_cam= sbuf
_DP_kvm= elf
_DP_casper= nv
_DP_cap_dns= nv
_DP_cap_grp= nv
_DP_cap_pwd= nv
_DP_cap_random= nv
_DP_cap_sysctl= nv
_DP_cap_syslog= nv
.if ${MK_OFED} != "no"
_DP_pcap= ibverbs mlx5
.endif
_DP_pjdlog= util
_DP_opie= md
_DP_usb= pthread
_DP_unbound= ssl crypto pthread
_DP_rt= pthread
.if ${MK_OPENSSL} == "no"
_DP_radius= md
.else
_DP_radius= crypto
.endif
_DP_rtld_db= elf procstat
_DP_procstat= kvm util elf
.if ${MK_CXX} == "yes"
.if ${MK_LIBCPLUSPLUS} != "no"
_DP_proc= cxxrt
.else
_DP_proc= supcplusplus
.endif
.endif
.if ${MK_CDDL} != "no"
_DP_proc+= ctf
.endif
_DP_proc+= elf procstat rtld_db util
_DP_mp= crypto
_DP_memstat= kvm
_DP_magic= z
_DP_mt= sbuf bsdxml
_DP_ldns= ssl crypto
.if ${MK_OPENSSL} != "no"
_DP_fetch= ssl crypto
.else
_DP_fetch= md
.endif
_DP_execinfo= elf
_DP_dwarf= elf
_DP_dpv= dialog figpar util ncursesw
_DP_dialog= ncursesw m
_DP_cuse= pthread
_DP_atf_cxx= atf_c
_DP_devstat= kvm
_DP_pam= radius tacplus opie md util
.if ${MK_KERBEROS} != "no"
_DP_pam+= krb5
.endif
.if ${MK_OPENSSH} != "no"
_DP_pam+= ssh
.endif
.if ${MK_NIS} != "no"
_DP_pam+= ypclnt
.endif
_DP_roken= crypt
_DP_kadm5clnt= com_err krb5 roken
_DP_kadm5srv= com_err hdb krb5 roken
_DP_heimntlm= crypto com_err krb5 roken
_DP_hx509= asn1 com_err crypto roken wind
_DP_hdb= asn1 com_err krb5 roken sqlite3
_DP_asn1= com_err roken
_DP_kdc= roken hdb hx509 krb5 heimntlm asn1 crypto
_DP_wind= com_err roken
_DP_heimbase= pthread
_DP_heimipcc= heimbase roken pthread
_DP_heimipcs= heimbase roken pthread
_DP_kafs5= asn1 krb5 roken
_DP_krb5+= asn1 com_err crypt crypto hx509 roken wind heimbase heimipcc
_DP_gssapi_krb5+= gssapi krb5 crypto roken asn1 com_err
_DP_lzma= pthread
_DP_ucl= m
_DP_vmmapi= util
_DP_opencsd= cxxrt
_DP_ctf= z
_DP_dtrace= ctf elf proc pthread rtld_db
_DP_xo= util
# The libc dependencies are not strictly needed but are defined to make the
# assert happy.
_DP_c= compiler_rt
.if ${MK_SSP} != "no"
_DP_c+= ssp_nonshared
.endif
_DP_stdthreads= pthread
_DP_tacplus= md
_DP_panel= ncurses
_DP_panelw= ncursesw
_DP_rpcsec_gss= gssapi
_DP_smb= kiconv
_DP_ulog= md
_DP_fifolog= z
_DP_ipf= kvm
_DP_zfs= md pthread umem util uutil m nvpair avl bsdxml geom nvpair z \
zfs_core
_DP_zfs_core= nvpair
_DP_zpool= md pthread z nvpair avl umem
_DP_be= zfs nvpair
# OFED support
.if ${MK_OFED} != "no"
_DP_cxgb4= ibverbs pthread
_DP_ibcm= ibverbs
_DP_ibmad= ibumad
_DP_ibnetdisc= osmcomp ibmad ibumad
_DP_ibumad=
_DP_ibverbs=
_DP_mlx4= ibverbs pthread
_DP_mlx5= ibverbs pthread
_DP_rdmacm= ibverbs
_DP_osmcomp= pthread
_DP_opensm= pthread
_DP_osmvendor= ibumad pthread
.endif
# Define special cases
LDADD_supcplusplus= -lsupc++
LIBATF_C= ${LIBDESTDIR}${LIBDIR_BASE}/libprivateatf-c.a
LIBATF_CXX= ${LIBDESTDIR}${LIBDIR_BASE}/libprivateatf-c++.a
LDADD_atf_c= -lprivateatf-c
LDADD_atf_cxx= -lprivateatf-c++
.for _l in ${_PRIVATELIBS}
LIB${_l:tu}?= ${LIBDESTDIR}${LIBDIR_BASE}/libprivate${_l}.a
.endfor
.for _l in ${_LIBRARIES}
.if ${_INTERNALLIBS:M${_l}} || !defined(SYSROOT)
LDADD_${_l}_L+= -L${LIB${_l:tu}DIR}
.endif
DPADD_${_l}?= ${LIB${_l:tu}}
.if ${_PRIVATELIBS:M${_l}}
LDADD_${_l}?= -lprivate${_l}
.else
LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l}
.endif
# Add in all dependencies for static linkage.
.if defined(_DP_${_l}) && (${_INTERNALLIBS:M${_l}} || \
(defined(NO_SHARED) && (${NO_SHARED} != "no" && ${NO_SHARED} != "NO")))
.for _d in ${_DP_${_l}}
DPADD_${_l}+= ${DPADD_${_d}}
LDADD_${_l}+= ${LDADD_${_d}}
.endfor
.endif
.endfor
# These are special cases where the library is broken and anything that uses
# it needs to add more dependencies. Broken usually means that it has a
# cyclic dependency and cannot link its own dependencies. This is bad, please
# fix the library instead.
# Unless the library itself is broken then the proper place to define
# dependencies is _DP_* above.
# libatf-c++ exposes libatf-c abi hence we need to explicit link to atf_c for
# atf_cxx
DPADD_atf_cxx+= ${DPADD_atf_c}
LDADD_atf_cxx+= ${LDADD_atf_c}
# Detect LDADD/DPADD that should be LIBADD, before modifying LDADD here.
_BADLDADD=
.for _l in ${LDADD:M-l*:N-l*/*:C,^-l,,}
.if ${_LIBRARIES:M${_l}} && !${_PRIVATELIBS:M${_l}}
_BADLDADD+= ${_l}
.endif
.endfor
.if !empty(_BADLDADD)
.error ${.CURDIR}: These libraries should be LIBADD+=foo rather than DPADD/LDADD+=-lfoo: ${_BADLDADD}
.endif
.for _l in ${LIBADD}
DPADD+= ${DPADD_${_l}}
LDADD+= ${LDADD_${_l}}
.endfor
# INTERNALLIB definitions.
LIBELFTCDIR= ${OBJTOP}/lib/libelftc
LIBELFTC?= ${LIBELFTCDIR}/libelftc.a
LIBPEDIR= ${OBJTOP}/lib/libpe
LIBPE?= ${LIBPEDIR}/libpe.a
LIBOPENBSDDIR= ${OBJTOP}/lib/libopenbsd
LIBOPENBSD?= ${LIBOPENBSDDIR}/libopenbsd.a
LIBSMDIR= ${OBJTOP}/lib/libsm
LIBSM?= ${LIBSMDIR}/libsm.a
LIBSMDBDIR= ${OBJTOP}/lib/libsmdb
LIBSMDB?= ${LIBSMDBDIR}/libsmdb.a
LIBSMUTILDIR= ${OBJTOP}/lib/libsmutil
LIBSMUTIL?= ${LIBSMUTILDIR}/libsmutil.a
LIBNETBSDDIR?= ${OBJTOP}/lib/libnetbsd
LIBNETBSD?= ${LIBNETBSDDIR}/libnetbsd.a
LIBVERSDIR?= ${OBJTOP}/kerberos5/lib/libvers
LIBVERS?= ${LIBVERSDIR}/libvers.a
LIBSLDIR= ${OBJTOP}/kerberos5/lib/libsl
LIBSL?= ${LIBSLDIR}/libsl.a
LIBIPFDIR= ${OBJTOP}/sbin/ipf/libipf
LIBIPF?= ${LIBIPFDIR}/libipf.a
LIBTELNETDIR= ${OBJTOP}/lib/libtelnet
LIBTELNET?= ${LIBTELNETDIR}/libtelnet.a
LIBCRONDIR= ${OBJTOP}/usr.sbin/cron/lib
LIBCRON?= ${LIBCRONDIR}/libcron.a
LIBNTPDIR= ${OBJTOP}/usr.sbin/ntp/libntp
LIBNTP?= ${LIBNTPDIR}/libntp.a
LIBNTPEVENTDIR= ${OBJTOP}/usr.sbin/ntp/libntpevent
LIBNTPEVENT?= ${LIBNTPEVENTDIR}/libntpevent.a
LIBOPTSDIR= ${OBJTOP}/usr.sbin/ntp/libopts
LIBOPTS?= ${LIBOPTSDIR}/libopts.a
LIBPARSEDIR= ${OBJTOP}/usr.sbin/ntp/libparse
LIBPARSE?= ${LIBPARSEDIR}/libparse.a
LIBLPRDIR= ${OBJTOP}/usr.sbin/lpr/common_source
LIBLPR?= ${LIBLPRDIR}/liblpr.a
LIBFIFOLOGDIR= ${OBJTOP}/usr.sbin/fifolog/lib
LIBFIFOLOG?= ${LIBFIFOLOGDIR}/libfifolog.a
LIBBSNMPTOOLSDIR= ${OBJTOP}/usr.sbin/bsnmpd/tools/libbsnmptools
LIBBSNMPTOOLS?= ${LIBBSNMPTOOLSDIR}/libbsnmptools.a
LIBAMUDIR= ${OBJTOP}/usr.sbin/amd/libamu
LIBAMU?= ${LIBAMUDIR}/libamu.a
LIBBE?= ${LIBBEDIR}/libbe.a
LIBPMCSTATDIR= ${OBJTOP}/lib/libpmcstat
LIBPMCSTAT?= ${LIBPMCSTATDIR}/libpmcstat.a
LIBC_NOSSP_PICDIR= ${OBJTOP}/lib/libc
LIBC_NOSSP_PIC?= ${LIBC_NOSSP_PICDIR}/libc_nossp_pic.a
# Define a directory for each library. This is useful for adding -L in when
# not using a --sysroot or for meta mode bootstrapping when there is no
# Makefile.depend. These are sorted by directory.
LIBAVLDIR= ${OBJTOP}/cddl/lib/libavl
LIBCTFDIR= ${OBJTOP}/cddl/lib/libctf
LIBDTRACEDIR= ${OBJTOP}/cddl/lib/libdtrace
LIBNVPAIRDIR= ${OBJTOP}/cddl/lib/libnvpair
LIBUMEMDIR= ${OBJTOP}/cddl/lib/libumem
LIBUUTILDIR= ${OBJTOP}/cddl/lib/libuutil
LIBZFSDIR= ${OBJTOP}/cddl/lib/libzfs
LIBZFS_COREDIR= ${OBJTOP}/cddl/lib/libzfs_core
LIBZPOOLDIR= ${OBJTOP}/cddl/lib/libzpool
# OFED support
LIBCXGB4DIR= ${OBJTOP}/lib/ofed/libcxgb4
LIBIBCMDIR= ${OBJTOP}/lib/ofed/libibcm
LIBIBMADDIR= ${OBJTOP}/lib/ofed/libibmad
LIBIBNETDISCDIR=${OBJTOP}/lib/ofed/libibnetdisc
LIBIBUMADDIR= ${OBJTOP}/lib/ofed/libibumad
LIBIBVERBSDIR= ${OBJTOP}/lib/ofed/libibverbs
LIBMLX4DIR= ${OBJTOP}/lib/ofed/libmlx4
LIBMLX5DIR= ${OBJTOP}/lib/ofed/libmlx5
LIBRDMACMDIR= ${OBJTOP}/lib/ofed/librdmacm
LIBOSMCOMPDIR= ${OBJTOP}/lib/ofed/complib
LIBOPENSMDIR= ${OBJTOP}/lib/ofed/libopensm
LIBOSMVENDORDIR=${OBJTOP}/lib/ofed/libvendor
LIBDIALOGDIR= ${OBJTOP}/gnu/lib/libdialog
LIBGCOVDIR= ${OBJTOP}/gnu/lib/libgcov
LIBGOMPDIR= ${OBJTOP}/gnu/lib/libgomp
LIBGNUREGEXDIR= ${OBJTOP}/gnu/lib/libregex
LIBSSPDIR= ${OBJTOP}/gnu/lib/libssp
LIBSSP_NONSHAREDDIR= ${OBJTOP}/gnu/lib/libssp/libssp_nonshared
LIBSUPCPLUSPLUSDIR= ${OBJTOP}/gnu/lib/libsupc++
LIBASN1DIR= ${OBJTOP}/kerberos5/lib/libasn1
LIBGSSAPI_KRB5DIR= ${OBJTOP}/kerberos5/lib/libgssapi_krb5
LIBGSSAPI_NTLMDIR= ${OBJTOP}/kerberos5/lib/libgssapi_ntlm
LIBGSSAPI_SPNEGODIR= ${OBJTOP}/kerberos5/lib/libgssapi_spnego
LIBHDBDIR= ${OBJTOP}/kerberos5/lib/libhdb
LIBHEIMBASEDIR= ${OBJTOP}/kerberos5/lib/libheimbase
LIBHEIMIPCCDIR= ${OBJTOP}/kerberos5/lib/libheimipcc
LIBHEIMIPCSDIR= ${OBJTOP}/kerberos5/lib/libheimipcs
LIBHEIMNTLMDIR= ${OBJTOP}/kerberos5/lib/libheimntlm
LIBHX509DIR= ${OBJTOP}/kerberos5/lib/libhx509
LIBKADM5CLNTDIR= ${OBJTOP}/kerberos5/lib/libkadm5clnt
LIBKADM5SRVDIR= ${OBJTOP}/kerberos5/lib/libkadm5srv
LIBKAFS5DIR= ${OBJTOP}/kerberos5/lib/libkafs5
LIBKDCDIR= ${OBJTOP}/kerberos5/lib/libkdc
LIBKRB5DIR= ${OBJTOP}/kerberos5/lib/libkrb5
LIBROKENDIR= ${OBJTOP}/kerberos5/lib/libroken
LIBWINDDIR= ${OBJTOP}/kerberos5/lib/libwind
LIBATF_CDIR= ${OBJTOP}/lib/atf/libatf-c
LIBATF_CXXDIR= ${OBJTOP}/lib/atf/libatf-c++
LIBALIASDIR= ${OBJTOP}/lib/libalias/libalias
LIBBLACKLISTDIR= ${OBJTOP}/lib/libblacklist
LIBBLOCKSRUNTIMEDIR= ${OBJTOP}/lib/libblocksruntime
LIBBSNMPDIR= ${OBJTOP}/lib/libbsnmp/libbsnmp
LIBCASPERDIR= ${OBJTOP}/lib/libcasper/libcasper
LIBCAP_DNSDIR= ${OBJTOP}/lib/libcasper/services/cap_dns
LIBCAP_GRPDIR= ${OBJTOP}/lib/libcasper/services/cap_grp
LIBCAP_PWDDIR= ${OBJTOP}/lib/libcasper/services/cap_pwd
LIBCAP_RANDOMDIR= ${OBJTOP}/lib/libcasper/services/cap_random
LIBCAP_SYSCTLDIR= ${OBJTOP}/lib/libcasper/services/cap_sysctl
LIBCAP_SYSLOGDIR= ${OBJTOP}/lib/libcasper/services/cap_syslog
LIBBSDXMLDIR= ${OBJTOP}/lib/libexpat
LIBKVMDIR= ${OBJTOP}/lib/libkvm
LIBPTHREADDIR= ${OBJTOP}/lib/libthr
LIBMDIR= ${OBJTOP}/lib/msun
LIBFORMDIR= ${OBJTOP}/lib/ncurses/form
LIBFORMLIBWDIR= ${OBJTOP}/lib/ncurses/formw
LIBMENUDIR= ${OBJTOP}/lib/ncurses/menu
LIBMENULIBWDIR= ${OBJTOP}/lib/ncurses/menuw
LIBNCURSESDIR= ${OBJTOP}/lib/ncurses/ncurses
LIBNCURSESWDIR= ${OBJTOP}/lib/ncurses/ncursesw
LIBPANELDIR= ${OBJTOP}/lib/ncurses/panel
LIBPANELWDIR= ${OBJTOP}/lib/ncurses/panelw
LIBCRYPTODIR= ${OBJTOP}/secure/lib/libcrypto
LIBSSHDIR= ${OBJTOP}/secure/lib/libssh
LIBSSLDIR= ${OBJTOP}/secure/lib/libssl
LIBTEKENDIR= ${OBJTOP}/sys/teken/libteken
LIBEGACYDIR= ${OBJTOP}/tools/build
LIBLNDIR= ${OBJTOP}/usr.bin/lex/lib
LIBTERMCAPDIR= ${LIBNCURSESDIR}
LIBTERMCAPWDIR= ${LIBNCURSESWDIR}
# Default other library directories to lib/libNAME.
.for lib in ${_LIBRARIES}
LIB${lib:tu}DIR?= ${OBJTOP}/lib/lib${lib}
.endfor
# Validate that listed LIBADD are valid.
.for _l in ${LIBADD}
.if empty(_LIBRARIES:M${_l})
_BADLIBADD+= ${_l}
.endif
.endfor
.if !empty(_BADLIBADD)
.error ${.CURDIR}: Invalid LIBADD used which may need to be added to ${_this:T}: ${_BADLIBADD}
.endif
# Sanity check that libraries are defined here properly when building them.
.if defined(LIB) && ${_LIBRARIES:M${LIB}} != ""
.if !empty(LIBADD) && \
(!defined(_DP_${LIB}) || ${LIBADD:O:u} != ${_DP_${LIB}:O:u})
.error ${.CURDIR}: Missing or incorrect _DP_${LIB} entry in ${_this:T}. Should match LIBADD for ${LIB} ('${LIBADD}' vs '${_DP_${LIB}}')
.endif
# Note that OBJTOP is not yet defined here but for the purpose of the check
# it is fine as it resolves to the SRC directory.
.if !defined(LIB${LIB:tu}DIR) || !exists(${SRCTOP}/${LIB${LIB:tu}DIR:S,^${OBJTOP}/,,})
.error ${.CURDIR}: Missing or incorrect value for LIB${LIB:tu}DIR in ${_this:T}: ${LIB${LIB:tu}DIR:S,^${OBJTOP}/,,}
.endif
.if ${_INTERNALLIBS:M${LIB}} != "" && !defined(LIB${LIB:tu})
.error ${.CURDIR}: Missing value for LIB${LIB:tu} in ${_this:T}. Likely should be: LIB${LIB:tu}?= $${LIB${LIB:tu}DIR}/lib${LIB}.a
.endif
.endif
.endif # !target(__<src.libnames.mk>__)
Index: stable/12/share/mk/src.opts.mk
===================================================================
--- stable/12/share/mk/src.opts.mk (revision 346144)
+++ stable/12/share/mk/src.opts.mk (revision 346145)
@@ -1,575 +1,578 @@
# $FreeBSD$
#
# Option file for FreeBSD /usr/src builds.
#
# Users define WITH_FOO and WITHOUT_FOO on the command line or in /etc/src.conf
# and /etc/make.conf files. These translate in the build system to MK_FOO={yes,no}
# with sensible (usually) defaults.
#
# Makefiles must include bsd.opts.mk after defining specific MK_FOO options that
# are applicable for that Makefile (typically there are none, but sometimes there
# are exceptions). Recursive makes usually add MK_FOO=no for options that they wish
# to omit from that make.
#
# Makefiles must include bsd.mkopt.mk before they test the value of any MK_FOO
# variable.
#
# Makefiles may also assume that this file is included by src.opts.mk should it
# need variables defined there prior to the end of the Makefile where
# bsd.{subdir,lib.bin}.mk is traditionally included.
#
# The old-style YES_FOO and NO_FOO are being phased out. No new instances of them
# should be added. Old instances should be removed since they were just to
# bridge the gap between FreeBSD 4 and FreeBSD 5.
#
# Makefiles should never test WITH_FOO or WITHOUT_FOO directly (although an
# exception is made for _WITHOUT_SRCONF which turns off this mechanism
# completely inside bsd.*.mk files).
#
.if !target(__<src.opts.mk>__)
__<src.opts.mk>__:
.include <bsd.own.mk>
#
# Define MK_* variables (which are either "yes" or "no") for users
# to set via WITH_*/WITHOUT_* in /etc/src.conf and override in the
# make(1) environment.
# These should be tested with `== "no"' or `!= "no"' in makefiles.
# The NO_* variables should only be set by makefiles for variables
# that haven't been converted over.
#
# These options are used by the src builds. Those listed in
# __DEFAULT_YES_OPTIONS default to 'yes' and will build unless turned
# off. __DEFAULT_NO_OPTIONS will default to 'no' and won't build
# unless turned on. Any options listed in 'BROKEN_OPTIONS' will be
# hard-wired to 'no'. "Broken" here means not working or
# not-appropriate and/or not supported. It doesn't imply something is
# wrong with the code. There's not a single good word for this, so
# BROKEN was selected as the least imperfect one considered at the
# time. Options are added to BROKEN_OPTIONS list on a per-arch basis.
# At this time, there's no provision for mutually incompatible options.
__DEFAULT_YES_OPTIONS = \
ACCT \
ACPI \
AMD \
APM \
AT \
ATM \
AUDIT \
AUTHPF \
AUTOFS \
BHYVE \
BINUTILS \
BINUTILS_BOOTSTRAP \
BLACKLIST \
BLUETOOTH \
BOOT \
BOOTPARAMD \
BOOTPD \
BSD_CPIO \
BSDINSTALL \
BSNMP \
BZIP2 \
CALENDAR \
CAPSICUM \
CASPER \
CCD \
CDDL \
CPP \
CROSS_COMPILER \
CRYPT \
CTM \
CUSE \
CXX \
DIALOG \
DICT \
DMAGENT \
DYNAMICROOT \
ED_CRYPTO \
EE \
EFI \
ELFTOOLCHAIN_BOOTSTRAP \
EXAMPLES \
FDT \
FILE \
FINGER \
FLOPPY \
FMTREE \
FORTH \
FP_LIBC \
FREEBSD_UPDATE \
FTP \
GAMES \
GCOV \
GDB \
GNU_DIFF \
GNU_GREP \
GPIO \
HAST \
HTML \
ICONV \
INET \
INET6 \
INETD \
IPFILTER \
IPFW \
ISCSI \
JAIL \
KDUMP \
KVM \
LDNS \
LDNS_UTILS \
LEGACY_CONSOLE \
LIB32 \
LIBPTHREAD \
LIBTHR \
LLVM_COV \
LOADER_GELI \
LOADER_LUA \
LOADER_OFW \
LOADER_UBOOT \
LOCALES \
LOCATE \
LPR \
LS_COLORS \
LZMA_SUPPORT \
MAIL \
MAILWRAPPER \
MAKE \
NDIS \
NETCAT \
NETGRAPH \
NLS_CATALOGS \
NS_CACHING \
NTP \
OFED \
OPENSSL \
PAM \
PC_SYSINSTALL \
PF \
PKGBOOTSTRAP \
PMC \
PORTSNAP \
PPP \
QUOTAS \
RADIUS_SUPPORT \
RBOOTD \
REPRODUCIBLE_BUILD \
RESCUE \
ROUTED \
SENDMAIL \
SERVICESDB \
SETUID_LOGIN \
SHAREDOCS \
SOURCELESS \
SOURCELESS_HOST \
SOURCELESS_UCODE \
SVNLITE \
SYSCONS \
SYSTEM_COMPILER \
SYSTEM_LINKER \
TALK \
TCP_WRAPPERS \
TCSH \
TELNET \
TEXTPROC \
TFTP \
TIMED \
UNBOUND \
USB \
UTMPX \
VI \
VT \
WIRELESS \
WPA_SUPPLICANT_EAPOL \
ZFS \
LOADER_ZFS \
ZONEINFO
__DEFAULT_NO_OPTIONS = \
+ BEARSSL \
BSD_GREP \
CLANG_EXTRAS \
DTRACE_TESTS \
GNU_GREP_COMPAT \
HESIOD \
LIBSOFT \
LOADER_FIREWIRE \
LOADER_FORCE_LE \
NAND \
OFED_EXTRA \
OPENLDAP \
RPCBIND_WARMSTART_SUPPORT \
SHARED_TOOLCHAIN \
SORT_THREADS \
SVN \
ZONEINFO_LEAPSECONDS_SUPPORT \
ZONEINFO_OLD_TIMEZONES_SUPPORT \
# LEFT/RIGHT. Left options which default to "yes" unless their corresponding
# RIGHT option is disabled.
__DEFAULT_DEPENDENT_OPTIONS= \
CLANG_FULL/CLANG \
LLVM_TARGET_ALL/CLANG \
+ LOADER_VERIEXEC/BEARSSL \
+ VERIEXEC/BEARSSL \
# MK_*_SUPPORT options which default to "yes" unless their corresponding
# MK_* variable is set to "no".
#
.for var in \
BLACKLIST \
BZIP2 \
INET \
INET6 \
KERBEROS \
KVM \
NETGRAPH \
PAM \
TESTS \
WIRELESS
__DEFAULT_DEPENDENT_OPTIONS+= ${var}_SUPPORT/${var}
.endfor
#
# Default behaviour of some options depends on the architecture. Unfortunately
# this means that we have to test TARGET_ARCH (the buildworld case) as well
# as MACHINE_ARCH (the non-buildworld case). Normally TARGET_ARCH is not
# used at all in bsd.*.mk, but we have to make an exception here if we want
# to allow defaults for some things like clang to vary by target architecture.
# Additional, per-target behavior should be rarely added only after much
# gnashing of teeth and grinding of gears.
#
.if defined(TARGET_ARCH)
__T=${TARGET_ARCH}
.else
__T=${MACHINE_ARCH}
.endif
.if defined(TARGET)
__TT=${TARGET}
.else
__TT=${MACHINE}
.endif
# All supported backends for LLVM_TARGET_XXX
__LLVM_TARGETS= \
aarch64 \
arm \
mips \
powerpc \
sparc \
x86
__LLVM_TARGET_FILT= C/(amd64|i386)/x86/:S/sparc64/sparc/:S/arm64/aarch64/
.for __llt in ${__LLVM_TARGETS}
# Default the given TARGET's LLVM_TARGET support to the value of MK_CLANG.
.if ${__TT:${__LLVM_TARGET_FILT}} == ${__llt}
__DEFAULT_DEPENDENT_OPTIONS+= LLVM_TARGET_${__llt:${__LLVM_TARGET_FILT}:tu}/CLANG
# Disable other targets for arm and armv6, to work around "relocation truncated
# to fit" errors with BFD ld, since libllvm.a will get too large to link.
.elif ${__T} == "arm" || ${__T} == "armv6"
__DEFAULT_NO_OPTIONS+=LLVM_TARGET_${__llt:tu}
# aarch64 needs arm for -m32 support.
.elif ${__TT} == "arm64" && ${__llt} == "arm"
__DEFAULT_DEPENDENT_OPTIONS+= LLVM_TARGET_ARM/LLVM_TARGET_AARCH64
# Default the rest of the LLVM_TARGETs to the value of MK_LLVM_TARGET_ALL
# which is based on MK_CLANG.
.else
__DEFAULT_DEPENDENT_OPTIONS+= LLVM_TARGET_${__llt:${__LLVM_TARGET_FILT}:tu}/LLVM_TARGET_ALL
.endif
.endfor
__DEFAULT_NO_OPTIONS+=LLVM_TARGET_BPF
.include <bsd.compiler.mk>
# If the compiler is not C++11 capable, disable Clang and use GCC instead.
# This means that architectures that have GCC 4.2 as default can not
# build Clang without using an external compiler.
.if ${COMPILER_FEATURES:Mc++11} && (${__T} == "aarch64" || \
${__T} == "amd64" || ${__TT} == "arm" || ${__T} == "i386")
# Clang is enabled, and will be installed as the default /usr/bin/cc.
__DEFAULT_YES_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_IS_CC LLD
__DEFAULT_NO_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX GPL_DTC
.elif ${COMPILER_FEATURES:Mc++11} && ${__T:Mriscv*} == "" && ${__T} != "sparc64"
# If an external compiler that supports C++11 is used as ${CC} and Clang
# supports the target, then Clang is enabled but GCC is installed as the
# default /usr/bin/cc.
__DEFAULT_YES_OPTIONS+=CLANG GCC GCC_BOOTSTRAP GNUCXX GPL_DTC LLD
__DEFAULT_NO_OPTIONS+=CLANG_BOOTSTRAP CLANG_IS_CC
.else
# Everything else disables Clang, and uses GCC instead.
__DEFAULT_YES_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX GPL_DTC
__DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_IS_CC LLD
.endif
# In-tree binutils/gcc are older versions without modern architecture support.
.if ${__T} == "aarch64" || ${__T:Mriscv*} != ""
BROKEN_OPTIONS+=BINUTILS BINUTILS_BOOTSTRAP GCC GCC_BOOTSTRAP GDB
.endif
.if ${__T:Mriscv*} != ""
BROKEN_OPTIONS+=OFED
.endif
.if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "i386" || \
${__T:Mriscv*} != "" || ${__TT} == "mips"
__DEFAULT_YES_OPTIONS+=LLVM_LIBUNWIND
.else
__DEFAULT_NO_OPTIONS+=LLVM_LIBUNWIND
.endif
.if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "armv7"
__DEFAULT_YES_OPTIONS+=LLD_BOOTSTRAP LLD_IS_LD
.elif ${__T} == "i386"
__DEFAULT_YES_OPTIONS+=LLD_BOOTSTRAP
__DEFAULT_NO_OPTIONS+=LLD_IS_LD
.else
__DEFAULT_NO_OPTIONS+=LLD_BOOTSTRAP LLD_IS_LD
.endif
.if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "i386"
__DEFAULT_YES_OPTIONS+=LLDB
.else
__DEFAULT_NO_OPTIONS+=LLDB
.endif
# LLVM lacks support for FreeBSD 64-bit atomic operations for ARMv4/ARMv5
.if ${__T} == "arm"
BROKEN_OPTIONS+=LLDB
.endif
# GDB in base is generally less functional than GDB in ports. Ports GDB
# sparc64 kernel support has not been tested.
.if ${__T} == "sparc64"
__DEFAULT_NO_OPTIONS+=GDB_LIBEXEC
.else
__DEFAULT_YES_OPTIONS+=GDB_LIBEXEC
.endif
# Only doing soft float API stuff on armv6 and armv7
.if ${__T} != "armv6" && ${__T} != "armv7"
BROKEN_OPTIONS+=LIBSOFT
.endif
.if ${__T:Mmips*}
BROKEN_OPTIONS+=SSP
.endif
# EFI doesn't exist on mips, powerpc, sparc or riscv.
.if ${__T:Mmips*} || ${__T:Mpowerpc*} || ${__T:Msparc64} || ${__T:Mriscv*}
BROKEN_OPTIONS+=EFI
.endif
# OFW is only for powerpc and sparc64, exclude others
.if ${__T:Mpowerpc*} == "" && ${__T:Msparc64} == ""
BROKEN_OPTIONS+=LOADER_OFW
.endif
# UBOOT is only for arm, mips and powerpc, exclude others
.if ${__T:Marm*} == "" && ${__T:Mmips*} == "" && ${__T:Mpowerpc*} == ""
BROKEN_OPTIONS+=LOADER_UBOOT
.endif
# GELI and Lua in loader currently cause boot failures on sparc64 and powerpc.
# Further debugging is required -- probably they are just broken on big
# endian systems generically (they jump to null pointers or try to read
# crazy high addresses, which is typical of endianness problems).
.if ${__T} == "sparc64" || ${__T:Mpowerpc*}
BROKEN_OPTIONS+=LOADER_GELI LOADER_LUA
.endif
# clang 7.0
BROKEN_OPTIONS+=RETPOLINE
.if ${__T:Mmips64*}
# profiling won't work on MIPS64 because there is only assembly for o32
BROKEN_OPTIONS+=PROFILE
.endif
.if ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "i386" || \
${__T} == "powerpc64" || ${__T} == "sparc64"
__DEFAULT_YES_OPTIONS+=CXGBETOOL
__DEFAULT_YES_OPTIONS+=MLX5TOOL
.else
__DEFAULT_NO_OPTIONS+=CXGBETOOL
__DEFAULT_NO_OPTIONS+=MLX5TOOL
.endif
# HyperV is currently x86-only
.if ${__T} == "amd64" || ${__T} == "i386"
__DEFAULT_YES_OPTIONS+=HYPERV
.else
__DEFAULT_NO_OPTIONS+=HYPERV
.endif
# NVME is only x86 and powerpc64
.if ${__T} == "amd64" || ${__T} == "i386" || ${__T} == "powerpc64"
__DEFAULT_YES_OPTIONS+=NVME
.else
__DEFAULT_NO_OPTIONS+=NVME
.endif
.include <bsd.mkopt.mk>
#
# MK_* options that default to "yes" if the compiler is a C++11 compiler.
#
.for var in \
LIBCPLUSPLUS
.if !defined(MK_${var})
.if ${COMPILER_FEATURES:Mc++11}
.if defined(WITHOUT_${var})
MK_${var}:= no
.else
MK_${var}:= yes
.endif
.else
.if defined(WITH_${var})
MK_${var}:= yes
.else
MK_${var}:= no
.endif
.endif
.endif
.endfor
#
# Force some options off if their dependencies are off.
# Order is somewhat important.
#
.if !${COMPILER_FEATURES:Mc++11}
MK_LLVM_LIBUNWIND:= no
.endif
.if ${MK_BINUTILS} == "no"
MK_GDB:= no
.endif
.if ${MK_CAPSICUM} == "no"
MK_CASPER:= no
.endif
.if ${MK_LIBPTHREAD} == "no"
MK_LIBTHR:= no
.endif
.if ${MK_LDNS} == "no"
MK_LDNS_UTILS:= no
MK_UNBOUND:= no
.endif
.if ${MK_SOURCELESS} == "no"
MK_SOURCELESS_HOST:= no
MK_SOURCELESS_UCODE:= no
.endif
.if ${MK_CDDL} == "no"
MK_ZFS:= no
MK_LOADER_ZFS:= no
MK_CTF:= no
.endif
.if ${MK_CRYPT} == "no"
MK_OPENSSL:= no
MK_OPENSSH:= no
MK_KERBEROS:= no
.endif
.if ${MK_CXX} == "no"
MK_CLANG:= no
MK_GNUCXX:= no
MK_TESTS:= no
.endif
.if ${MK_DIALOG} == "no"
MK_BSDINSTALL:= no
.endif
.if ${MK_MAIL} == "no"
MK_MAILWRAPPER:= no
MK_SENDMAIL:= no
MK_DMAGENT:= no
.endif
.if ${MK_NETGRAPH} == "no"
MK_ATM:= no
MK_BLUETOOTH:= no
.endif
.if ${MK_NLS} == "no"
MK_NLS_CATALOGS:= no
.endif
.if ${MK_OPENSSL} == "no"
MK_OPENSSH:= no
MK_KERBEROS:= no
.endif
.if ${MK_PF} == "no"
MK_AUTHPF:= no
.endif
.if ${MK_OFED} == "no"
MK_OFED_EXTRA:= no
.endif
.if ${MK_PORTSNAP} == "no"
# freebsd-update depends on phttpget from portsnap
MK_FREEBSD_UPDATE:= no
.endif
.if ${MK_TESTS} == "no"
MK_DTRACE_TESTS:= no
.endif
.if ${MK_ZONEINFO} == "no"
MK_ZONEINFO_LEAPSECONDS_SUPPORT:= no
MK_ZONEINFO_OLD_TIMEZONES_SUPPORT:= no
.endif
.if ${MK_CROSS_COMPILER} == "no"
MK_BINUTILS_BOOTSTRAP:= no
MK_CLANG_BOOTSTRAP:= no
MK_ELFTOOLCHAIN_BOOTSTRAP:= no
MK_GCC_BOOTSTRAP:= no
MK_LLD_BOOTSTRAP:= no
.endif
.if ${MK_TOOLCHAIN} == "no"
MK_BINUTILS:= no
MK_CLANG:= no
MK_GCC:= no
MK_GDB:= no
MK_INCLUDES:= no
MK_LLD:= no
MK_LLDB:= no
.endif
.if ${MK_CLANG} == "no"
MK_CLANG_EXTRAS:= no
MK_CLANG_FULL:= no
MK_LLVM_COV:= no
.endif
#
# MK_* options whose default value depends on another option.
#
.for vv in \
GSSAPI/KERBEROS \
MAN_UTILS/MAN
.if defined(WITH_${vv:H})
MK_${vv:H}:= yes
.elif defined(WITHOUT_${vv:H})
MK_${vv:H}:= no
.else
MK_${vv:H}:= ${MK_${vv:T}}
.endif
.endfor
#
# Set defaults for the MK_*_SUPPORT variables.
#
.if !${COMPILER_FEATURES:Mc++11}
MK_LLDB:= no
.endif
# gcc 4.8 and newer supports libc++, so suppress gnuc++ in that case.
# while in theory we could build it with that, we don't want to do
# that since it creates too much confusion for too little gain.
# XXX: This is incomplete and needs X_COMPILER_TYPE/VERSION checks too
# to prevent Makefile.inc1 from bootstrapping unneeded dependencies
# and to support 'make delete-old' when supplying an external toolchain.
.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} >= 40800
MK_GNUCXX:=no
MK_GCC:=no
.endif
.endif # !target(__<src.opts.mk>__)
Index: stable/12/stand/common/boot.c
===================================================================
--- stable/12/stand/common/boot.c (revision 346144)
+++ stable/12/stand/common/boot.c (revision 346145)
@@ -1,418 +1,422 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Loading modules, booting the system
*/
#include <stand.h>
#include <sys/reboot.h>
#include <sys/boot.h>
#include <string.h>
#include "bootstrap.h"
static int autoboot(int timeout, char *prompt);
static char *getbootfile(int try);
static int loadakernel(int try, int argc, char* argv[]);
/* List of kernel names to try (may be overwritten by boot.config) XXX should move from here? */
static const char *default_bootfiles = "kernel";
static int autoboot_tried;
/*
* The user wants us to boot.
*/
COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot);
static int
command_boot(int argc, char *argv[])
{
struct preloaded_file *fp;
/*
* See if the user has specified an explicit kernel to boot.
*/
if ((argc > 1) && (argv[1][0] != '-')) {
/* XXX maybe we should discard everything and start again? */
if (file_findfile(NULL, NULL) != NULL) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't boot '%s', kernel module already loaded", argv[1]);
return(CMD_ERROR);
}
/* find/load the kernel module */
if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0)
return(CMD_ERROR);
/* we have consumed all arguments */
argc = 1;
}
/*
* See if there is a kernel module already loaded
*/
if (file_findfile(NULL, NULL) == NULL)
if (loadakernel(0, argc - 1, argv + 1))
/* we have consumed all arguments */
argc = 1;
/*
* Loaded anything yet?
*/
if ((fp = file_findfile(NULL, NULL)) == NULL) {
command_errmsg = "no bootable kernel";
return(CMD_ERROR);
}
/*
* If we were given arguments, discard any previous.
* XXX should we merge arguments? Hard to DWIM.
*/
if (argc > 1) {
if (fp->f_args != NULL)
free(fp->f_args);
fp->f_args = unargv(argc - 1, argv + 1);
}
/* Hook for platform-specific autoloading of modules */
if (archsw.arch_autoload() != 0)
return(CMD_ERROR);
+#ifdef LOADER_VERIEXEC
+ verify_pcr_export(); /* for measured boot */
+#endif
+
/* Call the exec handler from the loader matching the kernel */
file_formats[fp->f_loader]->l_exec(fp);
return(CMD_ERROR);
}
/*
* Autoboot after a delay
*/
COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", command_autoboot);
static int
command_autoboot(int argc, char *argv[])
{
int howlong;
char *cp, *prompt;
prompt = NULL;
howlong = -1;
switch(argc) {
case 3:
prompt = argv[2];
/* FALLTHROUGH */
case 2:
howlong = strtol(argv[1], &cp, 0);
if (*cp != 0) {
snprintf(command_errbuf, sizeof(command_errbuf),
"bad delay '%s'", argv[1]);
return(CMD_ERROR);
}
/* FALLTHROUGH */
case 1:
return(autoboot(howlong, prompt));
}
command_errmsg = "too many arguments";
return(CMD_ERROR);
}
/*
* Called before we go interactive. If we think we can autoboot, and
* we haven't tried already, try now.
*/
void
autoboot_maybe()
{
char *cp;
cp = getenv("autoboot_delay");
if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO")))
autoboot(-1, NULL); /* try to boot automatically */
}
static int
autoboot(int timeout, char *prompt)
{
time_t when, otime, ntime;
int c, yes;
char *argv[2], *cp, *ep;
char *kernelname;
#ifdef BOOT_PROMPT_123
const char *seq = "123", *p = seq;
#endif
autoboot_tried = 1;
if (timeout == -1) {
timeout = 10;
/* try to get a delay from the environment */
if ((cp = getenv("autoboot_delay"))) {
timeout = strtol(cp, &ep, 0);
if (cp == ep)
timeout = 10; /* Unparseable? Set default! */
}
}
kernelname = getenv("kernelname");
if (kernelname == NULL) {
argv[0] = NULL;
loadakernel(0, 0, argv);
kernelname = getenv("kernelname");
if (kernelname == NULL) {
command_errmsg = "no valid kernel found";
return(CMD_ERROR);
}
}
if (timeout >= 0) {
otime = time(NULL);
when = otime + timeout; /* when to boot */
yes = 0;
#ifdef BOOT_PROMPT_123
printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or "
"1 2 3 sequence for command prompt." : prompt);
#else
printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or any other key for command prompt." : prompt);
#endif
for (;;) {
if (ischar()) {
c = getchar();
#ifdef BOOT_PROMPT_123
if ((c == '\r') || (c == '\n')) {
yes = 1;
break;
} else if (c != *p++)
p = seq;
if (*p == 0)
break;
#else
if ((c == '\r') || (c == '\n'))
yes = 1;
break;
#endif
}
ntime = time(NULL);
if (ntime >= when) {
yes = 1;
break;
}
if (ntime != otime) {
printf("\rBooting [%s] in %d second%s... ",
kernelname, (int)(when - ntime),
(when-ntime)==1?"":"s");
otime = ntime;
}
}
} else {
yes = 1;
}
if (yes)
printf("\rBooting [%s]... ", kernelname);
putchar('\n');
if (yes) {
argv[0] = "boot";
argv[1] = NULL;
return(command_boot(1, argv));
}
return(CMD_OK);
}
/*
* Scrounge for the name of the (try)'th file we will try to boot.
*/
static char *
getbootfile(int try)
{
static char *name = NULL;
const char *spec, *ep;
size_t len;
/* we use dynamic storage */
if (name != NULL) {
free(name);
name = NULL;
}
/*
* Try $bootfile, then try our builtin default
*/
if ((spec = getenv("bootfile")) == NULL)
spec = default_bootfiles;
while ((try > 0) && (spec != NULL)) {
spec = strchr(spec, ';');
if (spec)
spec++; /* skip over the leading ';' */
try--;
}
if (spec != NULL) {
if ((ep = strchr(spec, ';')) != NULL) {
len = ep - spec;
} else {
len = strlen(spec);
}
name = malloc(len + 1);
strncpy(name, spec, len);
name[len] = 0;
}
if (name && name[0] == 0) {
free(name);
name = NULL;
}
return(name);
}
/*
* Try to find the /etc/fstab file on the filesystem (rootdev),
* which should be be the root filesystem, and parse it to find
* out what the kernel ought to think the root filesystem is.
*
* If we're successful, set vfs.root.mountfrom to <vfstype>:<path>
* so that the kernel can tell both which VFS and which node to use
* to mount the device. If this variable's already set, don't
* overwrite it.
*/
int
getrootmount(char *rootdev)
{
char lbuf[128], *cp, *ep, *dev, *fstyp, *options;
int fd, error;
if (getenv("vfs.root.mountfrom") != NULL)
return(0);
error = 1;
sprintf(lbuf, "%s/etc/fstab", rootdev);
if ((fd = open(lbuf, O_RDONLY)) < 0)
goto notfound;
/* loop reading lines from /etc/fstab What was that about sscanf again? */
fstyp = NULL;
dev = NULL;
while (fgetstr(lbuf, sizeof(lbuf), fd) >= 0) {
if ((lbuf[0] == 0) || (lbuf[0] == '#'))
continue;
/* skip device name */
for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++)
;
if (*cp == 0) /* misformatted */
continue;
/* delimit and save */
*cp++ = 0;
free(dev);
dev = strdup(lbuf);
/* skip whitespace up to mountpoint */
while ((*cp != 0) && isspace(*cp))
cp++;
/* must have /<space> to be root */
if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1)))
continue;
/* skip whitespace up to fstype */
cp += 2;
while ((*cp != 0) && isspace(*cp))
cp++;
if (*cp == 0) /* misformatted */
continue;
/* skip text to end of fstype and delimit */
ep = cp;
while ((*cp != 0) && !isspace(*cp))
cp++;
*cp = 0;
free(fstyp);
fstyp = strdup(ep);
/* skip whitespace up to mount options */
cp += 1;
while ((*cp != 0) && isspace(*cp))
cp++;
if (*cp == 0) /* misformatted */
continue;
/* skip text to end of mount options and delimit */
ep = cp;
while ((*cp != 0) && !isspace(*cp))
cp++;
*cp = 0;
options = strdup(ep);
/* Build the <fstype>:<device> and save it in vfs.root.mountfrom */
sprintf(lbuf, "%s:%s", fstyp, dev);
setenv("vfs.root.mountfrom", lbuf, 0);
/* Don't override vfs.root.mountfrom.options if it is already set */
if (getenv("vfs.root.mountfrom.options") == NULL) {
/* save mount options */
setenv("vfs.root.mountfrom.options", options, 0);
}
free(options);
error = 0;
break;
}
close(fd);
free(dev);
free(fstyp);
notfound:
if (error) {
const char *currdev;
currdev = getenv("currdev");
if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) {
cp = strdup(currdev);
cp[strlen(cp) - 1] = '\0';
setenv("vfs.root.mountfrom", cp, 0);
error = 0;
free(cp);
}
}
return(error);
}
static int
loadakernel(int try, int argc, char* argv[])
{
char *cp;
for (try = 0; (cp = getbootfile(try)) != NULL; try++)
if (mod_loadkld(cp, argc - 1, argv + 1) != 0)
printf("can't load '%s'\n", cp);
else
return 1;
return 0;
}
Index: stable/12/stand/common/bootstrap.h
===================================================================
--- stable/12/stand/common/bootstrap.h (revision 346144)
+++ stable/12/stand/common/bootstrap.h (revision 346145)
@@ -1,349 +1,356 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _BOOTSTRAP_H_
#define _BOOTSTRAP_H_
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/linker_set.h>
/* Commands and return values; nonzero return sets command_errmsg != NULL */
typedef int (bootblk_cmd_t)(int argc, char *argv[]);
#define COMMAND_ERRBUFSZ (256)
extern const char *command_errmsg;
extern char command_errbuf[COMMAND_ERRBUFSZ];
#define CMD_OK 0
#define CMD_WARN 1
#define CMD_ERROR 2
#define CMD_CRIT 3
#define CMD_FATAL 4
/* interp.c */
void interact(void);
void interp_emit_prompt(void);
int interp_builtin_cmd(int argc, char *argv[]);
/* Called by interp.c for interp_*.c embedded interpreters */
int interp_include(const char *filename); /* Execute commands from filename */
void interp_init(void); /* Initialize interpreater */
int interp_run(const char *line); /* Run a single command */
/* interp_backslash.c */
char *backslash(const char *str);
/* interp_parse.c */
int parse(int *argc, char ***argv, const char *str);
/* boot.c */
void autoboot_maybe(void);
int getrootmount(char *rootdev);
/* misc.c */
char *unargv(int argc, char *argv[]);
void hexdump(caddr_t region, size_t len);
size_t strlenout(vm_offset_t str);
char *strdupout(vm_offset_t str);
void kern_bzero(vm_offset_t dest, size_t len);
int kern_pread(int fd, vm_offset_t dest, size_t len, off_t off);
void *alloc_pread(int fd, off_t off, size_t len);
/* bcache.c */
void bcache_init(size_t nblks, size_t bsize);
void bcache_add_dev(int);
void *bcache_allocate(void);
void bcache_free(void *);
int bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size,
char *buf, size_t *rsize);
/*
* Disk block cache
*/
struct bcache_devdata
{
int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
size_t size, char *buf, size_t *rsize);
void *dv_devdata;
void *dv_cache;
};
/*
* Modular console support.
*/
struct console
{
const char *c_name;
const char *c_desc;
int c_flags;
#define C_PRESENTIN (1<<0) /* console can provide input */
#define C_PRESENTOUT (1<<1) /* console can provide output */
#define C_ACTIVEIN (1<<2) /* user wants input from console */
#define C_ACTIVEOUT (1<<3) /* user wants output to console */
#define C_WIDEOUT (1<<4) /* c_out routine groks wide chars */
void (* c_probe)(struct console *cp); /* set c_flags to match hardware */
int (* c_init)(int arg); /* reinit XXX may need more args */
void (* c_out)(int c); /* emit c */
int (* c_in)(void); /* wait for and return input */
int (* c_ready)(void); /* return nonzer if input waiting */
};
extern struct console *consoles[];
void cons_probe(void);
/*
* Plug-and-play enumerator/configurator interface.
*/
struct pnphandler
{
const char *pp_name; /* handler/bus name */
void (* pp_enumerate)(void); /* enumerate PnP devices, add to chain */
};
struct pnpident
{
char *id_ident; /* ASCII identifier, actual format varies with bus/handler */
STAILQ_ENTRY(pnpident) id_link;
};
struct pnpinfo
{
char *pi_desc; /* ASCII description, optional */
int pi_revision; /* optional revision (or -1) if not supported */
char *pi_module; /* module/args nominated to handle device */
int pi_argc; /* module arguments */
char **pi_argv;
struct pnphandler *pi_handler; /* handler which detected this device */
STAILQ_HEAD(,pnpident) pi_ident; /* list of identifiers */
STAILQ_ENTRY(pnpinfo) pi_link;
};
STAILQ_HEAD(pnpinfo_stql, pnpinfo);
extern struct pnphandler *pnphandlers[]; /* provided by MD code */
void pnp_addident(struct pnpinfo *pi, char *ident);
struct pnpinfo *pnp_allocinfo(void);
void pnp_freeinfo(struct pnpinfo *pi);
void pnp_addinfo(struct pnpinfo *pi);
char *pnp_eisaformat(uint8_t *data);
/*
* < 0 - No ISA in system
* == 0 - Maybe ISA, search for read data port
* > 0 - ISA in system, value is read data port address
*/
extern int isapnp_readport;
/*
* Version information
*/
extern char bootprog_info[];
/*
* Interpreter information
*/
extern const char bootprog_interp[];
#define INTERP_DEFINE(interpstr) \
const char bootprog_interp[] = "$Interpreter:" interpstr
/*
* Preloaded file metadata header.
*
* Metadata are allocated on our heap, and copied into kernel space
* before executing the kernel.
*/
struct file_metadata
{
size_t md_size;
uint16_t md_type;
struct file_metadata *md_next;
char md_data[1]; /* data are immediately appended */
};
struct preloaded_file;
struct mod_depend;
struct kernel_module
{
char *m_name; /* module name */
int m_version; /* module version */
/* char *m_args;*/ /* arguments for the module */
struct preloaded_file *m_fp;
struct kernel_module *m_next;
};
/*
* Preloaded file information. Depending on type, file can contain
* additional units called 'modules'.
*
* At least one file (the kernel) must be loaded in order to boot.
* The kernel is always loaded first.
*
* String fields (m_name, m_type) should be dynamically allocated.
*/
struct preloaded_file
{
char *f_name; /* file name */
char *f_type; /* verbose file type, eg 'ELF kernel', 'pnptable', etc. */
char *f_args; /* arguments for the file */
struct file_metadata *f_metadata; /* metadata that will be placed in the module directory */
int f_loader; /* index of the loader that read the file */
vm_offset_t f_addr; /* load address */
size_t f_size; /* file size */
struct kernel_module *f_modules; /* list of modules if any */
struct preloaded_file *f_next; /* next file */
};
struct file_format
{
/* Load function must return EFTYPE if it can't handle the module supplied */
int (* l_load)(char *filename, uint64_t dest, struct preloaded_file **result);
/* Only a loader that will load a kernel (first module) should have an exec handler */
int (* l_exec)(struct preloaded_file *mp);
};
extern struct file_format *file_formats[]; /* supplied by consumer */
extern struct preloaded_file *preloaded_files;
int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]);
int mod_loadkld(const char *name, int argc, char *argv[]);
void unload(void);
struct preloaded_file *file_alloc(void);
struct preloaded_file *file_findfile(const char *name, const char *type);
struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type);
struct preloaded_file *file_loadraw(const char *name, char *type, int insert);
void file_discard(struct preloaded_file *fp);
void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p);
int file_addmodule(struct preloaded_file *fp, char *modname, int version,
struct kernel_module **newmp);
void file_removemetadata(struct preloaded_file *fp);
/* MI module loaders */
#ifdef __elfN
/* Relocation types. */
#define ELF_RELOC_REL 1
#define ELF_RELOC_RELA 2
/* Relocation offset for some architectures */
extern uint64_t __elfN(relocation_offset);
struct elf_file;
typedef Elf_Addr (symaddr_fn)(struct elf_file *ef, Elf_Size symidx);
int __elfN(loadfile)(char *filename, uint64_t dest, struct preloaded_file **result);
int __elfN(obj_loadfile)(char *filename, uint64_t dest,
struct preloaded_file **result);
int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr,
const void *reldata, int reltype, Elf_Addr relbase,
Elf_Addr dataaddr, void *data, size_t len);
int __elfN(loadfile_raw)(char *filename, uint64_t dest,
struct preloaded_file **result, int multiboot);
int __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest);
#endif
/*
* Support for commands
*/
struct bootblk_command
{
const char *c_name;
const char *c_desc;
bootblk_cmd_t *c_fn;
};
#define COMMAND_SET(tag, key, desc, func) \
static bootblk_cmd_t func; \
static struct bootblk_command _cmd_ ## tag = { key, desc, func }; \
DATA_SET(Xcommand_set, _cmd_ ## tag)
SET_DECLARE(Xcommand_set, struct bootblk_command);
/*
* The intention of the architecture switch is to provide a convenient
* encapsulation of the interface between the bootstrap MI and MD code.
* MD code may selectively populate the switch at runtime based on the
* actual configuration of the target system.
*/
struct arch_switch
{
/* Automatically load modules as required by detected hardware */
int (*arch_autoload)(void);
/* Locate the device for (name), return pointer to tail in (*path) */
int (*arch_getdev)(void **dev, const char *name, const char **path);
/* Copy from local address space to module address space, similar to bcopy() */
ssize_t (*arch_copyin)(const void *src, vm_offset_t dest,
const size_t len);
/* Copy to local address space from module address space, similar to bcopy() */
ssize_t (*arch_copyout)(const vm_offset_t src, void *dest,
const size_t len);
/* Read from file to module address space, same semantics as read() */
ssize_t (*arch_readin)(const int fd, vm_offset_t dest,
const size_t len);
/* Perform ISA byte port I/O (only for systems with ISA) */
int (*arch_isainb)(int port);
void (*arch_isaoutb)(int port, int value);
/*
* Interface to adjust the load address according to the "object"
* being loaded.
*/
uint64_t (*arch_loadaddr)(u_int type, void *data, uint64_t addr);
#define LOAD_ELF 1 /* data points to the ELF header. */
#define LOAD_RAW 2 /* data points to the file name. */
/*
* Interface to inform MD code about a loaded (ELF) segment. This
* can be used to flush caches and/or set up translations.
*/
#ifdef __elfN
void (*arch_loadseg)(Elf_Ehdr *eh, Elf_Phdr *ph, uint64_t delta);
#else
void (*arch_loadseg)(void *eh, void *ph, uint64_t delta);
#endif
/* Probe ZFS pool(s), if needed. */
void (*arch_zfs_probe)(void);
+ /* Return the hypervisor name/type or NULL if not virtualized. */
+ const char *(*arch_hypervisor)(void);
+
/* For kexec-type loaders, get ksegment structure */
void (*arch_kexec_kseg_get)(int *nseg, void **kseg);
};
extern struct arch_switch archsw;
/* This must be provided by the MD code, but should it be in the archsw? */
void delay(int delay);
void dev_cleanup(void);
time_t time(time_t *tloc);
#ifndef CTASSERT
#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed")
+#endif
+
+#ifdef LOADER_VERIEXEC
+#include <verify_file.h>
#endif
#endif /* !_BOOTSTRAP_H_ */
Index: stable/12/stand/common/interp_forth.c
===================================================================
--- stable/12/stand/common/interp_forth.c (revision 346144)
+++ stable/12/stand/common/interp_forth.c (revision 346145)
@@ -1,444 +1,457 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h> /* to pick up __FreeBSD_version */
#include <string.h>
#include <stand.h>
#include "bootstrap.h"
#include "ficl.h"
extern unsigned bootprog_rev;
INTERP_DEFINE("4th");
/* #define BFORTH_DEBUG */
#ifdef BFORTH_DEBUG
#define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
#else
#define DEBUG(fmt, args...)
#endif
/*
* Eventually, all builtin commands throw codes must be defined
* elsewhere, possibly bootstrap.h. For now, just this code, used
* just in this file, it is getting defined.
*/
#define BF_PARSE 100
/*
* FreeBSD loader default dictionary cells
*/
#ifndef BF_DICTSIZE
#define BF_DICTSIZE 10000
#endif
/*
* BootForth Interface to Ficl Forth interpreter.
*/
FICL_SYSTEM *bf_sys;
FICL_VM *bf_vm;
/*
* Shim for taking commands from BF and passing them out to 'standard'
* argv/argc command functions.
*/
static void
bf_command(FICL_VM *vm)
{
char *name, *line, *tail, *cp;
size_t len;
struct bootblk_command **cmdp;
bootblk_cmd_t *cmd;
int nstrings, i;
int argc, result;
char **argv;
/* Get the name of the current word */
name = vm->runningWord->name;
/* Find our command structure */
cmd = NULL;
SET_FOREACH(cmdp, Xcommand_set) {
if (((*cmdp)->c_name != NULL) && !strcmp(name, (*cmdp)->c_name))
cmd = (*cmdp)->c_fn;
}
if (cmd == NULL)
panic("callout for unknown command '%s'", name);
/* Check whether we have been compiled or are being interpreted */
if (stackPopINT(vm->pStack)) {
/*
* Get parameters from stack, in the format:
* an un ... a2 u2 a1 u1 n --
* Where n is the number of strings, a/u are pairs of
* address/size for strings, and they will be concatenated
* in LIFO order.
*/
nstrings = stackPopINT(vm->pStack);
for (i = 0, len = 0; i < nstrings; i++)
len += stackFetch(vm->pStack, i * 2).i + 1;
line = malloc(strlen(name) + len + 1);
strcpy(line, name);
if (nstrings)
for (i = 0; i < nstrings; i++) {
len = stackPopINT(vm->pStack);
cp = stackPopPtr(vm->pStack);
strcat(line, " ");
strncat(line, cp, len);
}
} else {
/* Get remainder of invocation */
tail = vmGetInBuf(vm);
for (cp = tail, len = 0; cp != vm->tib.end && *cp != 0 && *cp != '\n'; cp++, len++)
;
line = malloc(strlen(name) + len + 2);
strcpy(line, name);
if (len > 0) {
strcat(line, " ");
strncat(line, tail, len);
vmUpdateTib(vm, tail + len);
}
}
DEBUG("cmd '%s'", line);
command_errmsg = command_errbuf;
command_errbuf[0] = 0;
if (!parse(&argc, &argv, line)) {
result = (cmd)(argc, argv);
free(argv);
} else {
result=BF_PARSE;
}
switch (result) {
case CMD_CRIT:
printf("%s\n", command_errmsg);
break;
case CMD_FATAL:
panic("%s", command_errmsg);
}
free(line);
/*
* If there was error during nested ficlExec(), we may no longer have
* valid environment to return. Throw all exceptions from here.
*/
if (result != CMD_OK)
vmThrow(vm, result);
/* This is going to be thrown!!! */
stackPushINT(vm->pStack,result);
}
/*
* Replace a word definition (a builtin command) with another
* one that:
*
* - Throw error results instead of returning them on the stack
* - Pass a flag indicating whether the word was compiled or is
* being interpreted.
*
* There is one major problem with builtins that cannot be overcome
* in anyway, except by outlawing it. We want builtins to behave
* differently depending on whether they have been compiled or they
* are being interpreted. Notice that this is *not* the interpreter's
* current state. For example:
*
* : example ls ; immediate
* : problem example ; \ "ls" gets executed while compiling
* example \ "ls" gets executed while interpreting
*
* Notice that, though the current state is different in the two
* invocations of "example", in both cases "ls" has been
* *compiled in*, which is what we really want.
*
* The problem arises when you tick the builtin. For example:
*
* : example-1 ['] ls postpone literal ; immediate
* : example-2 example-1 execute ; immediate
* : problem example-2 ;
* example-2
*
* We have no way, when we get EXECUTEd, of knowing what our behavior
* should be. Thus, our only alternative is to "outlaw" this. See RFI
* 0007, and ANS Forth Standard's appendix D, item 6.7 for a related
* problem, concerning compile semantics.
*
* The problem is compounded by the fact that "' builtin CATCH" is valid
* and desirable. The only solution is to create an intermediary word.
* For example:
*
* : my-ls ls ;
* : example ['] my-ls catch ;
*
* So, with the below implementation, here is a summary of the behavior
* of builtins:
*
* ls -l \ "interpret" behavior, ie,
* \ takes parameters from TIB
* : ex-1 s" -l" 1 ls ; \ "compile" behavior, ie,
* \ takes parameters from the stack
* : ex-2 ['] ls catch ; immediate \ undefined behavior
* : ex-3 ['] ls catch ; \ undefined behavior
* ex-2 ex-3 \ "interpret" behavior,
* \ catch works
* : ex-4 ex-2 ; \ "compile" behavior,
* \ catch does not work
* : ex-5 ex-3 ; immediate \ same as ex-2
* : ex-6 ex-3 ; \ same as ex-3
* : ex-7 ['] ex-1 catch ; \ "compile" behavior,
* \ catch works
* : ex-8 postpone ls ; immediate \ same as ex-2
* : ex-9 postpone ls ; \ same as ex-3
*
* As the definition below is particularly tricky, and it's side effects
* must be well understood by those playing with it, I'll be heavy on
* the comments.
*
* (if you edit this definition, pay attention to trailing spaces after
* each word -- I warned you! :-) )
*/
#define BUILTIN_CONSTRUCTOR \
": builtin: " \
">in @ " /* save the tib index pointer */ \
"' " /* get next word's xt */ \
"swap >in ! " /* point again to next word */ \
"create " /* create a new definition of the next word */ \
", " /* save previous definition's xt */ \
"immediate " /* make the new definition an immediate word */ \
\
"does> " /* Now, the *new* definition will: */ \
"state @ if " /* if in compiling state: */ \
"1 postpone literal " /* pass 1 flag to indicate compile */ \
"@ compile, " /* compile in previous definition */ \
"postpone throw " /* throw stack-returned result */ \
"else " /* if in interpreting state: */ \
"0 swap " /* pass 0 flag to indicate interpret */ \
"@ execute " /* call previous definition */ \
"throw " /* throw stack-returned result */ \
"then ; "
/*
* Initialise the Forth interpreter, create all our commands as words.
*/
void
bf_init(void)
{
struct bootblk_command **cmdp;
char create_buf[41]; /* 31 characters-long builtins */
int fd;
bf_sys = ficlInitSystem(BF_DICTSIZE);
bf_vm = ficlNewVM(bf_sys);
/* Put all private definitions in a "builtins" vocabulary */
ficlExec(bf_vm, "vocabulary builtins also builtins definitions");
/* Builtin constructor word */
ficlExec(bf_vm, BUILTIN_CONSTRUCTOR);
/* make all commands appear as Forth words */
SET_FOREACH(cmdp, Xcommand_set) {
ficlBuild(bf_sys, (char *)(*cmdp)->c_name, bf_command, FW_DEFAULT);
ficlExec(bf_vm, "forth definitions builtins");
sprintf(create_buf, "builtin: %s", (*cmdp)->c_name);
ficlExec(bf_vm, create_buf);
ficlExec(bf_vm, "builtins definitions");
}
ficlExec(bf_vm, "only forth definitions");
/* Export some version numbers so that code can detect the loader/host version */
ficlSetEnv(bf_sys, "FreeBSD_version", __FreeBSD_version);
ficlSetEnv(bf_sys, "loader_version", bootprog_rev);
/* try to load and run init file if present */
if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) {
+#ifdef LOADER_VERIEXEC
+ if (verify_file(fd, "/boot/boot.4th", 0, VE_GUESS) < 0) {
+ close(fd);
+ return;
+ }
+#endif
(void)ficlExecFD(bf_vm, fd);
close(fd);
}
}
/*
* Feed a line of user input to the Forth interpreter
*/
static int
bf_run(const char *line)
{
int result;
/*
* ficl would require extensive changes to accept a const char *
* interface. Instead, cast it away here and hope for the best.
* We know at the present time the caller for us in the boot
* forth loader can tolerate the string being modified because
* the string is passed in here and then not touched again.
*/
result = ficlExec(bf_vm, __DECONST(char *, line));
DEBUG("ficlExec '%s' = %d", line, result);
switch (result) {
case VM_OUTOFTEXT:
case VM_ABORTQ:
case VM_QUIT:
case VM_ERREXIT:
break;
case VM_USEREXIT:
printf("No where to leave to!\n");
break;
case VM_ABORT:
printf("Aborted!\n");
break;
case BF_PARSE:
printf("Parse error!\n");
break;
default:
if (command_errmsg != NULL) {
printf("%s\n", command_errmsg);
command_errmsg = NULL;
}
}
if (result == VM_USEREXIT)
panic("interpreter exit");
setenv("interpret", bf_vm->state ? "" : "OK", 1);
return (result);
}
void
interp_init(void)
{
setenv("script.lang", "forth", 1);
bf_init();
/* Read our default configuration. */
interp_include("/boot/loader.rc");
}
int
interp_run(const char *input)
{
bf_vm->sourceID.i = 0;
return bf_run(input);
}
/*
* Header prepended to each line. The text immediately follows the header.
* We try to make this short in order to save memory -- the loader has
* limited memory available, and some of the forth files are very long.
*/
struct includeline
{
struct includeline *next;
char text[0];
};
int
interp_include(const char *filename)
{
struct includeline *script, *se, *sp;
char input[256]; /* big enough? */
int res;
char *cp;
int prevsrcid, fd, line;
if (((fd = open(filename, O_RDONLY)) == -1)) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't open '%s': %s", filename, strerror(errno));
return(CMD_ERROR);
}
+#ifdef LOADER_VERIEXEC
+ if (verify_file(fd, filename, 0, VE_GUESS) < 0) {
+ close(fd);
+ sprintf(command_errbuf,"can't verify '%s'", filename);
+ return(CMD_ERROR);
+ }
+#endif
/*
* Read the script into memory.
*/
script = se = NULL;
line = 0;
while (fgetstr(input, sizeof(input), fd) >= 0) {
line++;
cp = input;
/* Allocate script line structure and copy line, flags */
if (*cp == '\0')
continue; /* ignore empty line, save memory */
sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);
/* On malloc failure (it happens!), free as much as possible and exit */
if (sp == NULL) {
while (script != NULL) {
se = script;
script = script->next;
free(se);
}
snprintf(command_errbuf, sizeof(command_errbuf),
"file '%s' line %d: memory allocation failure - aborting",
filename, line);
close(fd);
return (CMD_ERROR);
}
strcpy(sp->text, cp);
sp->next = NULL;
if (script == NULL) {
script = sp;
} else {
se->next = sp;
}
se = sp;
}
close(fd);
/*
* Execute the script
*/
prevsrcid = bf_vm->sourceID.i;
bf_vm->sourceID.i = fd;
res = CMD_OK;
for (sp = script; sp != NULL; sp = sp->next) {
res = bf_run(sp->text);
if (res != VM_OUTOFTEXT) {
snprintf(command_errbuf, sizeof(command_errbuf),
"Error while including %s, in the line:\n%s",
filename, sp->text);
res = CMD_ERROR;
break;
} else
res = CMD_OK;
}
bf_vm->sourceID.i = prevsrcid;
while (script != NULL) {
se = script;
script = script->next;
free(se);
}
return(res);
}
Index: stable/12/stand/common/interp_simple.c
===================================================================
--- stable/12/stand/common/interp_simple.c (revision 346144)
+++ stable/12/stand/common/interp_simple.c (revision 346145)
@@ -1,194 +1,202 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Simple commandline interpreter, toplevel and misc.
*/
#include <stand.h>
#include <string.h>
#include "bootstrap.h"
INTERP_DEFINE("simp");
void
interp_init(void)
{
setenv("script.lang", "simple", 1);
/* Read our default configuration. */
interp_include("/boot/loader.rc");
}
int
interp_run(const char *input)
{
int argc;
char **argv;
if (parse(&argc, &argv, input)) {
printf("parse error\n");
return CMD_ERROR;
}
if (interp_builtin_cmd(argc, argv)) {
printf("%s: %s\n", argv[0], command_errmsg);
free(argv);
return CMD_ERROR;
}
free(argv);
return CMD_OK;
}
/*
* Header prepended to each line. The text immediately follows the header.
* We try to make this short in order to save memory -- the loader has
* limited memory available, and some of the forth files are very long.
*/
struct includeline
{
struct includeline *next;
int flags;
int line;
#define SL_QUIET (1<<0)
#define SL_IGNOREERR (1<<1)
char text[0];
};
int
interp_include(const char *filename)
{
struct includeline *script, *se, *sp;
char input[256]; /* big enough? */
int argc,res;
char **argv, *cp;
int fd, flags, line;
if (((fd = open(filename, O_RDONLY)) == -1)) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't open '%s': %s", filename, strerror(errno));
return(CMD_ERROR);
}
+#ifdef LOADER_VERIEXEC
+ if (verify_file(fd, filename, 0, VE_GUESS) < 0) {
+ close(fd);
+ sprintf(command_errbuf,"can't verify '%s'", filename);
+ return(CMD_ERROR);
+ }
+#endif
+
/*
* Read the script into memory.
*/
script = se = NULL;
line = 0;
while (fgetstr(input, sizeof(input), fd) >= 0) {
line++;
flags = 0;
/* Discard comments */
if (strncmp(input+strspn(input, " "), "\\ ", 2) == 0)
continue;
cp = input;
/* Echo? */
if (input[0] == '@') {
cp++;
flags |= SL_QUIET;
}
/* Error OK? */
if (input[0] == '-') {
cp++;
flags |= SL_IGNOREERR;
}
/* Allocate script line structure and copy line, flags */
if (*cp == '\0')
continue; /* ignore empty line, save memory */
sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);
/* On malloc failure (it happens!), free as much as possible and exit */
if (sp == NULL) {
while (script != NULL) {
se = script;
script = script->next;
free(se);
}
snprintf(command_errbuf, sizeof(command_errbuf),
"file '%s' line %d: memory allocation failure - aborting",
filename, line);
close(fd);
return (CMD_ERROR);
}
strcpy(sp->text, cp);
sp->flags = flags;
sp->line = line;
sp->next = NULL;
if (script == NULL) {
script = sp;
} else {
se->next = sp;
}
se = sp;
}
close(fd);
/*
* Execute the script
*/
argv = NULL;
res = CMD_OK;
for (sp = script; sp != NULL; sp = sp->next) {
/* print if not being quiet */
if (!(sp->flags & SL_QUIET)) {
interp_emit_prompt();
printf("%s\n", sp->text);
}
/* Parse the command */
if (!parse(&argc, &argv, sp->text)) {
if ((argc > 0) && (interp_builtin_cmd(argc, argv) != 0)) {
/* normal command */
printf("%s: %s\n", argv[0], command_errmsg);
if (!(sp->flags & SL_IGNOREERR)) {
res=CMD_ERROR;
break;
}
}
free(argv);
argv = NULL;
} else {
printf("%s line %d: parse error\n", filename, sp->line);
res=CMD_ERROR;
break;
}
}
if (argv != NULL)
free(argv);
while (script != NULL) {
se = script;
script = script->next;
free(se);
}
return(res);
}
Index: stable/12/stand/common/load_elf.c
===================================================================
--- stable/12/stand/common/load_elf.c (revision 346144)
+++ stable/12/stand/common/load_elf.c (revision 346145)
@@ -1,1216 +1,1222 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* Copyright (c) 1998 Peter Wemm <peter@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/exec.h>
#include <sys/linker.h>
#include <sys/module.h>
#include <sys/stdint.h>
#include <string.h>
#include <machine/elf.h>
#include <stand.h>
#define FREEBSD_ELF
#include <sys/link_elf.h>
#include "bootstrap.h"
#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l)
#if defined(__i386__) && __ELF_WORD_SIZE == 64
#undef ELF_TARG_CLASS
#undef ELF_TARG_MACH
#define ELF_TARG_CLASS ELFCLASS64
#define ELF_TARG_MACH EM_X86_64
#endif
typedef struct elf_file {
Elf_Phdr *ph;
Elf_Ehdr *ehdr;
Elf_Sym *symtab;
Elf_Hashelt *hashtab;
Elf_Hashelt nbuckets;
Elf_Hashelt nchains;
Elf_Hashelt *buckets;
Elf_Hashelt *chains;
Elf_Rel *rel;
size_t relsz;
Elf_Rela *rela;
size_t relasz;
char *strtab;
size_t strsz;
int fd;
caddr_t firstpage;
size_t firstlen;
int kernel;
uint64_t off;
} *elf_file_t;
static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef,
uint64_t loadaddr);
static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef,
const char* name, Elf_Sym* sym);
static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
Elf_Addr p, void *val, size_t len);
static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef,
Elf_Addr p_start, Elf_Addr p_end);
static symaddr_fn __elfN(symaddr);
static char *fake_modname(const char *name);
const char *__elfN(kerneltype) = "elf kernel";
const char *__elfN(moduletype) = "elf module";
uint64_t __elfN(relocation_offset) = 0;
extern void elf_wrong_field_size(void);
#define CONVERT_FIELD(b, f, e) \
switch (sizeof((b)->f)) { \
case 2: \
(b)->f = e ## 16toh((b)->f); \
break; \
case 4: \
(b)->f = e ## 32toh((b)->f); \
break; \
case 8: \
(b)->f = e ## 64toh((b)->f); \
break; \
default: \
/* Force a link time error. */ \
elf_wrong_field_size(); \
break; \
}
#define CONVERT_SWITCH(h, d, f) \
switch ((h)->e_ident[EI_DATA]) { \
case ELFDATA2MSB: \
f(d, be); \
break; \
case ELFDATA2LSB: \
f(d, le); \
break; \
default: \
return (EINVAL); \
}
static int elf_header_convert(Elf_Ehdr *ehdr)
{
/*
* Fixup ELF header endianness.
*
* The Xhdr structure was loaded using block read call to optimize file
* accesses. It might happen, that the endianness of the system memory
* is different that endianness of the ELF header. Swap fields here to
* guarantee that Xhdr always contain valid data regardless of
* architecture.
*/
#define HEADER_FIELDS(b, e) \
CONVERT_FIELD(b, e_type, e); \
CONVERT_FIELD(b, e_machine, e); \
CONVERT_FIELD(b, e_version, e); \
CONVERT_FIELD(b, e_entry, e); \
CONVERT_FIELD(b, e_phoff, e); \
CONVERT_FIELD(b, e_shoff, e); \
CONVERT_FIELD(b, e_flags, e); \
CONVERT_FIELD(b, e_ehsize, e); \
CONVERT_FIELD(b, e_phentsize, e); \
CONVERT_FIELD(b, e_phnum, e); \
CONVERT_FIELD(b, e_shentsize, e); \
CONVERT_FIELD(b, e_shnum, e); \
CONVERT_FIELD(b, e_shstrndx, e)
CONVERT_SWITCH(ehdr, ehdr, HEADER_FIELDS);
#undef HEADER_FIELDS
return (0);
}
static int elf_program_header_convert(const Elf_Ehdr *ehdr, Elf_Phdr *phdr)
{
#define PROGRAM_HEADER_FIELDS(b, e) \
CONVERT_FIELD(b, p_type, e); \
CONVERT_FIELD(b, p_flags, e); \
CONVERT_FIELD(b, p_offset, e); \
CONVERT_FIELD(b, p_vaddr, e); \
CONVERT_FIELD(b, p_paddr, e); \
CONVERT_FIELD(b, p_filesz, e); \
CONVERT_FIELD(b, p_memsz, e); \
CONVERT_FIELD(b, p_align, e)
CONVERT_SWITCH(ehdr, phdr, PROGRAM_HEADER_FIELDS);
#undef PROGRAM_HEADER_FIELDS
return (0);
}
static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr)
{
#define SECTION_HEADER_FIELDS(b, e) \
CONVERT_FIELD(b, sh_name, e); \
CONVERT_FIELD(b, sh_type, e); \
CONVERT_FIELD(b, sh_link, e); \
CONVERT_FIELD(b, sh_info, e); \
CONVERT_FIELD(b, sh_flags, e); \
CONVERT_FIELD(b, sh_addr, e); \
CONVERT_FIELD(b, sh_offset, e); \
CONVERT_FIELD(b, sh_size, e); \
CONVERT_FIELD(b, sh_addralign, e); \
CONVERT_FIELD(b, sh_entsize, e)
CONVERT_SWITCH(ehdr, shdr, SECTION_HEADER_FIELDS);
#undef SECTION_HEADER_FIELDS
return (0);
}
#undef CONVERT_SWITCH
#undef CONVERT_FIELD
static int
__elfN(load_elf_header)(char *filename, elf_file_t ef)
{
ssize_t bytes_read;
Elf_Ehdr *ehdr;
int err;
/*
* Open the image, read and validate the ELF header
*/
if (filename == NULL) /* can't handle nameless */
return (EFTYPE);
if ((ef->fd = open(filename, O_RDONLY)) == -1)
return (errno);
ef->firstpage = malloc(PAGE_SIZE);
if (ef->firstpage == NULL) {
close(ef->fd);
return (ENOMEM);
}
bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE);
ef->firstlen = (size_t)bytes_read;
if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) {
err = EFTYPE; /* could be EIO, but may be small file */
goto error;
}
ehdr = ef->ehdr = (Elf_Ehdr *)ef->firstpage;
/* Is it ELF? */
if (!IS_ELF(*ehdr)) {
err = EFTYPE;
goto error;
}
if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
ehdr->e_ident[EI_VERSION] != EV_CURRENT) /* Version ? */ {
err = EFTYPE;
goto error;
}
err = elf_header_convert(ehdr);
if (err)
goto error;
if (ehdr->e_version != EV_CURRENT || ehdr->e_machine != ELF_TARG_MACH) {
/* Machine ? */
err = EFTYPE;
goto error;
}
+#ifdef LOADER_VERIEXEC
+ if (verify_file(ef->fd, filename, bytes_read, VE_MUST) < 0) {
+ err = EAUTH;
+ goto error;
+ }
+#endif
return (0);
error:
if (ef->firstpage != NULL) {
free(ef->firstpage);
ef->firstpage = NULL;
}
if (ef->fd != -1) {
close(ef->fd);
ef->fd = -1;
}
return (err);
}
/*
* Attempt to load the file (file) as an ELF module. It will be stored at
* (dest), and a pointer to a module structure describing the loaded object
* will be saved in (result).
*/
int
__elfN(loadfile)(char *filename, uint64_t dest, struct preloaded_file **result)
{
return (__elfN(loadfile_raw)(filename, dest, result, 0));
}
int
__elfN(loadfile_raw)(char *filename, uint64_t dest,
struct preloaded_file **result, int multiboot)
{
struct preloaded_file *fp, *kfp;
struct elf_file ef;
Elf_Ehdr *ehdr;
int err;
fp = NULL;
bzero(&ef, sizeof(struct elf_file));
ef.fd = -1;
err = __elfN(load_elf_header)(filename, &ef);
if (err != 0)
return (err);
ehdr = ef.ehdr;
/*
* Check to see what sort of module we are.
*/
kfp = file_findfile(NULL, __elfN(kerneltype));
#ifdef __powerpc__
/*
* Kernels can be ET_DYN, so just assume the first loaded object is the
* kernel. This assumption will be checked later.
*/
if (kfp == NULL)
ef.kernel = 1;
#endif
if (ef.kernel || ehdr->e_type == ET_EXEC) {
/* Looks like a kernel */
if (kfp != NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_loadfile: kernel already loaded\n");
err = EPERM;
goto oerr;
}
/*
* Calculate destination address based on kernel entrypoint.
*
* For ARM, the destination address is independent of any values
* in the elf header (an ARM kernel can be loaded at any 2MB
* boundary), so we leave dest set to the value calculated by
* archsw.arch_loadaddr() and passed in to this function.
*/
#ifndef __arm__
if (ehdr->e_type == ET_EXEC)
dest = (ehdr->e_entry & ~PAGE_MASK);
#endif
if ((ehdr->e_entry & ~PAGE_MASK) == 0) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_loadfile: not a kernel (maybe static binary?)\n");
err = EPERM;
goto oerr;
}
ef.kernel = 1;
} else if (ehdr->e_type == ET_DYN) {
/* Looks like a kld module */
if (multiboot != 0) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_loadfile: can't load module as multiboot\n");
err = EPERM;
goto oerr;
}
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_loadfile: can't load module before kernel\n");
err = EPERM;
goto oerr;
}
if (strcmp(__elfN(kerneltype), kfp->f_type)) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_loadfile: can't load module with kernel type '%s'\n",
kfp->f_type);
err = EPERM;
goto oerr;
}
/* Looks OK, got ahead */
ef.kernel = 0;
} else {
err = EFTYPE;
goto oerr;
}
if (archsw.arch_loadaddr != NULL)
dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest);
else
dest = roundup(dest, PAGE_SIZE);
/*
* Ok, we think we should handle this.
*/
fp = file_alloc();
if (fp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_loadfile: cannot allocate module info\n");
err = EPERM;
goto out;
}
if (ef.kernel == 1 && multiboot == 0)
setenv("kernelname", filename, 1);
fp->f_name = strdup(filename);
if (multiboot == 0)
fp->f_type = strdup(ef.kernel ?
__elfN(kerneltype) : __elfN(moduletype));
else
fp->f_type = strdup("elf multiboot kernel");
#ifdef ELF_VERBOSE
if (ef.kernel)
printf("%s entry at 0x%jx\n", filename,
(uintmax_t)ehdr->e_entry);
#else
printf("%s ", filename);
#endif
fp->f_size = __elfN(loadimage)(fp, &ef, dest);
if (fp->f_size == 0 || fp->f_addr == 0)
goto ioerr;
/* save exec header as metadata */
file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr);
/* Load OK, return module pointer */
*result = (struct preloaded_file *)fp;
err = 0;
goto out;
ioerr:
err = EIO;
oerr:
file_discard(fp);
out:
if (ef.firstpage)
free(ef.firstpage);
if (ef.fd != -1)
close(ef.fd);
return (err);
}
/*
* With the file (fd) open on the image, and (ehdr) containing
* the Elf header, load the image at (off)
*/
static int
__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off)
{
int i;
u_int j;
Elf_Ehdr *ehdr;
Elf_Phdr *phdr, *php;
Elf_Shdr *shdr;
char *shstr;
int ret;
vm_offset_t firstaddr;
vm_offset_t lastaddr;
size_t chunk;
ssize_t result;
Elf_Addr ssym, esym;
Elf_Dyn *dp;
Elf_Addr adp;
Elf_Addr ctors;
int ndp;
int symstrindex;
int symtabindex;
Elf_Size size;
u_int fpcopy;
Elf_Sym sym;
Elf_Addr p_start, p_end;
dp = NULL;
shdr = NULL;
ret = 0;
firstaddr = lastaddr = 0;
ehdr = ef->ehdr;
if (ehdr->e_type == ET_EXEC) {
#if defined(__i386__) || defined(__amd64__)
#if __ELF_WORD_SIZE == 64
/* x86_64 relocates after locore */
off = - (off & 0xffffffffff000000ull);
#else
/* i386 relocates after locore */
off = - (off & 0xff000000u);
#endif
#elif defined(__powerpc__)
/*
* On the purely virtual memory machines like e500, the kernel
* is linked against its final VA range, which is most often
* not available at the loader stage, but only after kernel
* initializes and completes its VM settings. In such cases we
* cannot use p_vaddr field directly to load ELF segments, but
* put them at some 'load-time' locations.
*/
if (off & 0xf0000000u) {
off = -(off & 0xf0000000u);
/*
* XXX the physical load address should not be
* hardcoded. Note that the Book-E kernel assumes that
* it's loaded at a 16MB boundary for now...
*/
off += 0x01000000;
ehdr->e_entry += off;
#ifdef ELF_VERBOSE
printf("Converted entry 0x%08x\n", ehdr->e_entry);
#endif
} else
off = 0;
#elif defined(__arm__) && !defined(EFI)
/*
* The elf headers in arm kernels specify virtual addresses in
* all header fields, even the ones that should be physical
* addresses. We assume the entry point is in the first page,
* and masking the page offset will leave us with the virtual
* address the kernel was linked at. We subtract that from the
* load offset, making 'off' into the value which, when added
* to a virtual address in an elf header, translates it to a
* physical address. We do the va->pa conversion on the entry
* point address in the header now, so that later we can launch
* the kernel by just jumping to that address.
*
* When booting from UEFI the copyin and copyout functions
* handle adjusting the location relative to the first virtual
* address. Because of this there is no need to adjust the
* offset or entry point address as these will both be handled
* by the efi code.
*/
off -= ehdr->e_entry & ~PAGE_MASK;
ehdr->e_entry += off;
#ifdef ELF_VERBOSE
printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n",
ehdr->e_entry, off);
#endif
#else
off = 0; /* other archs use direct mapped kernels */
#endif
}
ef->off = off;
if (ef->kernel)
__elfN(relocation_offset) = off;
if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_loadimage: program header not within first page\n");
goto out;
}
phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
if (elf_program_header_convert(ehdr, phdr))
continue;
/* We want to load PT_LOAD segments only.. */
if (phdr[i].p_type != PT_LOAD)
continue;
#ifdef ELF_VERBOSE
printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx",
(long)phdr[i].p_filesz, (long)phdr[i].p_offset,
(long)(phdr[i].p_vaddr + off),
(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1));
#else
if ((phdr[i].p_flags & PF_W) == 0) {
printf("text=0x%lx ", (long)phdr[i].p_filesz);
} else {
printf("data=0x%lx", (long)phdr[i].p_filesz);
if (phdr[i].p_filesz < phdr[i].p_memsz)
printf("+0x%lx", (long)(phdr[i].p_memsz -
phdr[i].p_filesz));
printf(" ");
}
#endif
fpcopy = 0;
if (ef->firstlen > phdr[i].p_offset) {
fpcopy = ef->firstlen - phdr[i].p_offset;
archsw.arch_copyin(ef->firstpage + phdr[i].p_offset,
phdr[i].p_vaddr + off, fpcopy);
}
if (phdr[i].p_filesz > fpcopy) {
if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy,
phdr[i].p_filesz - fpcopy,
phdr[i].p_offset + fpcopy) != 0) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_loadimage: read failed\n");
goto out;
}
}
/* clear space from oversized segments; eg: bss */
if (phdr[i].p_filesz < phdr[i].p_memsz) {
#ifdef ELF_VERBOSE
printf(" (bss: 0x%lx-0x%lx)",
(long)(phdr[i].p_vaddr + off + phdr[i].p_filesz),
(long)(phdr[i].p_vaddr + off + phdr[i].p_memsz -1));
#endif
kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz,
phdr[i].p_memsz - phdr[i].p_filesz);
}
#ifdef ELF_VERBOSE
printf("\n");
#endif
if (archsw.arch_loadseg != NULL)
archsw.arch_loadseg(ehdr, phdr + i, off);
if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off))
firstaddr = phdr[i].p_vaddr + off;
if (lastaddr == 0 || lastaddr <
(phdr[i].p_vaddr + off + phdr[i].p_memsz))
lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz;
}
lastaddr = roundup(lastaddr, sizeof(long));
/*
* Get the section headers. We need this for finding the .ctors
* section as well as for loading any symbols. Both may be hard
* to do if reading from a .gz file as it involves seeking. I
* think the rule is going to have to be that you must strip a
* file to remove symbols before gzipping it.
*/
chunk = (size_t)ehdr->e_shnum * (size_t)ehdr->e_shentsize;
if (chunk == 0 || ehdr->e_shoff == 0)
goto nosyms;
shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk);
if (shdr == NULL) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_loadimage: failed to read section headers");
goto nosyms;
}
for (i = 0; i < ehdr->e_shnum; i++)
elf_section_header_convert(ehdr, &shdr[i]);
file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr);
/*
* Read the section string table and look for the .ctors section.
* We need to tell the kernel where it is so that it can call the
* ctors.
*/
chunk = shdr[ehdr->e_shstrndx].sh_size;
if (chunk) {
shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset,
chunk);
if (shstr) {
for (i = 0; i < ehdr->e_shnum; i++) {
if (strcmp(shstr + shdr[i].sh_name,
".ctors") != 0)
continue;
ctors = shdr[i].sh_addr;
file_addmetadata(fp, MODINFOMD_CTORS_ADDR,
sizeof(ctors), &ctors);
size = shdr[i].sh_size;
file_addmetadata(fp, MODINFOMD_CTORS_SIZE,
sizeof(size), &size);
break;
}
free(shstr);
}
}
/*
* Now load any symbols.
*/
symtabindex = -1;
symstrindex = -1;
for (i = 0; i < ehdr->e_shnum; i++) {
if (shdr[i].sh_type != SHT_SYMTAB)
continue;
for (j = 0; j < ehdr->e_phnum; j++) {
if (phdr[j].p_type != PT_LOAD)
continue;
if (shdr[i].sh_offset >= phdr[j].p_offset &&
(shdr[i].sh_offset + shdr[i].sh_size <=
phdr[j].p_offset + phdr[j].p_filesz)) {
shdr[i].sh_offset = 0;
shdr[i].sh_size = 0;
break;
}
}
if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0)
continue; /* alread loaded in a PT_LOAD above */
/* Save it for loading below */
symtabindex = i;
symstrindex = shdr[i].sh_link;
}
if (symtabindex < 0 || symstrindex < 0)
goto nosyms;
/* Ok, committed to a load. */
#ifndef ELF_VERBOSE
printf("syms=[");
#endif
ssym = lastaddr;
for (i = symtabindex; i >= 0; i = symstrindex) {
#ifdef ELF_VERBOSE
char *secname;
switch(shdr[i].sh_type) {
case SHT_SYMTAB: /* Symbol table */
secname = "symtab";
break;
case SHT_STRTAB: /* String table */
secname = "strtab";
break;
default:
secname = "WHOA!!";
break;
}
#endif
size = shdr[i].sh_size;
#if defined(__powerpc__)
#if __ELF_WORD_SIZE == 64
size = htobe64(size);
#else
size = htobe32(size);
#endif
#endif
archsw.arch_copyin(&size, lastaddr, sizeof(size));
lastaddr += sizeof(size);
#ifdef ELF_VERBOSE
printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname,
(uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset,
(uintmax_t)lastaddr,
(uintmax_t)(lastaddr + shdr[i].sh_size));
#else
if (i == symstrindex)
printf("+");
printf("0x%lx+0x%lx", (long)sizeof(size), (long)size);
#endif
if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_loadimage: could not seek for symbols - skipped!");
lastaddr = ssym;
ssym = 0;
goto nosyms;
}
result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size);
if (result < 0 || (size_t)result != shdr[i].sh_size) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_loadimage: could not read symbols - skipped! "
"(%ju != %ju)", (uintmax_t)result,
(uintmax_t)shdr[i].sh_size);
lastaddr = ssym;
ssym = 0;
goto nosyms;
}
/* Reset offsets relative to ssym */
lastaddr += shdr[i].sh_size;
lastaddr = roundup(lastaddr, sizeof(size));
if (i == symtabindex)
symtabindex = -1;
else if (i == symstrindex)
symstrindex = -1;
}
esym = lastaddr;
#ifndef ELF_VERBOSE
printf("]");
#endif
#if defined(__powerpc__)
/* On PowerPC we always need to provide BE data to the kernel */
#if __ELF_WORD_SIZE == 64
ssym = htobe64((uint64_t)ssym);
esym = htobe64((uint64_t)esym);
#else
ssym = htobe32((uint32_t)ssym);
esym = htobe32((uint32_t)esym);
#endif
#endif
file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym);
nosyms:
printf("\n");
ret = lastaddr - firstaddr;
fp->f_addr = firstaddr;
php = NULL;
for (i = 0; i < ehdr->e_phnum; i++) {
if (phdr[i].p_type == PT_DYNAMIC) {
php = phdr + i;
adp = php->p_vaddr;
file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp),
&adp);
break;
}
}
if (php == NULL) /* this is bad, we cannot get to symbols or _DYNAMIC */
goto out;
ndp = php->p_filesz / sizeof(Elf_Dyn);
if (ndp == 0)
goto out;
dp = malloc(php->p_filesz);
if (dp == NULL)
goto out;
archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz);
ef->strsz = 0;
for (i = 0; i < ndp; i++) {
if (dp[i].d_tag == 0)
break;
switch (dp[i].d_tag) {
case DT_HASH:
ef->hashtab =
(Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_STRTAB:
ef->strtab =
(char *)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_STRSZ:
ef->strsz = dp[i].d_un.d_val;
break;
case DT_SYMTAB:
ef->symtab =
(Elf_Sym *)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_REL:
ef->rel =
(Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_RELSZ:
ef->relsz = dp[i].d_un.d_val;
break;
case DT_RELA:
ef->rela =
(Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off);
break;
case DT_RELASZ:
ef->relasz = dp[i].d_un.d_val;
break;
default:
break;
}
}
if (ef->hashtab == NULL || ef->symtab == NULL ||
ef->strtab == NULL || ef->strsz == 0)
goto out;
COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets));
COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
ef->buckets = ef->hashtab + 2;
ef->chains = ef->buckets + ef->nbuckets;
if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set",
&sym) != 0)
return 0;
p_start = sym.st_value + ef->off;
if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set",
&sym) != 0)
return ENOENT;
p_end = sym.st_value + ef->off;
if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0)
goto out;
if (ef->kernel) /* kernel must not depend on anything */
goto out;
out:
if (dp)
free(dp);
if (shdr)
free(shdr);
return ret;
}
static char invalid_name[] = "bad";
char *
fake_modname(const char *name)
{
const char *sp, *ep;
char *fp;
size_t len;
sp = strrchr(name, '/');
if (sp)
sp++;
else
sp = name;
ep = strrchr(name, '.');
if (ep) {
if (ep == name) {
sp = invalid_name;
ep = invalid_name + sizeof(invalid_name) - 1;
}
} else
ep = name + strlen(name);
len = ep - sp;
fp = malloc(len + 1);
if (fp == NULL)
return NULL;
memcpy(fp, sp, len);
fp[len] = '\0';
return fp;
}
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
struct mod_metadata64 {
int md_version; /* structure version MDTV_* */
int md_type; /* type of entry MDT_* */
uint64_t md_data; /* specific data */
uint64_t md_cval; /* common string label */
};
#endif
#if defined(__amd64__) && __ELF_WORD_SIZE == 32
struct mod_metadata32 {
int md_version; /* structure version MDTV_* */
int md_type; /* type of entry MDT_* */
uint32_t md_data; /* specific data */
uint32_t md_cval; /* common string label */
};
#endif
int
__elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
{
struct elf_file ef;
int err, i, j;
Elf_Shdr *sh_meta, *shdr = NULL;
Elf_Shdr *sh_data[2];
char *shstrtab = NULL;
size_t size;
Elf_Addr p_start, p_end;
bzero(&ef, sizeof(struct elf_file));
ef.fd = -1;
err = __elfN(load_elf_header)(fp->f_name, &ef);
if (err != 0)
goto out;
if (ef.kernel == 1 || ef.ehdr->e_type == ET_EXEC) {
ef.kernel = 1;
} else if (ef.ehdr->e_type != ET_DYN) {
err = EFTYPE;
goto out;
}
size = (size_t)ef.ehdr->e_shnum * (size_t)ef.ehdr->e_shentsize;
shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size);
if (shdr == NULL) {
err = ENOMEM;
goto out;
}
/* Load shstrtab. */
shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset,
shdr[ef.ehdr->e_shstrndx].sh_size);
if (shstrtab == NULL) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"load_modmetadata: unable to load shstrtab\n");
err = EFTYPE;
goto out;
}
/* Find set_modmetadata_set and data sections. */
sh_data[0] = sh_data[1] = sh_meta = NULL;
for (i = 0, j = 0; i < ef.ehdr->e_shnum; i++) {
if (strcmp(&shstrtab[shdr[i].sh_name],
"set_modmetadata_set") == 0) {
sh_meta = &shdr[i];
}
if ((strcmp(&shstrtab[shdr[i].sh_name], ".data") == 0) ||
(strcmp(&shstrtab[shdr[i].sh_name], ".rodata") == 0)) {
sh_data[j++] = &shdr[i];
}
}
if (sh_meta == NULL || sh_data[0] == NULL || sh_data[1] == NULL) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"load_modmetadata: unable to find set_modmetadata_set or data sections\n");
err = EFTYPE;
goto out;
}
/* Load set_modmetadata_set into memory */
err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset);
if (err != 0) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"load_modmetadata: unable to load set_modmetadata_set: %d\n", err);
goto out;
}
p_start = dest;
p_end = dest + sh_meta->sh_size;
dest += sh_meta->sh_size;
/* Load data sections into memory. */
err = kern_pread(ef.fd, dest, sh_data[0]->sh_size,
sh_data[0]->sh_offset);
if (err != 0) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"load_modmetadata: unable to load data: %d\n", err);
goto out;
}
/*
* We have to increment the dest, so that the offset is the same into
* both the .rodata and .data sections.
*/
ef.off = -(sh_data[0]->sh_addr - dest);
dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr);
err = kern_pread(ef.fd, dest, sh_data[1]->sh_size,
sh_data[1]->sh_offset);
if (err != 0) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"load_modmetadata: unable to load data: %d\n", err);
goto out;
}
err = __elfN(parse_modmetadata)(fp, &ef, p_start, p_end);
if (err != 0) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"load_modmetadata: unable to parse metadata: %d\n", err);
goto out;
}
out:
if (shstrtab != NULL)
free(shstrtab);
if (shdr != NULL)
free(shdr);
if (ef.firstpage != NULL)
free(ef.firstpage);
if (ef.fd != -1)
close(ef.fd);
return (err);
}
int
__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef,
Elf_Addr p_start, Elf_Addr p_end)
{
struct mod_metadata md;
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
struct mod_metadata64 md64;
#elif defined(__amd64__) && __ELF_WORD_SIZE == 32
struct mod_metadata32 md32;
#endif
struct mod_depend *mdepend;
struct mod_version mver;
char *s;
int error, modcnt, minfolen;
Elf_Addr v, p;
modcnt = 0;
p = p_start;
while (p < p_end) {
COPYOUT(p, &v, sizeof(v));
error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v));
if (error == EOPNOTSUPP)
v += ef->off;
else if (error != 0)
return (error);
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
COPYOUT(v, &md64, sizeof(md64));
error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64));
if (error == EOPNOTSUPP) {
md64.md_cval += ef->off;
md64.md_data += ef->off;
} else if (error != 0)
return (error);
md.md_version = md64.md_version;
md.md_type = md64.md_type;
md.md_cval = (const char *)(uintptr_t)md64.md_cval;
md.md_data = (void *)(uintptr_t)md64.md_data;
#elif defined(__amd64__) && __ELF_WORD_SIZE == 32
COPYOUT(v, &md32, sizeof(md32));
error = __elfN(reloc_ptr)(fp, ef, v, &md32, sizeof(md32));
if (error == EOPNOTSUPP) {
md32.md_cval += ef->off;
md32.md_data += ef->off;
} else if (error != 0)
return (error);
md.md_version = md32.md_version;
md.md_type = md32.md_type;
md.md_cval = (const char *)(uintptr_t)md32.md_cval;
md.md_data = (void *)(uintptr_t)md32.md_data;
#else
COPYOUT(v, &md, sizeof(md));
error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md));
if (error == EOPNOTSUPP) {
md.md_cval += ef->off;
md.md_data = (void *)((uintptr_t)md.md_data +
(uintptr_t)ef->off);
} else if (error != 0)
return (error);
#endif
p += sizeof(Elf_Addr);
switch(md.md_type) {
case MDT_DEPEND:
if (ef->kernel) /* kernel must not depend on anything */
break;
s = strdupout((vm_offset_t)md.md_cval);
minfolen = sizeof(*mdepend) + strlen(s) + 1;
mdepend = malloc(minfolen);
if (mdepend == NULL)
return ENOMEM;
COPYOUT((vm_offset_t)md.md_data, mdepend,
sizeof(*mdepend));
strcpy((char*)(mdepend + 1), s);
free(s);
file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen,
mdepend);
free(mdepend);
break;
case MDT_VERSION:
s = strdupout((vm_offset_t)md.md_cval);
COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver));
file_addmodule(fp, s, mver.mv_version, NULL);
free(s);
modcnt++;
break;
}
}
if (modcnt == 0) {
s = fake_modname(fp->f_name);
file_addmodule(fp, s, 1, NULL);
free(s);
}
return 0;
}
static unsigned long
elf_hash(const char *name)
{
const unsigned char *p = (const unsigned char *) name;
unsigned long h = 0;
unsigned long g;
while (*p != '\0') {
h = (h << 4) + *p++;
if ((g = h & 0xf0000000) != 0)
h ^= g >> 24;
h &= ~g;
}
return h;
}
static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE)
"_lookup_symbol: corrupt symbol table\n";
int
__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef,
const char* name, Elf_Sym *symp)
{
Elf_Hashelt symnum;
Elf_Sym sym;
char *strp;
unsigned long hash;
hash = elf_hash(name);
COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum));
while (symnum != STN_UNDEF) {
if (symnum >= ef->nchains) {
printf(__elfN(bad_symtable));
return ENOENT;
}
COPYOUT(ef->symtab + symnum, &sym, sizeof(sym));
if (sym.st_name == 0) {
printf(__elfN(bad_symtable));
return ENOENT;
}
strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name));
if (strcmp(name, strp) == 0) {
free(strp);
if (sym.st_shndx != SHN_UNDEF ||
(sym.st_value != 0 &&
ELF_ST_TYPE(sym.st_info) == STT_FUNC)) {
*symp = sym;
return 0;
}
return ENOENT;
}
free(strp);
COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum));
}
return ENOENT;
}
/*
* Apply any intra-module relocations to the value. p is the load address
* of the value and val/len is the value to be modified. This does NOT modify
* the image in-place, because this is done by kern_linker later on.
*
* Returns EOPNOTSUPP if no relocation method is supplied.
*/
static int
__elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
Elf_Addr p, void *val, size_t len)
{
size_t n;
Elf_Rela a;
Elf_Rel r;
int error;
/*
* The kernel is already relocated, but we still want to apply
* offset adjustments.
*/
if (ef->kernel)
return (EOPNOTSUPP);
for (n = 0; n < ef->relsz / sizeof(r); n++) {
COPYOUT(ef->rel + n, &r, sizeof(r));
error = __elfN(reloc)(ef, __elfN(symaddr), &r, ELF_RELOC_REL,
ef->off, p, val, len);
if (error != 0)
return (error);
}
for (n = 0; n < ef->relasz / sizeof(a); n++) {
COPYOUT(ef->rela + n, &a, sizeof(a));
error = __elfN(reloc)(ef, __elfN(symaddr), &a, ELF_RELOC_RELA,
ef->off, p, val, len);
if (error != 0)
return (error);
}
return (0);
}
static Elf_Addr
__elfN(symaddr)(struct elf_file *ef, Elf_Size symidx)
{
/* Symbol lookup by index not required here. */
return (0);
}
Index: stable/12/stand/common/load_elf_obj.c
===================================================================
--- stable/12/stand/common/load_elf_obj.c (revision 346144)
+++ stable/12/stand/common/load_elf_obj.c (revision 346145)
@@ -1,541 +1,548 @@
/*-
* Copyright (c) 2004 Ian Dowse <iedowse@freebsd.org>
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* Copyright (c) 1998 Peter Wemm <peter@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/exec.h>
#include <sys/linker.h>
#include <sys/module.h>
#include <stdint.h>
#include <string.h>
#include <machine/elf.h>
#include <stand.h>
#define FREEBSD_ELF
#include <sys/link_elf.h>
#include "bootstrap.h"
#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l)
#if defined(__i386__) && __ELF_WORD_SIZE == 64
#undef ELF_TARG_CLASS
#undef ELF_TARG_MACH
#define ELF_TARG_CLASS ELFCLASS64
#define ELF_TARG_MACH EM_X86_64
#endif
typedef struct elf_file {
Elf_Ehdr hdr;
Elf_Shdr *e_shdr;
int symtabindex; /* Index of symbol table */
int shstrindex; /* Index of section name string table */
int fd;
vm_offset_t off;
} *elf_file_t;
static int __elfN(obj_loadimage)(struct preloaded_file *mp, elf_file_t ef,
uint64_t loadaddr);
static int __elfN(obj_lookup_set)(struct preloaded_file *mp, elf_file_t ef,
const char *name, Elf_Addr *startp, Elf_Addr *stopp, int *countp);
static int __elfN(obj_reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
Elf_Addr p, void *val, size_t len);
static int __elfN(obj_parse_modmetadata)(struct preloaded_file *mp,
elf_file_t ef);
static Elf_Addr __elfN(obj_symaddr)(struct elf_file *ef, Elf_Size symidx);
const char *__elfN(obj_kerneltype) = "elf kernel";
const char *__elfN(obj_moduletype) = "elf obj module";
/*
* Attempt to load the file (file) as an ELF module. It will be stored at
* (dest), and a pointer to a module structure describing the loaded object
* will be saved in (result).
*/
int
__elfN(obj_loadfile)(char *filename, uint64_t dest,
struct preloaded_file **result)
{
struct preloaded_file *fp, *kfp;
struct elf_file ef;
Elf_Ehdr *hdr;
int err;
ssize_t bytes_read;
fp = NULL;
bzero(&ef, sizeof(struct elf_file));
/*
* Open the image, read and validate the ELF header
*/
if (filename == NULL) /* can't handle nameless */
return(EFTYPE);
if ((ef.fd = open(filename, O_RDONLY)) == -1)
return(errno);
hdr = &ef.hdr;
bytes_read = read(ef.fd, hdr, sizeof(*hdr));
if (bytes_read != sizeof(*hdr)) {
err = EFTYPE; /* could be EIO, but may be small file */
goto oerr;
}
/* Is it ELF? */
if (!IS_ELF(*hdr)) {
err = EFTYPE;
goto oerr;
}
if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
hdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
hdr->e_version != EV_CURRENT ||
hdr->e_machine != ELF_TARG_MACH || /* Machine ? */
hdr->e_type != ET_REL) {
err = EFTYPE;
goto oerr;
}
if (hdr->e_shnum * hdr->e_shentsize == 0 || hdr->e_shoff == 0 ||
hdr->e_shentsize != sizeof(Elf_Shdr)) {
err = EFTYPE;
goto oerr;
}
+#ifdef LOADER_VERIEXEC
+ if (verify_file(ef.fd, filename, bytes_read, VE_MUST) < 0) {
+ err = EAUTH;
+ goto oerr;
+ }
+#endif
+
kfp = file_findfile(NULL, __elfN(obj_kerneltype));
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadfile: can't load module before kernel\n");
err = EPERM;
goto oerr;
}
if (archsw.arch_loadaddr != NULL)
dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
else
dest = roundup(dest, PAGE_SIZE);
/*
* Ok, we think we should handle this.
*/
fp = file_alloc();
if (fp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadfile: cannot allocate module info\n");
err = EPERM;
goto out;
}
fp->f_name = strdup(filename);
fp->f_type = strdup(__elfN(obj_moduletype));
printf("%s ", filename);
fp->f_size = __elfN(obj_loadimage)(fp, &ef, dest);
if (fp->f_size == 0 || fp->f_addr == 0)
goto ioerr;
/* save exec header as metadata */
file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*hdr), hdr);
/* Load OK, return module pointer */
*result = (struct preloaded_file *)fp;
err = 0;
goto out;
ioerr:
err = EIO;
oerr:
file_discard(fp);
out:
close(ef.fd);
if (ef.e_shdr != NULL)
free(ef.e_shdr);
return(err);
}
/*
* With the file (fd) open on the image, and (ehdr) containing
* the Elf header, load the image at (off)
*/
static int
__elfN(obj_loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off)
{
Elf_Ehdr *hdr;
Elf_Shdr *shdr, *cshdr, *lshdr;
vm_offset_t firstaddr, lastaddr;
int i, nsym, res, ret, shdrbytes, symstrindex;
ret = 0;
firstaddr = lastaddr = (vm_offset_t)off;
hdr = &ef->hdr;
ef->off = (vm_offset_t)off;
/* Read in the section headers. */
shdrbytes = hdr->e_shnum * hdr->e_shentsize;
shdr = alloc_pread(ef->fd, (off_t)hdr->e_shoff, shdrbytes);
if (shdr == NULL) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadimage: read section headers failed\n");
goto out;
}
ef->e_shdr = shdr;
/*
* Decide where to load everything, but don't read it yet.
* We store the load address as a non-zero sh_addr value.
* Start with the code/data and bss.
*/
for (i = 0; i < hdr->e_shnum; i++)
shdr[i].sh_addr = 0;
for (i = 0; i < hdr->e_shnum; i++) {
if (shdr[i].sh_size == 0)
continue;
switch (shdr[i].sh_type) {
case SHT_PROGBITS:
case SHT_NOBITS:
#if defined(__i386__) || defined(__amd64__)
case SHT_X86_64_UNWIND:
#endif
if ((shdr[i].sh_flags & SHF_ALLOC) == 0)
break;
lastaddr = roundup(lastaddr, shdr[i].sh_addralign);
shdr[i].sh_addr = (Elf_Addr)lastaddr;
lastaddr += shdr[i].sh_size;
break;
}
}
/* Symbols. */
nsym = 0;
for (i = 0; i < hdr->e_shnum; i++) {
switch (shdr[i].sh_type) {
case SHT_SYMTAB:
nsym++;
ef->symtabindex = i;
shdr[i].sh_addr = (Elf_Addr)lastaddr;
lastaddr += shdr[i].sh_size;
break;
}
}
if (nsym != 1) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadimage: file has no valid symbol table\n");
goto out;
}
lastaddr = roundup(lastaddr, shdr[ef->symtabindex].sh_addralign);
shdr[ef->symtabindex].sh_addr = (Elf_Addr)lastaddr;
lastaddr += shdr[ef->symtabindex].sh_size;
symstrindex = shdr[ef->symtabindex].sh_link;
if (symstrindex < 0 || symstrindex >= hdr->e_shnum ||
shdr[symstrindex].sh_type != SHT_STRTAB) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadimage: file has invalid symbol strings\n");
goto out;
}
lastaddr = roundup(lastaddr, shdr[symstrindex].sh_addralign);
shdr[symstrindex].sh_addr = (Elf_Addr)lastaddr;
lastaddr += shdr[symstrindex].sh_size;
/* Section names. */
if (hdr->e_shstrndx == 0 || hdr->e_shstrndx >= hdr->e_shnum ||
shdr[hdr->e_shstrndx].sh_type != SHT_STRTAB) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadimage: file has no section names\n");
goto out;
}
ef->shstrindex = hdr->e_shstrndx;
lastaddr = roundup(lastaddr, shdr[ef->shstrindex].sh_addralign);
shdr[ef->shstrindex].sh_addr = (Elf_Addr)lastaddr;
lastaddr += shdr[ef->shstrindex].sh_size;
/* Relocation tables. */
for (i = 0; i < hdr->e_shnum; i++) {
switch (shdr[i].sh_type) {
case SHT_REL:
case SHT_RELA:
if ((shdr[shdr[i].sh_info].sh_flags & SHF_ALLOC) == 0)
break;
lastaddr = roundup(lastaddr, shdr[i].sh_addralign);
shdr[i].sh_addr = (Elf_Addr)lastaddr;
lastaddr += shdr[i].sh_size;
break;
}
}
/* Clear the whole area, including bss regions. */
kern_bzero(firstaddr, lastaddr - firstaddr);
/* Figure section with the lowest file offset we haven't loaded yet. */
for (cshdr = NULL; /* none */; /* none */)
{
/*
* Find next section to load. The complexity of this loop is
* O(n^2), but with the number of sections being typically
* small, we do not care.
*/
lshdr = cshdr;
for (i = 0; i < hdr->e_shnum; i++) {
if (shdr[i].sh_addr == 0 ||
shdr[i].sh_type == SHT_NOBITS)
continue;
/* Skip sections that were loaded already. */
if (lshdr != NULL &&
lshdr->sh_offset >= shdr[i].sh_offset)
continue;
/* Find section with smallest offset. */
if (cshdr == lshdr ||
cshdr->sh_offset > shdr[i].sh_offset)
cshdr = &shdr[i];
}
if (cshdr == lshdr)
break;
if (kern_pread(ef->fd, (vm_offset_t)cshdr->sh_addr,
cshdr->sh_size, (off_t)cshdr->sh_offset) != 0) {
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadimage: read failed\n");
goto out;
}
}
file_addmetadata(fp, MODINFOMD_SHDR, shdrbytes, shdr);
res = __elfN(obj_parse_modmetadata)(fp, ef);
if (res != 0)
goto out;
ret = lastaddr - firstaddr;
fp->f_addr = firstaddr;
printf("size 0x%lx at 0x%lx", (u_long)ret, (u_long)firstaddr);
out:
printf("\n");
return ret;
}
#if defined(__i386__) && __ELF_WORD_SIZE == 64
struct mod_metadata64 {
int md_version; /* structure version MDTV_* */
int md_type; /* type of entry MDT_* */
uint64_t md_data; /* specific data */
uint64_t md_cval; /* common string label */
};
#endif
int
__elfN(obj_parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
{
struct mod_metadata md;
#if defined(__i386__) && __ELF_WORD_SIZE == 64
struct mod_metadata64 md64;
#endif
struct mod_depend *mdepend;
struct mod_version mver;
char *s;
int error, modcnt, minfolen;
Elf_Addr v, p, p_stop;
if (__elfN(obj_lookup_set)(fp, ef, "modmetadata_set", &p, &p_stop,
&modcnt) != 0)
return 0;
modcnt = 0;
while (p < p_stop) {
COPYOUT(p, &v, sizeof(v));
error = __elfN(obj_reloc_ptr)(fp, ef, p, &v, sizeof(v));
if (error != 0)
return (error);
#if defined(__i386__) && __ELF_WORD_SIZE == 64
COPYOUT(v, &md64, sizeof(md64));
error = __elfN(obj_reloc_ptr)(fp, ef, v, &md64, sizeof(md64));
if (error != 0)
return (error);
md.md_version = md64.md_version;
md.md_type = md64.md_type;
md.md_cval = (const char *)(uintptr_t)md64.md_cval;
md.md_data = (void *)(uintptr_t)md64.md_data;
#else
COPYOUT(v, &md, sizeof(md));
error = __elfN(obj_reloc_ptr)(fp, ef, v, &md, sizeof(md));
if (error != 0)
return (error);
#endif
p += sizeof(Elf_Addr);
switch(md.md_type) {
case MDT_DEPEND:
s = strdupout((vm_offset_t)md.md_cval);
minfolen = sizeof(*mdepend) + strlen(s) + 1;
mdepend = malloc(minfolen);
if (mdepend == NULL)
return ENOMEM;
COPYOUT((vm_offset_t)md.md_data, mdepend,
sizeof(*mdepend));
strcpy((char*)(mdepend + 1), s);
free(s);
file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen,
mdepend);
free(mdepend);
break;
case MDT_VERSION:
s = strdupout((vm_offset_t)md.md_cval);
COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver));
file_addmodule(fp, s, mver.mv_version, NULL);
free(s);
modcnt++;
break;
case MDT_MODULE:
case MDT_PNP_INFO:
break;
default:
printf("unknown type %d\n", md.md_type);
break;
}
}
return 0;
}
static int
__elfN(obj_lookup_set)(struct preloaded_file *fp, elf_file_t ef,
const char* name, Elf_Addr *startp, Elf_Addr *stopp, int *countp)
{
Elf_Ehdr *hdr;
Elf_Shdr *shdr;
char *p;
vm_offset_t shstrtab;
int i;
hdr = &ef->hdr;
shdr = ef->e_shdr;
shstrtab = shdr[ef->shstrindex].sh_addr;
for (i = 0; i < hdr->e_shnum; i++) {
if (shdr[i].sh_type != SHT_PROGBITS)
continue;
if (shdr[i].sh_name == 0)
continue;
p = strdupout(shstrtab + shdr[i].sh_name);
if (strncmp(p, "set_", 4) == 0 && strcmp(p + 4, name) == 0) {
*startp = shdr[i].sh_addr;
*stopp = shdr[i].sh_addr + shdr[i].sh_size;
*countp = (*stopp - *startp) / sizeof(Elf_Addr);
free(p);
return (0);
}
free(p);
}
return (ESRCH);
}
/*
* Apply any intra-module relocations to the value. p is the load address
* of the value and val/len is the value to be modified. This does NOT modify
* the image in-place, because this is done by kern_linker later on.
*/
static int
__elfN(obj_reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p,
void *val, size_t len)
{
Elf_Ehdr *hdr;
Elf_Shdr *shdr;
Elf_Addr off = p;
Elf_Addr base;
Elf_Rela a, *abase;
Elf_Rel r, *rbase;
int error, i, j, nrel, nrela;
hdr = &ef->hdr;
shdr = ef->e_shdr;
for (i = 0; i < hdr->e_shnum; i++) {
if (shdr[i].sh_type != SHT_RELA && shdr[i].sh_type != SHT_REL)
continue;
base = shdr[shdr[i].sh_info].sh_addr;
if (base == 0 || shdr[i].sh_addr == 0)
continue;
if (off < base || off + len > base +
shdr[shdr[i].sh_info].sh_size)
continue;
switch (shdr[i].sh_type) {
case SHT_RELA:
abase = (Elf_Rela *)(intptr_t)shdr[i].sh_addr;
nrela = shdr[i].sh_size / sizeof(Elf_Rela);
for (j = 0; j < nrela; j++) {
COPYOUT(abase + j, &a, sizeof(a));
error = __elfN(reloc)(ef, __elfN(obj_symaddr),
&a, ELF_RELOC_RELA, base, off, val, len);
if (error != 0)
return (error);
}
break;
case SHT_REL:
rbase = (Elf_Rel *)(intptr_t)shdr[i].sh_addr;
nrel = shdr[i].sh_size / sizeof(Elf_Rel);
for (j = 0; j < nrel; j++) {
COPYOUT(rbase + j, &r, sizeof(r));
error = __elfN(reloc)(ef, __elfN(obj_symaddr),
&r, ELF_RELOC_REL, base, off, val, len);
if (error != 0)
return (error);
}
break;
}
}
return (0);
}
/* Look up the address of a specified symbol. */
static Elf_Addr
__elfN(obj_symaddr)(struct elf_file *ef, Elf_Size symidx)
{
Elf_Sym sym;
Elf_Addr base;
if (symidx >= ef->e_shdr[ef->symtabindex].sh_size / sizeof(Elf_Sym))
return (0);
COPYOUT(ef->e_shdr[ef->symtabindex].sh_addr + symidx * sizeof(Elf_Sym),
&sym, sizeof(sym));
if (sym.st_shndx == SHN_UNDEF || sym.st_shndx >= ef->hdr.e_shnum)
return (0);
base = ef->e_shdr[sym.st_shndx].sh_addr;
if (base == 0)
return (0);
return (base + sym.st_value);
}
Index: stable/12/stand/common/module.c
===================================================================
--- stable/12/stand/common/module.c (revision 346144)
+++ stable/12/stand/common/module.c (revision 346145)
@@ -1,1095 +1,1124 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* file/module function dispatcher, support, etc.
*/
#include <stand.h>
#include <string.h>
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/stdint.h>
#include "bootstrap.h"
#define MDIR_REMOVED 0x0001
#define MDIR_NOHINTS 0x0002
struct moduledir {
char *d_path; /* path of modules directory */
u_char *d_hints; /* content of linker.hints file */
int d_hintsz; /* size of hints data */
int d_flags;
STAILQ_ENTRY(moduledir) d_link;
};
static int file_load(char *filename, vm_offset_t dest, struct preloaded_file **result);
static int file_load_dependencies(struct preloaded_file *base_mod);
static char * file_search(const char *name, char **extlist);
static struct kernel_module * file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo);
static int file_havepath(const char *name);
static char *mod_searchmodule(char *name, struct mod_depend *verinfo);
static void file_insert_tail(struct preloaded_file *mp);
struct file_metadata* metadata_next(struct file_metadata *base_mp, int type);
static void moduledir_readhints(struct moduledir *mdp);
static void moduledir_rebuild(void);
/* load address should be tweaked by first module loaded (kernel) */
static vm_offset_t loadaddr = 0;
#if defined(LOADER_FDT_SUPPORT)
static const char *default_searchpath =
"/boot/kernel;/boot/modules;/boot/dtb";
#else
static const char *default_searchpath ="/boot/kernel;/boot/modules";
#endif
static STAILQ_HEAD(, moduledir) moduledir_list = STAILQ_HEAD_INITIALIZER(moduledir_list);
struct preloaded_file *preloaded_files = NULL;
static char *kld_ext_list[] = {
".ko",
"",
".debug",
NULL
};
/*
* load an object, either a disk file or code module.
*
* To load a file, the syntax is:
*
* load -t <type> <path>
*
* code modules are loaded as:
*
* load <path> <options>
*/
COMMAND_SET(load, "load", "load a kernel or module", command_load);
static int
command_load(int argc, char *argv[])
{
struct preloaded_file *fp;
char *typestr;
- int dofile, dokld, ch, error;
+ char *prefix;
+ char *skip;
+ int dflag, dofile, dokld, ch, error;
- dokld = dofile = 0;
+ dflag = dokld = dofile = 0;
optind = 1;
optreset = 1;
typestr = NULL;
if (argc == 1) {
command_errmsg = "no filename specified";
return (CMD_CRIT);
}
- while ((ch = getopt(argc, argv, "kt:")) != -1) {
+ prefix = skip = NULL;
+ while ((ch = getopt(argc, argv, "dkp:s:t:")) != -1) {
switch(ch) {
+ case 'd':
+ dflag++;
+ break;
case 'k':
dokld = 1;
break;
+ case 'p':
+ prefix = optarg;
+ break;
+ case 's':
+ skip = optarg;
+ break;
case 't':
typestr = optarg;
dofile = 1;
break;
case '?':
default:
/* getopt has already reported an error */
return (CMD_OK);
}
}
argv += (optind - 1);
argc -= (optind - 1);
/*
* Request to load a raw file?
*/
if (dofile) {
if ((argc != 2) || (typestr == NULL) || (*typestr == 0)) {
command_errmsg = "invalid load type";
return (CMD_CRIT);
}
+#ifdef LOADER_VERIEXEC
+ if (strncmp(typestr, "manifest", 8) == 0) {
+ if (dflag > 0)
+ ve_debug_set(dflag);
+ return (load_manifest(argv[1], prefix, skip, NULL));
+ }
+#endif
+
fp = file_findfile(argv[1], typestr);
if (fp) {
snprintf(command_errbuf, sizeof(command_errbuf),
"warning: file '%s' already loaded", argv[1]);
return (CMD_WARN);
}
if (file_loadraw(argv[1], typestr, 1) != NULL)
return (CMD_OK);
/* Failing to load mfs_root is never going to end well! */
if (strcmp("mfs_root", typestr) == 0)
return (CMD_FATAL);
return (CMD_ERROR);
}
/*
* Do we have explicit KLD load ?
*/
if (dokld || file_havepath(argv[1])) {
error = mod_loadkld(argv[1], argc - 2, argv + 2);
if (error == EEXIST) {
snprintf(command_errbuf, sizeof(command_errbuf),
"warning: KLD '%s' already loaded", argv[1]);
return (CMD_WARN);
}
return (error == 0 ? CMD_OK : CMD_CRIT);
}
/*
* Looks like a request for a module.
*/
error = mod_load(argv[1], NULL, argc - 2, argv + 2);
if (error == EEXIST) {
snprintf(command_errbuf, sizeof(command_errbuf),
"warning: module '%s' already loaded", argv[1]);
return (CMD_WARN);
}
return (error == 0 ? CMD_OK : CMD_CRIT);
}
#ifdef LOADER_GELI_SUPPORT
COMMAND_SET(load_geli, "load_geli", "load a geli key", command_load_geli);
static int
command_load_geli(int argc, char *argv[])
{
char typestr[80];
char *cp;
int ch, num;
if (argc < 3) {
command_errmsg = "usage is [-n key#] <prov> <file>";
return(CMD_ERROR);
}
num = 0;
optind = 1;
optreset = 1;
while ((ch = getopt(argc, argv, "n:")) != -1) {
switch(ch) {
case 'n':
num = strtol(optarg, &cp, 0);
if (cp == optarg) {
snprintf(command_errbuf, sizeof(command_errbuf),
"bad key index '%s'", optarg);
return(CMD_ERROR);
}
break;
case '?':
default:
/* getopt has already reported an error */
return(CMD_OK);
}
}
argv += (optind - 1);
argc -= (optind - 1);
sprintf(typestr, "%s:geli_keyfile%d", argv[1], num);
return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR);
}
#endif
void
unload(void)
{
struct preloaded_file *fp;
while (preloaded_files != NULL) {
fp = preloaded_files;
preloaded_files = preloaded_files->f_next;
file_discard(fp);
}
loadaddr = 0;
unsetenv("kernelname");
}
COMMAND_SET(unload, "unload", "unload all modules", command_unload);
static int
command_unload(int argc, char *argv[])
{
unload();
return(CMD_OK);
}
COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod);
static int
command_lsmod(int argc, char *argv[])
{
struct preloaded_file *fp;
struct kernel_module *mp;
struct file_metadata *md;
char lbuf[80];
int ch, verbose, ret = 0;
verbose = 0;
optind = 1;
optreset = 1;
while ((ch = getopt(argc, argv, "v")) != -1) {
switch(ch) {
case 'v':
verbose = 1;
break;
case '?':
default:
/* getopt has already reported an error */
return(CMD_OK);
}
}
pager_open();
for (fp = preloaded_files; fp; fp = fp->f_next) {
snprintf(lbuf, sizeof(lbuf), " %p: ", (void *) fp->f_addr);
pager_output(lbuf);
pager_output(fp->f_name);
snprintf(lbuf, sizeof(lbuf), " (%s, 0x%lx)\n", fp->f_type,
(long)fp->f_size);
if (pager_output(lbuf))
break;
if (fp->f_args != NULL) {
pager_output(" args: ");
pager_output(fp->f_args);
if (pager_output("\n"))
break;
}
if (fp->f_modules) {
pager_output(" modules: ");
for (mp = fp->f_modules; mp; mp = mp->m_next) {
snprintf(lbuf, sizeof(lbuf), "%s.%d ", mp->m_name,
mp->m_version);
pager_output(lbuf);
}
if (pager_output("\n"))
break;
}
if (verbose) {
/* XXX could add some formatting smarts here to display some better */
for (md = fp->f_metadata; md != NULL; md = md->md_next) {
snprintf(lbuf, sizeof(lbuf), " 0x%04x, 0x%lx\n",
md->md_type, (long) md->md_size);
if (pager_output(lbuf))
break;
}
}
if (ret)
break;
}
pager_close();
return(CMD_OK);
}
/*
* File level interface, functions file_*
*/
int
file_load(char *filename, vm_offset_t dest, struct preloaded_file **result)
{
static int last_file_format = 0;
struct preloaded_file *fp;
int error;
int i;
if (archsw.arch_loadaddr != NULL)
dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest);
error = EFTYPE;
for (i = last_file_format, fp = NULL;
file_formats[i] && fp == NULL; i++) {
error = (file_formats[i]->l_load)(filename, dest, &fp);
if (error == 0) {
fp->f_loader = last_file_format = i; /* remember the loader */
*result = fp;
break;
} else if (last_file_format == i && i != 0) {
/* Restart from the beginning */
i = -1;
last_file_format = 0;
fp = NULL;
continue;
}
if (error == EFTYPE)
continue; /* Unknown to this handler? */
if (error) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't load file '%s': %s", filename, strerror(error));
break;
}
}
return (error);
}
static int
file_load_dependencies(struct preloaded_file *base_file)
{
struct file_metadata *md;
struct preloaded_file *fp;
struct mod_depend *verinfo;
struct kernel_module *mp;
char *dmodname;
int error;
md = file_findmetadata(base_file, MODINFOMD_DEPLIST);
if (md == NULL)
return (0);
error = 0;
do {
verinfo = (struct mod_depend*)md->md_data;
dmodname = (char *)(verinfo + 1);
if (file_findmodule(NULL, dmodname, verinfo) == NULL) {
printf("loading required module '%s'\n", dmodname);
error = mod_load(dmodname, verinfo, 0, NULL);
if (error)
break;
/*
* If module loaded via kld name which isn't listed
* in the linker.hints file, we should check if it have
* required version.
*/
mp = file_findmodule(NULL, dmodname, verinfo);
if (mp == NULL) {
snprintf(command_errbuf, sizeof(command_errbuf),
"module '%s' exists but with wrong version", dmodname);
error = ENOENT;
break;
}
}
md = metadata_next(md, MODINFOMD_DEPLIST);
} while (md);
if (!error)
return (0);
/* Load failed; discard everything */
while (base_file != NULL) {
fp = base_file;
base_file = base_file->f_next;
file_discard(fp);
}
return (error);
}
/*
* We've been asked to load (fname) as (type), so just suck it in,
* no arguments or anything.
*/
struct preloaded_file *
file_loadraw(const char *fname, char *type, int insert)
{
struct preloaded_file *fp;
char *name;
int fd, got;
vm_offset_t laddr;
/* We can't load first */
if ((file_findfile(NULL, NULL)) == NULL) {
command_errmsg = "can't load file before kernel";
return(NULL);
}
/* locate the file on the load path */
name = file_search(fname, NULL);
if (name == NULL) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't find '%s'", fname);
return(NULL);
}
if ((fd = open(name, O_RDONLY)) < 0) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't open '%s': %s", name, strerror(errno));
free(name);
return(NULL);
}
+
+#ifdef LOADER_VERIEXEC
+ if (verify_file(fd, name, 0, VE_MUST) < 0) {
+ sprintf(command_errbuf, "can't verify '%s'", name);
+ free(name);
+ close(fd);
+ return(NULL);
+ }
+#endif
if (archsw.arch_loadaddr != NULL)
loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
printf("%s ", name);
laddr = loadaddr;
for (;;) {
/* read in 4k chunks; size is not really important */
got = archsw.arch_readin(fd, laddr, 4096);
if (got == 0) /* end of file */
break;
if (got < 0) { /* error */
snprintf(command_errbuf, sizeof(command_errbuf),
"error reading '%s': %s", name, strerror(errno));
free(name);
close(fd);
return(NULL);
}
laddr += got;
}
printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr));
/* Looks OK so far; create & populate control structure */
fp = file_alloc();
fp->f_name = strdup(name);
fp->f_type = strdup(type);
fp->f_args = NULL;
fp->f_metadata = NULL;
fp->f_loader = -1;
fp->f_addr = loadaddr;
fp->f_size = laddr - loadaddr;
/* recognise space consumption */
loadaddr = laddr;
/* Add to the list of loaded files */
if (insert != 0)
file_insert_tail(fp);
close(fd);
return(fp);
}
/*
* Load the module (name), pass it (argc),(argv), add container file
* to the list of loaded files.
* If module is already loaded just assign new argc/argv.
*/
int
mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[])
{
struct kernel_module *mp;
int err;
char *filename;
if (file_havepath(modname)) {
printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname);
return (mod_loadkld(modname, argc, argv));
}
/* see if module is already loaded */
mp = file_findmodule(NULL, modname, verinfo);
if (mp) {
#ifdef moduleargs
if (mp->m_args)
free(mp->m_args);
mp->m_args = unargv(argc, argv);
#endif
snprintf(command_errbuf, sizeof(command_errbuf),
"warning: module '%s' already loaded", mp->m_name);
return (0);
}
/* locate file with the module on the search path */
filename = mod_searchmodule(modname, verinfo);
if (filename == NULL) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't find '%s'", modname);
return (ENOENT);
}
err = mod_loadkld(filename, argc, argv);
return (err);
}
/*
* Load specified KLD. If path is omitted, then try to locate it via
* search path.
*/
int
mod_loadkld(const char *kldname, int argc, char *argv[])
{
struct preloaded_file *fp, *last_file;
int err;
char *filename;
/*
* Get fully qualified KLD name
*/
filename = file_search(kldname, kld_ext_list);
if (filename == NULL) {
snprintf(command_errbuf, sizeof(command_errbuf),
"can't find '%s'", kldname);
return (ENOENT);
}
/*
* Check if KLD already loaded
*/
fp = file_findfile(filename, NULL);
if (fp) {
snprintf(command_errbuf, sizeof(command_errbuf),
"warning: KLD '%s' already loaded", filename);
free(filename);
return (0);
}
for (last_file = preloaded_files;
last_file != NULL && last_file->f_next != NULL;
last_file = last_file->f_next)
;
do {
err = file_load(filename, loadaddr, &fp);
if (err)
break;
fp->f_args = unargv(argc, argv);
loadaddr = fp->f_addr + fp->f_size;
file_insert_tail(fp); /* Add to the list of loaded files */
if (file_load_dependencies(fp) != 0) {
err = ENOENT;
last_file->f_next = NULL;
loadaddr = last_file->f_addr + last_file->f_size;
fp = NULL;
break;
}
} while(0);
if (err == EFTYPE) {
snprintf(command_errbuf, sizeof(command_errbuf),
"don't know how to load module '%s'", filename);
}
if (err && fp)
file_discard(fp);
free(filename);
return (err);
}
/*
* Find a file matching (name) and (type).
* NULL may be passed as a wildcard to either.
*/
struct preloaded_file *
file_findfile(const char *name, const char *type)
{
struct preloaded_file *fp;
for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
if (((name == NULL) || !strcmp(name, fp->f_name)) &&
((type == NULL) || !strcmp(type, fp->f_type)))
break;
}
return (fp);
}
/*
* Find a module matching (name) inside of given file.
* NULL may be passed as a wildcard.
*/
struct kernel_module *
file_findmodule(struct preloaded_file *fp, char *modname,
struct mod_depend *verinfo)
{
struct kernel_module *mp, *best;
int bestver, mver;
if (fp == NULL) {
for (fp = preloaded_files; fp; fp = fp->f_next) {
mp = file_findmodule(fp, modname, verinfo);
if (mp)
return (mp);
}
return (NULL);
}
best = NULL;
bestver = 0;
for (mp = fp->f_modules; mp; mp = mp->m_next) {
if (strcmp(modname, mp->m_name) == 0) {
if (verinfo == NULL)
return (mp);
mver = mp->m_version;
if (mver == verinfo->md_ver_preferred)
return (mp);
if (mver >= verinfo->md_ver_minimum &&
mver <= verinfo->md_ver_maximum &&
mver > bestver) {
best = mp;
bestver = mver;
}
}
}
return (best);
}
/*
* Make a copy of (size) bytes of data from (p), and associate them as
* metadata of (type) to the module (mp).
*/
void
file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p)
{
struct file_metadata *md;
md = malloc(sizeof(struct file_metadata) - sizeof(md->md_data) + size);
md->md_size = size;
md->md_type = type;
bcopy(p, md->md_data, size);
md->md_next = fp->f_metadata;
fp->f_metadata = md;
}
/*
* Find a metadata object of (type) associated with the file (fp)
*/
struct file_metadata *
file_findmetadata(struct preloaded_file *fp, int type)
{
struct file_metadata *md;
for (md = fp->f_metadata; md != NULL; md = md->md_next)
if (md->md_type == type)
break;
return(md);
}
/*
* Remove all metadata from the file.
*/
void
file_removemetadata(struct preloaded_file *fp)
{
struct file_metadata *md, *next;
for (md = fp->f_metadata; md != NULL; md = next)
{
next = md->md_next;
free(md);
}
fp->f_metadata = NULL;
}
struct file_metadata *
metadata_next(struct file_metadata *md, int type)
{
if (md == NULL)
return (NULL);
while((md = md->md_next) != NULL)
if (md->md_type == type)
break;
return (md);
}
static char *emptyextlist[] = { "", NULL };
/*
* Check if the given file is in place and return full path to it.
*/
static char *
file_lookup(const char *path, const char *name, int namelen, char **extlist)
{
struct stat st;
char *result, *cp, **cpp;
int pathlen, extlen, len;
pathlen = strlen(path);
extlen = 0;
if (extlist == NULL)
extlist = emptyextlist;
for (cpp = extlist; *cpp; cpp++) {
len = strlen(*cpp);
if (len > extlen)
extlen = len;
}
result = malloc(pathlen + namelen + extlen + 2);
if (result == NULL)
return (NULL);
bcopy(path, result, pathlen);
if (pathlen > 0 && result[pathlen - 1] != '/')
result[pathlen++] = '/';
cp = result + pathlen;
bcopy(name, cp, namelen);
cp += namelen;
for (cpp = extlist; *cpp; cpp++) {
strcpy(cp, *cpp);
if (stat(result, &st) == 0 && S_ISREG(st.st_mode))
return result;
}
free(result);
return NULL;
}
/*
* Check if file name have any qualifiers
*/
static int
file_havepath(const char *name)
{
const char *cp;
archsw.arch_getdev(NULL, name, &cp);
return (cp != name || strchr(name, '/') != NULL);
}
/*
* Attempt to find the file (name) on the module searchpath.
* If (name) is qualified in any way, we simply check it and
* return it or NULL. If it is not qualified, then we attempt
* to construct a path using entries in the environment variable
* module_path.
*
* The path we return a pointer to need never be freed, as we manage
* it internally.
*/
static char *
file_search(const char *name, char **extlist)
{
struct moduledir *mdp;
struct stat sb;
char *result;
int namelen;
/* Don't look for nothing */
if (name == NULL)
return(NULL);
if (*name == 0)
return(strdup(name));
if (file_havepath(name)) {
/* Qualified, so just see if it exists */
if (stat(name, &sb) == 0)
return(strdup(name));
return(NULL);
}
moduledir_rebuild();
result = NULL;
namelen = strlen(name);
STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
result = file_lookup(mdp->d_path, name, namelen, extlist);
if (result)
break;
}
return(result);
}
#define INT_ALIGN(base, ptr) ptr = \
(base) + roundup2((ptr) - (base), sizeof(int))
static char *
mod_search_hints(struct moduledir *mdp, const char *modname,
struct mod_depend *verinfo)
{
u_char *cp, *recptr, *bufend, *best;
char *result;
int *intp, bestver, blen, clen, found, ival, modnamelen, reclen;
moduledir_readhints(mdp);
modnamelen = strlen(modname);
found = 0;
result = NULL;
bestver = 0;
if (mdp->d_hints == NULL)
goto bad;
recptr = mdp->d_hints;
bufend = recptr + mdp->d_hintsz;
clen = blen = 0;
best = cp = NULL;
while (recptr < bufend && !found) {
intp = (int*)recptr;
reclen = *intp++;
ival = *intp++;
cp = (u_char*)intp;
switch (ival) {
case MDT_VERSION:
clen = *cp++;
if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
break;
cp += clen;
INT_ALIGN(mdp->d_hints, cp);
ival = *(int*)cp;
cp += sizeof(int);
clen = *cp++;
if (verinfo == NULL || ival == verinfo->md_ver_preferred) {
found = 1;
break;
}
if (ival >= verinfo->md_ver_minimum &&
ival <= verinfo->md_ver_maximum &&
ival > bestver) {
bestver = ival;
best = cp;
blen = clen;
}
break;
default:
break;
}
recptr += reclen + sizeof(int);
}
/*
* Finally check if KLD is in the place
*/
if (found)
result = file_lookup(mdp->d_path, (const char *)cp, clen, NULL);
else if (best)
result = file_lookup(mdp->d_path, (const char *)best, blen, NULL);
bad:
/*
* If nothing found or hints is absent - fallback to the old way
* by using "kldname[.ko]" as module name.
*/
if (!found && !bestver && result == NULL)
result = file_lookup(mdp->d_path, modname, modnamelen, kld_ext_list);
return result;
}
/*
* Attempt to locate the file containing the module (name)
*/
static char *
mod_searchmodule(char *name, struct mod_depend *verinfo)
{
struct moduledir *mdp;
char *result;
moduledir_rebuild();
/*
* Now we ready to lookup module in the given directories
*/
result = NULL;
STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
result = mod_search_hints(mdp, name, verinfo);
if (result)
break;
}
return(result);
}
int
file_addmodule(struct preloaded_file *fp, char *modname, int version,
struct kernel_module **newmp)
{
struct kernel_module *mp;
struct mod_depend mdepend;
bzero(&mdepend, sizeof(mdepend));
mdepend.md_ver_preferred = version;
mp = file_findmodule(fp, modname, &mdepend);
if (mp)
return (EEXIST);
mp = malloc(sizeof(struct kernel_module));
if (mp == NULL)
return (ENOMEM);
bzero(mp, sizeof(struct kernel_module));
mp->m_name = strdup(modname);
mp->m_version = version;
mp->m_fp = fp;
mp->m_next = fp->f_modules;
fp->f_modules = mp;
if (newmp)
*newmp = mp;
return (0);
}
/*
* Throw a file away
*/
void
file_discard(struct preloaded_file *fp)
{
struct file_metadata *md, *md1;
struct kernel_module *mp, *mp1;
if (fp == NULL)
return;
md = fp->f_metadata;
while (md) {
md1 = md;
md = md->md_next;
free(md1);
}
mp = fp->f_modules;
while (mp) {
if (mp->m_name)
free(mp->m_name);
mp1 = mp;
mp = mp->m_next;
free(mp1);
}
if (fp->f_name != NULL)
free(fp->f_name);
if (fp->f_type != NULL)
free(fp->f_type);
if (fp->f_args != NULL)
free(fp->f_args);
free(fp);
}
/*
* Allocate a new file; must be used instead of malloc()
* to ensure safe initialisation.
*/
struct preloaded_file *
file_alloc(void)
{
struct preloaded_file *fp;
if ((fp = malloc(sizeof(struct preloaded_file))) != NULL) {
bzero(fp, sizeof(struct preloaded_file));
}
return (fp);
}
/*
* Add a module to the chain
*/
static void
file_insert_tail(struct preloaded_file *fp)
{
struct preloaded_file *cm;
/* Append to list of loaded file */
fp->f_next = NULL;
if (preloaded_files == NULL) {
preloaded_files = fp;
} else {
for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
;
cm->f_next = fp;
}
}
static char *
moduledir_fullpath(struct moduledir *mdp, const char *fname)
{
char *cp;
cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2);
if (cp == NULL)
return NULL;
strcpy(cp, mdp->d_path);
strcat(cp, "/");
strcat(cp, fname);
return (cp);
}
/*
* Read linker.hints file into memory performing some sanity checks.
*/
static void
moduledir_readhints(struct moduledir *mdp)
{
struct stat st;
char *path;
int fd, size, version;
if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS))
return;
path = moduledir_fullpath(mdp, "linker.hints");
if (stat(path, &st) != 0 ||
st.st_size < (ssize_t)(sizeof(version) + sizeof(int)) ||
st.st_size > LINKER_HINTS_MAX || (fd = open(path, O_RDONLY)) < 0) {
free(path);
mdp->d_flags |= MDIR_NOHINTS;
return;
}
free(path);
size = read(fd, &version, sizeof(version));
if (size != sizeof(version) || version != LINKER_HINTS_VERSION)
goto bad;
size = st.st_size - size;
mdp->d_hints = malloc(size);
if (mdp->d_hints == NULL)
goto bad;
if (read(fd, mdp->d_hints, size) != size)
goto bad;
mdp->d_hintsz = size;
close(fd);
return;
bad:
close(fd);
if (mdp->d_hints) {
free(mdp->d_hints);
mdp->d_hints = NULL;
}
mdp->d_flags |= MDIR_NOHINTS;
return;
}
/*
* Extract directories from the ';' separated list, remove duplicates.
*/
static void
moduledir_rebuild(void)
{
struct moduledir *mdp, *mtmp;
const char *path, *cp, *ep;
size_t cplen;
path = getenv("module_path");
if (path == NULL)
path = default_searchpath;
/*
* Rebuild list of module directories if it changed
*/
STAILQ_FOREACH(mdp, &moduledir_list, d_link)
mdp->d_flags |= MDIR_REMOVED;
for (ep = path; *ep != 0; ep++) {
cp = ep;
for (; *ep != 0 && *ep != ';'; ep++)
;
/*
* Ignore trailing slashes
*/
for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; cplen--)
;
STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
if (strlen(mdp->d_path) != cplen || bcmp(cp, mdp->d_path, cplen) != 0)
continue;
mdp->d_flags &= ~MDIR_REMOVED;
break;
}
if (mdp == NULL) {
mdp = malloc(sizeof(*mdp) + cplen + 1);
if (mdp == NULL)
return;
mdp->d_path = (char*)(mdp + 1);
bcopy(cp, mdp->d_path, cplen);
mdp->d_path[cplen] = 0;
mdp->d_hints = NULL;
mdp->d_flags = 0;
STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link);
}
if (*ep == 0)
break;
}
/*
* Delete unused directories if any
*/
mdp = STAILQ_FIRST(&moduledir_list);
while (mdp) {
if ((mdp->d_flags & MDIR_REMOVED) == 0) {
mdp = STAILQ_NEXT(mdp, d_link);
} else {
if (mdp->d_hints)
free(mdp->d_hints);
mtmp = mdp;
mdp = STAILQ_NEXT(mdp, d_link);
STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link);
free(mtmp);
}
}
return;
}
Index: stable/12/stand/ficl/Makefile.depend
===================================================================
--- stable/12/stand/ficl/Makefile.depend (revision 346144)
+++ stable/12/stand/ficl/Makefile.depend (revision 346145)
@@ -1,14 +1,12 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- include \
- include/xlocale \
- lib/msun \
+ stand/libsa \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif
Index: stable/12/stand/ficl/ficl.h
===================================================================
--- stable/12/stand/ficl/ficl.h (revision 346144)
+++ stable/12/stand/ficl/ficl.h (revision 346145)
@@ -1,1164 +1,1168 @@
/*******************************************************************
** f i c l . h
** Forth Inspired Command Language
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 19 July 1997
** Dedicated to RHS, in loving memory
** $Id: ficl.h,v 1.18 2001/12/05 07:21:34 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
** All rights reserved.
**
** Get the latest Ficl release at http://ficl.sourceforge.net
**
** I am interested in hearing from anyone who uses ficl. If you have
** a problem, a success story, a defect, an enhancement request, or
** if you would like to contribute to the ficl release, please
** contact me by email at the address above.
**
** L I C E N S E and D I S C L A I M E R
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
*/
/* $FreeBSD$ */
#if !defined (__FICL_H__)
#define __FICL_H__
/*
** Ficl (Forth-inspired command language) is an ANS Forth
** interpreter written in C. Unlike traditional Forths, this
** interpreter is designed to be embedded into other systems
** as a command/macro/development prototype language.
**
** Where Forths usually view themselves as the center of the system
** and expect the rest of the system to be coded in Forth, Ficl
** acts as a component of the system. It is easy to export
** code written in C or ASM to Ficl in the style of TCL, or to invoke
** Ficl code from a compiled module. This allows you to do incremental
** development in a way that combines the best features of threaded
** languages (rapid development, quick code/test/debug cycle,
** reasonably fast) with the best features of C (everyone knows it,
** easier to support large blocks of code, efficient, type checking).
**
** Ficl provides facilities for interoperating
** with programs written in C: C functions can be exported to Ficl,
** and Ficl commands can be executed via a C calling interface. The
** interpreter is re-entrant, so it can be used in multiple instances
** in a multitasking system. Unlike Forth, Ficl's outer interpreter
** expects a text block as input, and returns to the caller after each
** text block, so the "data pump" is somewhere in external code. This
** is more like TCL than Forth, which usually expcets to be at the center
** of the system, requesting input at its convenience. Each Ficl virtual
** machine can be bound to a different I/O channel, and is independent
** of all others in in the same address space except that all virtual
** machines share a common dictionary (a sort or open symbol table that
** defines all of the elements of the language).
**
** Code is written in ANSI C for portability.
**
** Summary of Ficl features and constraints:
** - Standard: Implements the ANSI Forth CORE word set and part
** of the CORE EXT word-set, SEARCH and SEARCH EXT, TOOLS and
** TOOLS EXT, LOCAL and LOCAL ext and various extras.
** - Extensible: you can export code written in Forth, C,
** or asm in a straightforward way. Ficl provides open
** facilities for extending the language in an application
** specific way. You can even add new control structures!
** - Ficl and C can interact in two ways: Ficl can encapsulate
** C code, or C code can invoke Ficl code.
** - Thread-safe, re-entrant: The shared system dictionary
** uses a locking mechanism that you can either supply
** or stub out to provide exclusive access. Each Ficl
** virtual machine has an otherwise complete state, and
** each can be bound to a separate I/O channel (or none at all).
** - Simple encapsulation into existing systems: a basic implementation
** requires three function calls (see the example program in testmain.c).
** - ROMable: Ficl is designed to work in RAM-based and ROM code / RAM data
** environments. It does require somewhat more memory than a pure
** ROM implementation because it builds its system dictionary in
** RAM at startup time.
** - Written an ANSI C to be as simple as I can make it to understand,
** support, debug, and port. Compiles without complaint at /Az /W4
** (require ANSI C, max warnings) under Microsoft VC++ 5.
** - Does full 32 bit math (but you need to implement
** two mixed precision math primitives (see sysdep.c))
** - Indirect threaded interpreter is not the fastest kind of
** Forth there is (see pForth 68K for a really fast subroutine
** threaded interpreter), but it's the cleanest match to a
** pure C implementation.
**
** P O R T I N G F i c l
**
** To install Ficl on your target system, you need an ANSI C compiler
** and its runtime library. Inspect the system dependent macros and
** functions in sysdep.h and sysdep.c and edit them to suit your
** system. For example, INT16 is a short on some compilers and an
** int on others. Check the default CELL alignment controlled by
** FICL_ALIGN. If necessary, add new definitions of ficlMalloc, ficlFree,
** ficlLockDictionary, and ficlTextOut to work with your operating system.
** Finally, use testmain.c as a guide to installing the Ficl system and
** one or more virtual machines into your code. You do not need to include
** testmain.c in your build.
**
** T o D o L i s t
**
** 1. Unimplemented system dependent CORE word: key
** 2. Ficl uses the PAD in some CORE words - this violates the standard,
** but it's cleaner for a multithreaded system. I'll have to make a
** second pad for reference by the word PAD to fix this.
**
** F o r M o r e I n f o r m a t i o n
**
** Web home of ficl
** http://ficl.sourceforge.net
** Check this website for Forth literature (including the ANSI standard)
** http://www.taygeta.com/forthlit.html
** and here for software and more links
** http://www.taygeta.com/forth.html
**
** Obvious Performance enhancement opportunities
** Compile speed
** - work on interpret speed
** - turn off locals (FICL_WANT_LOCALS)
** Interpret speed
** - Change inner interpreter (and everything else)
** so that a definition is a list of pointers to functions
** and inline data rather than pointers to words. This gets
** rid of vm->runningWord and a level of indirection in the
** inner loop. I'll look at it for ficl 3.0
** - Make the main hash table a bigger prime (HASHSIZE)
** - FORGET about twiddling the hash function - my experience is
** that that is a waste of time.
** - Eliminate the need to pass the pVM parameter on the stack
** by dedicating a register to it. Most words need access to the
** vm, but the parameter passing overhead can be reduced. One way
** requires that the host OS have a task switch callout. Create
** a global variable for the running VM and refer to it in words
** that need VM access. Alternative: use thread local storage.
** For single threaded implementations, you can just use a global.
** The first two solutions create portability problems, so I
** haven't considered doing them. Another possibility is to
** declare the pVm parameter to be "register", and hope the compiler
** pays attention.
**
*/
/*
** Revision History:
**
** 15 Apr 1999 (sadler) Merged FreeBSD changes for exception wordset and
** counted strings in ficlExec.
** 12 Jan 1999 (sobral) Corrected EVALUATE behavior. Now TIB has an
** "end" field, and all words respect this. ficlExec is passed a "size"
** of TIB, as well as vmPushTib. This size is used to calculate the "end"
** of the string, ie, base+size. If the size is not known, pass -1.
**
** 10 Jan 1999 (sobral) EXCEPTION word set has been added, and existing
** words has been modified to conform to EXCEPTION EXT word set.
**
** 27 Aug 1998 (sadler) testing and corrections for LOCALS, LOCALS EXT,
** SEARCH / SEARCH EXT, TOOLS / TOOLS EXT.
** Added .X to display in hex, PARSE and PARSE-WORD to supplement WORD,
** EMPTY to clear stack.
**
** 29 jun 1998 (sadler) added variable sized hash table support
** and ANS Forth optional SEARCH & SEARCH EXT word set.
** 26 May 1998 (sadler)
** FICL_PROMPT macro
** 14 April 1998 (sadler) V1.04
** Ficlwin: Windows version, Skip Carter's Linux port
** 5 March 1998 (sadler) V1.03
** Bug fixes -- passes John Ryan's ANS test suite "core.fr"
**
** 24 February 1998 (sadler) V1.02
** -Fixed bugs in <# # #>
** -Changed FICL_WORD so that storage for the name characters
** can be allocated from the dictionary as needed rather than
** reserving 32 bytes in each word whether needed or not -
** this saved 50% of the dictionary storage requirement.
** -Added words in testmain for Win32 functions system,chdir,cwd,
** also added a word that loads and evaluates a file.
**
** December 1997 (sadler)
** -Added VM_RESTART exception handling in ficlExec -- this lets words
** that require additional text to succeed (like :, create, variable...)
** recover gracefully from an empty input buffer rather than emitting
** an error message. Definitions can span multiple input blocks with
** no restrictions.
** -Changed #include order so that <assert.h> is included in sysdep.h,
** and sysdep is included in all other files. This lets you define
** NDEBUG in sysdep.h to disable assertions if you want to.
** -Make PC specific system dependent code conditional on _M_IX86
** defined so that ports can coexist in sysdep.h/sysdep.c
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "sysdep.h"
#include <limits.h> /* UCHAR_MAX */
/*
** Forward declarations... read on.
*/
struct ficl_word;
typedef struct ficl_word FICL_WORD;
struct vm;
typedef struct vm FICL_VM;
struct ficl_dict;
typedef struct ficl_dict FICL_DICT;
struct ficl_system;
typedef struct ficl_system FICL_SYSTEM;
struct ficl_system_info;
typedef struct ficl_system_info FICL_SYSTEM_INFO;
/*
** the Good Stuff starts here...
*/
#define FICL_VER "3.03"
#define FICL_VER_MAJOR 3
#define FICL_VER_MINOR 3
#if !defined (FICL_PROMPT)
#define FICL_PROMPT "ok> "
#endif
/*
** ANS Forth requires false to be zero, and true to be the ones
** complement of false... that unifies logical and bitwise operations
** nicely.
*/
#define FICL_TRUE ((unsigned long)~(0L))
#define FICL_FALSE (0)
#define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE)
/*
** A CELL is the main storage type. It must be large enough
** to contain a pointer or a scalar. In order to accommodate
** 32 bit and 64 bit processors, use abstract types for int,
** unsigned, and float.
*/
typedef union _cell
{
FICL_INT i;
FICL_UNS u;
#if (FICL_WANT_FLOAT)
FICL_FLOAT f;
#endif
void *p;
void (*fn)(void);
} CELL;
/*
** LVALUEtoCELL does a little pointer trickery to cast any CELL sized
** lvalue (informal definition: an expression whose result has an
** address) to CELL. Remember that constants and casts are NOT
** themselves lvalues!
*/
#define LVALUEtoCELL(v) (*(CELL *)&v)
/*
** PTRtoCELL is a cast through void * intended to satisfy the
** most outrageously pedantic compiler... (I won't mention
** its name)
*/
#define PTRtoCELL (CELL *)(void *)
#define PTRtoSTRING (FICL_STRING *)(void *)
/*
** Strings in FICL are stored in Pascal style - with a count
** preceding the text. We'll also NULL-terminate them so that
** they work with the usual C lib string functions. (Belt &
** suspenders? You decide.)
** STRINGINFO hides the implementation with a couple of
** macros for use in internal routines.
*/
typedef unsigned char FICL_COUNT;
#define FICL_STRING_MAX UCHAR_MAX
typedef struct _ficl_string
{
FICL_COUNT count;
char text[1];
} FICL_STRING;
typedef struct
{
FICL_UNS count;
char *cp;
} STRINGINFO;
#define SI_COUNT(si) (si.count)
#define SI_PTR(si) (si.cp)
#define SI_SETLEN(si, len) (si.count = (FICL_UNS)(len))
#define SI_SETPTR(si, ptr) (si.cp = (char *)(ptr))
/*
** Init a STRINGINFO from a pointer to NULL-terminated string
*/
#define SI_PSZ(si, psz) \
{si.cp = psz; si.count = (FICL_COUNT)strlen(psz);}
/*
** Init a STRINGINFO from a pointer to FICL_STRING
*/
#define SI_PFS(si, pfs) \
{si.cp = pfs->text; si.count = pfs->count;}
/*
** Ficl uses this little structure to hold the address of
** the block of text it's working on and an index to the next
** unconsumed character in the string. Traditionally, this is
** done by a Text Input Buffer, so I've called this struct TIB.
**
** Since this structure also holds the size of the input buffer,
** and since evaluate requires that, let's put the size here.
** The size is stored as an end-pointer because that is what the
** null-terminated string aware functions find most easy to deal
** with.
** Notice, though, that nobody really uses this except evaluate,
** so it might just be moved to FICL_VM instead. (sobral)
*/
typedef struct
{
FICL_INT index;
char *end;
char *cp;
} TIB;
/*
** Stacks get heavy use in Ficl and Forth...
** Each virtual machine implements two of them:
** one holds parameters (data), and the other holds return
** addresses and control flow information for the virtual
** machine. (Note: C's automatic stack is implicitly used,
** but not modeled because it doesn't need to be...)
** Here's an abstract type for a stack
*/
typedef struct _ficlStack
{
FICL_UNS nCells; /* size of the stack */
CELL *pFrame; /* link reg for stack frame */
CELL *sp; /* stack pointer */
CELL base[1]; /* Top of stack */
} FICL_STACK;
/*
** Stack methods... many map closely to required Forth words.
*/
FICL_STACK *stackCreate (unsigned nCells);
void stackDelete (FICL_STACK *pStack);
int stackDepth (FICL_STACK *pStack);
void stackDrop (FICL_STACK *pStack, int n);
CELL stackFetch (FICL_STACK *pStack, int n);
CELL stackGetTop (FICL_STACK *pStack);
void stackLink (FICL_STACK *pStack, int nCells);
void stackPick (FICL_STACK *pStack, int n);
CELL stackPop (FICL_STACK *pStack);
void *stackPopPtr (FICL_STACK *pStack);
FICL_UNS stackPopUNS (FICL_STACK *pStack);
FICL_INT stackPopINT (FICL_STACK *pStack);
void stackPush (FICL_STACK *pStack, CELL c);
void stackPushPtr (FICL_STACK *pStack, void *ptr);
void stackPushUNS (FICL_STACK *pStack, FICL_UNS u);
void stackPushINT (FICL_STACK *pStack, FICL_INT i);
void stackReset (FICL_STACK *pStack);
void stackRoll (FICL_STACK *pStack, int n);
void stackSetTop (FICL_STACK *pStack, CELL c);
void stackStore (FICL_STACK *pStack, int n, CELL c);
void stackUnlink (FICL_STACK *pStack);
#if (FICL_WANT_FLOAT)
float stackPopFloat (FICL_STACK *pStack);
void stackPushFloat(FICL_STACK *pStack, FICL_FLOAT f);
#endif
/*
** Shortcuts (Guy Carver)
*/
#define PUSHPTR(p) stackPushPtr(pVM->pStack,p)
#define PUSHUNS(u) stackPushUNS(pVM->pStack,u)
#define PUSHINT(i) stackPushINT(pVM->pStack,i)
#define PUSHFLOAT(f) stackPushFloat(pVM->fStack,f)
#define PUSH(c) stackPush(pVM->pStack,c)
#define POPPTR() stackPopPtr(pVM->pStack)
#define POPUNS() stackPopUNS(pVM->pStack)
#define POPINT() stackPopINT(pVM->pStack)
#define POPFLOAT() stackPopFloat(pVM->fStack)
#define POP() stackPop(pVM->pStack)
#define GETTOP() stackGetTop(pVM->pStack)
#define SETTOP(c) stackSetTop(pVM->pStack,LVALUEtoCELL(c))
#define GETTOPF() stackGetTop(pVM->fStack)
#define SETTOPF(c) stackSetTop(pVM->fStack,LVALUEtoCELL(c))
#define STORE(n,c) stackStore(pVM->pStack,n,LVALUEtoCELL(c))
#define DEPTH() stackDepth(pVM->pStack)
#define DROP(n) stackDrop(pVM->pStack,n)
#define DROPF(n) stackDrop(pVM->fStack,n)
#define FETCH(n) stackFetch(pVM->pStack,n)
#define PICK(n) stackPick(pVM->pStack,n)
#define PICKF(n) stackPick(pVM->fStack,n)
#define ROLL(n) stackRoll(pVM->pStack,n)
#define ROLLF(n) stackRoll(pVM->fStack,n)
/*
** The virtual machine (VM) contains the state for one interpreter.
** Defined operations include:
** Create & initialize
** Delete
** Execute a block of text
** Parse a word out of the input stream
** Call return, and branch
** Text output
** Throw an exception
*/
typedef FICL_WORD ** IPTYPE; /* the VM's instruction pointer */
/*
** Each VM has a placeholder for an output function -
** this makes it possible to have each VM do I/O
** through a different device. If you specify no
** OUTFUNC, it defaults to ficlTextOut.
*/
typedef void (*OUTFUNC)(FICL_VM *pVM, char *text, int fNewline);
/*
** Each VM operates in one of two non-error states: interpreting
** or compiling. When interpreting, words are simply executed.
** When compiling, most words in the input stream have their
** addresses inserted into the word under construction. Some words
** (known as IMMEDIATE) are executed in the compile state, too.
*/
/* values of STATE */
#define INTERPRET 0
#define COMPILE 1
/*
** The pad is a small scratch area for text manipulation. ANS Forth
** requires it to hold at least 84 characters.
*/
#if !defined nPAD
#define nPAD 256
#endif
/*
** ANS Forth requires that a word's name contain {1..31} characters.
*/
#if !defined nFICLNAME
#define nFICLNAME 31
#endif
/*
** OK - now we can really define the VM...
*/
struct vm
{
FICL_SYSTEM *pSys; /* Which system this VM belongs to */
FICL_VM *link; /* Ficl keeps a VM list for simple teardown */
jmp_buf *pState; /* crude exception mechanism... */
OUTFUNC textOut; /* Output callback - see sysdep.c */
void * pExtend; /* vm extension pointer for app use - initialized from FICL_SYSTEM */
short fRestart; /* Set TRUE to restart runningWord */
IPTYPE ip; /* instruction pointer */
FICL_WORD *runningWord;/* address of currently running word (often just *(ip-1) ) */
FICL_UNS state; /* compiling or interpreting */
FICL_UNS base; /* number conversion base */
FICL_STACK *pStack; /* param stack */
FICL_STACK *rStack; /* return stack */
#if FICL_WANT_FLOAT
FICL_STACK *fStack; /* float stack (optional) */
#endif
CELL sourceID; /* -1 if EVALUATE, 0 if normal input */
TIB tib; /* address of incoming text string */
#if FICL_WANT_USER
CELL user[FICL_USER_CELLS];
#endif
char pad[nPAD]; /* the scratch area (see above) */
};
/*
** A FICL_CODE points to a function that gets called to help execute
** a word in the dictionary. It always gets passed a pointer to the
** running virtual machine, and from there it can get the address
** of the parameter area of the word it's supposed to operate on.
** For precompiled words, the code is all there is. For user defined
** words, the code assumes that the word's parameter area is a list
** of pointers to the code fields of other words to execute, and
** may also contain inline data. The first parameter is always
** a pointer to a code field.
*/
typedef void (*FICL_CODE)(FICL_VM *pVm);
#if 0
#define VM_ASSERT(pVM) assert((*(pVM->ip - 1)) == pVM->runningWord)
#else
#define VM_ASSERT(pVM)
#endif
/*
** Ficl models memory as a contiguous space divided into
** words in a linked list called the dictionary.
** A FICL_WORD starts each entry in the list.
** Version 1.02: space for the name characters is allotted from
** the dictionary ahead of the word struct, rather than using
** a fixed size array for each name.
*/
struct ficl_word
{
struct ficl_word *link; /* Previous word in the dictionary */
UNS16 hash;
UNS8 flags; /* Immediate, Smudge, Compile-only */
FICL_COUNT nName; /* Number of chars in word name */
char *name; /* First nFICLNAME chars of word name */
FICL_CODE code; /* Native code to execute the word */
CELL param[1]; /* First data cell of the word */
};
/*
** Worst-case size of a word header: nFICLNAME chars in name
*/
#define CELLS_PER_WORD \
( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \
/ (sizeof (CELL)) )
int wordIsImmediate(FICL_WORD *pFW);
int wordIsCompileOnly(FICL_WORD *pFW);
/* flag values for word header */
#define FW_IMMEDIATE 1 /* execute me even if compiling */
#define FW_COMPILE 2 /* error if executed when not compiling */
#define FW_SMUDGE 4 /* definition in progress - hide me */
#define FW_ISOBJECT 8 /* word is an object or object member variable */
#define FW_COMPIMMED (FW_IMMEDIATE | FW_COMPILE)
#define FW_DEFAULT 0
/*
** Exit codes for vmThrow
*/
#define VM_INNEREXIT -256 /* tell ficlExecXT to exit inner loop */
#define VM_OUTOFTEXT -257 /* hungry - normal exit */
#define VM_RESTART -258 /* word needs more text to succeed - re-run it */
#define VM_USEREXIT -259 /* user wants to quit */
#define VM_ERREXIT -260 /* interp found an error */
#define VM_BREAK -261 /* debugger breakpoint */
#define VM_ABORT -1 /* like errexit -- abort */
#define VM_ABORTQ -2 /* like errexit -- abort" */
#define VM_QUIT -56 /* like errexit, but leave pStack & base alone */
void vmBranchRelative(FICL_VM *pVM, int offset);
FICL_VM * vmCreate (FICL_VM *pVM, unsigned nPStack, unsigned nRStack);
void vmDelete (FICL_VM *pVM);
void vmExecute (FICL_VM *pVM, FICL_WORD *pWord);
FICL_DICT *vmGetDict (FICL_VM *pVM);
char * vmGetString (FICL_VM *pVM, FICL_STRING *spDest, char delimiter);
STRINGINFO vmGetWord (FICL_VM *pVM);
STRINGINFO vmGetWord0 (FICL_VM *pVM);
int vmGetWordToPad (FICL_VM *pVM);
STRINGINFO vmParseString (FICL_VM *pVM, char delimiter);
STRINGINFO vmParseStringEx(FICL_VM *pVM, char delimiter, char fSkipLeading);
CELL vmPop (FICL_VM *pVM);
void vmPush (FICL_VM *pVM, CELL c);
void vmPopIP (FICL_VM *pVM);
void vmPushIP (FICL_VM *pVM, IPTYPE newIP);
void vmQuit (FICL_VM *pVM);
void vmReset (FICL_VM *pVM);
void vmSetTextOut (FICL_VM *pVM, OUTFUNC textOut);
void vmTextOut (FICL_VM *pVM, char *text, int fNewline);
void vmTextOut (FICL_VM *pVM, char *text, int fNewline);
void vmThrow (FICL_VM *pVM, int except);
void vmThrowErr (FICL_VM *pVM, char *fmt, ...);
#define vmGetRunningWord(pVM) ((pVM)->runningWord)
/*
** The inner interpreter - coded as a macro (see note for
** INLINE_INNER_LOOP in sysdep.h for complaints about VC++ 5
*/
#define M_VM_STEP(pVM) \
FICL_WORD *tempFW = *(pVM)->ip++; \
(pVM)->runningWord = tempFW; \
tempFW->code(pVM);
#define M_INNER_LOOP(pVM) \
for (;;) { M_VM_STEP(pVM) }
#if INLINE_INNER_LOOP != 0
#define vmInnerLoop(pVM) M_INNER_LOOP(pVM)
#else
void vmInnerLoop(FICL_VM *pVM);
#endif
/*
** vmCheckStack needs a vm pointer because it might have to say
** something if it finds a problem. Parms popCells and pushCells
** correspond to the number of parameters on the left and right of
** a word's stack effect comment.
*/
void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells);
#if FICL_WANT_FLOAT
void vmCheckFStack(FICL_VM *pVM, int popCells, int pushCells);
#endif
/*
** TIB access routines...
** ANS forth seems to require the input buffer to be represented
** as a pointer to the start of the buffer, and an index to the
** next character to read.
** PushTib points the VM to a new input string and optionally
** returns a copy of the current state
** PopTib restores the TIB state given a saved TIB from PushTib
** GetInBuf returns a pointer to the next unused char of the TIB
*/
void vmPushTib (FICL_VM *pVM, char *text, FICL_INT nChars, TIB *pSaveTib);
void vmPopTib (FICL_VM *pVM, TIB *pTib);
#define vmGetInBuf(pVM) ((pVM)->tib.cp + (pVM)->tib.index)
#define vmGetInBufLen(pVM) ((pVM)->tib.end - (pVM)->tib.cp)
#define vmGetInBufEnd(pVM) ((pVM)->tib.end)
#define vmGetTibIndex(pVM) (pVM)->tib.index
#define vmSetTibIndex(pVM, i) (pVM)->tib.index = i
#define vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp
/*
** Generally useful string manipulators omitted by ANSI C...
** ltoa complements strtol
*/
#if defined(_WIN32) && !FICL_MAIN
/* #SHEESH
** Why do Microsoft Meatballs insist on contaminating
** my namespace with their string functions???
*/
#pragma warning(disable: 4273)
#endif
int isPowerOfTwo(FICL_UNS u);
char *ltoa( FICL_INT value, char *string, int radix );
char *ultoa(FICL_UNS value, char *string, int radix );
char digit_to_char(int value);
char *strrev( char *string );
char *skipSpace(char *cp, char *end);
char *caseFold(char *cp);
int strincmp(char *cp1, char *cp2, FICL_UNS count);
#if defined(_WIN32) && !FICL_MAIN
#pragma warning(default: 4273)
#endif
/*
** Ficl hash table - variable size.
** assert(size > 0)
** If size is 1, the table degenerates into a linked list.
** A WORDLIST (see the search order word set in DPANS) is
** just a pointer to a FICL_HASH in this implementation.
*/
#if !defined HASHSIZE /* Default size of hash table. For most uniform */
#define HASHSIZE 241 /* performance, use a prime number! */
#endif
typedef struct ficl_hash
{
struct ficl_hash *link; /* link to parent class wordlist for OO */
char *name; /* optional pointer to \0 terminated wordlist name */
unsigned size; /* number of buckets in the hash */
FICL_WORD *table[1];
} FICL_HASH;
void hashForget (FICL_HASH *pHash, void *where);
UNS16 hashHashCode (STRINGINFO si);
void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW);
FICL_WORD *hashLookup (FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode);
void hashReset (FICL_HASH *pHash);
/*
** A Dictionary is a linked list of FICL_WORDs. It is also Ficl's
** memory model. Description of fields:
**
** here -- points to the next free byte in the dictionary. This
** pointer is forced to be CELL-aligned before a definition is added.
** Do not assume any specific alignment otherwise - Use dictAlign().
**
** smudge -- pointer to word currently being defined (or last defined word)
** If the definition completes successfully, the word will be
** linked into the hash table. If unsuccessful, dictUnsmudge
** uses this pointer to restore the previous state of the dictionary.
** Smudge prevents unintentional recursion as a side-effect: the
** dictionary search algo examines only completed definitions, so a
** word cannot invoke itself by name. See the ficl word "recurse".
** NOTE: smudge always points to the last word defined. IMMEDIATE
** makes use of this fact. Smudge is initially NULL.
**
** pForthWords -- pointer to the default wordlist (FICL_HASH).
** This is the initial compilation list, and contains all
** ficl's precompiled words.
**
** pCompile -- compilation wordlist - initially equal to pForthWords
** pSearch -- array of pointers to wordlists. Managed as a stack.
** Highest index is the first list in the search order.
** nLists -- number of lists in pSearch. nLists-1 is the highest
** filled slot in pSearch, and points to the first wordlist
** in the search order
** size -- number of cells in the dictionary (total)
** dict -- start of data area. Must be at the end of the struct.
*/
struct ficl_dict
{
CELL *here;
FICL_WORD *smudge;
FICL_HASH *pForthWords;
FICL_HASH *pCompile;
FICL_HASH *pSearch[FICL_DEFAULT_VOCS];
int nLists;
unsigned size; /* Number of cells in dict (total)*/
CELL *dict; /* Base of dictionary memory */
};
void *alignPtr(void *ptr);
void dictAbortDefinition(FICL_DICT *pDict);
void dictAlign (FICL_DICT *pDict);
int dictAllot (FICL_DICT *pDict, int n);
int dictAllotCells (FICL_DICT *pDict, int nCells);
void dictAppendCell (FICL_DICT *pDict, CELL c);
void dictAppendChar (FICL_DICT *pDict, char c);
FICL_WORD *dictAppendWord (FICL_DICT *pDict,
char *name,
FICL_CODE pCode,
UNS8 flags);
FICL_WORD *dictAppendWord2(FICL_DICT *pDict,
STRINGINFO si,
FICL_CODE pCode,
UNS8 flags);
void dictAppendUNS (FICL_DICT *pDict, FICL_UNS u);
int dictCellsAvail (FICL_DICT *pDict);
int dictCellsUsed (FICL_DICT *pDict);
void dictCheck (FICL_DICT *pDict, FICL_VM *pVM, int n);
void dictCheckThreshold(FICL_DICT* dp);
FICL_DICT *dictCreate(unsigned nCELLS);
FICL_DICT *dictCreateHashed(unsigned nCells, unsigned nHash);
FICL_HASH *dictCreateWordlist(FICL_DICT *dp, int nBuckets);
void dictDelete (FICL_DICT *pDict);
void dictEmpty (FICL_DICT *pDict, unsigned nHash);
#if FICL_WANT_FLOAT
void dictHashSummary(FICL_VM *pVM);
#endif
int dictIncludes (FICL_DICT *pDict, void *p);
FICL_WORD *dictLookup (FICL_DICT *pDict, STRINGINFO si);
#if FICL_WANT_LOCALS
FICL_WORD *ficlLookupLoc (FICL_SYSTEM *pSys, STRINGINFO si);
#endif
void dictResetSearchOrder(FICL_DICT *pDict);
void dictSetFlags (FICL_DICT *pDict, UNS8 set, UNS8 clr);
void dictSetImmediate(FICL_DICT *pDict);
void dictUnsmudge (FICL_DICT *pDict);
CELL *dictWhere (FICL_DICT *pDict);
/*
** P A R S E S T E P
** (New for 2.05)
** See words.c: interpWord
** By default, ficl goes through two attempts to parse each token from its input
** stream: it first attempts to match it with a word in the dictionary, and
** if that fails, it attempts to convert it into a number. This mechanism is now
** extensible by additional steps. This allows extensions like floating point and
** double number support to be factored cleanly.
**
** Each parse step is a function that receives the next input token as a STRINGINFO.
** If the parse step matches the token, it must apply semantics to the token appropriate
** to the present value of VM.state (compiling or interpreting), and return FICL_TRUE.
** Otherwise it returns FICL_FALSE. See words.c: isNumber for an example
**
** Note: for the sake of efficiency, it's a good idea both to limit the number
** of parse steps and to code each parse step so that it rejects tokens that
** do not match as quickly as possible.
*/
typedef int (*FICL_PARSE_STEP)(FICL_VM *pVM, STRINGINFO si);
/*
** Appends a parse step function to the end of the parse list (see
** FICL_PARSE_STEP notes in ficl.h for details). Returns 0 if successful,
** nonzero if there's no more room in the list. Each parse step is a word in
** the dictionary. Precompiled parse steps can use (PARSE-STEP) as their
** CFA - see parenParseStep in words.c.
*/
int ficlAddParseStep(FICL_SYSTEM *pSys, FICL_WORD *pFW); /* ficl.c */
void ficlAddPrecompiledParseStep(FICL_SYSTEM *pSys, char *name, FICL_PARSE_STEP pStep);
void ficlListParseSteps(FICL_VM *pVM);
/*
** FICL_BREAKPOINT record.
** origXT - if NULL, this breakpoint is unused. Otherwise it stores the xt
** that the breakpoint overwrote. This is restored to the dictionary when the
** BP executes or gets cleared
** address - the location of the breakpoint (address of the instruction that
** has been replaced with the breakpoint trap
** origXT - The original contents of the location with the breakpoint
** Note: address is NULL when this breakpoint is empty
*/
typedef struct FICL_BREAKPOINT
{
void *address;
FICL_WORD *origXT;
} FICL_BREAKPOINT;
/*
** F I C L _ S Y S T E M
** The top level data structure of the system - ficl_system ties a list of
** virtual machines with their corresponding dictionaries. Ficl 3.0 will
** support multiple Ficl systems, allowing multiple concurrent sessions
** to separate dictionaries with some constraints.
** The present model allows multiple sessions to one dictionary provided
** you implement ficlLockDictionary() as specified in sysdep.h
** Note: the pExtend pointer is there to provide context for applications. It is copied
** to each VM's pExtend field as that VM is created.
*/
struct ficl_system
{
FICL_SYSTEM *link;
void *pExtend; /* Initializes VM's pExtend pointer (for application use) */
FICL_VM *vmList;
FICL_DICT *dp;
FICL_DICT *envp;
#ifdef FICL_WANT_LOCALS
FICL_DICT *localp;
#endif
FICL_WORD *pInterp[3];
FICL_WORD *parseList[FICL_MAX_PARSE_STEPS];
OUTFUNC textOut;
FICL_WORD *pBranchParen;
FICL_WORD *pDoParen;
FICL_WORD *pDoesParen;
FICL_WORD *pExitInner;
FICL_WORD *pExitParen;
FICL_WORD *pBranch0;
FICL_WORD *pInterpret;
FICL_WORD *pLitParen;
FICL_WORD *pTwoLitParen;
FICL_WORD *pLoopParen;
FICL_WORD *pPLoopParen;
FICL_WORD *pQDoParen;
FICL_WORD *pSemiParen;
FICL_WORD *pOfParen;
FICL_WORD *pStore;
FICL_WORD *pDrop;
FICL_WORD *pCStringLit;
FICL_WORD *pStringLit;
#if FICL_WANT_LOCALS
FICL_WORD *pGetLocalParen;
FICL_WORD *pGet2LocalParen;
FICL_WORD *pGetLocal0;
FICL_WORD *pGetLocal1;
FICL_WORD *pToLocalParen;
FICL_WORD *pTo2LocalParen;
FICL_WORD *pToLocal0;
FICL_WORD *pToLocal1;
FICL_WORD *pLinkParen;
FICL_WORD *pUnLinkParen;
FICL_INT nLocals;
CELL *pMarkLocals;
#endif
FICL_BREAKPOINT bpStep;
};
struct ficl_system_info
{
int size; /* structure size tag for versioning */
int nDictCells; /* Size of system's Dictionary */
OUTFUNC textOut; /* default textOut function */
void *pExtend; /* Initializes VM's pExtend pointer - for application use */
int nEnvCells; /* Size of Environment dictionary */
};
#define ficlInitInfo(x) { memset((x), 0, sizeof(FICL_SYSTEM_INFO)); \
(x)->size = sizeof(FICL_SYSTEM_INFO); }
/*
** External interface to FICL...
*/
/*
** f i c l I n i t S y s t e m
** Binds a global dictionary to the interpreter system and initializes
** the dict to contain the ANSI CORE wordset.
** You can specify the address and size of the allocated area.
** Using ficlInitSystemEx you can also specify the text output function.
** After that, ficl manages it.
** First step is to set up the static pointers to the area.
** Then write the "precompiled" portion of the dictionary in.
** The dictionary needs to be at least large enough to hold the
** precompiled part. Try 1K cells minimum. Use "words" to find
** out how much of the dictionary is used at any time.
*/
FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi);
/* Deprecated call */
FICL_SYSTEM *ficlInitSystem(int nDictCells);
/*
** f i c l T e r m S y s t e m
** Deletes the system dictionary and all virtual machines that
** were created with ficlNewVM (see below). Call this function to
** reclaim all memory used by the dictionary and VMs.
*/
void ficlTermSystem(FICL_SYSTEM *pSys);
/*
** f i c l E v a l u a t e
** Evaluates a block of input text in the context of the
** specified interpreter. Also sets SOURCE-ID properly.
**
** PLEASE USE THIS FUNCTION when throwing a hard-coded
** string to the FICL interpreter.
*/
int ficlEvaluate(FICL_VM *pVM, char *pText);
/*
** f i c l E x e c
** Evaluates a block of input text in the context of the
** specified interpreter. Emits any requested output to the
** interpreter's output function. If the input string is NULL
** terminated, you can pass -1 as nChars rather than count it.
** Execution returns when the text block has been executed,
** or an error occurs.
** Returns one of the VM_XXXX codes defined in ficl.h:
** VM_OUTOFTEXT is the normal exit condition
** VM_ERREXIT means that the interp encountered a syntax error
** and the vm has been reset to recover (some or all
** of the text block got ignored
** VM_USEREXIT means that the user executed the "bye" command
** to shut down the interpreter. This would be a good
** time to delete the vm, etc -- or you can ignore this
** signal.
** VM_ABORT and VM_ABORTQ are generated by 'abort' and 'abort"'
** commands.
** Preconditions: successful execution of ficlInitSystem,
** Successful creation and init of the VM by ficlNewVM (or equiv)
**
** If you call ficlExec() or one of its brothers, you MUST
** ensure pVM->sourceID was set to a sensible value.
** ficlExec() explicitly DOES NOT manage SOURCE-ID for you.
*/
int ficlExec (FICL_VM *pVM, char *pText);
int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT nChars);
int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord);
/*
** ficlExecFD(FICL_VM *pVM, int fd);
* Evaluates text from file passed in via fd.
* Execution returns when all of file has been executed or an
* error occurs.
*/
int ficlExecFD(FICL_VM *pVM, int fd);
/*
** Create a new VM from the heap, and link it into the system VM list.
** Initializes the VM and binds default sized stacks to it. Returns the
** address of the VM, or NULL if an error occurs.
** Precondition: successful execution of ficlInitSystem
*/
FICL_VM *ficlNewVM(FICL_SYSTEM *pSys);
/*
** Force deletion of a VM. You do not need to do this
** unless you're creating and discarding a lot of VMs.
** For systems that use a constant pool of VMs for the life
** of the system, ficltermSystem takes care of VM cleanup
** automatically.
*/
void ficlFreeVM(FICL_VM *pVM);
/*
** Set the stack sizes (return and parameter) to be used for all
** subsequently created VMs. Returns actual stack size to be used.
*/
int ficlSetStackSize(int nStackCells);
/*
** Returns the address of the most recently defined word in the system
** dictionary with the given name, or NULL if no match.
** Precondition: successful execution of ficlInitSystem
*/
FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name);
/*
** f i c l G e t D i c t
** Utility function - returns the address of the system dictionary.
** Precondition: successful execution of ficlInitSystem
*/
FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys);
FICL_DICT *ficlGetEnv (FICL_SYSTEM *pSys);
void ficlSetEnv (FICL_SYSTEM *pSys, char *name, FICL_UNS value);
void ficlSetEnvD(FICL_SYSTEM *pSys, char *name, FICL_UNS hi, FICL_UNS lo);
#if FICL_WANT_LOCALS
FICL_DICT *ficlGetLoc (FICL_SYSTEM *pSys);
#endif
/*
** f i c l B u i l d
** Builds a word into the system default dictionary in a thread-safe way.
** Preconditions: system must be initialized, and there must
** be enough space for the new word's header! Operation is
** controlled by ficlLockDictionary, so any initialization
** required by your version of the function (if you "overrode"
** it) must be complete at this point.
** Parameters:
** name -- the name of the word to be built
** code -- code to execute when the word is invoked - must take a single param
** pointer to a FICL_VM
** flags -- 0 or more of FW_IMMEDIATE, FW_COMPILE, use bitwise OR!
** Most words can use FW_DEFAULT.
** nAllot - number of extra cells to allocate in the parameter area (usually zero)
*/
int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, char flags);
/*
** f i c l C o m p i l e C o r e
** Builds the ANS CORE wordset into the dictionary - called by
** ficlInitSystem - no need to waste dict space by doing it again.
*/
void ficlCompileCore(FICL_SYSTEM *pSys);
void ficlCompilePrefix(FICL_SYSTEM *pSys);
void ficlCompileSearch(FICL_SYSTEM *pSys);
void ficlCompileSoftCore(FICL_SYSTEM *pSys);
void ficlCompileTools(FICL_SYSTEM *pSys);
void ficlCompileFile(FICL_SYSTEM *pSys);
#if FICL_WANT_FLOAT
void ficlCompileFloat(FICL_SYSTEM *pSys);
int ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si ); /* float.c */
#endif
#if FICL_PLATFORM_EXTEND
void ficlCompilePlatform(FICL_SYSTEM *pSys);
#endif
int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si);
/*
** from words.c...
*/
void constantParen(FICL_VM *pVM);
void twoConstParen(FICL_VM *pVM);
int ficlParseNumber(FICL_VM *pVM, STRINGINFO si);
void ficlTick(FICL_VM *pVM);
void parseStepParen(FICL_VM *pVM);
/*
** From tools.c
*/
int isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW);
/*
** The following supports SEE and the debugger.
*/
typedef enum
{
BRANCH,
COLON,
CONSTANT,
CREATE,
DO,
DOES,
IF,
LITERAL,
LOOP,
OF,
PLOOP,
PRIMITIVE,
QDO,
STRINGLIT,
CSTRINGLIT,
#if FICL_WANT_USER
USER,
#endif
VARIABLE,
} WORDKIND;
WORDKIND ficlWordClassify(FICL_WORD *pFW);
/*
** Dictionary on-demand resizing
*/
extern CELL dictThreshold;
extern CELL dictIncrease;
/*
** Various FreeBSD goodies
*/
#if defined(__i386__) && !defined(TESTMAIN)
extern void ficlOutb(FICL_VM *pVM);
extern void ficlInb(FICL_VM *pVM);
#endif
extern void ficlSetenv(FICL_VM *pVM);
extern void ficlSetenvq(FICL_VM *pVM);
extern void ficlGetenv(FICL_VM *pVM);
extern void ficlUnsetenv(FICL_VM *pVM);
extern void ficlCopyin(FICL_VM *pVM);
extern void ficlCopyout(FICL_VM *pVM);
extern void ficlFindfile(FICL_VM *pVM);
extern void ficlCcall(FICL_VM *pVM);
#if !defined(TESTMAIN)
extern void ficlPnpdevices(FICL_VM *pVM);
extern void ficlPnphandlers(FICL_VM *pVM);
#endif
/*
** Used with File-Access wordset.
*/
#define FICL_FAM_READ 1
#define FICL_FAM_WRITE 2
#define FICL_FAM_APPEND 4
#define FICL_FAM_BINARY 8
#define FICL_FAM_OPEN_MODE(fam) ((fam) & (FICL_FAM_READ | FICL_FAM_WRITE | FICL_FAM_APPEND))
#if (FICL_WANT_FILE)
typedef struct ficlFILE
{
FILE *f;
char filename[256];
} ficlFILE;
#endif
#include <sys/linker_set.h>
typedef void ficlCompileFcn(FICL_SYSTEM *);
#define FICL_COMPILE_SET(func) \
DATA_SET(Xficl_compile_set, func)
SET_DECLARE(Xficl_compile_set, ficlCompileFcn);
+#ifdef LOADER_VERIEXEC
+#include <verify_file.h>
+#endif
+
#ifdef __cplusplus
}
#endif
#endif /* __FICL_H__ */
Index: stable/12/stand/ficl/fileaccess.c
===================================================================
--- stable/12/stand/ficl/fileaccess.c (revision 346144)
+++ stable/12/stand/ficl/fileaccess.c (revision 346145)
@@ -1,425 +1,432 @@
/* $FreeBSD$ */
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include "ficl.h"
#if FICL_WANT_FILE
/*
**
** fileaccess.c
**
** Implements all of the File Access word set that can be implemented in portable C.
**
*/
static void pushIor(FICL_VM *pVM, int success)
{
int ior;
if (success)
ior = 0;
else
ior = errno;
stackPushINT(pVM->pStack, ior);
}
static void ficlFopen(FICL_VM *pVM, char *writeMode) /* ( c-addr u fam -- fileid ior ) */
{
int fam = stackPopINT(pVM->pStack);
int length = stackPopINT(pVM->pStack);
void *address = (void *)stackPopPtr(pVM->pStack);
char mode[4];
FILE *f;
char *filename = (char *)alloca(length + 1);
memcpy(filename, address, length);
filename[length] = 0;
*mode = 0;
switch (FICL_FAM_OPEN_MODE(fam))
{
case 0:
stackPushPtr(pVM->pStack, NULL);
stackPushINT(pVM->pStack, EINVAL);
return;
case FICL_FAM_READ:
strcat(mode, "r");
break;
case FICL_FAM_WRITE:
strcat(mode, writeMode);
break;
case FICL_FAM_READ | FICL_FAM_WRITE:
strcat(mode, writeMode);
strcat(mode, "+");
break;
}
strcat(mode, (fam & FICL_FAM_BINARY) ? "b" : "t");
f = fopen(filename, mode);
if (f == NULL)
stackPushPtr(pVM->pStack, NULL);
else
+#ifdef LOADER_VERIEXEC
+ if (*mode == 'r' &&
+ verify_file(fileno(f), filename, 0, VE_GUESS) < 0) {
+ fclose(f);
+ stackPushPtr(pVM->pStack, NULL);
+ } else
+#endif
{
- ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE));
- strcpy(ff->filename, filename);
- ff->f = f;
- stackPushPtr(pVM->pStack, ff);
+ ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE));
+ strcpy(ff->filename, filename);
+ ff->f = f;
+ stackPushPtr(pVM->pStack, ff);
- fseek(f, 0, SEEK_SET);
- }
+ fseek(f, 0, SEEK_SET);
+ }
pushIor(pVM, f != NULL);
}
static void ficlOpenFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
{
ficlFopen(pVM, "a");
}
static void ficlCreateFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
{
ficlFopen(pVM, "w");
}
static int closeFiclFILE(ficlFILE *ff) /* ( fileid -- ior ) */
{
FILE *f = ff->f;
free(ff);
return !fclose(f);
}
static void ficlCloseFile(FICL_VM *pVM) /* ( fileid -- ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
pushIor(pVM, closeFiclFILE(ff));
}
static void ficlDeleteFile(FICL_VM *pVM) /* ( c-addr u -- ior ) */
{
int length = stackPopINT(pVM->pStack);
void *address = (void *)stackPopPtr(pVM->pStack);
char *filename = (char *)alloca(length + 1);
memcpy(filename, address, length);
filename[length] = 0;
pushIor(pVM, !unlink(filename));
}
static void ficlRenameFile(FICL_VM *pVM) /* ( c-addr1 u1 c-addr2 u2 -- ior ) */
{
int length;
void *address;
char *from;
char *to;
length = stackPopINT(pVM->pStack);
address = (void *)stackPopPtr(pVM->pStack);
to = (char *)alloca(length + 1);
memcpy(to, address, length);
to[length] = 0;
length = stackPopINT(pVM->pStack);
address = (void *)stackPopPtr(pVM->pStack);
from = (char *)alloca(length + 1);
memcpy(from, address, length);
from[length] = 0;
pushIor(pVM, !rename(from, to));
}
static void ficlFileStatus(FICL_VM *pVM) /* ( c-addr u -- x ior ) */
{
struct stat statbuf;
int length = stackPopINT(pVM->pStack);
void *address = (void *)stackPopPtr(pVM->pStack);
char *filename = (char *)alloca(length + 1);
memcpy(filename, address, length);
filename[length] = 0;
if (stat(filename, &statbuf) == 0)
{
/*
** the "x" left on the stack is implementation-defined.
** I push the file's access mode (readable, writeable, is directory, etc)
** as defined by ANSI C.
*/
stackPushINT(pVM->pStack, statbuf.st_mode);
stackPushINT(pVM->pStack, 0);
}
else
{
stackPushINT(pVM->pStack, -1);
stackPushINT(pVM->pStack, ENOENT);
}
}
static void ficlFilePosition(FICL_VM *pVM) /* ( fileid -- ud ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
long ud = ftell(ff->f);
stackPushINT(pVM->pStack, ud);
pushIor(pVM, ud != -1);
}
static long fileSize(FILE *f)
{
struct stat statbuf;
statbuf.st_size = -1;
if (fstat(fileno(f), &statbuf) != 0)
return -1;
return statbuf.st_size;
}
static void ficlFileSize(FICL_VM *pVM) /* ( fileid -- ud ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
long ud = fileSize(ff->f);
stackPushINT(pVM->pStack, ud);
pushIor(pVM, ud != -1);
}
#define nLINEBUF 256
static void ficlIncludeFile(FICL_VM *pVM) /* ( i*x fileid -- j*x ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
CELL id = pVM->sourceID;
int result = VM_OUTOFTEXT;
long currentPosition, totalSize;
long size;
pVM->sourceID.p = (void *)ff;
currentPosition = ftell(ff->f);
totalSize = fileSize(ff->f);
size = totalSize - currentPosition;
if ((totalSize != -1) && (currentPosition != -1) && (size > 0))
{
char *buffer = (char *)malloc(size);
long got = fread(buffer, 1, size, ff->f);
if (got == size)
result = ficlExecC(pVM, buffer, size);
}
#if 0
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
CELL id = pVM->sourceID;
char cp[nLINEBUF];
int nLine = 0;
int keepGoing;
int result;
pVM->sourceID.p = (void *)ff;
/* feed each line to ficlExec */
keepGoing = TRUE;
while (keepGoing && fgets(cp, nLINEBUF, ff->f))
{
int len = strlen(cp) - 1;
nLine++;
if (len <= 0)
continue;
if (cp[len] == '\n')
cp[len] = '\0';
result = ficlExec(pVM, cp);
switch (result)
{
case VM_OUTOFTEXT:
case VM_USEREXIT:
break;
default:
pVM->sourceID = id;
keepGoing = FALSE;
break;
}
}
#endif /* 0 */
/*
** Pass an empty line with SOURCE-ID == -1 to flush
** any pending REFILLs (as required by FILE wordset)
*/
pVM->sourceID.i = -1;
ficlExec(pVM, "");
pVM->sourceID = id;
closeFiclFILE(ff);
}
static void ficlReadFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
int length = stackPopINT(pVM->pStack);
void *address = (void *)stackPopPtr(pVM->pStack);
int result;
clearerr(ff->f);
result = fread(address, 1, length, ff->f);
stackPushINT(pVM->pStack, result);
pushIor(pVM, ferror(ff->f) == 0);
}
static void ficlReadLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 flag ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
int length = stackPopINT(pVM->pStack);
char *address = (char *)stackPopPtr(pVM->pStack);
int error;
int flag;
if (feof(ff->f))
{
stackPushINT(pVM->pStack, -1);
stackPushINT(pVM->pStack, 0);
stackPushINT(pVM->pStack, 0);
return;
}
clearerr(ff->f);
*address = 0;
fgets(address, length, ff->f);
error = ferror(ff->f);
if (error != 0)
{
stackPushINT(pVM->pStack, -1);
stackPushINT(pVM->pStack, 0);
stackPushINT(pVM->pStack, error);
return;
}
length = strlen(address);
flag = (length > 0);
if (length && ((address[length - 1] == '\r') || (address[length - 1] == '\n')))
length--;
stackPushINT(pVM->pStack, length);
stackPushINT(pVM->pStack, flag);
stackPushINT(pVM->pStack, 0); /* ior */
}
static void ficlWriteFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
int length = stackPopINT(pVM->pStack);
void *address = (void *)stackPopPtr(pVM->pStack);
clearerr(ff->f);
fwrite(address, 1, length, ff->f);
pushIor(pVM, ferror(ff->f) == 0);
}
static void ficlWriteLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
size_t length = (size_t)stackPopINT(pVM->pStack);
void *address = (void *)stackPopPtr(pVM->pStack);
clearerr(ff->f);
if (fwrite(address, 1, length, ff->f) == length)
fwrite("\n", 1, 1, ff->f);
pushIor(pVM, ferror(ff->f) == 0);
}
static void ficlRepositionFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
size_t ud = (size_t)stackPopINT(pVM->pStack);
pushIor(pVM, fseek(ff->f, ud, SEEK_SET) == 0);
}
static void ficlFlushFile(FICL_VM *pVM) /* ( fileid -- ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
pushIor(pVM, fflush(ff->f) == 0);
}
#if FICL_HAVE_FTRUNCATE
static void ficlResizeFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
{
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
size_t ud = (size_t)stackPopINT(pVM->pStack);
pushIor(pVM, ftruncate(fileno(ff->f), ud) == 0);
}
#endif /* FICL_HAVE_FTRUNCATE */
#endif /* FICL_WANT_FILE */
void ficlCompileFile(FICL_SYSTEM *pSys)
{
#if FICL_WANT_FILE
FICL_DICT *dp = pSys->dp;
assert(dp);
dictAppendWord(dp, "create-file", ficlCreateFile, FW_DEFAULT);
dictAppendWord(dp, "open-file", ficlOpenFile, FW_DEFAULT);
dictAppendWord(dp, "close-file", ficlCloseFile, FW_DEFAULT);
dictAppendWord(dp, "include-file", ficlIncludeFile, FW_DEFAULT);
dictAppendWord(dp, "read-file", ficlReadFile, FW_DEFAULT);
dictAppendWord(dp, "read-line", ficlReadLine, FW_DEFAULT);
dictAppendWord(dp, "write-file", ficlWriteFile, FW_DEFAULT);
dictAppendWord(dp, "write-line", ficlWriteLine, FW_DEFAULT);
dictAppendWord(dp, "file-position", ficlFilePosition, FW_DEFAULT);
dictAppendWord(dp, "file-size", ficlFileSize, FW_DEFAULT);
dictAppendWord(dp, "reposition-file", ficlRepositionFile, FW_DEFAULT);
dictAppendWord(dp, "file-status", ficlFileStatus, FW_DEFAULT);
dictAppendWord(dp, "flush-file", ficlFlushFile, FW_DEFAULT);
dictAppendWord(dp, "delete-file", ficlDeleteFile, FW_DEFAULT);
dictAppendWord(dp, "rename-file", ficlRenameFile, FW_DEFAULT);
#ifdef FICL_HAVE_FTRUNCATE
dictAppendWord(dp, "resize-file", ficlResizeFile, FW_DEFAULT);
ficlSetEnv(pSys, "file", FICL_TRUE);
ficlSetEnv(pSys, "file-ext", FICL_TRUE);
#endif /* FICL_HAVE_FTRUNCATE */
#else
(void)pSys;
#endif /* FICL_WANT_FILE */
}
Index: stable/12/stand/ficl32/Makefile.depend
===================================================================
--- stable/12/stand/ficl32/Makefile.depend (revision 346144)
+++ stable/12/stand/ficl32/Makefile.depend (revision 346145)
@@ -1,14 +1,12 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- include \
- include/xlocale \
- lib/msun \
+ stand/libsa \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif
Index: stable/12/stand/i386/loader/Makefile.depend
===================================================================
--- stable/12/stand/i386/loader/Makefile.depend (revision 346144)
+++ stable/12/stand/i386/loader/Makefile.depend (revision 346145)
@@ -1,20 +1,17 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- include \
- include/xlocale \
- stand/ficl32 \
- stand/geli \
- stand/i386/btx/btx \
- stand/i386/btx/btxldr \
- stand/i386/btx/lib \
- stand/i386/libi386 \
- stand/libsa32 \
+ stand/${MACHINE_CPUARCH}/btx/btx \
+ stand/${MACHINE_CPUARCH}/btx/btxldr \
+ stand/${MACHINE_CPUARCH}/btx/lib \
+ stand/${MACHINE_CPUARCH}/libi386 \
+ stand/ficl \
+ stand/libsa \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif
Index: stable/12/stand/liblua/Makefile
===================================================================
--- stable/12/stand/liblua/Makefile (revision 346144)
+++ stable/12/stand/liblua/Makefile (revision 346145)
@@ -1,39 +1,42 @@
# $FreeBSD$
.include <bsd.init.mk>
.PATH: ${LUASRC}
.PATH: ${LIBLUASRC}
.include "${BOOTSRC}/lua.mk"
LIB= lua
INTERNALLIB=
# Core Lua.
SRCS= lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c \
lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c \
ltm.c lundump.c lvm.c lzio.c
SRCS+= lauxlib.c lbaselib.c lstrlib.c loadlib.c
# These aren't yet included, but link now, omitting them saves 15k
#SRCS+= lcorolib.c ldblib.c lutf8lib.c
# These aren't yet compatible with the boot environment, and some may never be
#SRCS+= lbitlib.c liolib.c lmathlib.c loslib.c ltablib.c
# Our utilities.
SRCS+= lerrno.c lfs.c lstd.c lutils.c
WARNS= 3
CFLAGS+= -DLUA_PATH_DEFAULT=\"/boot/lua/\?.lua\"
CFLAGS+= -ffreestanding -nostdlib -DLUA_USE_POSIX
CFLAGS+= -fno-stack-protector -D__BSD_VISIBLE
CFLAGS+= -I${BOOTSRC}/include -I${LIBLUASRC} -I${LUASRC} -I${LDRSRC}
.if ${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 0
CFLAGS+= -fPIC
.endif
+.if ${MK_LOADER_VERIEXEC} == "yes"
+CFLAGS+= -I${SRCTOP}/lib/libsecureboot/h -DLOADER_VERIEXEC
+.endif
.include <bsd.lib.mk>
Index: stable/12/stand/liblua/lstd.c
===================================================================
--- stable/12/stand/liblua/lstd.c (revision 346144)
+++ stable/12/stand/liblua/lstd.c (revision 346145)
@@ -1,252 +1,267 @@
/*-
* Copyright (c) 2014 Pedro Souza <pedrosouza@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "lstd.h"
#include "math.h"
+#ifdef LOADER_VERIEXEC
+#include <verify_file.h>
+#endif
+
FILE *
fopen(const char *filename, const char *mode)
{
struct stat st;
int fd, m, o;
FILE *f;
if (mode == NULL)
return NULL;
switch (*mode++) {
case 'r': /* open for reading */
m = O_RDONLY;
o = 0;
break;
case 'w': /* open for writing */
m = O_WRONLY;
/* These are not actually implemented yet */
o = O_CREAT | O_TRUNC;
break;
default: /* illegal mode */
return (NULL);
}
if (*mode == '+')
m = O_RDWR;
fd = open(filename, m | o);
if (fd < 0)
return NULL;
f = malloc(sizeof(FILE));
if (f == NULL) {
close(fd);
return NULL;
}
if (fstat(fd, &st) != 0) {
free(f);
close(fd);
return (NULL);
}
+
+#ifdef LOADER_VERIEXEC
+ /* only regular files and only reading makes sense */
+ if (S_ISREG(st.st_mode) && !(m & O_WRONLY)) {
+ if (verify_file(fd, filename, 0, VE_GUESS) < 0) {
+ free(f);
+ close(fd);
+ return (NULL);
+ }
+ }
+#endif
f->fd = fd;
f->offset = 0;
f->size = st.st_size;
return (f);
}
FILE *
freopen(const char *filename, const char *mode, FILE *stream)
{
fclose(stream);
return (fopen(filename, mode));
}
size_t
fread(void *ptr, size_t size, size_t count, FILE *stream)
{
size_t r;
if (stream == NULL)
return 0;
r = (size_t)read(stream->fd, ptr, size * count);
stream->offset += r;
return (r);
}
size_t
fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
{
ssize_t w;
if (stream == NULL || ptr == NULL)
return (0);
w = write(stream->fd, ptr, size * count);
if (w == -1)
return (0);
stream->offset += w;
return ((size_t)w);
}
int
fclose(FILE *stream)
{
if (stream == NULL)
return EOF;
close(stream->fd);
free(stream);
return (0);
}
int
ferror(FILE *stream)
{
return (stream == NULL || stream->fd < 0);
}
int
feof(FILE *stream)
{
if (stream == NULL)
return 1;
return (stream->offset >= stream->size);
}
int
getc(FILE *stream)
{
char ch;
size_t r;
if (stream == NULL)
return EOF;
r = read(stream->fd, &ch, 1);
if (r == 1)
return ch;
return EOF;
}
DIR *
opendir(const char *name)
{
DIR *dp;
int fd;
fd = open(name, O_RDONLY);
if (fd < 0)
return NULL;
dp = fdopendir(fd);
if (dp == NULL)
close(fd);
return dp;
}
DIR *
fdopendir(int fd)
{
DIR *dp;
dp = malloc(sizeof(*dp));
if (dp == NULL)
return NULL;
dp->fd = fd;
return dp;
}
int
closedir(DIR *dp)
{
close(dp->fd);
dp->fd = -1;
free(dp);
return 0;
}
void
luai_writestring(const char *s, int i)
{
while (i-- > 0)
putchar(*s++);
}
/*
* These routines from here on down are to implement the lua math
* library, but that's not presently included by default. They are
* little more than placeholders to allow compilation due to linkage
* issues with upstream Lua.
*/
int64_t
lstd_pow(int64_t x, int64_t y)
{
int64_t rv = 1;
if (y < 0)
return 0;
rv = x;
while (--y)
rv *= x;
return rv;
}
int64_t
lstd_floor(int64_t x)
{
return (x);
}
int64_t
lstd_fmod(int64_t a, int64_t b)
{
return (a % b);
}
/*
* This can't be implemented, so maybe it should just abort.
*/
int64_t
lstd_frexp(int64_t a, int *y)
{
*y = 0;
return 0;
}
Index: stable/12/stand/libsa/Makefile
===================================================================
--- stable/12/stand/libsa/Makefile (revision 346144)
+++ stable/12/stand/libsa/Makefile (revision 346145)
@@ -1,172 +1,177 @@
# $FreeBSD$
# Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $
#
# Notes:
# - We don't use the libc strerror/sys_errlist because the string table is
# quite large.
#
.include <bsd.init.mk>
LIBSA_CPUARCH?=${MACHINE_CPUARCH}
LIBC_SRC= ${SRCTOP}/lib/libc
LIB?= sa
# standalone components and stuff we have modified locally
SRCS+= gzguts.h zutil.h __main.c abort.c assert.c bcd.c environment.c getopt.c gets.c \
globals.c pager.c panic.c printf.c strdup.c strerror.c \
random.c sbrk.c twiddle.c zalloc.c zalloc_malloc.c
# private (pruned) versions of libc string functions
SRCS+= strcasecmp.c
.PATH: ${LIBC_SRC}/net
SRCS+= ntoh.c
# string functions from libc
.PATH: ${LIBC_SRC}/string
SRCS+= bcmp.c bcopy.c bzero.c ffs.c fls.c \
memccpy.c memchr.c memcmp.c memcpy.c memmove.c memset.c \
qdivrem.c strcat.c strchr.c strcmp.c strcpy.c stpcpy.c stpncpy.c \
strcspn.c strlcat.c strlcpy.c strlen.c strncat.c strncmp.c strncpy.c \
strnlen.c strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
# stdlib functions from libc
.PATH: ${LIBC_SRC}/stdlib
SRCS+= abs.c strtol.c strtoll.c strtoul.c strtoull.c
# common boot code
.PATH: ${SYSDIR}/kern
SRCS+= subr_boot.c
.if ${MACHINE_CPUARCH} == "arm"
.PATH: ${LIBC_SRC}/arm/gen
# Do not generate movt/movw, because the relocation fixup for them does not
# translate to the -Bsymbolic -pie format required by self_reloc() in loader(8).
# Also, the fpu is not available in a standalone environment.
.if ${COMPILER_VERSION} < 30800
CFLAGS.clang+= -mllvm -arm-use-movt=0
.else
CFLAGS.clang+= -mno-movt
.endif
CFLAGS.clang+= -mfpu=none
# Compiler support functions
.PATH: ${SRCTOP}/contrib/compiler-rt/lib/builtins/
# __clzsi2 and ctzsi2 for various builtin functions
SRCS+= clzsi2.c ctzsi2.c
# Divide and modulus functions called by the compiler
SRCS+= divmoddi4.c divmodsi4.c divdi3.c divsi3.c moddi3.c modsi3.c
SRCS+= udivmoddi4.c udivmodsi4.c udivdi3.c udivsi3.c umoddi3.c umodsi3.c
.PATH: ${SRCTOP}/contrib/compiler-rt/lib/builtins/arm/
SRCS+= aeabi_idivmod.S aeabi_ldivmod.S aeabi_uidivmod.S aeabi_uldivmod.S
SRCS+= aeabi_memcmp.S aeabi_memcpy.S aeabi_memmove.S aeabi_memset.S
.endif
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "riscv"
.PATH: ${LIBC_SRC}/${MACHINE_CPUARCH}/gen
.endif
.if ${MACHINE_CPUARCH} == "powerpc"
.PATH: ${LIBC_SRC}/quad
SRCS+= ashldi3.c ashrdi3.c lshrdi3.c
SRCS+= syncicache.c
.endif
.if ${MACHINE_CPUARCH} == "mips"
.PATH: ${LIBC_SRC}/quad
SRCS+= ashldi3.c ashrdi3.c lshrdi3.c
.endif
# uuid functions from libc
.PATH: ${LIBC_SRC}/uuid
SRCS+= uuid_create_nil.c uuid_equal.c uuid_from_string.c uuid_is_nil.c uuid_to_string.c
# _setjmp/_longjmp
.PATH: ${SASRC}/${LIBSA_CPUARCH}
SRCS+= _setjmp.S
# decompression functionality from libbz2
# NOTE: to actually test this functionality after libbz2 upgrade compile
# loader(8) with LOADER_BZIP2_SUPPORT defined
.PATH: ${SRCTOP}/contrib/bzip2
CFLAGS+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS
SRCS+=bzlib.c crctable.c decompress.c huffman.c randtable.c
# decompression functionality from zlib
.PATH: ${SRCTOP}/contrib/zlib
CFLAGS+=-DHAVE_MEMCPY -I${SRCTOP}/contrib/zlib
SRCS+= adler32.c crc32.c
SRCS+= infback.c inffast.c inflate.c inftrees.c zutil.c
# Create a subset of includes that are safe, as well as adjusting those that aren't
# The lists may drive people nuts, but they are explicitly opt-in
FAKE_DIRS=xlocale arpa
SAFE_INCS=a.out.h assert.h elf.h limits.h nlist.h setjmp.h stddef.h stdbool.h string.h strings.h time.h unistd.h uuid.h
STAND_H_INC=ctype.h fcntl.h signal.h stdio.h stdlib.h
OTHER_INC=stdarg.h errno.h stdint.h
beforedepend:
mkdir -p ${FAKE_DIRS}; \
for i in ${SAFE_INCS}; do \
ln -sf ${SRCTOP}/include/$$i $$i; \
done; \
ln -sf ${SYSDIR}/${MACHINE}/include/stdarg.h stdarg.h; \
ln -sf ${SYSDIR}/sys/errno.h errno.h; \
ln -sf ${SYSDIR}/sys/stdint.h stdint.h; \
ln -sf ${SRCTOP}/include/arpa/inet.h arpa/inet.h; \
ln -sf ${SRCTOP}/include/arpa/tftp.h arpa/tftp.h; \
for i in _time.h _strings.h _string.h; do \
[ -f xlocale/$$i ] || cp /dev/null xlocale/$$i; \
done; \
for i in ${STAND_H_INC}; do \
ln -sf ${SASRC}/stand.h $$i; \
done
CLEANDIRS+=${FAKE_DIRS}
CLEANFILES+= ${SAFE_INCS} ${STAND_H_INC} ${OTHER_INC}
# io routines
SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \
fstat.c close.c lseek.c open.c read.c write.c readdir.c
# network routines
SRCS+= arp.c ether.c ip.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c
# network info services:
SRCS+= bootp.c rarp.c bootparam.c
# boot filesystems
SRCS+= ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c
SRCS+= dosfs.c ext2fs.c
SRCS+= splitfs.c
SRCS+= pkgfs.c
.if ${MK_NAND} != "no"
SRCS+= nandfs.c
.endif
# kernel ufs support
.PATH: ${SRCTOP}/sys/ufs/ffs
SRCS+=ffs_subr.c ffs_tables.c
CFLAGS.bzipfs.c+= -I${SRCTOP}/contrib/bzip2
# explicit_bzero
.PATH: ${SYSDIR}/libkern
SRCS+= explicit_bzero.c
# Maybe GELI
.if ${MK_LOADER_GELI} == "yes"
.include "${SASRC}/geli/Makefile.inc"
.endif
+.if ${MK_LOADER_VERIEXEC} == "yes" && ${MK_BEARSSL} == "yes"
+.include "${SRCTOP}/lib/libbearssl/Makefile.libsa.inc"
+.include "${SRCTOP}/lib/libsecureboot/Makefile.libsa.inc"
+.endif
+
# Maybe ZFS
.if ${MK_LOADER_ZFS} == "yes"
.include "${SASRC}/zfs/Makefile.inc"
.endif
.include <bsd.lib.mk>
Index: stable/12/stand/libsa/Makefile.depend
===================================================================
--- stable/12/stand/libsa/Makefile.depend (revision 346144)
+++ stable/12/stand/libsa/Makefile.depend (revision 346145)
@@ -1,15 +1,11 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- include \
- include/arpa \
- include/xlocale \
- lib/libbz2 \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif
Index: stable/12/stand/libsa32/Makefile.depend
===================================================================
--- stable/12/stand/libsa32/Makefile.depend (revision 346144)
+++ stable/12/stand/libsa32/Makefile.depend (revision 346145)
@@ -1,15 +1,12 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- include \
- include/arpa \
- include/xlocale \
- lib/libbz2 \
+ stand/libsa \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif
Index: stable/12/stand/loader.mk
===================================================================
--- stable/12/stand/loader.mk (revision 346144)
+++ stable/12/stand/loader.mk (revision 346145)
@@ -1,166 +1,170 @@
# $FreeBSD$
.PATH: ${LDRSRC} ${BOOTSRC}/libsa
CFLAGS+=-I${LDRSRC}
SRCS+= boot.c commands.c console.c devopen.c interp.c
SRCS+= interp_backslash.c interp_parse.c ls.c misc.c
SRCS+= module.c
.if ${MACHINE} == "i386" || ${MACHINE_CPUARCH} == "amd64"
SRCS+= load_elf32.c load_elf32_obj.c reloc_elf32.c
SRCS+= load_elf64.c load_elf64_obj.c reloc_elf64.c
.elif ${MACHINE_CPUARCH} == "aarch64"
SRCS+= load_elf64.c reloc_elf64.c
.elif ${MACHINE_CPUARCH} == "arm"
SRCS+= load_elf32.c reloc_elf32.c
.elif ${MACHINE_CPUARCH} == "powerpc"
SRCS+= load_elf32.c reloc_elf32.c
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
.elif ${MACHINE_CPUARCH} == "sparc64"
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
.elif ${MACHINE_ARCH:Mmips64*} != ""
SRCS+= load_elf64.c reloc_elf64.c
SRCS+= metadata.c
.elif ${MACHINE} == "mips"
SRCS+= load_elf32.c reloc_elf32.c
SRCS+= metadata.c
.endif
.if ${LOADER_DISK_SUPPORT:Uyes} == "yes"
SRCS+= disk.c part.c
.endif
.if ${LOADER_NET_SUPPORT:Uno} == "yes"
SRCS+= dev_net.c
.endif
.if defined(HAVE_BCACHE)
SRCS+= bcache.c
.endif
.if defined(MD_IMAGE_SIZE)
CFLAGS+= -DMD_IMAGE_SIZE=${MD_IMAGE_SIZE}
SRCS+= md.c
.else
CLEANFILES+= md.o
.endif
# Machine-independant ISA PnP
.if defined(HAVE_ISABUS)
SRCS+= isapnp.c
.endif
.if defined(HAVE_PNP)
SRCS+= pnp.c
.endif
.if ${LOADER_INTERP} == "lua"
SRCS+= interp_lua.c
.include "${BOOTSRC}/lua.mk"
LDR_INTERP= ${LIBLUA}
LDR_INTERP32= ${LIBLUA32}
.elif ${LOADER_INTERP} == "4th"
SRCS+= interp_forth.c
.include "${BOOTSRC}/ficl.mk"
LDR_INTERP= ${LIBFICL}
LDR_INTERP32= ${LIBFICL32}
.elif ${LOADER_INTERP} == "simp"
SRCS+= interp_simple.c
.else
.error Unknown interpreter ${LOADER_INTERP}
.endif
+.if ${MK_LOADER_VERIEXEC} != "no"
+CFLAGS+= -DLOADER_VERIEXEC -I${SRCTOP}/lib/libsecureboot/h
+.endif
+
.if defined(BOOT_PROMPT_123)
CFLAGS+= -DBOOT_PROMPT_123
.endif
.if defined(LOADER_INSTALL_SUPPORT)
SRCS+= install.c
.endif
# Filesystem support
.if ${LOADER_CD9660_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_CD9660_SUPPORT
.endif
.if ${LOADER_EXT2FS_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_EXT2FS_SUPPORT
.endif
.if ${LOADER_MSDOS_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_MSDOS_SUPPORT
.endif
.if ${LOADER_NANDFS_SUPPORT:U${MK_NAND}} == "yes"
CFLAGS+= -DLOADER_NANDFS_SUPPORT
.endif
.if ${LOADER_UFS_SUPPORT:Uyes} == "yes"
CFLAGS+= -DLOADER_UFS_SUPPORT
.endif
# Compression
.if ${LOADER_GZIP_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_GZIP_SUPPORT
.endif
.if ${LOADER_BZIP2_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_BZIP2_SUPPORT
.endif
# Network related things
.if ${LOADER_NET_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_NET_SUPPORT
.endif
.if ${LOADER_NFS_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_NFS_SUPPORT
.endif
.if ${LOADER_TFTP_SUPPORT:Uno} == "yes"
CFLAGS+= -DLOADER_TFTP_SUPPORT
.endif
# Partition support
.if ${LOADER_GPT_SUPPORT:Uyes} == "yes"
CFLAGS+= -DLOADER_GPT_SUPPORT
.endif
.if ${LOADER_MBR_SUPPORT:Uyes} == "yes"
CFLAGS+= -DLOADER_MBR_SUPPORT
.endif
.if ${HAVE_ZFS:Uno} == "yes"
CFLAGS+= -DLOADER_ZFS_SUPPORT
CFLAGS+= -I${ZFSSRC}
CFLAGS+= -I${SYSDIR}/cddl/boot/zfs
SRCS+= zfs_cmd.c
.endif
LIBFICL= ${BOOTOBJ}/ficl/libficl.a
.if ${MACHINE} == "i386"
LIBFICL32= ${LIBFICL}
.else
LIBFICL32= ${BOOTOBJ}/ficl32/libficl.a
.endif
LIBLUA= ${BOOTOBJ}/liblua/liblua.a
.if ${MACHINE} == "i386"
LIBLUA32= ${LIBLUA}
.else
LIBLUA32= ${BOOTOBJ}/liblua32/liblua.a
.endif
CLEANFILES+= vers.c
VERSION_FILE?= ${.CURDIR}/version
.if ${MK_REPRODUCIBLE_BUILD} != no
REPRO_FLAG= -r
.endif
vers.c: ${LDRSRC}/newvers.sh ${VERSION_FILE}
sh ${LDRSRC}/newvers.sh ${REPRO_FLAG} ${VERSION_FILE} \
${NEWVERSWHAT}
.if !empty(HELP_FILES)
HELP_FILES+= ${LDRSRC}/help.common
CLEANFILES+= loader.help
FILES+= loader.help
loader.help: ${HELP_FILES}
cat ${HELP_FILES} | awk -f ${LDRSRC}/merge_help.awk > ${.TARGET}
.endif
Index: stable/12/tools/build/options/WITH_BEARSSL
===================================================================
--- stable/12/tools/build/options/WITH_BEARSSL (nonexistent)
+++ stable/12/tools/build/options/WITH_BEARSSL (revision 346145)
@@ -0,0 +1,11 @@
+.\" $FreeBSD$
+Build the BearSSL library.
+.Pp
+BearSSL is a tiny SSL library suitable for embedded environments.
+For details see
+.Lk http://www.BearSSL.org/
+.Pp
+This library is currently only used to perform
+signature verification and related operations
+for Verified Exec and
+.Xr loader 8 .
Property changes on: stable/12/tools/build/options/WITH_BEARSSL
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/tools/build/options/WITH_LOADER_VERIEXEC
===================================================================
--- stable/12/tools/build/options/WITH_LOADER_VERIEXEC (nonexistent)
+++ stable/12/tools/build/options/WITH_LOADER_VERIEXEC (revision 346145)
@@ -0,0 +1,7 @@
+.\" $FreeBSD$
+Enable building
+.Xr loader 8
+with support for verifcation similar to Verified Exec.
+.Pp
+It depends on
+.Va WITH_BEARSSL
Property changes on: stable/12/tools/build/options/WITH_LOADER_VERIEXEC
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12/tools/build/options/WITH_VERIEXEC
===================================================================
--- stable/12/tools/build/options/WITH_VERIEXEC (nonexistent)
+++ stable/12/tools/build/options/WITH_VERIEXEC (revision 346145)
@@ -0,0 +1,9 @@
+.\" $FreeBSD$
+Enable building
+.Xr veriexec 8
+which loads the contents of verified manifests into the kernel
+for use by
+.Xr mac_veriexec 4
+.Pp
+It depends on
+.Va WITH_BEARSSL
Property changes on: stable/12/tools/build/options/WITH_VERIEXEC
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+FreeBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: stable/12
===================================================================
--- stable/12 (revision 346144)
+++ stable/12 (revision 346145)
Property changes on: stable/12
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head:r343281,344564-344568,344780,344784,345289,346070

File Metadata

Mime Type
application/octet-stream
Expires
Fri, May 17, 12:08 AM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
RC1fo.kEI7bl
Default Alt Text
(4 MB)

Event Timeline