Initial import.
This commit is contained in:
commit
3210f38e04
292 changed files with 58526 additions and 0 deletions
21
LICENSE.txt
Normal file
21
LICENSE.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
606
Makefile
Normal file
606
Makefile
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
# Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
.POSIX:
|
||||
|
||||
# ========================================================================
|
||||
# Configurable elements: C compiler and flags, linker flags, static
|
||||
# library archival command.
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -W -Wall -Os -fPIC -I src -I inc
|
||||
#CFLAGS = -W -Wall -g -fPIC -I src -I inc
|
||||
LDFLAGS =
|
||||
AR = ar -rcs
|
||||
|
||||
# Nothing is meant to be changed below this line.
|
||||
|
||||
# ========================================================================
|
||||
|
||||
HEADERS = inc/bearssl.h inc/bearssl_block.h inc/bearssl_ec.h inc/bearssl_hash.h inc/bearssl_hmac.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 src/inner.h src/config.h
|
||||
BUILD = build
|
||||
|
||||
BEARSSLLIB = libbearssl.a
|
||||
BRSSL = brssl
|
||||
TESTCRYPTO = testcrypto
|
||||
TESTSPEED = testspeed
|
||||
TESTX509 = testx509
|
||||
TESTMATH = testmath
|
||||
|
||||
OBJCODEC = $(BUILD)/ccopy.o $(BUILD)/dec16be.o $(BUILD)/dec16le.o $(BUILD)/dec32be.o $(BUILD)/dec32le.o $(BUILD)/dec64be.o $(BUILD)/dec64le.o $(BUILD)/enc16be.o $(BUILD)/enc16le.o $(BUILD)/enc32be.o $(BUILD)/enc32le.o $(BUILD)/enc64be.o $(BUILD)/enc64le.o $(BUILD)/pemdec.o
|
||||
OBJEC = $(BUILD)/ec_prime_i31.o $(BUILD)/ec_prime_i31_secp256r1.o $(BUILD)/ec_prime_i31_secp384r1.o $(BUILD)/ec_prime_i31_secp521r1.o $(BUILD)/ec_secp256r1.o $(BUILD)/ec_secp384r1.o $(BUILD)/ec_secp521r1.o $(BUILD)/ecdsa_atr.o $(BUILD)/ecdsa_i31_bits.o $(BUILD)/ecdsa_i31_sign_asn1.o $(BUILD)/ecdsa_i31_sign_raw.o $(BUILD)/ecdsa_i31_vrfy_asn1.o $(BUILD)/ecdsa_i31_vrfy_raw.o $(BUILD)/ecdsa_rta.o
|
||||
OBJHASH = $(BUILD)/dig_oid.o $(BUILD)/dig_size.o $(BUILD)/ghash_ctmul.o $(BUILD)/ghash_ctmul32.o $(BUILD)/ghash_ctmul64.o $(BUILD)/md5.o $(BUILD)/md5sha1.o $(BUILD)/multihash.o $(BUILD)/sha1.o $(BUILD)/sha2big.o $(BUILD)/sha2small.o
|
||||
OBJINT31 = $(BUILD)/i31_add.o $(BUILD)/i31_bitlen.o $(BUILD)/i31_decmod.o $(BUILD)/i31_decode.o $(BUILD)/i31_decred.o $(BUILD)/i31_encode.o $(BUILD)/i31_fmont.o $(BUILD)/i31_iszero.o $(BUILD)/i31_modpow.o $(BUILD)/i31_montmul.o $(BUILD)/i31_mulacc.o $(BUILD)/i31_muladd.o $(BUILD)/i31_ninv31.o $(BUILD)/i31_reduce.o $(BUILD)/i31_rshift.o $(BUILD)/i31_sub.o $(BUILD)/i31_tmont.o
|
||||
OBJINT32 = $(BUILD)/i32_add.o $(BUILD)/i32_bitlen.o $(BUILD)/i32_decmod.o $(BUILD)/i32_decode.o $(BUILD)/i32_decred.o $(BUILD)/i32_div32.o $(BUILD)/i32_encode.o $(BUILD)/i32_fmont.o $(BUILD)/i32_iszero.o $(BUILD)/i32_modpow.o $(BUILD)/i32_montmul.o $(BUILD)/i32_mulacc.o $(BUILD)/i32_muladd.o $(BUILD)/i32_ninv32.o $(BUILD)/i32_reduce.o $(BUILD)/i32_sub.o $(BUILD)/i32_tmont.o
|
||||
OBJMAC = $(BUILD)/hmac.o $(BUILD)/hmac_ct.o
|
||||
OBJRAND = $(BUILD)/hmac_drbg.o
|
||||
OBJRSA = $(BUILD)/rsa_i31_pkcs1_sign.o $(BUILD)/rsa_i31_pkcs1_vrfy.o $(BUILD)/rsa_i31_priv.o $(BUILD)/rsa_i31_pub.o $(BUILD)/rsa_i32_pkcs1_sign.o $(BUILD)/rsa_i32_pkcs1_vrfy.o $(BUILD)/rsa_i32_priv.o $(BUILD)/rsa_i32_pub.o $(BUILD)/rsa_ssl_decrypt.o
|
||||
OBJSSL = $(BUILD)/prf.o $(BUILD)/prf_md5sha1.o $(BUILD)/prf_sha256.o $(BUILD)/prf_sha384.o $(BUILD)/ssl_client.o $(BUILD)/ssl_client_full.o $(BUILD)/ssl_engine.o $(BUILD)/ssl_hashes.o $(BUILD)/ssl_hs_client.o $(BUILD)/ssl_hs_server.o $(BUILD)/ssl_io.o $(BUILD)/ssl_lru.o $(BUILD)/ssl_rec_cbc.o $(BUILD)/ssl_rec_gcm.o $(BUILD)/ssl_server.o $(BUILD)/ssl_server_mine2g.o $(BUILD)/ssl_server_minf2g.o $(BUILD)/ssl_server_minr2g.o $(BUILD)/ssl_server_minu2g.o $(BUILD)/ssl_server_minv2g.o $(BUILD)/ssl_server_full_ec.o $(BUILD)/ssl_server_full_rsa.o $(BUILD)/ssl_single_ec.o $(BUILD)/ssl_single_rsa.o
|
||||
OBJSYMCIPHER = $(BUILD)/aes_big_cbcdec.o $(BUILD)/aes_big_cbcenc.o $(BUILD)/aes_big_ctr.o $(BUILD)/aes_big_dec.o $(BUILD)/aes_big_enc.o $(BUILD)/aes_common.o $(BUILD)/aes_ct.o $(BUILD)/aes_ct64.o $(BUILD)/aes_ct64_cbcdec.o $(BUILD)/aes_ct64_cbcenc.o $(BUILD)/aes_ct64_ctr.o $(BUILD)/aes_ct64_dec.o $(BUILD)/aes_ct64_enc.o $(BUILD)/aes_ct_cbcdec.o $(BUILD)/aes_ct_cbcenc.o $(BUILD)/aes_ct_ctr.o $(BUILD)/aes_ct_dec.o $(BUILD)/aes_ct_enc.o $(BUILD)/aes_small_cbcdec.o $(BUILD)/aes_small_cbcenc.o $(BUILD)/aes_small_ctr.o $(BUILD)/aes_small_dec.o $(BUILD)/aes_small_enc.o $(BUILD)/des_ct.o $(BUILD)/des_ct_cbcdec.o $(BUILD)/des_ct_cbcenc.o $(BUILD)/des_support.o $(BUILD)/des_tab.o $(BUILD)/des_tab_cbcdec.o $(BUILD)/des_tab_cbcenc.o
|
||||
OBJX509 = $(BUILD)/skey_decoder.o $(BUILD)/x509_decoder.o $(BUILD)/x509_knownkey.o $(BUILD)/x509_minimal.o
|
||||
OBJ = $(OBJCODEC) $(OBJEC) $(OBJHASH) $(OBJINT31) $(OBJINT32) $(OBJMAC) $(OBJRAND) $(OBJRSA) $(OBJSSL) $(OBJSYMCIPHER) $(OBJX509)
|
||||
OBJBRSSL = $(BUILD)/brssl.o $(BUILD)/certs.o $(BUILD)/chain.o $(BUILD)/client.o $(BUILD)/errors.o $(BUILD)/files.o $(BUILD)/keys.o $(BUILD)/names.o $(BUILD)/server.o $(BUILD)/skey.o $(BUILD)/sslio.o $(BUILD)/ta.o $(BUILD)/vector.o $(BUILD)/verify.o $(BUILD)/xmem.o
|
||||
OBJTESTCRYPTO = $(BUILD)/test_crypto.o
|
||||
OBJTESTSPEED = $(BUILD)/test_speed.o
|
||||
OBJTESTX509 = $(BUILD)/test_x509.o
|
||||
OBJTESTMATH = $(BUILD)/test_math.o
|
||||
|
||||
T0COMP = T0Comp.exe
|
||||
T0SRC = 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
|
||||
T0KERN = T0/kern.t0
|
||||
|
||||
all: compile
|
||||
|
||||
compile: $(BEARSSLLIB) $(BRSSL) $(TESTCRYPTO) $(TESTSPEED) $(TESTX509)
|
||||
|
||||
$(BEARSSLLIB): $(BUILD) $(OBJ)
|
||||
$(AR) $(BEARSSLLIB) $(OBJ)
|
||||
|
||||
$(BRSSL): $(BEARSSLLIB) $(OBJBRSSL)
|
||||
$(CC) $(LDFLAGS) -o $(BRSSL) $(OBJBRSSL) $(BEARSSLLIB)
|
||||
|
||||
$(TESTCRYPTO): $(BEARSSLLIB) $(OBJTESTCRYPTO)
|
||||
$(CC) $(LDFLAGS) -o $(TESTCRYPTO) $(OBJTESTCRYPTO) $(BEARSSLLIB)
|
||||
|
||||
$(TESTSPEED): $(BEARSSLLIB) $(OBJTESTSPEED)
|
||||
$(CC) $(LDFLAGS) -o $(TESTSPEED) $(OBJTESTSPEED) $(BEARSSLLIB)
|
||||
|
||||
$(TESTX509): $(BEARSSLLIB) $(OBJTESTX509)
|
||||
$(CC) $(LDFLAGS) -o $(TESTX509) $(OBJTESTX509) $(BEARSSLLIB)
|
||||
|
||||
$(TESTMATH): $(BEARSSLLIB) $(OBJTESTMATH)
|
||||
$(CC) $(LDFLAGS) -o $(TESTMATH) $(OBJTESTMATH) $(BEARSSLLIB) -lgmp
|
||||
|
||||
$(BUILD):
|
||||
-mkdir -p $(BUILD)
|
||||
|
||||
T0: $(T0COMP) T0Gen
|
||||
|
||||
T0Gen:
|
||||
mono T0Comp.exe -o src/codec/pemdec -r br_pem_decoder src/codec/pemdec.t0
|
||||
mono T0Comp.exe -o src/ssl/ssl_hs_client -r br_ssl_hs_client src/ssl/ssl_hs_common.t0 src/ssl/ssl_hs_client.t0
|
||||
mono T0Comp.exe -o src/ssl/ssl_hs_server -r br_ssl_hs_server src/ssl/ssl_hs_common.t0 src/ssl/ssl_hs_server.t0
|
||||
mono T0Comp.exe -o src/x509/skey_decoder -r br_skey_decoder src/x509/asn1.t0 src/x509/skey_decoder.t0
|
||||
mono T0Comp.exe -o src/x509/x509_decoder -r br_x509_decoder src/x509/asn1.t0 src/x509/x509_decoder.t0
|
||||
mono T0Comp.exe -o src/x509/x509_minimal -r br_x509_minimal src/x509/asn1.t0 src/x509/x509_minimal.t0
|
||||
|
||||
$(T0COMP): $(T0SRC) $(T0KERN)
|
||||
./mkT0.sh
|
||||
|
||||
clean:
|
||||
-rm -f $(OBJ) $(BEARSSLLIB) $(OBJSSL) $(BRSSL) $(OBJBRSSL) $(TESTCRYPTO) $(OBJTESTCRYPTO) $(TESTSPEED) $(OBJTESTSPEED) $(TESTX509) $(OBJTESTX509) $(TESTMATH) $(OBJTESTMATH)
|
||||
|
||||
$(BUILD)/ccopy.o: src/codec/ccopy.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ccopy.o src/codec/ccopy.c
|
||||
|
||||
$(BUILD)/dec16be.o: src/codec/dec16be.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dec16be.o src/codec/dec16be.c
|
||||
|
||||
$(BUILD)/dec16le.o: src/codec/dec16le.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dec16le.o src/codec/dec16le.c
|
||||
|
||||
$(BUILD)/dec32be.o: src/codec/dec32be.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dec32be.o src/codec/dec32be.c
|
||||
|
||||
$(BUILD)/dec32le.o: src/codec/dec32le.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dec32le.o src/codec/dec32le.c
|
||||
|
||||
$(BUILD)/dec64be.o: src/codec/dec64be.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dec64be.o src/codec/dec64be.c
|
||||
|
||||
$(BUILD)/dec64le.o: src/codec/dec64le.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dec64le.o src/codec/dec64le.c
|
||||
|
||||
$(BUILD)/enc16be.o: src/codec/enc16be.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/enc16be.o src/codec/enc16be.c
|
||||
|
||||
$(BUILD)/enc16le.o: src/codec/enc16le.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/enc16le.o src/codec/enc16le.c
|
||||
|
||||
$(BUILD)/enc32be.o: src/codec/enc32be.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/enc32be.o src/codec/enc32be.c
|
||||
|
||||
$(BUILD)/enc32le.o: src/codec/enc32le.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/enc32le.o src/codec/enc32le.c
|
||||
|
||||
$(BUILD)/enc64be.o: src/codec/enc64be.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/enc64be.o src/codec/enc64be.c
|
||||
|
||||
$(BUILD)/enc64le.o: src/codec/enc64le.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/enc64le.o src/codec/enc64le.c
|
||||
|
||||
$(BUILD)/pemdec.o: src/codec/pemdec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/pemdec.o src/codec/pemdec.c
|
||||
|
||||
$(BUILD)/ec_g_secp256r1.o: src/ec/ec_g_secp256r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_g_secp256r1.o src/ec/ec_g_secp256r1.c
|
||||
|
||||
$(BUILD)/ec_g_secp384r1.o: src/ec/ec_g_secp384r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_g_secp384r1.o src/ec/ec_g_secp384r1.c
|
||||
|
||||
$(BUILD)/ec_g_secp521r1.o: src/ec/ec_g_secp521r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_g_secp521r1.o src/ec/ec_g_secp521r1.c
|
||||
|
||||
|
||||
$(BUILD)/ec_prime_i31.o: src/ec/ec_prime_i31.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_prime_i31.o src/ec/ec_prime_i31.c
|
||||
|
||||
$(BUILD)/ec_prime_i31_secp256r1.o: src/ec/ec_prime_i31_secp256r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_prime_i31_secp256r1.o src/ec/ec_prime_i31_secp256r1.c
|
||||
|
||||
$(BUILD)/ec_prime_i31_secp384r1.o: src/ec/ec_prime_i31_secp384r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_prime_i31_secp384r1.o src/ec/ec_prime_i31_secp384r1.c
|
||||
|
||||
$(BUILD)/ec_prime_i31_secp521r1.o: src/ec/ec_prime_i31_secp521r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_prime_i31_secp521r1.o src/ec/ec_prime_i31_secp521r1.c
|
||||
|
||||
$(BUILD)/ec_secp256r1.o: src/ec/ec_secp256r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_secp256r1.o src/ec/ec_secp256r1.c
|
||||
|
||||
$(BUILD)/ec_secp384r1.o: src/ec/ec_secp384r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_secp384r1.o src/ec/ec_secp384r1.c
|
||||
|
||||
$(BUILD)/ec_secp521r1.o: src/ec/ec_secp521r1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ec_secp521r1.o src/ec/ec_secp521r1.c
|
||||
|
||||
$(BUILD)/ecdsa_atr.o: src/ec/ecdsa_atr.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ecdsa_atr.o src/ec/ecdsa_atr.c
|
||||
|
||||
$(BUILD)/ecdsa_i31_bits.o: src/ec/ecdsa_i31_bits.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ecdsa_i31_bits.o src/ec/ecdsa_i31_bits.c
|
||||
|
||||
$(BUILD)/ecdsa_i31_sign_asn1.o: src/ec/ecdsa_i31_sign_asn1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ecdsa_i31_sign_asn1.o src/ec/ecdsa_i31_sign_asn1.c
|
||||
|
||||
$(BUILD)/ecdsa_i31_sign_raw.o: src/ec/ecdsa_i31_sign_raw.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ecdsa_i31_sign_raw.o src/ec/ecdsa_i31_sign_raw.c
|
||||
|
||||
$(BUILD)/ecdsa_i31_vrfy_asn1.o: src/ec/ecdsa_i31_vrfy_asn1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ecdsa_i31_vrfy_asn1.o src/ec/ecdsa_i31_vrfy_asn1.c
|
||||
|
||||
$(BUILD)/ecdsa_i31_vrfy_raw.o: src/ec/ecdsa_i31_vrfy_raw.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ecdsa_i31_vrfy_raw.o src/ec/ecdsa_i31_vrfy_raw.c
|
||||
|
||||
$(BUILD)/ecdsa_rta.o: src/ec/ecdsa_rta.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ecdsa_rta.o src/ec/ecdsa_rta.c
|
||||
|
||||
$(BUILD)/dig_oid.o: src/hash/dig_oid.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dig_oid.o src/hash/dig_oid.c
|
||||
|
||||
$(BUILD)/dig_size.o: src/hash/dig_size.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/dig_size.o src/hash/dig_size.c
|
||||
|
||||
$(BUILD)/ghash_ctmul.o: src/hash/ghash_ctmul.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ghash_ctmul.o src/hash/ghash_ctmul.c
|
||||
|
||||
$(BUILD)/ghash_ctmul32.o: src/hash/ghash_ctmul32.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ghash_ctmul32.o src/hash/ghash_ctmul32.c
|
||||
|
||||
$(BUILD)/ghash_ctmul64.o: src/hash/ghash_ctmul64.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ghash_ctmul64.o src/hash/ghash_ctmul64.c
|
||||
|
||||
$(BUILD)/md5.o: src/hash/md5.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/md5.o src/hash/md5.c
|
||||
|
||||
$(BUILD)/md5sha1.o: src/hash/md5sha1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/md5sha1.o src/hash/md5sha1.c
|
||||
|
||||
$(BUILD)/multihash.o: src/hash/multihash.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/multihash.o src/hash/multihash.c
|
||||
|
||||
$(BUILD)/sha1.o: src/hash/sha1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/sha1.o src/hash/sha1.c
|
||||
|
||||
$(BUILD)/sha2big.o: src/hash/sha2big.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/sha2big.o src/hash/sha2big.c
|
||||
|
||||
$(BUILD)/sha2small.o: src/hash/sha2small.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/sha2small.o src/hash/sha2small.c
|
||||
|
||||
$(BUILD)/i31_add.o: src/int/i31_add.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_add.o src/int/i31_add.c
|
||||
|
||||
$(BUILD)/i31_bitlen.o: src/int/i31_bitlen.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_bitlen.o src/int/i31_bitlen.c
|
||||
|
||||
$(BUILD)/i31_decmod.o: src/int/i31_decmod.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_decmod.o src/int/i31_decmod.c
|
||||
|
||||
$(BUILD)/i31_decode.o: src/int/i31_decode.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_decode.o src/int/i31_decode.c
|
||||
|
||||
$(BUILD)/i31_decred.o: src/int/i31_decred.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_decred.o src/int/i31_decred.c
|
||||
|
||||
$(BUILD)/i31_encode.o: src/int/i31_encode.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_encode.o src/int/i31_encode.c
|
||||
|
||||
$(BUILD)/i31_fmont.o: src/int/i31_fmont.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_fmont.o src/int/i31_fmont.c
|
||||
|
||||
$(BUILD)/i31_iszero.o: src/int/i31_iszero.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_iszero.o src/int/i31_iszero.c
|
||||
|
||||
$(BUILD)/i31_modpow.o: src/int/i31_modpow.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_modpow.o src/int/i31_modpow.c
|
||||
|
||||
$(BUILD)/i31_montmul.o: src/int/i31_montmul.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_montmul.o src/int/i31_montmul.c
|
||||
|
||||
$(BUILD)/i31_mulacc.o: src/int/i31_mulacc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_mulacc.o src/int/i31_mulacc.c
|
||||
|
||||
$(BUILD)/i31_muladd.o: src/int/i31_muladd.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_muladd.o src/int/i31_muladd.c
|
||||
|
||||
$(BUILD)/i31_ninv31.o: src/int/i31_ninv31.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_ninv31.o src/int/i31_ninv31.c
|
||||
|
||||
$(BUILD)/i31_reduce.o: src/int/i31_reduce.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_reduce.o src/int/i31_reduce.c
|
||||
|
||||
$(BUILD)/i31_rshift.o: src/int/i31_rshift.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_rshift.o src/int/i31_rshift.c
|
||||
|
||||
$(BUILD)/i31_sub.o: src/int/i31_sub.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_sub.o src/int/i31_sub.c
|
||||
|
||||
$(BUILD)/i31_tmont.o: src/int/i31_tmont.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i31_tmont.o src/int/i31_tmont.c
|
||||
|
||||
$(BUILD)/i32_add.o: src/int/i32_add.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_add.o src/int/i32_add.c
|
||||
|
||||
$(BUILD)/i32_bitlen.o: src/int/i32_bitlen.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_bitlen.o src/int/i32_bitlen.c
|
||||
|
||||
$(BUILD)/i32_decmod.o: src/int/i32_decmod.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_decmod.o src/int/i32_decmod.c
|
||||
|
||||
$(BUILD)/i32_decode.o: src/int/i32_decode.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_decode.o src/int/i32_decode.c
|
||||
|
||||
$(BUILD)/i32_decred.o: src/int/i32_decred.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_decred.o src/int/i32_decred.c
|
||||
|
||||
$(BUILD)/i32_div32.o: src/int/i32_div32.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_div32.o src/int/i32_div32.c
|
||||
|
||||
$(BUILD)/i32_encode.o: src/int/i32_encode.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_encode.o src/int/i32_encode.c
|
||||
|
||||
$(BUILD)/i32_fmont.o: src/int/i32_fmont.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_fmont.o src/int/i32_fmont.c
|
||||
|
||||
$(BUILD)/i32_iszero.o: src/int/i32_iszero.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_iszero.o src/int/i32_iszero.c
|
||||
|
||||
$(BUILD)/i32_modpow.o: src/int/i32_modpow.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_modpow.o src/int/i32_modpow.c
|
||||
|
||||
$(BUILD)/i32_montmul.o: src/int/i32_montmul.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_montmul.o src/int/i32_montmul.c
|
||||
|
||||
$(BUILD)/i32_mulacc.o: src/int/i32_mulacc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_mulacc.o src/int/i32_mulacc.c
|
||||
|
||||
$(BUILD)/i32_muladd.o: src/int/i32_muladd.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_muladd.o src/int/i32_muladd.c
|
||||
|
||||
$(BUILD)/i32_ninv32.o: src/int/i32_ninv32.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_ninv32.o src/int/i32_ninv32.c
|
||||
|
||||
$(BUILD)/i32_reduce.o: src/int/i32_reduce.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_reduce.o src/int/i32_reduce.c
|
||||
|
||||
$(BUILD)/i32_sub.o: src/int/i32_sub.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_sub.o src/int/i32_sub.c
|
||||
|
||||
$(BUILD)/i32_tmont.o: src/int/i32_tmont.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/i32_tmont.o src/int/i32_tmont.c
|
||||
|
||||
$(BUILD)/hmac.o: src/mac/hmac.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/hmac.o src/mac/hmac.c
|
||||
|
||||
$(BUILD)/hmac_ct.o: src/mac/hmac_ct.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/hmac_ct.o src/mac/hmac_ct.c
|
||||
|
||||
$(BUILD)/hmac_drbg.o: src/rand/hmac_drbg.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/hmac_drbg.o src/rand/hmac_drbg.c
|
||||
|
||||
$(BUILD)/rsa_i31_pkcs1_sign.o: src/rsa/rsa_i31_pkcs1_sign.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i31_pkcs1_sign.o src/rsa/rsa_i31_pkcs1_sign.c
|
||||
|
||||
$(BUILD)/rsa_i31_pkcs1_vrfy.o: src/rsa/rsa_i31_pkcs1_vrfy.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i31_pkcs1_vrfy.o src/rsa/rsa_i31_pkcs1_vrfy.c
|
||||
|
||||
$(BUILD)/rsa_i31_priv.o: src/rsa/rsa_i31_priv.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i31_priv.o src/rsa/rsa_i31_priv.c
|
||||
|
||||
$(BUILD)/rsa_i31_pub.o: src/rsa/rsa_i31_pub.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i31_pub.o src/rsa/rsa_i31_pub.c
|
||||
|
||||
$(BUILD)/rsa_i32_pkcs1_sign.o: src/rsa/rsa_i32_pkcs1_sign.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i32_pkcs1_sign.o src/rsa/rsa_i32_pkcs1_sign.c
|
||||
|
||||
$(BUILD)/rsa_i32_pkcs1_vrfy.o: src/rsa/rsa_i32_pkcs1_vrfy.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i32_pkcs1_vrfy.o src/rsa/rsa_i32_pkcs1_vrfy.c
|
||||
|
||||
$(BUILD)/rsa_i32_priv.o: src/rsa/rsa_i32_priv.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i32_priv.o src/rsa/rsa_i32_priv.c
|
||||
|
||||
$(BUILD)/rsa_i32_pub.o: src/rsa/rsa_i32_pub.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_i32_pub.o src/rsa/rsa_i32_pub.c
|
||||
|
||||
$(BUILD)/rsa_ssl_decrypt.o: src/rsa/rsa_ssl_decrypt.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/rsa_ssl_decrypt.o src/rsa/rsa_ssl_decrypt.c
|
||||
|
||||
$(BUILD)/prf.o: src/ssl/prf.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/prf.o src/ssl/prf.c
|
||||
|
||||
$(BUILD)/prf_md5sha1.o: src/ssl/prf_md5sha1.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/prf_md5sha1.o src/ssl/prf_md5sha1.c
|
||||
|
||||
$(BUILD)/prf_sha256.o: src/ssl/prf_sha256.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/prf_sha256.o src/ssl/prf_sha256.c
|
||||
|
||||
$(BUILD)/prf_sha384.o: src/ssl/prf_sha384.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/prf_sha384.o src/ssl/prf_sha384.c
|
||||
|
||||
$(BUILD)/ssl_client.o: src/ssl/ssl_client.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_client.o src/ssl/ssl_client.c
|
||||
|
||||
$(BUILD)/ssl_client_full.o: src/ssl/ssl_client_full.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_client_full.o src/ssl/ssl_client_full.c
|
||||
|
||||
$(BUILD)/ssl_engine.o: src/ssl/ssl_engine.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_engine.o src/ssl/ssl_engine.c
|
||||
|
||||
$(BUILD)/ssl_hashes.o: src/ssl/ssl_hashes.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_hashes.o src/ssl/ssl_hashes.c
|
||||
|
||||
$(BUILD)/ssl_hs_client.o: src/ssl/ssl_hs_client.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_hs_client.o src/ssl/ssl_hs_client.c
|
||||
|
||||
$(BUILD)/ssl_hs_server.o: src/ssl/ssl_hs_server.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_hs_server.o src/ssl/ssl_hs_server.c
|
||||
|
||||
$(BUILD)/ssl_io.o: src/ssl/ssl_io.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_io.o src/ssl/ssl_io.c
|
||||
|
||||
$(BUILD)/ssl_lru.o: src/ssl/ssl_lru.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_lru.o src/ssl/ssl_lru.c
|
||||
|
||||
$(BUILD)/ssl_rec_cbc.o: src/ssl/ssl_rec_cbc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_rec_cbc.o src/ssl/ssl_rec_cbc.c
|
||||
|
||||
$(BUILD)/ssl_rec_gcm.o: src/ssl/ssl_rec_gcm.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_rec_gcm.o src/ssl/ssl_rec_gcm.c
|
||||
|
||||
$(BUILD)/ssl_server.o: src/ssl/ssl_server.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server.o src/ssl/ssl_server.c
|
||||
|
||||
$(BUILD)/ssl_server_mine2g.o: src/ssl/ssl_server_mine2g.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_mine2g.o src/ssl/ssl_server_mine2g.c
|
||||
|
||||
$(BUILD)/ssl_server_minf2g.o: src/ssl/ssl_server_minf2g.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_minf2g.o src/ssl/ssl_server_minf2g.c
|
||||
|
||||
$(BUILD)/ssl_server_minr2g.o: src/ssl/ssl_server_minr2g.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_minr2g.o src/ssl/ssl_server_minr2g.c
|
||||
|
||||
$(BUILD)/ssl_server_minu2g.o: src/ssl/ssl_server_minu2g.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_minu2g.o src/ssl/ssl_server_minu2g.c
|
||||
|
||||
$(BUILD)/ssl_server_minv2g.o: src/ssl/ssl_server_minv2g.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_minv2g.o src/ssl/ssl_server_minv2g.c
|
||||
|
||||
$(BUILD)/ssl_server_full_ec.o: src/ssl/ssl_server_full_ec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_full_ec.o src/ssl/ssl_server_full_ec.c
|
||||
|
||||
$(BUILD)/ssl_server_full_rsa.o: src/ssl/ssl_server_full_rsa.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_server_full_rsa.o src/ssl/ssl_server_full_rsa.c
|
||||
|
||||
$(BUILD)/ssl_single_ec.o: src/ssl/ssl_single_ec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_single_ec.o src/ssl/ssl_single_ec.c
|
||||
|
||||
$(BUILD)/ssl_single_rsa.o: src/ssl/ssl_single_rsa.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ssl_single_rsa.o src/ssl/ssl_single_rsa.c
|
||||
|
||||
$(BUILD)/aes_big_cbcdec.o: src/symcipher/aes_big_cbcdec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_cbcdec.o src/symcipher/aes_big_cbcdec.c
|
||||
|
||||
$(BUILD)/aes_big_cbcenc.o: src/symcipher/aes_big_cbcenc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_cbcenc.o src/symcipher/aes_big_cbcenc.c
|
||||
|
||||
$(BUILD)/aes_big_ctr.o: src/symcipher/aes_big_ctr.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_ctr.o src/symcipher/aes_big_ctr.c
|
||||
|
||||
$(BUILD)/aes_big_dec.o: src/symcipher/aes_big_dec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_dec.o src/symcipher/aes_big_dec.c
|
||||
|
||||
$(BUILD)/aes_big_enc.o: src/symcipher/aes_big_enc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_big_enc.o src/symcipher/aes_big_enc.c
|
||||
|
||||
$(BUILD)/aes_common.o: src/symcipher/aes_common.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_common.o src/symcipher/aes_common.c
|
||||
|
||||
$(BUILD)/aes_ct.o: src/symcipher/aes_ct.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct.o src/symcipher/aes_ct.c
|
||||
|
||||
$(BUILD)/aes_ct64.o: src/symcipher/aes_ct64.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct64.o src/symcipher/aes_ct64.c
|
||||
|
||||
$(BUILD)/aes_ct64_cbcdec.o: src/symcipher/aes_ct64_cbcdec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct64_cbcdec.o src/symcipher/aes_ct64_cbcdec.c
|
||||
|
||||
$(BUILD)/aes_ct64_cbcenc.o: src/symcipher/aes_ct64_cbcenc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct64_cbcenc.o src/symcipher/aes_ct64_cbcenc.c
|
||||
|
||||
$(BUILD)/aes_ct64_ctr.o: src/symcipher/aes_ct64_ctr.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct64_ctr.o src/symcipher/aes_ct64_ctr.c
|
||||
|
||||
$(BUILD)/aes_ct64_dec.o: src/symcipher/aes_ct64_dec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct64_dec.o src/symcipher/aes_ct64_dec.c
|
||||
|
||||
$(BUILD)/aes_ct64_enc.o: src/symcipher/aes_ct64_enc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct64_enc.o src/symcipher/aes_ct64_enc.c
|
||||
|
||||
$(BUILD)/aes_ct_cbcdec.o: src/symcipher/aes_ct_cbcdec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct_cbcdec.o src/symcipher/aes_ct_cbcdec.c
|
||||
|
||||
$(BUILD)/aes_ct_cbcenc.o: src/symcipher/aes_ct_cbcenc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct_cbcenc.o src/symcipher/aes_ct_cbcenc.c
|
||||
|
||||
$(BUILD)/aes_ct_ctr.o: src/symcipher/aes_ct_ctr.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct_ctr.o src/symcipher/aes_ct_ctr.c
|
||||
|
||||
$(BUILD)/aes_ct_dec.o: src/symcipher/aes_ct_dec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct_dec.o src/symcipher/aes_ct_dec.c
|
||||
|
||||
$(BUILD)/aes_ct_enc.o: src/symcipher/aes_ct_enc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_ct_enc.o src/symcipher/aes_ct_enc.c
|
||||
|
||||
$(BUILD)/aes_small_cbcdec.o: src/symcipher/aes_small_cbcdec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_small_cbcdec.o src/symcipher/aes_small_cbcdec.c
|
||||
|
||||
$(BUILD)/aes_small_cbcenc.o: src/symcipher/aes_small_cbcenc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_small_cbcenc.o src/symcipher/aes_small_cbcenc.c
|
||||
|
||||
$(BUILD)/aes_small_ctr.o: src/symcipher/aes_small_ctr.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_small_ctr.o src/symcipher/aes_small_ctr.c
|
||||
|
||||
$(BUILD)/aes_small_dec.o: src/symcipher/aes_small_dec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_small_dec.o src/symcipher/aes_small_dec.c
|
||||
|
||||
$(BUILD)/aes_small_enc.o: src/symcipher/aes_small_enc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/aes_small_enc.o src/symcipher/aes_small_enc.c
|
||||
|
||||
$(BUILD)/des_ct.o: src/symcipher/des_ct.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/des_ct.o src/symcipher/des_ct.c
|
||||
|
||||
$(BUILD)/des_ct_cbcdec.o: src/symcipher/des_ct_cbcdec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/des_ct_cbcdec.o src/symcipher/des_ct_cbcdec.c
|
||||
|
||||
$(BUILD)/des_ct_cbcenc.o: src/symcipher/des_ct_cbcenc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/des_ct_cbcenc.o src/symcipher/des_ct_cbcenc.c
|
||||
|
||||
$(BUILD)/des_support.o: src/symcipher/des_support.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/des_support.o src/symcipher/des_support.c
|
||||
|
||||
$(BUILD)/des_tab.o: src/symcipher/des_tab.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/des_tab.o src/symcipher/des_tab.c
|
||||
|
||||
$(BUILD)/des_tab_cbcdec.o: src/symcipher/des_tab_cbcdec.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/des_tab_cbcdec.o src/symcipher/des_tab_cbcdec.c
|
||||
|
||||
$(BUILD)/des_tab_cbcenc.o: src/symcipher/des_tab_cbcenc.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/des_tab_cbcenc.o src/symcipher/des_tab_cbcenc.c
|
||||
|
||||
$(BUILD)/skey_decoder.o: src/x509/skey_decoder.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/skey_decoder.o src/x509/skey_decoder.c
|
||||
|
||||
$(BUILD)/x509_decoder.o: src/x509/x509_decoder.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/x509_decoder.o src/x509/x509_decoder.c
|
||||
|
||||
$(BUILD)/x509_knownkey.o: src/x509/x509_knownkey.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/x509_knownkey.o src/x509/x509_knownkey.c
|
||||
|
||||
$(BUILD)/x509_minimal.o: src/x509/x509_minimal.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/x509_minimal.o src/x509/x509_minimal.c
|
||||
|
||||
$(BUILD)/test_crypto.o: test/test_crypto.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/test_crypto.o test/test_crypto.c
|
||||
|
||||
$(BUILD)/test_math.o: test/test_math.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/test_math.o test/test_math.c
|
||||
|
||||
$(BUILD)/test_speed.o: test/test_speed.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/test_speed.o test/test_speed.c
|
||||
|
||||
$(BUILD)/test_x509.o: test/test_x509.c $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/test_x509.o test/test_x509.c
|
||||
|
||||
$(BUILD)/brssl.o: tools/brssl.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/brssl.o tools/brssl.c
|
||||
|
||||
$(BUILD)/certs.o: tools/certs.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/certs.o tools/certs.c
|
||||
|
||||
$(BUILD)/chain.o: tools/chain.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/chain.o tools/chain.c
|
||||
|
||||
$(BUILD)/client.o: tools/client.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/client.o tools/client.c
|
||||
|
||||
$(BUILD)/errors.o: tools/errors.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/errors.o tools/errors.c
|
||||
|
||||
$(BUILD)/files.o: tools/files.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/files.o tools/files.c
|
||||
|
||||
$(BUILD)/keys.o: tools/keys.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/keys.o tools/keys.c
|
||||
|
||||
$(BUILD)/names.o: tools/names.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/names.o tools/names.c
|
||||
|
||||
$(BUILD)/server.o: tools/server.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/server.o tools/server.c
|
||||
|
||||
$(BUILD)/skey.o: tools/skey.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/skey.o tools/skey.c
|
||||
|
||||
$(BUILD)/sslio.o: tools/sslio.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/sslio.o tools/sslio.c
|
||||
|
||||
$(BUILD)/ta.o: tools/ta.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/ta.o tools/ta.c
|
||||
|
||||
$(BUILD)/vector.o: tools/vector.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/vector.o tools/vector.c
|
||||
|
||||
$(BUILD)/verify.o: tools/verify.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/verify.o tools/verify.c
|
||||
|
||||
$(BUILD)/xmem.o: tools/xmem.c tools/brssl.h $(HEADERS)
|
||||
$(CC) $(CFLAGS) -c -o $(BUILD)/xmem.o tools/xmem.c
|
||||
169
README.txt
Normal file
169
README.txt
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
# Disclaimer
|
||||
|
||||
BearSSL is for now considered alpha-level software. This means that it
|
||||
probably still has some bugs, possibly very serious ones (e.g. buffer
|
||||
overflows -- one of the perks of using C as programming language). It
|
||||
still lacks some functionalities. The API will probably change and may
|
||||
break both source and binary compatibility.
|
||||
|
||||
In other words, you would be quite mad to use it for any production
|
||||
purpose. Right now, this is 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
|
||||
|
||||
As of version 0.1, BearSSL is a simple static library. Most of the
|
||||
process is rather manual and old-style, and there is no installer (this
|
||||
will be added in a later version, in particular when all the man pages
|
||||
for BearSSL functions are written).
|
||||
|
||||
1. Have a look at the top of the `Makefile`. There you can configure the
|
||||
command names and flags for invoking the C compiler, linker, and
|
||||
static library archiver.
|
||||
|
||||
2. There are a few configurable switches in `src/config.h`. These switches
|
||||
relate to compile-time options, e.g. support of a system-provided
|
||||
random source. On usual platforms (e.g. Linux or OS X), auto-detection
|
||||
should work, but you can always override things with `config.h`.
|
||||
|
||||
3. Type `make`. This should produce the static library (`libbearssl.a`),
|
||||
the test executables (`testcrypto`, `testspeed` and `testx509`), and
|
||||
the command-line debug tool (`brssl`). You might want to run the tests:
|
||||
|
||||
- `testcrypto all` runs the cryptographic tests (test vectors on all
|
||||
implemented cryptogaphic functions). It can be slow.
|
||||
|
||||
- `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.
|
||||
|
||||
- `testx509` runs X.509 validation tests. The test certificates are
|
||||
all in `test/x509/`.
|
||||
|
||||
4. The `brssl` command-line tool 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).
|
||||
|
||||
5. 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` ans `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.
|
||||
|
||||
# API Usage
|
||||
|
||||
Right now there is little documentation. The following principles are
|
||||
maintained:
|
||||
|
||||
- All public symbols (global functions and data elements, macros) have
|
||||
a name that starts with `br_` or `BR_`.
|
||||
|
||||
- The header files (the `bearssl_*.h` in the `inc` directory) contain
|
||||
for now the most complete documentation (as comments).
|
||||
|
||||
- Context structures are allocated by the caller. BearSSL does not
|
||||
contain any single `malloc()` call; this means that there is no
|
||||
"freeing up" call to be done. When you don't need some BearSSL
|
||||
functionality, just cease to call it, and that's it.
|
||||
|
||||
- BearSSL contains no modifiable static data. It is thus thread-safe
|
||||
and reentrant, _for distinct contexts_. Accessing the same context
|
||||
structure from distinct threads, though, is a recipe for disaster.
|
||||
|
||||
- The main SSL I/O API is organised as a state machine. A running
|
||||
SSL engine (client or server) has four I/O ports:
|
||||
|
||||
- It can receive bytes from the transport medium ("record data").
|
||||
- It can send bytes to the transport medium.
|
||||
- It can receive application data, to be sent to the peer through
|
||||
the SSL tunnel.
|
||||
- It can produce application data, built from the records sent by
|
||||
the peer.
|
||||
|
||||
BearSSL never performs I/O by itself; it expects the caller to
|
||||
provide or retrieve the data. Each port consists in a pair of
|
||||
functions: one yields the pointer to the buffer from which data
|
||||
can be read or to which data can be written, and the maximum
|
||||
size for such an operation; the other function is used to
|
||||
inform the engine about how many bytes were actually read or
|
||||
written.
|
||||
|
||||
For instance, if the `br_ssl_engine_sendrec_buf()` function returns a
|
||||
non-NULL pointer, then this means that there are bytes to be sent to
|
||||
the transport medium. When the caller has indeed sent some or all of
|
||||
these bytes, it informs the engine with
|
||||
`br_ssl_engine_sendrec_ack()`.
|
||||
|
||||
This state-machine API means that the engine never blocks. Each
|
||||
invocation may trigger computations, but will always return as
|
||||
promptly as the CPU power allows. All the I/O waiting is supposed to
|
||||
be done on the outside. This structure allows managing several
|
||||
concurrent SSL engines, along with other I/O tasks, with a single
|
||||
mono-threaded loop using `select()` or `poll()`. It also makes it
|
||||
easier to integrate BearSSL with various transport mechanisms (e.g.
|
||||
messages in the EAP-TLS authentication framework).
|
||||
|
||||
- Nevertheless, there are situations where simple blocking calls _can_
|
||||
be used, and are convenient. For these situations, use the
|
||||
`br_sslio_context` wrapper. Then do blocking reads and writes with
|
||||
`br_sslio_read()` and similar functions. The sample client code
|
||||
in `samples/client_basic.c` shows how such things are done.
|
||||
112
T0/BlobWriter.cs
Normal file
112
T0/BlobWriter.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
/*
|
||||
* A simple class for writing out bytes as hexadecimal constants or
|
||||
* explicit expressions for the initializer of a C array of 'unsigned
|
||||
* char'. It starts every line with a given number of tabs, and aims at
|
||||
* keeping lines below a given threshold (each indentation tab counts as
|
||||
* 8 characters). An explicit newline is inserted before the first
|
||||
* element, and commas are used as separators.
|
||||
*/
|
||||
|
||||
class BlobWriter {
|
||||
|
||||
TextWriter w;
|
||||
int maxLineLen;
|
||||
int indent;
|
||||
int lineLen;
|
||||
|
||||
/*
|
||||
* Create a new instance. 'maxLineLen' is in characters, and
|
||||
* 'indent' is the number of tab characters at the start of
|
||||
* each line.
|
||||
*/
|
||||
internal BlobWriter(TextWriter w, int maxLineLen, int indent)
|
||||
{
|
||||
this.w = w;
|
||||
this.maxLineLen = maxLineLen;
|
||||
this.indent = indent;
|
||||
lineLen = -1;
|
||||
}
|
||||
|
||||
void DoNL()
|
||||
{
|
||||
w.WriteLine();
|
||||
for (int i = 0; i < indent; i ++) {
|
||||
w.Write('\t');
|
||||
}
|
||||
lineLen = (indent << 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a new byte value; it will be converted to an hexadecimal
|
||||
* constant in the output.
|
||||
*/
|
||||
internal void Append(byte b)
|
||||
{
|
||||
if (lineLen < 0) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(',');
|
||||
lineLen ++;
|
||||
if ((lineLen + 5) > maxLineLen) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(' ');
|
||||
lineLen ++;
|
||||
}
|
||||
}
|
||||
w.Write("0x{0:X2}", b);
|
||||
lineLen += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a C expression, which will be used as is. The expression
|
||||
* may resolve to several bytes if it uses internal commas. The
|
||||
* writer will try to honour the expected line length, but it
|
||||
* won't insert a newline character inside the expression.
|
||||
*/
|
||||
internal void Append(string expr)
|
||||
{
|
||||
if (lineLen < 0) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(',');
|
||||
lineLen ++;
|
||||
if ((lineLen + 1 + expr.Length) > maxLineLen) {
|
||||
DoNL();
|
||||
} else {
|
||||
w.Write(' ');
|
||||
lineLen ++;
|
||||
}
|
||||
}
|
||||
w.Write("{0}", expr);
|
||||
lineLen += expr.Length;
|
||||
}
|
||||
}
|
||||
181
T0/CPU.cs
Normal file
181
T0/CPU.cs
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Execution of code during compilation is done in a virtual CPU
|
||||
* incarnated by this class, that contains the relevant registers.
|
||||
*
|
||||
* Accesses to the data on the stack are mapped to accesses to an
|
||||
* internal array, with no explicit control on boundaries. Since the
|
||||
* internal array may be larger than the actual stack contents,
|
||||
* nonsensical accesses may still "work" to some extent. The whole
|
||||
* thing won't derail beyond the CLR VM, though.
|
||||
*/
|
||||
|
||||
class CPU {
|
||||
|
||||
/*
|
||||
* Next instruction to execute is in ipBuf[ipOff].
|
||||
*/
|
||||
internal Opcode[] ipBuf;
|
||||
internal int ipOff;
|
||||
|
||||
/*
|
||||
* stackBuf and stackPtr implement the data stack. The system
|
||||
* stack uses frames; 'rsp' points to the current top frame.
|
||||
*/
|
||||
TValue[] stackBuf;
|
||||
int stackPtr;
|
||||
Frame rsp;
|
||||
|
||||
internal CPU()
|
||||
{
|
||||
stackBuf = new TValue[16];
|
||||
stackPtr = -1;
|
||||
rsp = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter a function, reserving space for 'numLocals' local variables.
|
||||
*/
|
||||
internal void Enter(Opcode[] code, int numLocals)
|
||||
{
|
||||
Frame f = new Frame(rsp, numLocals);
|
||||
rsp = f;
|
||||
f.savedIpBuf = ipBuf;
|
||||
f.savedIpOff = ipOff;
|
||||
ipBuf = code;
|
||||
ipOff = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit the current function.
|
||||
*/
|
||||
internal void Exit()
|
||||
{
|
||||
ipBuf = rsp.savedIpBuf;
|
||||
ipOff = rsp.savedIpOff;
|
||||
rsp = rsp.upper;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current stack depth (number of elements).
|
||||
*/
|
||||
internal int Depth {
|
||||
get {
|
||||
return stackPtr + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a value from the stack.
|
||||
*/
|
||||
internal TValue Pop()
|
||||
{
|
||||
return stackBuf[stackPtr --];
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a value on the stack.
|
||||
*/
|
||||
internal void Push(TValue v)
|
||||
{
|
||||
int len = stackBuf.Length;
|
||||
if (++ stackPtr == len) {
|
||||
TValue[] nbuf = new TValue[len << 1];
|
||||
Array.Copy(stackBuf, 0, nbuf, 0, len);
|
||||
stackBuf = nbuf;
|
||||
}
|
||||
stackBuf[stackPtr] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look at the value at depth 'depth' (0 is top of stack). The
|
||||
* stack is unchanged.
|
||||
*/
|
||||
internal TValue Peek(int depth)
|
||||
{
|
||||
return stackBuf[stackPtr - depth];
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate the stack at depth 'depth': the value at that depth
|
||||
* is moved to the top of stack.
|
||||
*/
|
||||
internal void Rot(int depth)
|
||||
{
|
||||
TValue v = stackBuf[stackPtr - depth];
|
||||
Array.Copy(stackBuf, stackPtr - (depth - 1),
|
||||
stackBuf, stackPtr - depth, depth);
|
||||
stackBuf[stackPtr] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inverse-rotate the stack at depth 'depth': the value at the
|
||||
* top of stack is moved to that depth.
|
||||
*/
|
||||
internal void NRot(int depth)
|
||||
{
|
||||
TValue v = stackBuf[stackPtr];
|
||||
Array.Copy(stackBuf, stackPtr - depth,
|
||||
stackBuf, stackPtr - (depth - 1), depth);
|
||||
stackBuf[stackPtr - depth] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current contents of the local variable 'num'.
|
||||
*/
|
||||
internal TValue GetLocal(int num)
|
||||
{
|
||||
return rsp.locals[num];
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the contents of the local variable 'num'.
|
||||
*/
|
||||
internal void PutLocal(int num, TValue v)
|
||||
{
|
||||
rsp.locals[num] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
* The system stack really is a linked list of Frame instances.
|
||||
*/
|
||||
class Frame {
|
||||
|
||||
internal Frame upper;
|
||||
internal Opcode[] savedIpBuf;
|
||||
internal int savedIpOff;
|
||||
internal TValue[] locals;
|
||||
|
||||
internal Frame(Frame upper, int numLocals)
|
||||
{
|
||||
this.upper = upper;
|
||||
locals = new TValue[numLocals];
|
||||
}
|
||||
}
|
||||
}
|
||||
88
T0/CodeElement.cs
Normal file
88
T0/CodeElement.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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 Encode(BlobWriter bw);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
78
T0/CodeElementJump.cs
Normal file
78
T0/CodeElementJump.cs
Normal file
|
|
@ -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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementJump : CodeElement {
|
||||
|
||||
uint jumpType;
|
||||
CodeElement target;
|
||||
|
||||
internal CodeElementJump(uint jumpType)
|
||||
{
|
||||
this.jumpType = jumpType;
|
||||
}
|
||||
|
||||
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 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)
|
||||
{
|
||||
if (bw == null) {
|
||||
return Length;
|
||||
}
|
||||
int len = Encode7EUnsigned(jumpType, bw);
|
||||
int joff = JumpOff;
|
||||
if (joff == Int32.MinValue) {
|
||||
throw new Exception("Unresolved addresses");
|
||||
}
|
||||
return len + Encode7ESigned(joff, bw);
|
||||
}
|
||||
}
|
||||
46
T0/CodeElementUInt.cs
Normal file
46
T0/CodeElementUInt.cs
Normal file
|
|
@ -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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUInt : CodeElement {
|
||||
|
||||
uint val;
|
||||
|
||||
internal CodeElementUInt(uint val) : base()
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val, null);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
return Encode7EUnsigned(val, bw);
|
||||
}
|
||||
}
|
||||
56
T0/CodeElementUIntExpr.cs
Normal file
56
T0/CodeElementUIntExpr.cs
Normal file
|
|
@ -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.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val, null)
|
||||
+ (cx.GetMaxBitLength(off) + 6) / 7;
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
int len1 = 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;
|
||||
}
|
||||
}
|
||||
51
T0/CodeElementUIntInt.cs
Normal file
51
T0/CodeElementUIntInt.cs
Normal file
|
|
@ -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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntInt : CodeElement {
|
||||
|
||||
uint val1;
|
||||
int val2;
|
||||
|
||||
internal CodeElementUIntInt(uint val1, int val2) : base()
|
||||
{
|
||||
this.val1 = val1;
|
||||
this.val2 = val2;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val1, null)
|
||||
+ Encode7ESigned(val2, null);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
int len = Encode7EUnsigned(val1, bw);
|
||||
len += Encode7ESigned(val2, bw);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
50
T0/CodeElementUIntUInt.cs
Normal file
50
T0/CodeElementUIntUInt.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class CodeElementUIntUInt : CodeElement {
|
||||
|
||||
uint val1, val2;
|
||||
|
||||
internal CodeElementUIntUInt(uint val1, uint val2) : base()
|
||||
{
|
||||
this.val1 = val1;
|
||||
this.val2 = val2;
|
||||
}
|
||||
|
||||
internal override int Length {
|
||||
get {
|
||||
return Encode7EUnsigned(val1, null)
|
||||
+ Encode7EUnsigned(val2, null);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int Encode(BlobWriter bw)
|
||||
{
|
||||
int len = Encode7EUnsigned(val1, bw);
|
||||
len += Encode7EUnsigned(val2, bw);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
198
T0/ConstData.cs
Normal file
198
T0/ConstData.cs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
class ConstData {
|
||||
|
||||
internal long ID { get; private set; }
|
||||
internal int Address { get; set; }
|
||||
internal int Length {
|
||||
get {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] buf;
|
||||
int len;
|
||||
|
||||
internal ConstData(T0Comp ctx)
|
||||
{
|
||||
ID = ctx.NextBlobID();
|
||||
buf = new byte[4];
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void Expand(int elen)
|
||||
{
|
||||
int tlen = len + elen;
|
||||
if (tlen > buf.Length) {
|
||||
int nlen = Math.Max(buf.Length << 1, tlen);
|
||||
byte[] nbuf = new byte[nlen];
|
||||
Array.Copy(buf, 0, nbuf, 0, len);
|
||||
buf = nbuf;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Add8(byte b)
|
||||
{
|
||||
Expand(1);
|
||||
buf[len ++] = b;
|
||||
}
|
||||
|
||||
internal void Add16(int x)
|
||||
{
|
||||
Expand(2);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void Add24(int x)
|
||||
{
|
||||
Expand(3);
|
||||
buf[len ++] = (byte)(x >> 16);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void Add32(int x)
|
||||
{
|
||||
Expand(4);
|
||||
buf[len ++] = (byte)(x >> 24);
|
||||
buf[len ++] = (byte)(x >> 16);
|
||||
buf[len ++] = (byte)(x >> 8);
|
||||
buf[len ++] = (byte)x;
|
||||
}
|
||||
|
||||
internal void AddString(string s)
|
||||
{
|
||||
byte[] sd = Encoding.UTF8.GetBytes(s);
|
||||
Expand(sd.Length + 1);
|
||||
Array.Copy(sd, 0, buf, len, sd.Length);
|
||||
buf[len + sd.Length] = 0;
|
||||
len += sd.Length + 1;
|
||||
}
|
||||
|
||||
void CheckIndex(int off, int dlen)
|
||||
{
|
||||
if (off < 0 || off > (len - dlen)) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
internal void Set8(int off, byte v)
|
||||
{
|
||||
CheckIndex(off, 1);
|
||||
buf[off] = v;
|
||||
}
|
||||
|
||||
internal byte Read8(int off)
|
||||
{
|
||||
CheckIndex(off, 1);
|
||||
return buf[off];
|
||||
}
|
||||
|
||||
internal int Read16(int off)
|
||||
{
|
||||
CheckIndex(off, 2);
|
||||
return (buf[off] << 8) | buf[off + 1];
|
||||
}
|
||||
|
||||
internal int Read24(int off)
|
||||
{
|
||||
CheckIndex(off, 3);
|
||||
return (buf[off] << 16) | (buf[off + 1] << 8) | buf[off + 2];
|
||||
}
|
||||
|
||||
internal int Read32(int off)
|
||||
{
|
||||
CheckIndex(off, 4);
|
||||
return (buf[off] << 24) | (buf[off + 1] << 16)
|
||||
| (buf[off + 2] << 8) | buf[off + 3];
|
||||
}
|
||||
|
||||
internal string ToString(int off)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
int x = DecodeUTF8(ref off);
|
||||
if (x == 0) {
|
||||
return sb.ToString();
|
||||
}
|
||||
if (x < 0x10000) {
|
||||
sb.Append((char)x);
|
||||
} else {
|
||||
x -= 0x10000;
|
||||
sb.Append((char)(0xD800 + (x >> 10)));
|
||||
sb.Append((char)(0xDC00 + (x & 0x3FF)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DecodeUTF8(ref int off)
|
||||
{
|
||||
if (off >= len) {
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
int x = buf[off ++];
|
||||
if (x < 0xC0 || x > 0xF7) {
|
||||
return x;
|
||||
}
|
||||
int elen, acc;
|
||||
if (x >= 0xF0) {
|
||||
elen = 3;
|
||||
acc = x & 0x07;
|
||||
} else if (x >= 0xE0) {
|
||||
elen = 2;
|
||||
acc = x & 0x0F;
|
||||
} else {
|
||||
elen = 1;
|
||||
acc = x & 0x1F;
|
||||
}
|
||||
if (off + elen > len) {
|
||||
return x;
|
||||
}
|
||||
for (int i = 0; i < elen; i ++) {
|
||||
int y = buf[off + i];
|
||||
if (y < 0x80 || y >= 0xC0) {
|
||||
return x;
|
||||
}
|
||||
acc = (acc << 6) + (y & 0x3F);
|
||||
}
|
||||
if (acc > 0x10FFFF) {
|
||||
return x;
|
||||
}
|
||||
off += elen;
|
||||
return acc;
|
||||
}
|
||||
|
||||
internal void Encode(BlobWriter bw)
|
||||
{
|
||||
for (int i = 0; i < len; i ++) {
|
||||
bw.Append(buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
117
T0/Opcode.cs
Normal file
117
T0/Opcode.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
abstract class Opcode {
|
||||
|
||||
internal Opcode()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute this opcode.
|
||||
*/
|
||||
internal abstract void Run(CPU cpu);
|
||||
|
||||
/*
|
||||
* Resolve the target (word reference) for this opcode.
|
||||
*/
|
||||
internal virtual void ResolveTarget(Word target)
|
||||
{
|
||||
throw new Exception("Not a call opcode");
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve the jump offset for this opcode. Displacement is
|
||||
* relative to the address of the opcode that immediately follows
|
||||
* the jump code; thus, 0 implies no jump at all.
|
||||
*/
|
||||
internal virtual void ResolveJump(int disp)
|
||||
{
|
||||
throw new Exception("Not a jump opcode");
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the Word that this opcode references; this can happen
|
||||
* only with "call" and "const" opcodes. For all other opcodes,
|
||||
* this method returns null.
|
||||
*/
|
||||
internal virtual Word GetReference(T0Comp ctx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the data block that this opcode references; this can happen
|
||||
* only with "const" opcodes. For all other opcodes, this method
|
||||
* returns null.
|
||||
*/
|
||||
internal virtual ConstData GetDataBlock(T0Comp ctx)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether this opcode may "fall through", i.e. execution
|
||||
* may at least potentially proceed to the next opcode.
|
||||
*/
|
||||
internal virtual bool MayFallThrough {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get jump displacement. For non-jump opcodes, this returns 0.
|
||||
*/
|
||||
internal virtual int JumpDisp {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get stack effect for this opcode (number of elements added to
|
||||
* the stack, could be negative). For OpcodeCall, this returns
|
||||
* 0.
|
||||
*/
|
||||
internal virtual int StackAction {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract CodeElement ToCodeElement();
|
||||
|
||||
/*
|
||||
* This method is called for the CodeElement corresponding to
|
||||
* this opcode, at gcode[off]; it is used to compute actual
|
||||
* byte jump offsets when converting code to C.
|
||||
*/
|
||||
internal virtual void FixUp(CodeElement[] gcode, int off)
|
||||
{
|
||||
}
|
||||
}
|
||||
71
T0/OpcodeCall.cs
Normal file
71
T0/OpcodeCall.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeCall : Opcode {
|
||||
|
||||
Word target;
|
||||
|
||||
internal OpcodeCall() : this(null)
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeCall(Word target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
internal override void ResolveTarget(Word target)
|
||||
{
|
||||
if (this.target != null) {
|
||||
throw new Exception("Opcode already resolved");
|
||||
}
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
target.Run(cpu);
|
||||
}
|
||||
|
||||
internal override Word GetReference(T0Comp ctx)
|
||||
{
|
||||
if (target == null) {
|
||||
throw new Exception("Unresolved call target");
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUInt((uint)target.Slot);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "call " + (target == null ? "UNRESOLVED" : target.Name);
|
||||
}
|
||||
}
|
||||
95
T0/OpcodeConst.cs
Normal file
95
T0/OpcodeConst.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeConst : Opcode {
|
||||
|
||||
TValue val;
|
||||
|
||||
internal OpcodeConst(TValue val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Push(val);
|
||||
}
|
||||
|
||||
internal override Word GetReference(T0Comp ctx)
|
||||
{
|
||||
TPointerXT xt = val.ptr as TPointerXT;
|
||||
if (xt == null) {
|
||||
return null;
|
||||
}
|
||||
xt.Resolve(ctx);
|
||||
return xt.Target;
|
||||
}
|
||||
|
||||
internal override ConstData GetDataBlock(T0Comp ctx)
|
||||
{
|
||||
TPointerBlob bp = val.ptr as TPointerBlob;
|
||||
return bp == null ? null : bp.Blob;
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
if (val.ptr == null) {
|
||||
return new CodeElementUIntInt(1, val.Int);
|
||||
}
|
||||
TPointerXT xt = val.ptr as TPointerXT;
|
||||
if (xt != null) {
|
||||
if (val.x != 0) {
|
||||
throw new Exception(
|
||||
"Cannot compile XT: non-zero offset");
|
||||
}
|
||||
return new CodeElementUIntInt(1, xt.Target.Slot);
|
||||
}
|
||||
TPointerBlob bp = val.ptr as TPointerBlob;
|
||||
if (bp != null) {
|
||||
return new CodeElementUIntInt(1,
|
||||
val.x + bp.Blob.Address);
|
||||
}
|
||||
TPointerExpr cx = val.ptr as TPointerExpr;
|
||||
if (cx != null) {
|
||||
return new CodeElementUIntExpr(1, cx, val.x);
|
||||
}
|
||||
throw new Exception(String.Format(
|
||||
"Cannot embed constant (type = {0})",
|
||||
val.ptr.GetType().FullName));
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "const " + val.ToString();
|
||||
}
|
||||
}
|
||||
57
T0/OpcodeGetLocal.cs
Normal file
57
T0/OpcodeGetLocal.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeGetLocal : Opcode {
|
||||
|
||||
int num;
|
||||
|
||||
internal OpcodeGetLocal(int num)
|
||||
{
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Push(cpu.GetLocal(num));
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUIntUInt(2, (uint)num);
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "getlocal " + num;
|
||||
}
|
||||
}
|
||||
64
T0/OpcodeJump.cs
Normal file
64
T0/OpcodeJump.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
abstract class OpcodeJump : Opcode {
|
||||
|
||||
int disp;
|
||||
|
||||
internal OpcodeJump() : this(Int32.MinValue)
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJump(int disp)
|
||||
{
|
||||
this.disp = disp;
|
||||
}
|
||||
|
||||
internal override int JumpDisp {
|
||||
get {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.ipOff += disp;
|
||||
}
|
||||
|
||||
internal override void ResolveJump(int disp)
|
||||
{
|
||||
if (this.disp != Int32.MinValue) {
|
||||
throw new Exception("Jump already resolved");
|
||||
}
|
||||
this.disp = disp;
|
||||
}
|
||||
|
||||
internal override void FixUp(CodeElement[] gcode, int off)
|
||||
{
|
||||
gcode[off].SetJumpTarget(gcode[off + 1 + disp]);
|
||||
}
|
||||
}
|
||||
65
T0/OpcodeJumpIf.cs
Normal file
65
T0/OpcodeJumpIf.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpIf : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpIf() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpIf(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
TValue v = cpu.Pop();
|
||||
if (v.Bool) {
|
||||
base.Run(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(5);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jumpif UNRESOLVED";
|
||||
} else {
|
||||
return "jumpif disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
T0/OpcodeJumpIfNot.cs
Normal file
65
T0/OpcodeJumpIfNot.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpIfNot : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpIfNot() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpIfNot(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
TValue v = cpu.Pop();
|
||||
if (!v.Bool) {
|
||||
base.Run(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(6);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jumpifnot UNRESOLVED";
|
||||
} else {
|
||||
return "jumpifnot disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
||||
61
T0/OpcodeJumpUncond.cs
Normal file
61
T0/OpcodeJumpUncond.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeJumpUncond : OpcodeJump {
|
||||
|
||||
internal OpcodeJumpUncond() : base()
|
||||
{
|
||||
}
|
||||
|
||||
internal OpcodeJumpUncond(int disp) : base(disp)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Unconditional jumps do not "fall through" unless they
|
||||
* happen to be a jump to the next instruction...
|
||||
*/
|
||||
internal override bool MayFallThrough {
|
||||
get {
|
||||
return JumpDisp == 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementJump(4);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (JumpDisp == Int32.MinValue) {
|
||||
return "jump UNRESOLVED";
|
||||
} else {
|
||||
return "jump disp=" + JumpDisp;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
T0/OpcodePutLocal.cs
Normal file
57
T0/OpcodePutLocal.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodePutLocal : Opcode {
|
||||
|
||||
int num;
|
||||
|
||||
internal OpcodePutLocal(int num)
|
||||
{
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.PutLocal(num, cpu.Pop());
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUIntUInt(3, (uint)num);
|
||||
}
|
||||
|
||||
internal override int StackAction {
|
||||
get {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "putlocal " + num;
|
||||
}
|
||||
}
|
||||
50
T0/OpcodeRet.cs
Normal file
50
T0/OpcodeRet.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class OpcodeRet : Opcode {
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
cpu.Exit();
|
||||
}
|
||||
|
||||
internal override bool MayFallThrough {
|
||||
get {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal override CodeElement ToCodeElement()
|
||||
{
|
||||
return new CodeElementUInt(0);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "ret";
|
||||
}
|
||||
}
|
||||
129
T0/SType.cs
Normal file
129
T0/SType.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
using System;
|
||||
|
||||
/*
|
||||
* This structure contains the stack effect of a word: number of stack
|
||||
* element consumed on input, and number of stack element produced on
|
||||
* output.
|
||||
*/
|
||||
|
||||
struct SType {
|
||||
|
||||
/*
|
||||
* Get number of stack elements consumed on input; this is -1 if
|
||||
* the stack effect is not known.
|
||||
*/
|
||||
internal int DataIn {
|
||||
get {
|
||||
return din;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get number of stack elements produced on output; this is -1 if
|
||||
* either the stack effect is not known, or if the word never
|
||||
* exits.
|
||||
*/
|
||||
internal int DataOut {
|
||||
get {
|
||||
return dout;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell whether the stack effect is known.
|
||||
*/
|
||||
internal bool IsKnown {
|
||||
get {
|
||||
return din >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell whether the stack effect is known and the word never exits.
|
||||
*/
|
||||
internal bool NoExit {
|
||||
get {
|
||||
return din >= 0 && dout < 0;
|
||||
}
|
||||
}
|
||||
|
||||
int din, dout;
|
||||
|
||||
internal SType(int din, int dout)
|
||||
{
|
||||
if (din < 0) {
|
||||
din = -1;
|
||||
}
|
||||
if (dout < 0) {
|
||||
dout = -1;
|
||||
}
|
||||
this.din = din;
|
||||
this.dout = dout;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special value for the unknown stack effect.
|
||||
*/
|
||||
internal static SType UNKNOWN = new SType(-1, -1);
|
||||
|
||||
/*
|
||||
* Constant for the "blank stack effect".
|
||||
*/
|
||||
internal static SType BLANK = new SType(0, 0);
|
||||
|
||||
public static bool operator ==(SType s1, SType s2)
|
||||
{
|
||||
return s1.din == s2.din && s1.dout == s2.dout;
|
||||
}
|
||||
|
||||
public static bool operator !=(SType s1, SType s2)
|
||||
{
|
||||
return s1.din != s2.din || s1.dout != s2.dout;
|
||||
}
|
||||
|
||||
public override bool Equals(Object obj)
|
||||
{
|
||||
return (obj is SType) && ((SType)obj == this);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return din * 31 + dout * 17;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (!IsKnown) {
|
||||
return "UNKNOWN";
|
||||
} else if (NoExit) {
|
||||
return string.Format("in:{0},noexit", din);
|
||||
} else {
|
||||
return string.Format("in:{0},out:{1}", din, dout);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether this stack effect is a sub-effect of the provided
|
||||
* stack effect s. Stack effect s1 is a sub-effect of stack-effect
|
||||
* s2 if any of the following holds:
|
||||
* -- s1 and s2 are known, s1.din <= s2.din and s1 does not exit.
|
||||
* -- s1 and s2 are known, s1.din <= s2.din, s1 and s2 exit,
|
||||
* and s1.din - s1.dout == s2.din - s2.dout.
|
||||
*/
|
||||
internal bool IsSubOf(SType s)
|
||||
{
|
||||
if (!IsKnown || !s.IsKnown) {
|
||||
return false;
|
||||
}
|
||||
if (din > s.din) {
|
||||
return false;
|
||||
}
|
||||
if (NoExit) {
|
||||
return true;
|
||||
}
|
||||
if (s.NoExit) {
|
||||
return false;
|
||||
}
|
||||
return (din - dout) == (s.din - s.dout);
|
||||
}
|
||||
}
|
||||
2070
T0/T0Comp.cs
Normal file
2070
T0/T0Comp.cs
Normal file
File diff suppressed because it is too large
Load diff
64
T0/TPointerBase.cs
Normal file
64
T0/TPointerBase.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerBase {
|
||||
|
||||
/* obsolete
|
||||
internal virtual TValue Get(TValue vp)
|
||||
{
|
||||
throw new Exception(
|
||||
"cannot get values from this pointer");
|
||||
}
|
||||
|
||||
internal virtual void Set(TValue vp, TValue nval)
|
||||
{
|
||||
throw new Exception(
|
||||
"cannot set values to this pointer");
|
||||
}
|
||||
*/
|
||||
|
||||
internal virtual bool ToBool(TValue vp)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
internal virtual void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
throw new Exception("value is not an xt: " + ToString());
|
||||
}
|
||||
|
||||
internal virtual string ToString(TValue vp)
|
||||
{
|
||||
return String.Format("{0}+{1}",
|
||||
GetType().Name, vp.x);
|
||||
}
|
||||
|
||||
internal virtual bool Equals(TPointerBase tp)
|
||||
{
|
||||
return this == tp;
|
||||
}
|
||||
}
|
||||
75
T0/TPointerBlob.cs
Normal file
75
T0/TPointerBlob.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerBlob : TPointerBase {
|
||||
|
||||
internal ConstData Blob { get; private set; }
|
||||
|
||||
internal TPointerBlob(ConstData cd)
|
||||
{
|
||||
this.Blob = cd;
|
||||
}
|
||||
|
||||
internal TPointerBlob(T0Comp owner, string s)
|
||||
{
|
||||
Blob = new ConstData(owner);
|
||||
Blob.AddString(s);
|
||||
}
|
||||
|
||||
/* obsolete
|
||||
internal override TValue Get8(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read8(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get16(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read16(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get24(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read24(vp.x));
|
||||
}
|
||||
|
||||
internal override TValue Get32(TValue vp)
|
||||
{
|
||||
return new TValue((int)Blob.Read32(vp.x));
|
||||
}
|
||||
*/
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return Blob.ToString(vp.x);
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
TPointerBlob tb = tp as TPointerBlob;
|
||||
return tb != null && Blob == tb.Blob;
|
||||
}
|
||||
}
|
||||
97
T0/TPointerExpr.cs
Normal file
97
T0/TPointerExpr.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
class TPointerExpr : TPointerBase {
|
||||
|
||||
string expr;
|
||||
int min, max;
|
||||
|
||||
internal TPointerExpr(string expr, int min, int max)
|
||||
{
|
||||
this.expr = expr;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
internal override bool ToBool(TValue vp)
|
||||
{
|
||||
throw new Exception("Cannot evaluate C-expr at compile time");
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return ToCExpr(vp.x);
|
||||
}
|
||||
|
||||
internal string ToCExpr(int off)
|
||||
{
|
||||
if (off == 0) {
|
||||
return expr;
|
||||
} else if (off > 0) {
|
||||
return String.Format(
|
||||
"(uint32_t)({0}) + {1}", expr, off);
|
||||
} else {
|
||||
return String.Format(
|
||||
"(uint32_t)({0}) - {1}", expr, -(long)off);
|
||||
}
|
||||
}
|
||||
|
||||
internal int GetMaxBitLength(int off)
|
||||
{
|
||||
long rmin = (long)min + off;
|
||||
long rmax = (long)max + off;
|
||||
int numBits = 1;
|
||||
if (rmin < 0) {
|
||||
numBits = Math.Max(numBits, BitLength(rmin));
|
||||
}
|
||||
if (rmax > 0) {
|
||||
numBits = Math.Max(numBits, BitLength(rmax));
|
||||
}
|
||||
return Math.Min(numBits, 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the minimal bit length of a value. This is for a signed
|
||||
* representation: the length includes a sign bit. Thus, the
|
||||
* returned value will be at least 1.
|
||||
*/
|
||||
static int BitLength(long v)
|
||||
{
|
||||
int num = 1;
|
||||
if (v < 0) {
|
||||
while (v != -1) {
|
||||
num ++;
|
||||
v >>= 1;
|
||||
}
|
||||
} else {
|
||||
while (v != 0) {
|
||||
num ++;
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
44
T0/TPointerNull.cs
Normal file
44
T0/TPointerNull.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerNull : TPointerBase {
|
||||
|
||||
internal override bool ToBool(TValue vp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
return tp is TPointerNull;
|
||||
}
|
||||
}
|
||||
73
T0/TPointerXT.cs
Normal file
73
T0/TPointerXT.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class TPointerXT : TPointerBase {
|
||||
|
||||
internal string Name {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
internal Word Target {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
internal TPointerXT(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Target = null;
|
||||
}
|
||||
|
||||
internal TPointerXT(Word target)
|
||||
{
|
||||
this.Name = target.Name;
|
||||
this.Target = target;
|
||||
}
|
||||
|
||||
internal void Resolve(T0Comp ctx)
|
||||
{
|
||||
if (Target == null) {
|
||||
Target = ctx.Lookup(Name);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
Resolve(ctx);
|
||||
Target.Run(cpu);
|
||||
}
|
||||
|
||||
internal override string ToString(TValue vp)
|
||||
{
|
||||
return String.Format("<'{0}>", Name);
|
||||
}
|
||||
|
||||
internal override bool Equals(TPointerBase tp)
|
||||
{
|
||||
TPointerXT tx = tp as TPointerXT;
|
||||
return tx != null && Name == tx.Name;
|
||||
}
|
||||
}
|
||||
231
T0/TValue.cs
Normal file
231
T0/TValue.cs
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Each value is represented with a TValue structure. Integers use the 'x'
|
||||
* field, and 'ptr' is null; for pointers, the 'ptr' field is used, and the
|
||||
* 'x' is then an offset in the object represented by 'ptr'.
|
||||
*/
|
||||
|
||||
struct TValue {
|
||||
|
||||
internal int x;
|
||||
internal TPointerBase ptr;
|
||||
|
||||
internal TValue(int x)
|
||||
{
|
||||
this.x = x;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(uint x)
|
||||
{
|
||||
this.x = (int)x;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(bool b)
|
||||
{
|
||||
this.x = b ? -1 : 0;
|
||||
this.ptr = null;
|
||||
}
|
||||
|
||||
internal TValue(int x, TPointerBase ptr)
|
||||
{
|
||||
this.x = x;
|
||||
this.ptr = ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert this value to a boolean; integer 0 and null pointer are
|
||||
* 'false', other values are 'true'.
|
||||
*/
|
||||
internal bool Bool {
|
||||
get {
|
||||
if (ptr == null) {
|
||||
return x != 0;
|
||||
} else {
|
||||
return ptr.ToBool(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get this value as an integer. Pointers cannot be converted to
|
||||
* integers.
|
||||
*/
|
||||
internal int Int {
|
||||
get {
|
||||
if (ptr == null) {
|
||||
return x;
|
||||
}
|
||||
throw new Exception("not an integer: " + ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get this value as an unsigned integer. This is the integer
|
||||
* value, reduced modulo 2^32 in the 0..2^32-1 range.
|
||||
*/
|
||||
internal uint UInt {
|
||||
get {
|
||||
return (uint)Int;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* String format of integers uses decimal representation. For
|
||||
* pointers, this depends on the pointed-to value.
|
||||
*/
|
||||
public override string ToString()
|
||||
{
|
||||
if (ptr == null) {
|
||||
return String.Format("{0}", x);
|
||||
} else {
|
||||
return ptr.ToString(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this value is an XT, then execute it. Otherwise, an exception
|
||||
* is thrown.
|
||||
*/
|
||||
internal void Execute(T0Comp ctx, CPU cpu)
|
||||
{
|
||||
ToXT().Execute(ctx, cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert this value to an XT. On failure, an exception is thrown.
|
||||
*/
|
||||
internal TPointerXT ToXT()
|
||||
{
|
||||
TPointerXT xt = ptr as TPointerXT;
|
||||
if (xt == null) {
|
||||
throw new Exception(
|
||||
"value is not an xt: " + ToString());
|
||||
}
|
||||
return xt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare this value to another.
|
||||
*/
|
||||
internal bool Equals(TValue v)
|
||||
{
|
||||
if (x != v.x) {
|
||||
return false;
|
||||
}
|
||||
if (ptr == v.ptr) {
|
||||
return true;
|
||||
}
|
||||
if (ptr == null || v.ptr == null) {
|
||||
return false;
|
||||
}
|
||||
return ptr.Equals(v.ptr);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(bool val)
|
||||
{
|
||||
return new TValue(val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(sbyte val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(byte val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(short val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(ushort val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(char val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(int val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator TValue(uint val)
|
||||
{
|
||||
return new TValue((int)val);
|
||||
}
|
||||
|
||||
public static implicit operator bool(TValue v)
|
||||
{
|
||||
return v.Bool;
|
||||
}
|
||||
|
||||
public static implicit operator sbyte(TValue v)
|
||||
{
|
||||
return (sbyte)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator byte(TValue v)
|
||||
{
|
||||
return (byte)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator short(TValue v)
|
||||
{
|
||||
return (short)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator ushort(TValue v)
|
||||
{
|
||||
return (ushort)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator char(TValue v)
|
||||
{
|
||||
return (char)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator int(TValue v)
|
||||
{
|
||||
return (int)v.Int;
|
||||
}
|
||||
|
||||
public static implicit operator uint(TValue v)
|
||||
{
|
||||
return (uint)v.Int;
|
||||
}
|
||||
}
|
||||
172
T0/Word.cs
Normal file
172
T0/Word.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* A "word" is a function with a name. Words can be either native or
|
||||
* interpreted; native words are implemented as some in-compiler special
|
||||
* code.
|
||||
*
|
||||
* Some native words (not all of them) have a C implementation and can
|
||||
* thus be part of the generated C code. Native words with no C
|
||||
* implementation can be used only during compilation; this is typically
|
||||
* the case for words that support the syntax (e.g. 'if').
|
||||
*/
|
||||
|
||||
abstract class Word {
|
||||
|
||||
/*
|
||||
* The compiler context for this word.
|
||||
*/
|
||||
internal T0Comp TC {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Immediate words are executed immediately when encountered in the
|
||||
* source code, even while compiling another word.
|
||||
*/
|
||||
internal bool Immediate {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each word has a unique name. Names are case-sensitive.
|
||||
*/
|
||||
internal string Name {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Words are allocated slot numbers when output code is generated.
|
||||
*/
|
||||
internal int Slot {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each word may have a known stack effect.
|
||||
*/
|
||||
internal SType StackEffect {
|
||||
get; set;
|
||||
}
|
||||
|
||||
internal Word(T0Comp owner, string name)
|
||||
{
|
||||
TC = owner;
|
||||
Name = name;
|
||||
StackEffect = SType.UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolving a word means looking up all references to external
|
||||
* words.
|
||||
*/
|
||||
internal virtual void Resolve()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute this word. If the word is native, then its code is
|
||||
* run right away; if the word is interpreted, then the entry
|
||||
* sequence is executed.
|
||||
*/
|
||||
internal virtual void Run(CPU cpu)
|
||||
{
|
||||
throw new Exception(String.Format(
|
||||
"cannot run '{0}' at compile-time", Name));
|
||||
}
|
||||
|
||||
/*
|
||||
* All words may have an explicit C implementations. To be part
|
||||
* of the generated C code, a word must either be interpreted,
|
||||
* or have an explicit C implementation, or both.
|
||||
*/
|
||||
internal string CCode {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all words referenced from this one. This implies
|
||||
* resolving the word.
|
||||
*/
|
||||
internal virtual List<Word> GetReferences()
|
||||
{
|
||||
return new List<Word>();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all data blocks directly referenced from this one. This
|
||||
* implies resolving the word.
|
||||
*/
|
||||
internal virtual List<ConstData> GetDataBlocks()
|
||||
{
|
||||
return new List<ConstData>();
|
||||
}
|
||||
|
||||
/*
|
||||
* Produce the code elements for this word.
|
||||
*/
|
||||
internal virtual void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
throw new Exception("Word does not yield code elements");
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute/verify stack effect for this word.
|
||||
*/
|
||||
internal virtual void AnalyseFlow()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Get maximum data stack usage for this word. This is the number
|
||||
* of extra slots that this word may need on the data stack. If
|
||||
* the stack effect is not known, this returns -1.
|
||||
*/
|
||||
internal virtual int MaxDataStack {
|
||||
get {
|
||||
SType se = StackEffect;
|
||||
if (!se.IsKnown) {
|
||||
return -1;
|
||||
}
|
||||
if (se.NoExit) {
|
||||
return 0;
|
||||
} else {
|
||||
return Math.Min(0, se.DataOut - se.DataIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get maximum return stack usage for this word.
|
||||
*/
|
||||
internal virtual int MaxReturnStack {
|
||||
get {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
385
T0/WordBuilder.cs
Normal file
385
T0/WordBuilder.cs
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* A WordBuilder instance organizes construction of a new interpreted word.
|
||||
*
|
||||
* Opcodes are accumulated with specific methods. A control-flow stack
|
||||
* is maintained to resolve jumps.
|
||||
*
|
||||
* Each instance shall be used for only one word.
|
||||
*/
|
||||
|
||||
class WordBuilder {
|
||||
|
||||
T0Comp TC;
|
||||
string name;
|
||||
int[] cfStack;
|
||||
int cfPtr;
|
||||
List<Opcode> code;
|
||||
List<string> toResolve;
|
||||
Dictionary<string, int> locals;
|
||||
bool jumpToLast;
|
||||
|
||||
internal SType StackEffect {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new instance, with the specified word name.
|
||||
*/
|
||||
internal WordBuilder(T0Comp TC, string name)
|
||||
{
|
||||
this.TC = TC;
|
||||
this.name = name;
|
||||
cfStack = new int[16];
|
||||
cfPtr = -1;
|
||||
code = new List<Opcode>();
|
||||
toResolve = new List<string>();
|
||||
locals = new Dictionary<string, int>();
|
||||
jumpToLast = true;
|
||||
StackEffect = SType.UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the word. The control-flow stack must be empty. A 'ret'
|
||||
* opcode is automatically appended if required.
|
||||
*/
|
||||
internal Word Build()
|
||||
{
|
||||
if (cfPtr != -1) {
|
||||
throw new Exception("control-flow stack is not empty");
|
||||
}
|
||||
if (jumpToLast || code[code.Count - 1].MayFallThrough) {
|
||||
Ret();
|
||||
}
|
||||
Word w = new WordInterpreted(TC, name, locals.Count,
|
||||
code.ToArray(), toResolve.ToArray());
|
||||
w.StackEffect = StackEffect;
|
||||
return w;
|
||||
}
|
||||
|
||||
void Add(Opcode op)
|
||||
{
|
||||
Add(op, null);
|
||||
}
|
||||
|
||||
void Add(Opcode op, string refName)
|
||||
{
|
||||
code.Add(op);
|
||||
toResolve.Add(refName);
|
||||
jumpToLast = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate the control-flow stack at depth 'depth'.
|
||||
*/
|
||||
internal void CSRoll(int depth)
|
||||
{
|
||||
int x = cfStack[cfPtr - depth];
|
||||
Array.Copy(cfStack, cfPtr - (depth - 1),
|
||||
cfStack, cfPtr - depth, depth);
|
||||
cfStack[cfPtr] = x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a copy of the control-flow element at depth 'depth', and
|
||||
* push it on top of the control-flow stack.
|
||||
*/
|
||||
internal void CSPick(int depth)
|
||||
{
|
||||
int x = cfStack[cfPtr - depth];
|
||||
CSPush(x);
|
||||
}
|
||||
|
||||
void CSPush(int x)
|
||||
{
|
||||
int len = cfStack.Length;
|
||||
if (++ cfPtr == len) {
|
||||
int[] ncf = new int[len << 1];
|
||||
Array.Copy(cfStack, 0, ncf, 0, len);
|
||||
cfStack = ncf;
|
||||
}
|
||||
cfStack[cfPtr] = x;
|
||||
}
|
||||
|
||||
int CSPop()
|
||||
{
|
||||
return cfStack[cfPtr --];
|
||||
}
|
||||
|
||||
/*
|
||||
* Push an origin on the control-flow stack, corresponding to the
|
||||
* next opcode to add.
|
||||
*/
|
||||
internal void CSPushOrig()
|
||||
{
|
||||
CSPush(code.Count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a destination on the control-flow stack, corresponding to
|
||||
* the next opcode to add.
|
||||
*/
|
||||
internal void CSPushDest()
|
||||
{
|
||||
CSPush(-code.Count - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop an origin from the control-flow stack. An exception is
|
||||
* thrown if the value is not an origin.
|
||||
*/
|
||||
internal int CSPopOrig()
|
||||
{
|
||||
int x = CSPop();
|
||||
if (x < 0) {
|
||||
throw new Exception("not an origin");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop a destination from the control-flow stack. An exception is
|
||||
* thrown if the value is not a destination.
|
||||
*/
|
||||
internal int CSPopDest()
|
||||
{
|
||||
int x = CSPop();
|
||||
if (x >= 0) {
|
||||
throw new Exception("not a destination");
|
||||
}
|
||||
return -x - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "push literal" opcode.
|
||||
*/
|
||||
internal void Literal(TValue v)
|
||||
{
|
||||
Add(new OpcodeConst(v));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile a "call" by name. This method implements the support
|
||||
* for local variables:
|
||||
*
|
||||
* - If the target is '>' followed by a local variable name, then
|
||||
* a "put local" opcode is added.
|
||||
*
|
||||
* - Otherwise, if the target is a local variable name, then a
|
||||
* "get local" opcode is added.
|
||||
*
|
||||
* - Otherwise, a call to the named word is added. The target name
|
||||
* will be resolved later on (typically, when the word containing
|
||||
* the call opcode is first invoked, or when C code is generated).
|
||||
*/
|
||||
internal void Call(string target)
|
||||
{
|
||||
string lname;
|
||||
bool write;
|
||||
if (target.StartsWith(">")) {
|
||||
lname = target.Substring(1);
|
||||
write = true;
|
||||
} else {
|
||||
lname = target;
|
||||
write = false;
|
||||
}
|
||||
int lnum;
|
||||
if (locals.TryGetValue(lname, out lnum)) {
|
||||
if (write) {
|
||||
Add(new OpcodePutLocal(lnum));
|
||||
} else {
|
||||
Add(new OpcodeGetLocal(lnum));
|
||||
}
|
||||
} else {
|
||||
Add(new OpcodeCall(), target);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode to the designated word.
|
||||
*/
|
||||
internal void CallExt(Word wtarget)
|
||||
{
|
||||
Add(new OpcodeCall(wtarget), null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode to a word which is not currently resolved.
|
||||
* This method ignores local variables.
|
||||
*/
|
||||
internal void CallExt(string target)
|
||||
{
|
||||
Add(new OpcodeCall(), target);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "get local" opcode; the provided local name must already
|
||||
* be defined.
|
||||
*/
|
||||
internal void GetLocal(string name)
|
||||
{
|
||||
int lnum;
|
||||
if (locals.TryGetValue(name, out lnum)) {
|
||||
Add(new OpcodeGetLocal(lnum));
|
||||
} else {
|
||||
throw new Exception("no such local: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "put local" opcode; the provided local name must already
|
||||
* be defined.
|
||||
*/
|
||||
internal void PutLocal(string name)
|
||||
{
|
||||
int lnum;
|
||||
if (locals.TryGetValue(name, out lnum)) {
|
||||
Add(new OpcodePutLocal(lnum));
|
||||
} else {
|
||||
throw new Exception("no such local: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a new local name.
|
||||
*/
|
||||
internal void DefLocal(string lname)
|
||||
{
|
||||
if (locals.ContainsKey(lname)) {
|
||||
throw new Exception(String.Format(
|
||||
"local already defined: {0}", lname));
|
||||
}
|
||||
locals[lname] = locals.Count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "call" opcode whose target is an XT value (which may be
|
||||
* resolved or as yet unresolved).
|
||||
*/
|
||||
internal void Call(TPointerXT xt)
|
||||
{
|
||||
if (xt.Target == null) {
|
||||
Add(new OpcodeCall(), xt.Name);
|
||||
} else {
|
||||
Add(new OpcodeCall(xt.Target));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a "ret" opcode.
|
||||
*/
|
||||
internal void Ret()
|
||||
{
|
||||
Add(new OpcodeRet());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward unconditional jump. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void Ahead()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpUncond());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'true'. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void AheadIf()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpIf());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a forward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'false'. The new opcode address is
|
||||
* pushed on the control-flow stack as an origin.
|
||||
*/
|
||||
internal void AheadIfNot()
|
||||
{
|
||||
CSPushOrig();
|
||||
Add(new OpcodeJumpIfNot());
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve a previous forward jump to the current code address.
|
||||
* The top of control-flow stack is popped and must be an origin.
|
||||
*/
|
||||
internal void Then()
|
||||
{
|
||||
int x = CSPopOrig();
|
||||
code[x].ResolveJump(code.Count - x - 1);
|
||||
jumpToLast = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push the current code address on the control-flow stack as a
|
||||
* destination, to be used by an ulterior backward jump.
|
||||
*/
|
||||
internal void Begin()
|
||||
{
|
||||
CSPushDest();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward unconditional jump. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void Again()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpUncond(x - code.Count - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'true'. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void AgainIf()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpIf(x - code.Count - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a backward conditional jump, which will be taken at runtime
|
||||
* if the top-of-stack value is 'false'. The jump target is popped
|
||||
* from the control-flow stack as a destination.
|
||||
*/
|
||||
internal void AgainIfNot()
|
||||
{
|
||||
int x = CSPopDest();
|
||||
Add(new OpcodeJumpIfNot(x - code.Count - 1));
|
||||
}
|
||||
}
|
||||
96
T0/WordData.cs
Normal file
96
T0/WordData.cs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
class WordData : Word {
|
||||
|
||||
ConstData blob;
|
||||
string baseBlobName;
|
||||
int offset;
|
||||
bool ongoingResolution;
|
||||
|
||||
internal WordData(T0Comp owner, string name,
|
||||
ConstData blob, int offset)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.blob = blob;
|
||||
this.offset = offset;
|
||||
StackEffect = new SType(0, 1);
|
||||
}
|
||||
|
||||
internal WordData(T0Comp owner, string name,
|
||||
string baseBlobName, int offset)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.baseBlobName = baseBlobName;
|
||||
this.offset = offset;
|
||||
StackEffect = new SType(0, 1);
|
||||
}
|
||||
|
||||
internal override void Resolve()
|
||||
{
|
||||
if (blob != null) {
|
||||
return;
|
||||
}
|
||||
if (ongoingResolution) {
|
||||
throw new Exception(String.Format(
|
||||
"circular reference in blobs ({0})", Name));
|
||||
}
|
||||
ongoingResolution = true;
|
||||
WordData wd = TC.Lookup(baseBlobName) as WordData;
|
||||
if (wd == null) {
|
||||
throw new Exception(String.Format(
|
||||
"data word '{0}' based on non-data word '{1}'",
|
||||
Name, baseBlobName));
|
||||
}
|
||||
wd.Resolve();
|
||||
blob = wd.blob;
|
||||
offset += wd.offset;
|
||||
ongoingResolution = false;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
Resolve();
|
||||
cpu.Push(new TValue(offset, new TPointerBlob(blob)));
|
||||
}
|
||||
|
||||
internal override List<ConstData> GetDataBlocks()
|
||||
{
|
||||
Resolve();
|
||||
List<ConstData> r = new List<ConstData>();
|
||||
r.Add(blob);
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
Resolve();
|
||||
dst.Add(new CodeElementUInt(0));
|
||||
dst.Add(new CodeElementUIntInt(1, blob.Address + offset));
|
||||
dst.Add(new CodeElementUInt(0));
|
||||
}
|
||||
}
|
||||
283
T0/WordInterpreted.cs
Normal file
283
T0/WordInterpreted.cs
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* The implementation for interpreted words.
|
||||
*/
|
||||
|
||||
class WordInterpreted : Word {
|
||||
|
||||
/*
|
||||
* Get the number of local variables for this word.
|
||||
*/
|
||||
internal int NumLocals {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the sequence of opcodes for this word.
|
||||
*/
|
||||
internal Opcode[] Code {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
string[] toResolve;
|
||||
|
||||
internal WordInterpreted(T0Comp owner, string name,
|
||||
int numLocals, Opcode[] code, string[] toResolve)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.Code = code;
|
||||
this.toResolve = toResolve;
|
||||
NumLocals = numLocals;
|
||||
}
|
||||
|
||||
internal override void Resolve()
|
||||
{
|
||||
if (toResolve == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < toResolve.Length; i ++) {
|
||||
string tt = toResolve[i];
|
||||
if (tt == null) {
|
||||
continue;
|
||||
}
|
||||
Code[i].ResolveTarget(TC.Lookup(tt));
|
||||
}
|
||||
toResolve = null;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
Resolve();
|
||||
cpu.Enter(Code, NumLocals);
|
||||
}
|
||||
|
||||
internal override List<Word> GetReferences()
|
||||
{
|
||||
Resolve();
|
||||
List<Word> r = new List<Word>();
|
||||
foreach (Opcode op in Code) {
|
||||
Word w = op.GetReference(TC);
|
||||
if (w != null) {
|
||||
r.Add(w);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override List<ConstData> GetDataBlocks()
|
||||
{
|
||||
Resolve();
|
||||
List<ConstData> r = new List<ConstData>();
|
||||
foreach (Opcode op in Code) {
|
||||
ConstData cd = op.GetDataBlock(TC);
|
||||
if (cd != null) {
|
||||
r.Add(cd);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
internal override void GenerateCodeElements(List<CodeElement> dst)
|
||||
{
|
||||
Resolve();
|
||||
int n = Code.Length;
|
||||
CodeElement[] gcode = new CodeElement[n];
|
||||
for (int i = 0; i < n; i ++) {
|
||||
gcode[i] = Code[i].ToCodeElement();
|
||||
}
|
||||
for (int i = 0; i < n; i ++) {
|
||||
Code[i].FixUp(gcode, i);
|
||||
}
|
||||
dst.Add(new CodeElementUInt((uint)NumLocals));
|
||||
for (int i = 0; i < n; i ++) {
|
||||
dst.Add(gcode[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int flowAnalysis;
|
||||
int maxDataStack;
|
||||
int maxReturnStack;
|
||||
|
||||
bool MergeSA(int[] sa, int j, int c)
|
||||
{
|
||||
if (sa[j] == Int32.MinValue) {
|
||||
sa[j] = c;
|
||||
return true;
|
||||
} else if (sa[j] != c) {
|
||||
throw new Exception(string.Format(
|
||||
"In word '{0}', offset {1}:"
|
||||
+ " stack action mismatch ({2} / {3})",
|
||||
Name, j, sa[j], c));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void AnalyseFlow()
|
||||
{
|
||||
switch (flowAnalysis) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
return;
|
||||
default:
|
||||
throw new Exception("recursive call detected in '"
|
||||
+ Name + "'");
|
||||
}
|
||||
flowAnalysis = 2;
|
||||
int n = Code.Length;
|
||||
int[] sa = new int[n];
|
||||
for (int i = 0; i < n; i ++) {
|
||||
sa[i] = Int32.MinValue;
|
||||
}
|
||||
sa[0] = 0;
|
||||
int[] toExplore = new int[n];
|
||||
int tX = 0, tY = 0;
|
||||
int off = 0;
|
||||
|
||||
int exitSA = Int32.MinValue;
|
||||
int mds = 0;
|
||||
int mrs = 0;
|
||||
|
||||
int maxDepth = 0;
|
||||
|
||||
for (;;) {
|
||||
Opcode op = Code[off];
|
||||
bool mft = op.MayFallThrough;
|
||||
int c = sa[off];
|
||||
int a;
|
||||
if (op is OpcodeCall) {
|
||||
Word w = op.GetReference(TC);
|
||||
w.AnalyseFlow();
|
||||
SType se = w.StackEffect;
|
||||
if (!se.IsKnown) {
|
||||
throw new Exception(string.Format(
|
||||
"call from '{0}' to '{1}'"
|
||||
+ " with unknown stack effect",
|
||||
Name, w.Name));
|
||||
}
|
||||
if (se.NoExit) {
|
||||
mft = false;
|
||||
a = 0;
|
||||
} else {
|
||||
a = se.DataOut - se.DataIn;
|
||||
}
|
||||
mds = Math.Max(mds, c + w.MaxDataStack);
|
||||
mrs = Math.Max(mrs, w.MaxReturnStack);
|
||||
maxDepth = Math.Min(maxDepth, c - se.DataIn);
|
||||
} else if (op is OpcodeRet) {
|
||||
if (exitSA == Int32.MinValue) {
|
||||
exitSA = c;
|
||||
} else if (exitSA != c) {
|
||||
throw new Exception(string.Format(
|
||||
"'{0}': exit stack action"
|
||||
+ " mismatch: {1} / {2}"
|
||||
+ " (offset {3})",
|
||||
Name, exitSA, c, off));
|
||||
}
|
||||
a = 0;
|
||||
} else {
|
||||
a = op.StackAction;
|
||||
mds = Math.Max(mds, c + a);
|
||||
}
|
||||
c += a;
|
||||
maxDepth = Math.Min(maxDepth, c);
|
||||
|
||||
int j = op.JumpDisp;
|
||||
if (j != 0) {
|
||||
j += off + 1;
|
||||
toExplore[tY ++] = j;
|
||||
MergeSA(sa, j, c);
|
||||
}
|
||||
off ++;
|
||||
if (!mft || !MergeSA(sa, off, c)) {
|
||||
if (tX < tY) {
|
||||
off = toExplore[tX ++];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxDataStack = mds;
|
||||
maxReturnStack = 1 + NumLocals + mrs;
|
||||
|
||||
/*
|
||||
* TODO: see about this warning. Usage of a 'fail'
|
||||
* word (that does not exit) within a 'case..endcase'
|
||||
* structure will make an unreachable opcode. In a future
|
||||
* version we might want to automatically remove dead
|
||||
* opcodes.
|
||||
for (int i = 0; i < n; i ++) {
|
||||
if (sa[i] == Int32.MinValue) {
|
||||
Console.WriteLine("warning: word '{0}',"
|
||||
+ " offset {1}: unreachable opcode",
|
||||
Name, i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
SType computed;
|
||||
if (exitSA == Int32.MinValue) {
|
||||
computed = new SType(-maxDepth, -1);
|
||||
} else {
|
||||
computed = new SType(-maxDepth, -maxDepth + exitSA);
|
||||
}
|
||||
|
||||
if (StackEffect.IsKnown) {
|
||||
if (!computed.IsSubOf(StackEffect)) {
|
||||
throw new Exception(string.Format(
|
||||
"word '{0}':"
|
||||
+ " computed stack effect {1}"
|
||||
+ " does not match declared {2}",
|
||||
Name, computed.ToString(),
|
||||
StackEffect.ToString()));
|
||||
}
|
||||
} else {
|
||||
StackEffect = computed;
|
||||
}
|
||||
|
||||
flowAnalysis = 1;
|
||||
}
|
||||
|
||||
internal override int MaxDataStack {
|
||||
get {
|
||||
AnalyseFlow();
|
||||
return maxDataStack;
|
||||
}
|
||||
}
|
||||
|
||||
internal override int MaxReturnStack {
|
||||
get {
|
||||
AnalyseFlow();
|
||||
return maxReturnStack;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
T0/WordNative.cs
Normal file
59
T0/WordNative.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
* Class for native words.
|
||||
*/
|
||||
|
||||
class WordNative : Word {
|
||||
|
||||
/*
|
||||
* A type for the native implementation: a method that takes a
|
||||
* CPU as parameter, and returns nothing.
|
||||
*/
|
||||
internal delegate void NativeRun(CPU cpu);
|
||||
|
||||
NativeRun code;
|
||||
|
||||
internal WordNative(T0Comp owner, string name, NativeRun code)
|
||||
: base(owner, name)
|
||||
{
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
internal WordNative(T0Comp owner, string name,
|
||||
SType stackEffect, NativeRun code)
|
||||
: this(owner, name, code)
|
||||
{
|
||||
StackEffect = stackEffect;
|
||||
}
|
||||
|
||||
internal override void Run(CPU cpu)
|
||||
{
|
||||
code(cpu);
|
||||
}
|
||||
}
|
||||
309
T0/kern.t0
Normal file
309
T0/kern.t0
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
: \ `\n parse drop ; immediate
|
||||
|
||||
\ This file defines the core non-native functions (mainly used for
|
||||
\ parsing words, i.e. not part of the generated output). The line above
|
||||
\ defines the syntax for comments.
|
||||
|
||||
\ Define parenthesis comments.
|
||||
\ : ( `) parse drop ; immediate
|
||||
|
||||
: else postpone ahead 1 cs-roll postpone then ; immediate
|
||||
: while postpone if 1 cs-roll ; immediate
|
||||
: repeat postpone again postpone then ; immediate
|
||||
|
||||
: ['] ' ; immediate
|
||||
: [compile] compile ; immediate
|
||||
|
||||
: 2drop drop drop ;
|
||||
: dup2 over over ;
|
||||
|
||||
\ Local variables are defined with the native word '(local)'. We define
|
||||
\ a helper construction that mimics what is found in Apple's Open Firmware
|
||||
\ implementation. The syntax is: { a b ... ; c d ... }
|
||||
\ I.e. there is an opening brace, then some names. Names appearing before
|
||||
\ the semicolon are locals that are both defined and then filled with the
|
||||
\ values on stack (in stack order: { a b } fills 'b' with the top-of-stack,
|
||||
\ and 'a' with the value immediately below). Names appearing after the
|
||||
\ semicolon are not initialized.
|
||||
: __deflocal ( from_stack name -- )
|
||||
dup (local) swap if
|
||||
compile-local-write
|
||||
else
|
||||
drop
|
||||
then ;
|
||||
: __deflocals ( from_stack -- )
|
||||
next-word
|
||||
dup "}" eqstr if
|
||||
2drop ret
|
||||
then
|
||||
dup ";" eqstr if
|
||||
2drop 0 __deflocals ret
|
||||
then
|
||||
over __deflocals
|
||||
__deflocal ;
|
||||
: {
|
||||
-1 __deflocals ; immediate
|
||||
|
||||
\ Data building words.
|
||||
: data:
|
||||
new-data-block next-word define-data-word ;
|
||||
: hexb|
|
||||
0 0 { acc z }
|
||||
begin
|
||||
char
|
||||
dup `| = if
|
||||
z if "Truncated hexadecimal byte" puts cr exitvm then
|
||||
ret
|
||||
then
|
||||
dup 0x20 > if
|
||||
hexval
|
||||
z if acc 4 << + data-add8 else >acc then
|
||||
z not >z
|
||||
then
|
||||
again ;
|
||||
|
||||
\ Convert hexadecimal character to number. Complain loudly if conversion
|
||||
\ is not possible.
|
||||
: hexval ( char -- x )
|
||||
hexval-nf dup 0 < if "Not an hex digit: " puts . cr exitvm then ;
|
||||
|
||||
\ Convert hexadecimal character to number. If not an hexadecimal digit,
|
||||
\ return -1.
|
||||
: hexval-nf ( char -- x )
|
||||
dup dup `0 >= swap `9 <= and if `0 - ret then
|
||||
dup dup `A >= swap `F <= and if `A - 10 + ret then
|
||||
dup dup `a >= swap `f <= and if `a - 10 + ret then
|
||||
drop -1 ;
|
||||
|
||||
\ Convert decimal character to number. Complain loudly if conversion
|
||||
\ is not possible.
|
||||
: decval ( char -- x )
|
||||
decval-nf dup 0 < if "Not a decimal digit: " puts . cr exitvm then ;
|
||||
|
||||
\ Convert decimal character to number. If not a decimal digit,
|
||||
\ return -1.
|
||||
: decval-nf ( char -- x )
|
||||
dup dup `0 >= swap `9 <= and if `0 - ret then
|
||||
drop -1 ;
|
||||
|
||||
\ Commonly used shorthands.
|
||||
: 1+ 1 + ;
|
||||
: 2+ 2 + ;
|
||||
: 1- 1 - ;
|
||||
: 2- 2 - ;
|
||||
: 0= 0 = ;
|
||||
: 0<> 0 <> ;
|
||||
: 0< 0 < ;
|
||||
: 0> 0 > ;
|
||||
|
||||
\ Get a 16-bit value from the constant data block. This uses big-endian
|
||||
\ encoding.
|
||||
: data-get16 ( addr -- x )
|
||||
dup data-get8 8 << swap 1+ data-get8 + ;
|
||||
|
||||
\ The case..endcase construction is the equivalent of 'switch' is C.
|
||||
\ Usage:
|
||||
\ case
|
||||
\ E1 of C1 endof
|
||||
\ E2 of C2 endof
|
||||
\ ...
|
||||
\ CN
|
||||
\ endcase
|
||||
\
|
||||
\ Upon entry, it considers the TOS (let's call it X). It will then evaluate
|
||||
\ E1, which should yield a single value Y1; at that point, the X value is
|
||||
\ still on the stack, just below Y1, and must remain untouched. The 'of'
|
||||
\ word compares X with Y1; if they are equal, C1 is executed, and then
|
||||
\ control jumps to after the 'endcase'. The X value is popped from the
|
||||
\ stack immediately before evaluating C1.
|
||||
\
|
||||
\ If X and Y1 are not equal, flow proceeds to E2, to obtain a value Y2 to
|
||||
\ compare with X. And so on.
|
||||
\
|
||||
\ If none of the 'of' clauses found a match, then CN is evaluated. When CN
|
||||
\ is evaluated, the X value is on the TOS, and CN must either leave it on
|
||||
\ the stack, or replace it with exactly one value; the 'endcase' word
|
||||
\ expects (and drops) one value.
|
||||
\
|
||||
\ Implementation: this is mostly copied from ANS Forth specification,
|
||||
\ although simplified a bit because we know that our control-flow stack
|
||||
\ is independent of the data stack. During compilation, the number of
|
||||
\ clauses is maintained on the stack; each of..endof clause really is
|
||||
\ an 'if..else' that must be terminated with a matching 'then' in 'endcase'.
|
||||
|
||||
: case 0 ; immediate
|
||||
: of 1+ postpone over postpone = postpone if postpone drop ; immediate
|
||||
: endof postpone else ; immediate
|
||||
: endcase
|
||||
postpone drop
|
||||
begin dup while 1- postpone then repeat drop ; immediate
|
||||
|
||||
\ A simpler and more generic "case": there is no management for a value
|
||||
\ on the stack, and each test is supposed to come up with its own boolean
|
||||
\ value.
|
||||
: choice 0 ; immediate
|
||||
: uf 1+ postpone if ; immediate
|
||||
: ufnot 1+ postpone ifnot ; immediate
|
||||
: enduf postpone else ; immediate
|
||||
: endchoice begin dup while 1- postpone then repeat drop ; immediate
|
||||
|
||||
\ C implementations for native words that can be used in generated code.
|
||||
add-cc: co { T0_CO(); }
|
||||
add-cc: execute { T0_ENTER(ip, rp, T0_POP()); }
|
||||
add-cc: drop { (void)T0_POP(); }
|
||||
add-cc: dup { T0_PUSH(T0_PEEK(0)); }
|
||||
add-cc: swap { T0_SWAP(); }
|
||||
add-cc: over { T0_PUSH(T0_PEEK(1)); }
|
||||
add-cc: rot { T0_ROT(); }
|
||||
add-cc: -rot { T0_NROT(); }
|
||||
add-cc: roll { T0_ROLL(T0_POP()); }
|
||||
add-cc: pick { T0_PICK(T0_POP()); }
|
||||
add-cc: + {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a + b);
|
||||
}
|
||||
add-cc: - {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a - b);
|
||||
}
|
||||
add-cc: neg {
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-a);
|
||||
}
|
||||
add-cc: * {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a * b);
|
||||
}
|
||||
add-cc: / {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSHi(a / b);
|
||||
}
|
||||
add-cc: u/ {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a / b);
|
||||
}
|
||||
add-cc: % {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSHi(a % b);
|
||||
}
|
||||
add-cc: u% {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a % b);
|
||||
}
|
||||
add-cc: < {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
}
|
||||
add-cc: <= {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
}
|
||||
add-cc: > {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a > b));
|
||||
}
|
||||
add-cc: >= {
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
}
|
||||
add-cc: = {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a == b));
|
||||
}
|
||||
add-cc: <> {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a != b));
|
||||
}
|
||||
add-cc: u< {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
}
|
||||
add-cc: u<= {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
}
|
||||
add-cc: u> {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a > b));
|
||||
}
|
||||
add-cc: u>= {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
}
|
||||
add-cc: and {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a & b);
|
||||
}
|
||||
add-cc: or {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a | b);
|
||||
}
|
||||
add-cc: xor {
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a ^ b);
|
||||
}
|
||||
add-cc: not {
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(~a);
|
||||
}
|
||||
add-cc: << {
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x << c);
|
||||
}
|
||||
add-cc: >> {
|
||||
int c = (int)T0_POPi();
|
||||
int32_t x = T0_POPi();
|
||||
T0_PUSHi(x >> c);
|
||||
}
|
||||
add-cc: u>> {
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x >> c);
|
||||
}
|
||||
add-cc: data-get8 {
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(t0_datablock[addr]);
|
||||
}
|
||||
|
||||
add-cc: . {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf(" %ld", (long)T0_POPi());
|
||||
}
|
||||
add-cc: putc {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("%c", (char)T0_POPi());
|
||||
}
|
||||
add-cc: puts {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("%s", &t0_datablock[T0_POPi()]);
|
||||
}
|
||||
add-cc: cr {
|
||||
extern int printf(const char *fmt, ...);
|
||||
printf("\n");
|
||||
}
|
||||
add-cc: eqstr {
|
||||
const void *b = &t0_datablock[T0_POPi()];
|
||||
const void *a = &t0_datablock[T0_POPi()];
|
||||
T0_PUSH(-(int32_t)(strcmp(a, b) == 0));
|
||||
}
|
||||
BIN
T0Comp.exe
Executable file
BIN
T0Comp.exe
Executable file
Binary file not shown.
0
build/.do_not_remove
Normal file
0
build/.do_not_remove
Normal file
42
inc/bearssl.h
Normal file
42
inc/bearssl.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
#include "bearssl_rand.h"
|
||||
#include "bearssl_prf.h"
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_rsa.h"
|
||||
#include "bearssl_ec.h"
|
||||
#include "bearssl_ssl.h"
|
||||
#include "bearssl_x509.h"
|
||||
#include "bearssl_pem.h"
|
||||
|
||||
#endif
|
||||
476
inc/bearssl_block.h
Normal file
476
inc/bearssl_block.h
Normal file
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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>
|
||||
|
||||
/*
|
||||
* Block Ciphers
|
||||
* -------------
|
||||
*
|
||||
* 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,
|
||||
* initialized with the encryption key. Each set of functions is
|
||||
* provided both as named functions, and through an OOP interface.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* 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 size (in bytes) of the context structure for subkeys
|
||||
* block_size cipher block size (in bytes)
|
||||
* log_block_size base-2 logarithm of cipher block size
|
||||
* init pointer to the key expansion function
|
||||
* run pointer to the encryption/decryption function
|
||||
*
|
||||
* Static, constant instances of these structures are defined, under
|
||||
* the names:
|
||||
*
|
||||
* br_xxx_cbcenc_vtable
|
||||
* br_xxx_cbcdec_vtable
|
||||
* br_xxx_ctr_vtable
|
||||
*
|
||||
*
|
||||
* Implemented Block Ciphers
|
||||
* -------------------------
|
||||
*
|
||||
* Function Name Allowed key lengths (bytes)
|
||||
*
|
||||
* AES aes_ct 16, 24 and 32
|
||||
* AES aes_ct64 16, 24 and 32
|
||||
* AES aes_big 16, 24 and 32
|
||||
* AES aes_small 16, 24 and 32
|
||||
* DES des_ct 8, 16 and 24
|
||||
* DES des_tab 8, 16 and 24
|
||||
*
|
||||
* '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, for faster processing
|
||||
* on 64-bit machines.
|
||||
*
|
||||
* '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'.
|
||||
*/
|
||||
|
||||
typedef struct br_block_cbcenc_class_ br_block_cbcenc_class;
|
||||
struct br_block_cbcenc_class_ {
|
||||
size_t context_size;
|
||||
unsigned block_size;
|
||||
unsigned log_block_size;
|
||||
void (*init)(const br_block_cbcenc_class **ctx,
|
||||
const void *key, size_t key_len);
|
||||
void (*run)(const br_block_cbcenc_class *const *ctx,
|
||||
void *iv, void *data, size_t len);
|
||||
};
|
||||
|
||||
typedef struct br_block_cbcdec_class_ br_block_cbcdec_class;
|
||||
struct br_block_cbcdec_class_ {
|
||||
size_t context_size;
|
||||
unsigned block_size;
|
||||
unsigned log_block_size;
|
||||
void (*init)(const br_block_cbcdec_class **ctx,
|
||||
const void *key, size_t key_len);
|
||||
void (*run)(const br_block_cbcdec_class *const *ctx,
|
||||
void *iv, void *data, size_t len);
|
||||
};
|
||||
|
||||
typedef struct br_block_ctr_class_ br_block_ctr_class;
|
||||
struct br_block_ctr_class_ {
|
||||
size_t context_size;
|
||||
unsigned block_size;
|
||||
unsigned log_block_size;
|
||||
void (*init)(const br_block_ctr_class **ctx,
|
||||
const void *key, size_t key_len);
|
||||
uint32_t (*run)(const br_block_ctr_class *const *ctx,
|
||||
const void *iv, uint32_t cc, 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.
|
||||
*/
|
||||
#define br_aes_big_BLOCK_SIZE 16
|
||||
typedef struct {
|
||||
const br_block_cbcenc_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_big_cbcenc_keys;
|
||||
typedef struct {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_big_cbcdec_keys;
|
||||
typedef struct {
|
||||
const br_block_ctr_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_big_ctr_keys;
|
||||
extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable;
|
||||
extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable;
|
||||
extern const br_block_ctr_class br_aes_big_ctr_vtable;
|
||||
void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define br_aes_small_BLOCK_SIZE 16
|
||||
typedef struct {
|
||||
const br_block_cbcenc_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_small_cbcenc_keys;
|
||||
typedef struct {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_small_cbcdec_keys;
|
||||
typedef struct {
|
||||
const br_block_ctr_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_small_ctr_keys;
|
||||
extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable;
|
||||
extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable;
|
||||
extern const br_block_ctr_class br_aes_small_ctr_vtable;
|
||||
void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define br_aes_ct_BLOCK_SIZE 16
|
||||
typedef struct {
|
||||
const br_block_cbcenc_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_ct_cbcenc_keys;
|
||||
typedef struct {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_ct_cbcdec_keys;
|
||||
typedef struct {
|
||||
const br_block_ctr_class *vtable;
|
||||
uint32_t skey[60];
|
||||
unsigned num_rounds;
|
||||
} br_aes_ct_ctr_keys;
|
||||
extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable;
|
||||
extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable;
|
||||
extern const br_block_ctr_class br_aes_ct_ctr_vtable;
|
||||
void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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.)
|
||||
*/
|
||||
#define br_aes_ct64_BLOCK_SIZE 16
|
||||
typedef struct {
|
||||
const br_block_cbcenc_class *vtable;
|
||||
uint64_t skey[30];
|
||||
unsigned num_rounds;
|
||||
} br_aes_ct64_cbcenc_keys;
|
||||
typedef struct {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
uint64_t skey[30];
|
||||
unsigned num_rounds;
|
||||
} br_aes_ct64_cbcdec_keys;
|
||||
typedef struct {
|
||||
const br_block_ctr_class *vtable;
|
||||
uint64_t skey[30];
|
||||
unsigned num_rounds;
|
||||
} br_aes_ct64_ctr_keys;
|
||||
extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable;
|
||||
extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable;
|
||||
extern const br_block_ctr_class br_aes_ct64_ctr_vtable;
|
||||
void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
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);
|
||||
|
||||
/*
|
||||
* These structures are large enough to accommodate subkeys for all
|
||||
* AES implementations.
|
||||
*/
|
||||
typedef union {
|
||||
const br_block_cbcenc_class *vtable;
|
||||
br_aes_big_cbcenc_keys big;
|
||||
br_aes_small_cbcenc_keys small;
|
||||
br_aes_ct_cbcenc_keys ct;
|
||||
br_aes_ct64_cbcenc_keys ct64;
|
||||
} br_aes_gen_cbcenc_keys;
|
||||
typedef union {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
br_aes_big_cbcdec_keys big;
|
||||
br_aes_small_cbcdec_keys small;
|
||||
br_aes_ct_cbcdec_keys ct;
|
||||
br_aes_ct64_cbcdec_keys ct64;
|
||||
} br_aes_gen_cbcdec_keys;
|
||||
typedef union {
|
||||
const br_block_ctr_class *vtable;
|
||||
br_aes_big_ctr_keys big;
|
||||
br_aes_small_ctr_keys small;
|
||||
br_aes_ct_ctr_keys ct;
|
||||
br_aes_ct64_ctr_keys ct64;
|
||||
} br_aes_gen_ctr_keys;
|
||||
|
||||
/*
|
||||
* Traditional, table-based implementation for DES/3DES. Since tables are
|
||||
* used, cache-timing attacks are conceptually possible.
|
||||
*/
|
||||
#define br_des_tab_BLOCK_SIZE 8
|
||||
typedef struct {
|
||||
const br_block_cbcenc_class *vtable;
|
||||
uint32_t skey[96];
|
||||
unsigned num_rounds;
|
||||
} br_des_tab_cbcenc_keys;
|
||||
typedef struct {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
uint32_t skey[96];
|
||||
unsigned num_rounds;
|
||||
} br_des_tab_cbcdec_keys;
|
||||
extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable;
|
||||
extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable;
|
||||
void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
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.
|
||||
*/
|
||||
#define br_des_ct_BLOCK_SIZE 8
|
||||
typedef struct {
|
||||
const br_block_cbcenc_class *vtable;
|
||||
uint32_t skey[96];
|
||||
unsigned num_rounds;
|
||||
} br_des_ct_cbcenc_keys;
|
||||
typedef struct {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
uint32_t skey[96];
|
||||
unsigned num_rounds;
|
||||
} br_des_ct_cbcdec_keys;
|
||||
extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable;
|
||||
extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable;
|
||||
void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx,
|
||||
const void *key, size_t len);
|
||||
void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv,
|
||||
void *data, size_t len);
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
typedef union {
|
||||
const br_block_cbcdec_class *vtable;
|
||||
br_des_tab_cbcdec_keys tab;
|
||||
br_des_ct_cbcdec_keys ct;
|
||||
} br_des_gen_cbcdec_keys;
|
||||
|
||||
#endif
|
||||
220
inc/bearssl_ec.h
Normal file
220
inc/bearssl_ec.h
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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>
|
||||
|
||||
/*
|
||||
* Elliptic Curves
|
||||
* ---------------
|
||||
*
|
||||
* 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
|
||||
* }
|
||||
*
|
||||
* Low-level implementations defined here work on the "raw" format.
|
||||
* Conversion functions are provided.
|
||||
*
|
||||
* Note that for a given signature, the "raw" format is not fully
|
||||
* deterministic, in that it does not enforce a minimal common length.
|
||||
* The functions below MUST ensure, when producing signatures, that
|
||||
* the signature length never exceeds 2*qlen, where qlen is the length,
|
||||
* in bytes, of the minimal unsigned big-endian encoding of the curve
|
||||
* subgroup order.
|
||||
*
|
||||
* Conversion of a "raw" format signature into "asn1" may enlarge a
|
||||
* signature by no more than 9 bytes for all supported curves.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
#define BR_EC_sect163k1 1
|
||||
#define BR_EC_sect163r1 2
|
||||
#define BR_EC_sect163r2 3
|
||||
#define BR_EC_sect193r1 4
|
||||
#define BR_EC_sect193r2 5
|
||||
#define BR_EC_sect233k1 6
|
||||
#define BR_EC_sect233r1 7
|
||||
#define BR_EC_sect239k1 8
|
||||
#define BR_EC_sect283k1 9
|
||||
#define BR_EC_sect283r1 10
|
||||
#define BR_EC_sect409k1 11
|
||||
#define BR_EC_sect409r1 12
|
||||
#define BR_EC_sect571k1 13
|
||||
#define BR_EC_sect571r1 14
|
||||
#define BR_EC_secp160k1 15
|
||||
#define BR_EC_secp160r1 16
|
||||
#define BR_EC_secp160r2 17
|
||||
#define BR_EC_secp192k1 18
|
||||
#define BR_EC_secp192r1 19
|
||||
#define BR_EC_secp224k1 20
|
||||
#define BR_EC_secp224r1 21
|
||||
#define BR_EC_secp256k1 22
|
||||
#define BR_EC_secp256r1 23
|
||||
#define BR_EC_secp384r1 24
|
||||
#define BR_EC_secp521r1 25
|
||||
#define BR_EC_brainpoolP256r1 26
|
||||
#define BR_EC_brainpoolP384r1 27
|
||||
#define BR_EC_brainpoolP512r1 28
|
||||
|
||||
/*
|
||||
* Structure for an EC public key.
|
||||
*/
|
||||
typedef struct {
|
||||
int curve;
|
||||
unsigned char *q;
|
||||
size_t qlen;
|
||||
} br_ec_public_key;
|
||||
|
||||
/*
|
||||
* Structure for an EC private key.
|
||||
*/
|
||||
typedef struct {
|
||||
int curve;
|
||||
unsigned char *x;
|
||||
size_t xlen;
|
||||
} br_ec_private_key;
|
||||
|
||||
/*
|
||||
* Type for an EC implementation.
|
||||
*
|
||||
* supported_curves
|
||||
* Bit mask for supported curves: if curve 'id' is supported, then
|
||||
* bit '1 << id' is set.
|
||||
*
|
||||
* generator
|
||||
* Get a pointer to the conventional generator for a given curve.
|
||||
*
|
||||
* order
|
||||
* Get a pointer to the curve order (minimal unsigned big-endian
|
||||
* encoding).
|
||||
*
|
||||
* mul
|
||||
* Compute x*G. Provided point G (encoded size Glen) must be valid and
|
||||
* distinct from the point at infinity. 'x' must be non-zero and less
|
||||
* than the curve order. On error, 0 is returned; an invalid G (or
|
||||
* point at infinity) is always detected, as well as a case of x = 0.
|
||||
* However, if x is a non-zero multiple of the curve order, then it is
|
||||
* not guaranteed that an error is reported.
|
||||
*
|
||||
* muladd
|
||||
* compute x*A+y*B, result being written over A. Points and multipliers
|
||||
* must fulfill the same conditions as for mul().
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t supported_curves;
|
||||
const unsigned char *(*generator)(int curve, size_t *len);
|
||||
const unsigned char *(*order)(int curve, size_t *len);
|
||||
uint32_t (*mul)(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
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;
|
||||
|
||||
/*
|
||||
* The 'i31' implementation for elliptic curves. 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;
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len);
|
||||
|
||||
/*
|
||||
* Convert a signature from "asn1" to "raw". Conversion is done "in
|
||||
* place" and the new length is returned. Conversion in that direction
|
||||
* always reduced signature length. On error, 0 is returned (error
|
||||
* conditions include an invalid signature format or an oversized
|
||||
* integer).
|
||||
*/
|
||||
size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Verify ECDSA signature. Returned value is 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);
|
||||
|
||||
/*
|
||||
* ECDSA implementation using the "i31" integers.
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
#endif
|
||||
424
inc/bearssl_hash.h
Normal file
424
inc/bearssl_hash.h
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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>
|
||||
|
||||
/*
|
||||
* Hash Functions
|
||||
* --------------
|
||||
*
|
||||
* For hash function '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: the numerical value of these identifiers MUST match the
|
||||
* constants for hash function identification in TLS 1.2 (see RFC
|
||||
* 5246, section 7.4.1.4.1). These are values 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)
|
||||
* Initialize the provided context. Previous contents of the structure
|
||||
* are ignored. This calls resets the context to the start of a new
|
||||
* hash computation.
|
||||
*
|
||||
* 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 accomodate 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.
|
||||
*
|
||||
* 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.)
|
||||
*
|
||||
*
|
||||
* An object-oriented API is also available: the first field of the
|
||||
* context is a pointer to a br_hash_class structure, that has the
|
||||
* following contents:
|
||||
*
|
||||
* context_size total size of the required context structure
|
||||
* desc descriptor (see below)
|
||||
* init context initialization or reset (function pointer)
|
||||
* update process some more bytes (function pointer)
|
||||
* out get hash output so far (function pointer)
|
||||
* state get copy of internal state (function pointer)
|
||||
* set_state reset the internal state (function pointer)
|
||||
*
|
||||
* The descriptor is a combination of the following elements:
|
||||
* bits 0 to 7 hash algorithm identifier
|
||||
* bits 8 to 14 hash output size (in bytes)
|
||||
* bits 15 to 22 hash internal state size (in bytes)
|
||||
* bits 23 to 26 log (base 2) of hash internal block size (in bytes)
|
||||
* bit 28 1 if using MD padding, 0 otherwise
|
||||
* bit 29 1 if MD padding uses a 128-bit bit length, 0 otherwise
|
||||
* bit 30 1 if MD padding is big-endian, 0 otherwise
|
||||
*
|
||||
* For function 'xxx', the br_xxx_init() function sets the first field
|
||||
* to a pointer to the relevant br_hash_class instance (i.e.
|
||||
* br_xxx_vtable).
|
||||
*
|
||||
* Users of this object-oriented API 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 2^4 and no more
|
||||
* than 2^8.
|
||||
* For functions that do not have an internal block size that is a
|
||||
* power of 2, the relevant element is 0.
|
||||
*/
|
||||
|
||||
typedef struct br_hash_class_ br_hash_class;
|
||||
struct br_hash_class_ {
|
||||
size_t context_size;
|
||||
uint32_t desc;
|
||||
void (*init)(const br_hash_class **ctx);
|
||||
void (*update)(const br_hash_class **ctx, const void *data, size_t len);
|
||||
void (*out)(const br_hash_class *const *ctx, void *dst);
|
||||
uint64_t (*state)(const br_hash_class *const *ctx, void *dst);
|
||||
void (*set_state)(const br_hash_class **ctx,
|
||||
const void *stb, uint64_t count);
|
||||
};
|
||||
|
||||
#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)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define br_md5_ID 1
|
||||
#define br_md5_SIZE 16
|
||||
extern const br_hash_class br_md5_vtable;
|
||||
typedef struct {
|
||||
const br_hash_class *vtable;
|
||||
unsigned char buf[64];
|
||||
uint64_t count;
|
||||
uint32_t val[4];
|
||||
} br_md5_context;
|
||||
void br_md5_init(br_md5_context *ctx);
|
||||
void br_md5_update(br_md5_context *ctx, const void *data, size_t len);
|
||||
void br_md5_out(const br_md5_context *ctx, void *out);
|
||||
uint64_t br_md5_state(const br_md5_context *ctx, void *out);
|
||||
void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count);
|
||||
|
||||
#define br_sha1_ID 2
|
||||
#define br_sha1_SIZE 20
|
||||
extern const br_hash_class br_sha1_vtable;
|
||||
typedef struct {
|
||||
const br_hash_class *vtable;
|
||||
unsigned char buf[64];
|
||||
uint64_t count;
|
||||
uint32_t val[5];
|
||||
} br_sha1_context;
|
||||
void br_sha1_init(br_sha1_context *ctx);
|
||||
void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len);
|
||||
void br_sha1_out(const br_sha1_context *ctx, void *out);
|
||||
uint64_t br_sha1_state(const br_sha1_context *ctx, void *out);
|
||||
void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count);
|
||||
|
||||
#define br_sha224_ID 3
|
||||
#define br_sha224_SIZE 28
|
||||
extern const br_hash_class br_sha224_vtable;
|
||||
typedef struct {
|
||||
const br_hash_class *vtable;
|
||||
unsigned char buf[64];
|
||||
uint64_t count;
|
||||
uint32_t val[8];
|
||||
} br_sha224_context;
|
||||
void br_sha224_init(br_sha224_context *ctx);
|
||||
void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len);
|
||||
void br_sha224_out(const br_sha224_context *ctx, void *out);
|
||||
uint64_t br_sha224_state(const br_sha224_context *ctx, void *out);
|
||||
void br_sha224_set_state(br_sha224_context *ctx,
|
||||
const void *stb, uint64_t count);
|
||||
|
||||
#define br_sha256_ID 4
|
||||
#define br_sha256_SIZE 32
|
||||
extern const br_hash_class br_sha256_vtable;
|
||||
typedef br_sha224_context br_sha256_context;
|
||||
void br_sha256_init(br_sha256_context *ctx);
|
||||
#define br_sha256_update br_sha224_update
|
||||
void br_sha256_out(const br_sha256_context *ctx, void *out);
|
||||
#define br_sha256_state br_sha224_state
|
||||
#define br_sha256_set_state br_sha224_set_state
|
||||
|
||||
#define br_sha384_ID 5
|
||||
#define br_sha384_SIZE 48
|
||||
extern const br_hash_class br_sha384_vtable;
|
||||
typedef struct {
|
||||
const br_hash_class *vtable;
|
||||
unsigned char buf[128];
|
||||
uint64_t count;
|
||||
uint64_t val[8];
|
||||
} br_sha384_context;
|
||||
void br_sha384_init(br_sha384_context *ctx);
|
||||
void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len);
|
||||
void br_sha384_out(const br_sha384_context *ctx, void *out);
|
||||
uint64_t br_sha384_state(const br_sha384_context *ctx, void *out);
|
||||
void br_sha384_set_state(br_sha384_context *ctx,
|
||||
const void *stb, uint64_t count);
|
||||
|
||||
#define br_sha512_ID 6
|
||||
#define br_sha512_SIZE 64
|
||||
extern const br_hash_class br_sha512_vtable;
|
||||
typedef br_sha384_context br_sha512_context;
|
||||
void br_sha512_init(br_sha512_context *ctx);
|
||||
#define br_sha512_update br_sha384_update
|
||||
void br_sha512_out(const br_sha512_context *ctx, void *out);
|
||||
#define br_sha512_state br_sha384_state
|
||||
#define br_sha512_set_state br_sha384_set_state
|
||||
|
||||
/*
|
||||
* "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.
|
||||
*/
|
||||
#define br_md5sha1_ID 0
|
||||
#define br_md5sha1_SIZE 36
|
||||
extern const br_hash_class br_md5sha1_vtable;
|
||||
typedef struct {
|
||||
const br_hash_class *vtable;
|
||||
unsigned char buf[64];
|
||||
uint64_t count;
|
||||
uint32_t val_md5[4];
|
||||
uint32_t val_sha1[5];
|
||||
} br_md5sha1_context;
|
||||
void br_md5sha1_init(br_md5sha1_context *ctx);
|
||||
void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len);
|
||||
void br_md5sha1_out(const br_md5sha1_context *ctx, void *out);
|
||||
uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out);
|
||||
void br_md5sha1_set_state(br_md5sha1_context *ctx,
|
||||
const void *stb, uint64_t count);
|
||||
|
||||
/*
|
||||
* 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_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.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
unsigned char buf[128];
|
||||
uint64_t count;
|
||||
uint32_t val_32[25];
|
||||
uint64_t val_64[16];
|
||||
const br_hash_class *impl[6];
|
||||
} br_multihash_context;
|
||||
|
||||
/*
|
||||
* Clear a complete multihash context. This should always be called once
|
||||
* on a given context, before setting implementation pointers.
|
||||
*/
|
||||
void br_multihash_zero(br_multihash_context *ctx);
|
||||
|
||||
/*
|
||||
* Set a hash function implementation, identified by ID.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the configured hash implementation, identified by ID. This returns
|
||||
* NULL for unsupported hash implementations. The hash identifier MUST
|
||||
* be a valid one (from br_md5_ID to br_sha512_ID, inclusive).
|
||||
*/
|
||||
static inline const br_hash_class *
|
||||
br_multihash_getimpl(const br_multihash_context *ctx, int id)
|
||||
{
|
||||
return ctx->impl[id - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset a multihash context. The hash functions for which implementation
|
||||
* pointers have been set are reset and initialized.
|
||||
*/
|
||||
void br_multihash_init(br_multihash_context *ctx);
|
||||
|
||||
/*
|
||||
* Input some bytes into the context.
|
||||
*/
|
||||
void br_multihash_update(br_multihash_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Get the hash of the bytes injected so far, with the specified hash
|
||||
* function. The hash function is given by ID (e.g. br_md5_ID for MD5).
|
||||
* The hash output is written on 'dst'. The hash length is returned (in
|
||||
* bytes); if the specified hash function is not implemented by this
|
||||
* context, then this function returns 0.
|
||||
*
|
||||
* Obtaining the hash output does not invalidate the current hashing
|
||||
* operation, thus "partial hashes" can be obtained.
|
||||
*/
|
||||
size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Implementation of GHASH using normal 32x32->64 multiplications. It is
|
||||
* constant-time (if multiplications are constant-time).
|
||||
*/
|
||||
void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Implementation of GHASH using normal 32x32->32 multiplications; this
|
||||
* may be faster than br_ghash_ctmul() on platforms for which the inner
|
||||
* multiplication opcode does not yield the upper 32 bits of the product.
|
||||
* It is constant-time (if multiplications are constant-time).
|
||||
*/
|
||||
void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Implementation of GHASH using 64x64->64 multiplications. It is
|
||||
* constant-time (if multiplications are constant-time).
|
||||
*/
|
||||
void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len);
|
||||
|
||||
#endif
|
||||
148
inc/bearssl_hmac.h
Normal file
148
inc/bearssl_hmac.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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"
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Key context.
|
||||
*/
|
||||
typedef struct {
|
||||
const br_hash_class *dig_vtable;
|
||||
unsigned char ksi[64], kso[64];
|
||||
} br_hmac_key_context;
|
||||
|
||||
/*
|
||||
* Initialize the key context with the provided key, using the hash function
|
||||
* identified by digest_class.
|
||||
*/
|
||||
void br_hmac_key_init(br_hmac_key_context *kc,
|
||||
const br_hash_class *digest_class, const void *key, size_t key_len);
|
||||
|
||||
/*
|
||||
* A helper structure that is big enough to accommodate all context
|
||||
* structures for all hash functions for which HMAC is supported.
|
||||
*/
|
||||
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_hmac_allhash_context;
|
||||
|
||||
/*
|
||||
* Context for an HMAC computation.
|
||||
*/
|
||||
typedef struct {
|
||||
br_hmac_allhash_context dig;
|
||||
unsigned char kso[64];
|
||||
size_t out_len;
|
||||
} br_hmac_context;
|
||||
|
||||
/*
|
||||
* Initialize 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.
|
||||
*/
|
||||
void br_hmac_init(br_hmac_context *ctx,
|
||||
const br_hmac_key_context *kc, size_t out_len);
|
||||
|
||||
/*
|
||||
* Get the MAC output size. The context must have been initialized.
|
||||
*/
|
||||
#define br_hmac_size(ctx) ((ctx)->out_len)
|
||||
|
||||
/*
|
||||
* Process some more bytes.
|
||||
*/
|
||||
void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Compute the HMAC output. The destination buffer MUST be large enough
|
||||
* to accomodate the result. 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).
|
||||
*/
|
||||
size_t br_hmac_out(const br_hmac_context *ctx, void *out);
|
||||
|
||||
/*
|
||||
* 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 bytes 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^30.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Returned value is the MAC 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);
|
||||
|
||||
#endif
|
||||
125
inc/bearssl_pem.h
Normal file
125
inc/bearssl_pem.h
Normal file
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PEM_H__
|
||||
#define BR_BEARSSL_PEM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Context for a PEM decoder.
|
||||
*/
|
||||
typedef struct {
|
||||
/* 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;
|
||||
|
||||
} br_pem_decoder_context;
|
||||
|
||||
/*
|
||||
* Initialise a PEM decoder structure.
|
||||
*/
|
||||
void br_pem_decoder_init(br_pem_decoder_context *ctx);
|
||||
|
||||
/*
|
||||
* 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 produced. When an event is produced, it must
|
||||
* be read (with br_pem_decoder_event()); until the event is read, this
|
||||
* function will return 0.
|
||||
*/
|
||||
size_t br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Set the receiver for decoded data. The provided function (with opaque
|
||||
* context pointer) will be called with successive data chunks.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the last event. This is 0 if no event has been produced. Calling
|
||||
* ths function clears the event and allows new source bytes to be
|
||||
* processed.
|
||||
*/
|
||||
int br_pem_decoder_event(br_pem_decoder_context *ctx);
|
||||
|
||||
/*
|
||||
* This event is called when the start of a new object has been detected.
|
||||
* The object name (normalised to uppercase) can be accessed with
|
||||
* br_pem_decoder_name(). The caller MUST provide an appropriate receiver
|
||||
* (with br_pem_decoder_setdest()) before sending new data bytes.
|
||||
*/
|
||||
#define BR_PEM_BEGIN_OBJ 1
|
||||
|
||||
/*
|
||||
* This event is called when the end of the current object is reached
|
||||
* (normally).
|
||||
*/
|
||||
#define BR_PEM_END_OBJ 2
|
||||
|
||||
/*
|
||||
* This event is called when decoding fails while decoding 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
|
||||
|
||||
/*
|
||||
* Get the name of the encountered object. That name is normalised to
|
||||
* uppercase (for ASCII characters).
|
||||
*/
|
||||
static inline const char *
|
||||
br_pem_decoder_name(br_pem_decoder_context *ctx)
|
||||
{
|
||||
return ctx->name;
|
||||
}
|
||||
|
||||
#endif
|
||||
66
inc/bearssl_prf.h
Normal file
66
inc/bearssl_prf.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PRF_H__
|
||||
#define BR_BEARSSL_PRF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* The TLS PRF
|
||||
* -----------
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void br_tls10_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len);
|
||||
|
||||
void br_tls12_sha256_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len);
|
||||
|
||||
void br_tls12_sha384_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len);
|
||||
|
||||
/*
|
||||
* A convenient type name for a PRF implementation.
|
||||
*/
|
||||
typedef void (*br_tls_prf_impl)(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len,
|
||||
const char *label, const void *seed, size_t seed_len);
|
||||
|
||||
#endif
|
||||
149
inc/bearssl_rand.h
Normal file
149
inc/bearssl_rand.h
Normal file
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_RAND_H__
|
||||
#define BR_BEARSSL_RAND_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.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).
|
||||
*
|
||||
* An object-oriented API is defined, with rules similar to that of
|
||||
* hash functions. The context structure for a PRNG must start with
|
||||
* a pointer to the vtable. The vtable contains the following fields:
|
||||
*
|
||||
* context_size size of the context structure for this PRNG
|
||||
* init initialize context with an initial seed
|
||||
* generate produce some pseudo-random bytes
|
||||
* update insert some additional seed
|
||||
*
|
||||
* Note that the init() method may accept additional parameters, provided
|
||||
* as a 'const void *' pointer at API level. These additional parameters
|
||||
* depend on the implemented PRNG.
|
||||
*/
|
||||
|
||||
typedef struct br_prng_class_ br_prng_class;
|
||||
struct br_prng_class_ {
|
||||
size_t context_size;
|
||||
void (*init)(const br_prng_class **ctx, const void *params,
|
||||
const void *seed, size_t seed_len);
|
||||
void (*generate)(const br_prng_class **ctx, void *out, size_t len);
|
||||
void (*update)(const br_prng_class **ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
};
|
||||
|
||||
/*
|
||||
* HMAC_DRBG is a pseudo-random number generator based on HMAC (with
|
||||
* an underlying hash function). HMAC_DRBG is specified in NIST Special
|
||||
* Publication 800-90A. It works as a stateful machine:
|
||||
* -- It has an internal state.
|
||||
* -- The state can be updated with additional "entropy" (some bytes
|
||||
* provided from the outside).
|
||||
* -- Each request is for some bits (up to some limit). For each request,
|
||||
* an internal "reseed counter" is incremented.
|
||||
* -- When the reseed counter reaches a given threshold, a reseed is
|
||||
* necessary.
|
||||
*
|
||||
* Standard limits are quite high: each request can produce up to 2^19
|
||||
* bits (i.e. 64 kB of data), and the threshold for the reseed counter
|
||||
* is 2^48. In practice, we cannot really reach that reseed counter, so
|
||||
* the implementation simply omits the counter. Similarly, we consider
|
||||
* that it is up to callers NOT to ask for more than 64 kB of randomness
|
||||
* in one go. Under these conditions, this implementation cannot fail,
|
||||
* and thus functions need not return any status code.
|
||||
*
|
||||
* (Asking for more than 64 kB of data in one generate() call won't make
|
||||
* the implementation fail, and, as far as we know, it will not induce
|
||||
* any actual weakness; this is "merely" out of the formal usage range
|
||||
* defined for HMAC_DRBG.)
|
||||
*
|
||||
* A dedicated context structure (caller allocated, as usual) contains
|
||||
* the current PRNG state.
|
||||
*
|
||||
* For the OOP interface, the "additional parameters" are a pointer to
|
||||
* the class of the hash function to use.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
const br_prng_class *vtable;
|
||||
unsigned char K[64];
|
||||
unsigned char V[64];
|
||||
const br_hash_class *digest_class;
|
||||
} br_hmac_drbg_context;
|
||||
|
||||
extern const br_prng_class br_hmac_drbg_vtable;
|
||||
|
||||
/*
|
||||
* Initialize a HMAC_DRBG instance, with the provided initial seed (of
|
||||
* 'len' bytes). The 'seed' used here is what is called, in SP 800-90A
|
||||
* terminology, the concatenation of the "seed", "nonce" and
|
||||
* "personalization string", in that order.
|
||||
*
|
||||
* Formally, the underlying digest can only be SHA-1 or one of the SHA-2
|
||||
* functions. This implementation also works with any other implemented
|
||||
* hash function (e.g. MD5), but such usage is non-standard and not
|
||||
* recommended.
|
||||
*/
|
||||
void br_hmac_drbg_init(br_hmac_drbg_context *ctx,
|
||||
const br_hash_class *digest_class, const void *seed, size_t len);
|
||||
|
||||
/*
|
||||
* Obtain some pseudorandom bits from HMAC_DRBG. The provided context
|
||||
* is updated. The output bits are written in 'out' ('len' bytes). The
|
||||
* size of the requested chunk of pseudorandom bits MUST NOT exceed
|
||||
* 64 kB (the function won't fail if more bytes are requested, but
|
||||
* the usage will be outside of the HMAC_DRBG specification limits).
|
||||
*/
|
||||
void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len);
|
||||
|
||||
/*
|
||||
* Update an HMAC_DRBG instance with some new entropy. The extra 'seed'
|
||||
* complements the current state but does not completely replace any
|
||||
* previous seed. The process is such that pushing new entropy, even of
|
||||
* questionable quality, will not make the output "less random" in any
|
||||
* practical way.
|
||||
*/
|
||||
void br_hmac_drbg_update(br_hmac_drbg_context *ctx,
|
||||
const void *seed, size_t len);
|
||||
|
||||
/*
|
||||
* Get the hash function implementation used by a given instance of
|
||||
* HMAC_DRBG.
|
||||
*/
|
||||
static inline const br_hash_class *
|
||||
br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)
|
||||
{
|
||||
return ctx->digest_class;
|
||||
}
|
||||
|
||||
#endif
|
||||
227
inc/bearssl_rsa.h
Normal file
227
inc/bearssl_rsa.h
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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>
|
||||
|
||||
/*
|
||||
* RSA
|
||||
* ---
|
||||
*
|
||||
* A RSA engine consists in two functions, for public-key and private-key
|
||||
* operations (modular exponentiations). In both cases, the same buffer is
|
||||
* used as source and destination.
|
||||
*
|
||||
* Key elements are provided as arrays of bytes, in big-endian unsigned
|
||||
* encoding (leading zeros are correctly skipped, hence signed encodings
|
||||
* can also be used). The source/destination array (x[]) is an array of
|
||||
* bytes that, per PKCS#1 rules, MUST have the same length as the modulus,
|
||||
* exactly: missing or extra leading bytes, even of value 0x00, are not
|
||||
* tolerated for x[].
|
||||
*
|
||||
* Parameter validation: the engine MUST gracefully handle incorrect key
|
||||
* parameters (e.g. an even modulus); it needs not detect all cases of
|
||||
* incorrect key parameters. For public key operations, the engine MUST
|
||||
* validate the length of x[] (it must match the numerical length, in
|
||||
* bytes, of the modulus); it MUST also check that the provided x[]
|
||||
* decodes to an integer that is numerically less than the modulus. For
|
||||
* private key operation, the engine may assume that the length and
|
||||
* contents of x[] are appropriate (it MUST NOT allow an invalid value
|
||||
* to result in a buffer overflow, but an invalid input x[] may result
|
||||
* in an undetected invalid output).
|
||||
*
|
||||
* Constant-time requirements: the following information may leak through
|
||||
* execution time and memory access pattern:
|
||||
* -- the actual bit length of the modulus;
|
||||
* -- the actual bit length of each prime factor;
|
||||
* -- the byte lengths as provided to the function calls.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A structure type for a RSA public key, consisting in a modulus and
|
||||
* a public exponent, encoded in unsigned big-endian format. The two
|
||||
* arrays may be larger than needed; functions that accept a RSA public
|
||||
* key are supposed to check the actual modulus length when needed.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char *n;
|
||||
size_t nlen;
|
||||
unsigned char *e;
|
||||
size_t elen;
|
||||
} br_rsa_public_key;
|
||||
|
||||
/*
|
||||
* A structure type for a RSA private key. The key elements are:
|
||||
* n_bitlen modulus bit length
|
||||
* p prime modulus factor
|
||||
* q other prime modulus factor (may be greater or lower than p)
|
||||
* dp private exponent, reduced modulo p-1
|
||||
* dq private exponent, reduced modulo q-1
|
||||
* iq CRT coefficient: q*iq = 1 mod p.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t n_bitlen;
|
||||
unsigned char *p;
|
||||
size_t plen;
|
||||
unsigned char *q;
|
||||
size_t qlen;
|
||||
unsigned char *dp;
|
||||
size_t dplen;
|
||||
unsigned char *dq;
|
||||
size_t dqlen;
|
||||
unsigned char *iq;
|
||||
size_t iqlen;
|
||||
} br_rsa_private_key;
|
||||
|
||||
/*
|
||||
* Type for a public-key engine. The source buffer x[], of size xlen,
|
||||
* is modified in place.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error.
|
||||
*
|
||||
* If the source buffer length (xlen) does not exactly match the modulus
|
||||
* length, then an error is reported and x[] is unmodified.
|
||||
*/
|
||||
typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen,
|
||||
const br_rsa_public_key *pk);
|
||||
|
||||
/*
|
||||
* Type for a RSA signature verification engine (PKCS#1 v1.5 signatures).
|
||||
* 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 be NULL, in which case the raw hash value should
|
||||
* be used with the PKCS#1 v1.5 "type 1" padding (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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Type for a 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.
|
||||
*/
|
||||
typedef uint32_t (*br_rsa_private)(unsigned char *x,
|
||||
const br_rsa_private_key *sk);
|
||||
|
||||
/*
|
||||
* Type for a RSA signature generation engine (PKCS#1 v1.5 signatures).
|
||||
* 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 be NULL, in which case the raw hash value should
|
||||
* be used with the PKCS#1 v1.5 "type 1" padding (used in SSL/TLS up
|
||||
* to TLS-1.1, with a 36-byte hash value).
|
||||
* -- The hashed data, and length (in bytes).
|
||||
* -- The private key.
|
||||
* -- The output buffer.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* RSA "i32" engine. Integers are internally represented as arrays of
|
||||
* 32-bit integers, and the core multiplication primitive is the
|
||||
* 32x32->64 multiplication.
|
||||
*/
|
||||
|
||||
uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen,
|
||||
const br_rsa_public_key *pk);
|
||||
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);
|
||||
uint32_t br_rsa_i32_private(unsigned char *x,
|
||||
const br_rsa_private_key *sk);
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen,
|
||||
const br_rsa_public_key *pk);
|
||||
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);
|
||||
uint32_t br_rsa_i31_private(unsigned char *x,
|
||||
const br_rsa_private_key *sk);
|
||||
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);
|
||||
|
||||
/*
|
||||
* Perform RSA decryption for SSL/TLS. This function uses the provided core
|
||||
* and private key to decrypt the message in data[] of size 'len'. The
|
||||
* buffer is modified; the decryption result MUST have length 48, and
|
||||
* is written into the first 48 bytes of data[].
|
||||
*
|
||||
* In success, this rturns 1. On error, 0 is returned, and the buffer
|
||||
* contents are indeterminate.
|
||||
*/
|
||||
uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk,
|
||||
unsigned char *data, size_t len);
|
||||
|
||||
#endif
|
||||
1856
inc/bearssl_ssl.h
Normal file
1856
inc/bearssl_ssl.h
Normal file
File diff suppressed because it is too large
Load diff
733
inc/bearssl_x509.h
Normal file
733
inc/bearssl_x509.h
Normal file
|
|
@ -0,0 +1,733 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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"
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* X.509 error codes are in the 32..63 range.
|
||||
*/
|
||||
|
||||
/* Validation was successful; this is not actually an error. */
|
||||
#define BR_ERR_X509_OK 32
|
||||
|
||||
/* Invalid value in an ASN.1 structure. */
|
||||
#define BR_ERR_X509_INVALID_VALUE 33
|
||||
|
||||
/* Truncated certificate. */
|
||||
#define BR_ERR_X509_TRUNCATED 34
|
||||
|
||||
/* Empty certificate chain (no certificate at all). */
|
||||
#define BR_ERR_X509_EMPTY_CHAIN 35
|
||||
|
||||
/* Decoding error: inner element extends beyond outer element size. */
|
||||
#define BR_ERR_X509_INNER_TRUNC 36
|
||||
|
||||
/* Decoding error: unsupported tag class (application or private). */
|
||||
#define BR_ERR_X509_BAD_TAG_CLASS 37
|
||||
|
||||
/* Decoding error: unsupported tag value. */
|
||||
#define BR_ERR_X509_BAD_TAG_VALUE 38
|
||||
|
||||
/* Decoding error: indefinite length. */
|
||||
#define BR_ERR_X509_INDEFINITE_LENGTH 39
|
||||
|
||||
/* Decoding error: extraneous element. */
|
||||
#define BR_ERR_X509_EXTRA_ELEMENT 40
|
||||
|
||||
/* Decoding error: unexpected element. */
|
||||
#define BR_ERR_X509_UNEXPECTED 41
|
||||
|
||||
/* Decoding error: expected constructed element, but is primitive. */
|
||||
#define BR_ERR_X509_NOT_CONSTRUCTED 42
|
||||
|
||||
/* Decoding error: expected primitive element, but is constructed. */
|
||||
#define BR_ERR_X509_NOT_PRIMITIVE 43
|
||||
|
||||
/* Decoding error: BIT STRING length is not multiple of 8. */
|
||||
#define BR_ERR_X509_PARTIAL_BYTE 44
|
||||
|
||||
/* Decoding error: BOOLEAN value has invalid length. */
|
||||
#define BR_ERR_X509_BAD_BOOLEAN 45
|
||||
|
||||
/* Decoding error: value is off-limits. */
|
||||
#define BR_ERR_X509_OVERFLOW 46
|
||||
|
||||
/* Invalid distinguished name. */
|
||||
#define BR_ERR_X509_BAD_DN 47
|
||||
|
||||
/* Invalid date/time representation. */
|
||||
#define BR_ERR_X509_BAD_TIME 48
|
||||
|
||||
/* Certificate contains unsupported features that cannot be ignored. */
|
||||
#define BR_ERR_X509_UNSUPPORTED 49
|
||||
|
||||
/* Key or signature size exceeds internal limits. */
|
||||
#define BR_ERR_X509_LIMIT_EXCEEDED 50
|
||||
|
||||
/* Key type does not match that which was expected. */
|
||||
#define BR_ERR_X509_WRONG_KEY_TYPE 51
|
||||
|
||||
/* Signature is invalid. */
|
||||
#define BR_ERR_X509_BAD_SIGNATURE 52
|
||||
|
||||
/* Validation time is unknown. */
|
||||
#define BR_ERR_X509_TIME_UNKNOWN 53
|
||||
|
||||
/* Certificate is expired or not yet valid. */
|
||||
#define BR_ERR_X509_EXPIRED 54
|
||||
|
||||
/* Issuer/Subject DN mismatch in the chain. */
|
||||
#define BR_ERR_X509_DN_MISMATCH 55
|
||||
|
||||
/* Expected server name was not found in the chain. */
|
||||
#define BR_ERR_X509_BAD_SERVER_NAME 56
|
||||
|
||||
/* Unknown critical extension in certificate. */
|
||||
#define BR_ERR_X509_CRITICAL_EXTENSION 57
|
||||
|
||||
/* Not a CA, or path length constraint violation */
|
||||
#define BR_ERR_X509_NOT_CA 58
|
||||
|
||||
/* Key Usage extension prohibits intended usage. */
|
||||
#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59
|
||||
|
||||
/* Public key found in certificate is too small. */
|
||||
#define BR_ERR_X509_WEAK_PUBLIC_KEY 60
|
||||
|
||||
/* Chain could not be linked to a trust anchor. */
|
||||
#define BR_ERR_X509_NOT_TRUSTED 62
|
||||
|
||||
/*
|
||||
* A structure to encode public keys.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char key_type;
|
||||
union {
|
||||
br_rsa_public_key rsa;
|
||||
br_ec_public_key ec;
|
||||
} key;
|
||||
} br_x509_pkey;
|
||||
|
||||
/*
|
||||
* A trust anchor consists in:
|
||||
* -- an encoded DN
|
||||
* -- a public key
|
||||
* -- flags
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char *dn;
|
||||
size_t dn_len;
|
||||
/* unsigned char hashed_DN[64]; */
|
||||
unsigned flags;
|
||||
br_x509_pkey pkey;
|
||||
} br_x509_trust_anchor;
|
||||
|
||||
/* Trust anchor flag: trust anchor is a CA and thus acceptable for
|
||||
signing other certificates. Without this flag, the trust anchor
|
||||
is only for direct trust (name and key match EE certificate). */
|
||||
#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.
|
||||
*/
|
||||
#define BR_KEYTYPE_RSA 1
|
||||
#define BR_KEYTYPE_EC 2
|
||||
|
||||
#define BR_KEYTYPE_KEYX 0x10 /* key is for key exchange or encryption */
|
||||
#define BR_KEYTYPE_SIGN 0x20 /* key is for verifying signatures */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
typedef struct br_x509_class_ br_x509_class;
|
||||
struct br_x509_class_ {
|
||||
size_t context_size;
|
||||
void (*start_chain)(const br_x509_class **ctx,
|
||||
unsigned expected_key_type,
|
||||
const char *server_name);
|
||||
void (*start_cert)(const br_x509_class **ctx, uint32_t length);
|
||||
void (*append)(const br_x509_class **ctx,
|
||||
const unsigned char *buf, size_t len);
|
||||
void (*end_cert)(const br_x509_class **ctx);
|
||||
unsigned (*end_chain)(const br_x509_class **ctx);
|
||||
const br_x509_pkey *(*get_pkey)(const br_x509_class *const *ctx);
|
||||
};
|
||||
|
||||
/*
|
||||
* The "known key" X.509 engine is a trivial engine that completely
|
||||
* ignores the certificates, and instead reports an externally
|
||||
* configured public key.
|
||||
*/
|
||||
typedef struct {
|
||||
const br_x509_class *vtable;
|
||||
br_x509_pkey pkey;
|
||||
} br_x509_knownkey_context;
|
||||
extern const br_x509_class br_x509_knownkey_vtable;
|
||||
|
||||
/*
|
||||
* Initialize a "known key" X.509 engine with a known RSA public key.
|
||||
* The provided pointers are linked in, not copied, so they must
|
||||
* remain valid while the public key may be in usage (i.e. at least up
|
||||
* to the end of the handshake -- and since there may be renegotiations,
|
||||
* these buffers should stay until the connection is finished).
|
||||
*/
|
||||
void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
|
||||
const br_rsa_public_key *pk);
|
||||
|
||||
/*
|
||||
* Initialize a "known key" X.509 engine with a known EC public key.
|
||||
* The provided pointers are linked in, not copied, so they must
|
||||
* remain valid while the public key may be in usage (i.e. at least up
|
||||
* to the end of the handshake -- and since there may be renegotiations,
|
||||
* these buffers should stay until the connection is finished).
|
||||
*/
|
||||
void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
|
||||
const br_ec_public_key *pk);
|
||||
|
||||
/*
|
||||
* 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 implementation (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.
|
||||
*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* The "minimal" X.509 engine performs basic decoding of certificates and
|
||||
* some validations:
|
||||
* -- DN matching
|
||||
* -- signatures
|
||||
* -- validity dates
|
||||
* -- Basic Constraints extension
|
||||
* -- Server name check against SAN extension
|
||||
*/
|
||||
typedef struct {
|
||||
const br_x509_class *vtable;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Expected EE key type and usage. */
|
||||
unsigned char expected_key_type;
|
||||
|
||||
/* 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];
|
||||
|
||||
/*
|
||||
* Public key cryptography implementations (signature verification).
|
||||
*/
|
||||
br_rsa_pkcs1_vrfy irsa;
|
||||
br_ecdsa_vrfy iecdsa;
|
||||
const br_ec_impl *iec;
|
||||
|
||||
} br_x509_minimal_context;
|
||||
extern const br_x509_class br_x509_minimal_vtable;
|
||||
|
||||
/*
|
||||
* Initialize a "minimal" X.509 engine. Parameters are:
|
||||
* -- context to initialize
|
||||
* -- hash function to use for hashing normalized DN
|
||||
* -- list of trust anchors
|
||||
*
|
||||
* After initialization, some hash function implementations for signature
|
||||
* verification MUST be added.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Set a hash function implementation, identified by ID, for purposes of
|
||||
* verifying signatures on certificates. This must be called after
|
||||
* br_x509_minimal_init().
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a RSA implementation, for purposes of verifying signatures on
|
||||
* certificates. This must be called after br_x509_minimal_init().
|
||||
*/
|
||||
static inline void
|
||||
br_x509_minimal_set_rsa(br_x509_minimal_context *ctx,
|
||||
br_rsa_pkcs1_vrfy irsa)
|
||||
{
|
||||
ctx->irsa = irsa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an ECDSA implementation, for purposes of verifying signatures on
|
||||
* certificates. This must be called after br_x509_minimal_init().
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the validation time, normally to the current date and time.
|
||||
* This consists in two 32-bit counts:
|
||||
*
|
||||
* -- 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).
|
||||
*
|
||||
* 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,
|
||||
* validation will fail (except in case of direct trust of the EE key).
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the minimal acceptable length for RSA keys, in bytes. Default
|
||||
* is 128 bytes, which means RSA keys of 1017 bits or more. This setting
|
||||
* applies to keys extracted from certificates (EE and intermediate CA).
|
||||
* It does _not_ apply to "CA" trust anchors.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* An X.509 decoder context. This is not for X.509 validation, but for
|
||||
* using certificates as trust anchors (e.g. self-signed certificates
|
||||
* read from files).
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
/* 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;
|
||||
|
||||
} br_x509_decoder_context;
|
||||
|
||||
/*
|
||||
* Initialise an X.509 decoder context for processing a new certificate.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Push some certificate bytes into a decoder context.
|
||||
*/
|
||||
void br_x509_decoder_push(br_x509_decoder_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get decoder error. 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static inline int
|
||||
br_x509_decoder_isCA(br_x509_decoder_context *ctx)
|
||||
{
|
||||
return ctx->isCA;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the issuing CA key type (type of key 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.
|
||||
*/
|
||||
static inline int
|
||||
br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx)
|
||||
{
|
||||
return ctx->signer_key_type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the identifier for the hash function used to sign the decoded
|
||||
* certificate. This is 0 if the hash function was not recognised.
|
||||
*/
|
||||
static inline int
|
||||
br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx)
|
||||
{
|
||||
return ctx->signer_hash_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Type for an X.509 certificate (DER-encoded).
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
size_t data_len;
|
||||
} br_x509_certificate;
|
||||
|
||||
/*
|
||||
* Private key decoder context.
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
/* 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];
|
||||
|
||||
} br_skey_decoder_context;
|
||||
|
||||
/*
|
||||
* Initialise a private key decoder context.
|
||||
*/
|
||||
void br_skey_decoder_init(br_skey_decoder_context *ctx);
|
||||
|
||||
/*
|
||||
* Push some data bytes into a private key decoder context.
|
||||
*/
|
||||
void br_skey_decoder_push(br_skey_decoder_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Get the decoding status for a private key. This is either 0 on success,
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the decoded private key type. This is 0 if decoding is not finished
|
||||
* or failed.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
mkT0.sh
Executable file
11
mkT0.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#! /bin/sh
|
||||
|
||||
CSC=$(which mono-csc || which dmcs || echo "none")
|
||||
|
||||
if [ $CSC = "none" ]; then
|
||||
echo "Error: Please install mono-devel."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
$CSC /out:T0Comp.exe /main:T0Comp /res:T0/kern.t0,t0-kernel T0/*.cs
|
||||
36
samples/README.txt
Normal file
36
samples/README.txt
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
This directory contains sample code for using BearSSL.
|
||||
|
||||
client_basic.c
|
||||
|
||||
A sample client code, that connects to a server, performs a SSL
|
||||
handshake, sends a basic HTTP GET request, and dumps the complete
|
||||
answer on stdout.
|
||||
|
||||
Compile it against BearSSL headers (in the ../inc directory) and
|
||||
library (libbearssl.a). This code will validate the server
|
||||
certificate against two hardcoded trust anchors.
|
||||
|
||||
server_basic.c
|
||||
|
||||
A sample SSL server, that serves one client at a time. It reads a
|
||||
single HTTP request (that it does not really parse; it just waits for
|
||||
the two successive line endings that mark the end of the request),
|
||||
and pushes a basic response.
|
||||
|
||||
Compile it against BearSSL headers (in the ../inc directory) and
|
||||
library (libbearssl.a). Depending on compilation options (see the
|
||||
code), it will use one of several certificate chains, that exercise
|
||||
various combinations of RSA and EC keys and signatures. These
|
||||
certificate chains link to the trust anchors that are hardcoded
|
||||
in client_basic.c, so the sample client and the sample server can
|
||||
be tested against each other.
|
||||
|
||||
custom_profile.c
|
||||
|
||||
A sample C source file that shows how to write your own client or
|
||||
server profiles (selections of cipher suites and algorithms).
|
||||
|
||||
|
||||
The .pem files are certificate and keys corresponding to the chains
|
||||
and anchors used by the sample client and server. They are provided
|
||||
for reference only; these files are not used by the examples.
|
||||
14
samples/cert-ee-ec+rsa.pem
Normal file
14
samples/cert-ee-ec+rsa.pem
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICcTCCAVmgAwIBAgIUbmO7Sc5BfgOM9Ubyiq5hCDWwlLMwDQYJKoZIhvcNAQELBQAwJzELMAkG
|
||||
A1UEBhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEy
|
||||
MzEyMzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIB
|
||||
BggqhkjOPQMBBwNCAARfOJ2n/02Kr/Y0OUYa/Drf9COqqer7xQjeAI6+eaU3WExt3QHKq0ffibbH
|
||||
Fx84/B0gFN1FwOCPk044C/zpmaFJo2YwZDAfBgNVHSMEGDAWgBR8z6PGKffzxaoZ0MAW6+BAD85E
|
||||
pzAdBgNVHQ4EFgQUww6GqnW0FcDllQkyvl6SdankRJswDAYDVR0TAQH/BAIwADAUBgNVHREEDTAL
|
||||
gglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEBAI6JY6ebqBCOnhjQpHrdLIIWjwsO1cpXu19v
|
||||
/FcowCG6rZSoF0JF1zH3hFcZRiQ8x0k4P0h6CRrrUbrFdY5MsiWwxyI+5+VG27E2/BuFUbDtgxbw
|
||||
OnnaXShq7mogTLBwXrDtem0tGsm0ccLEox0lhjBUsZgmwVHg+DGtZ0id5qFSOyBHyXDagLWk9D9y
|
||||
azcwVzksRptE8dlOu6Zf45rFf2y2Zcu/QHKS0Gj2rnl+JMFbaDAoU3FhevQ2ezvCtuwf3DBABA3q
|
||||
swrPddO9nqtxcWh/pUFSAOmzruQe8btpxjvV3tLCJWkIPDfM94Jq5ah7agLavaQBMzPz3kYA7HXP
|
||||
4H0=
|
||||
-----END CERTIFICATE-----
|
||||
10
samples/cert-ee-ec.pem
Normal file
10
samples/cert-ee-ec.pem
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBsDCCAVagAwIBAgIUHE0AkWniRqyQfGRcU/H/t8HLbnowCgYIKoZIzj0EAwIwJzELMAkGA1UE
|
||||
BhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEy
|
||||
MzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggq
|
||||
hkjOPQMBBwNCAARfOJ2n/02Kr/Y0OUYa/Drf9COqqer7xQjeAI6+eaU3WExt3QHKq0ffibbHFx84
|
||||
/B0gFN1FwOCPk044C/zpmaFJo2YwZDAfBgNVHSMEGDAWgBTw0PEi+XpIFwZ7Pb249c1VnFw+cDAd
|
||||
BgNVHQ4EFgQUww6GqnW0FcDllQkyvl6SdankRJswDAYDVR0TAQH/BAIwADAUBgNVHREEDTALggls
|
||||
b2NhbGhvc3QwCgYIKoZIzj0EAwIDSAAwRQIhAJH79ATQ5S4B1IzwF2IP3MyAyhjEQHwnA8s0Aw2b
|
||||
yFlNAiAFVWni2KFAMzQOfkkyZB0/ax/QLbcvUgRWr9M3j4eZog==
|
||||
-----END CERTIFICATE-----
|
||||
17
samples/cert-ee-rsa.pem
Normal file
17
samples/cert-ee-rsa.pem
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPDCCAiSgAwIBAgIUWNq6Ns3toNpcEDNzjgxkknmSrwMwDQYJKoZIhvcNAQELBQAwJzELMAkG
|
||||
A1UEBhMCQ0ExGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAeFw0xMDAxMDEwMDAwMDBaFw0zNzEy
|
||||
MzEyMzU5NTlaMCExCzAJBgNVBAYTAkNBMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQDUeh0nuis6Z7KRavvng0TK7Rx1rd1Ng2LWqmiVsiQhexWuKplo
|
||||
Fe1m8LhY59P1LsbZKl7nDi7n/GdZwMhhfUukb92f2ciFh2THuhoPKdSWqHiaa2IgqTLQ7qmMKGFH
|
||||
olAqY/Yh3trY1fB/xQCCcOajv1yJJ09RkncDw7DMLjvsI/IvU0GviZP/0oCxQ5fe1hmgkhJ6PWZ5
|
||||
4cG84Xdwoos9RoRTP+ROQkE3kh4f/Tiz9++HOYDTVs/04BPeZLBypAOExEHtb/o+4soEINLX3CyC
|
||||
K3ribaEcSNvPiU80lz0oqFPa58HhcxWjMHZ/jyNCFD1RNNJarTyby8j+f26OQPO9AgMBAAGjZjBk
|
||||
MB8GA1UdIwQYMBaAFMUBrXzmY8mcF1/FoqfhUF/o9ajGMB0GA1UdDgQWBBTFAa185mPJnBdfxaKn
|
||||
4VBf6PWoxjAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsF
|
||||
AAOCAQEAcbNdIcIO19DG+Epzh00iAifQx/j9Gm1iWIIIdiAHwEiS8+mYWusNTlaVY2hNq9QAduA3
|
||||
zwsRYVlc3valFFnZJZ9Z2dNehqwdpiwyQhkyE0ALVM1nJra9tJakyh9/N9aodes6gVEwuflKAW/R
|
||||
1u1P3z8wYAZnko5hhV8atYyzD2Gp+t9dxGQA6oexM199y6OFJG4sZTvqcz+G0/3o5ALGYWomF1IB
|
||||
JVx/qM5pH6xhLLcEr/2kepnLJhVM/3TUcwxXDCbr1yrcXMNBu8Lzzha9jnv76d+rIQ2Rs43Yz8j0
|
||||
SbnQ4xZwP7Pe1Acl+kZEUolNicjiyrUzf8chvSjv/mZ0Aw==
|
||||
-----END CERTIFICATE-----
|
||||
10
samples/cert-ica-ec.pem
Normal file
10
samples/cert-ica-ec.pem
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBqTCCAU6gAwIBAgIUINPr4oz+2uajLF478mY6KzZ7sMowCgYIKoZIzj0EAwIwHDELMAkGA1UE
|
||||
BhMCQ0ExDTALBgNVBAMTBFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMzcxMjMxMjM1OTU5WjAnMQsw
|
||||
CQYDVQQGEwJDQTEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0D
|
||||
AQcDQgAEcC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDN
|
||||
SZ4Hv9CunebQsycWoaNjMGEwHwYDVR0jBBgwFoAUlUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0O
|
||||
BBYEFPDQ8SL5ekgXBns9vbj1zVWcXD5wMA4GA1UdDwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/
|
||||
MAoGCCqGSM49BAMCA0kAMEYCIQCF40ZomdYCellmHLdPNS0INjhhfgVI2GlDH+tW6a0GDgIhAIJw
|
||||
tGIDSUbIVFkF2XjbUxzgbmb1DxQ7yS04EnCRVvmp
|
||||
-----END CERTIFICATE-----
|
||||
17
samples/cert-ica-rsa.pem
Normal file
17
samples/cert-ica-rsa.pem
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDNDCCAhygAwIBAgIUcA9g7vAHmpxprJdiJk9dBbb5j0gwDQYJKoZIhvcNAQELBQAwHDELMAkG
|
||||
A1UEBhMCQ0ExDTALBgNVBAMTBFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMzcxMjMxMjM1OTU5WjAn
|
||||
MQswCQYDVQQGEwJDQTEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
||||
AAOCAQ8AMIIBCgKCAQEAs+hrr5wWUuOBDFCrJc7MDcfyH39Q3yxcNdZiLmMnQafkU6hLJ/oTkaP6
|
||||
CUovO17Pd7OKwc1JlZx1DWR07+TXS7mhm2jSMHFI6vdLFN8/R6nYu+yPKMz637QflHyW/AgFKPno
|
||||
9C8v7mKcijrghVhgtg8tMLTAQVSRTB9frfEZ8MAipn3YP3k0WUJ7W7VBxGR/Us88NyKhL3kllCRB
|
||||
wj/6x3X7SLUNGKf0VPMubthDWMSrUOgFrZG2HgF1s1Sc3qCZFfus8VyXSVHM71gSb3NrszQUAQ9a
|
||||
nfqq1pPT4urDq7xO7cxRobj4lLa0LKiGKx/2UUMpUl4TibNqeGBOTsAbpQIDAQABo2MwYTAfBgNV
|
||||
HSMEGDAWgBTDCry0kGOWkkW8J6DwWIkq1XgAEjAdBgNVHQ4EFgQUfM+jxin388WqGdDAFuvgQA/O
|
||||
RKcwDgYDVR0PAQH/BAQDAgCGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFQ7
|
||||
9OrG5OjAWxKyrfq9qfRiA61XTG8Hp0c1dT5IoltxEAGPk5mdp0fjjj6vLboG/tTkl7wQjaalOjzm
|
||||
Ics72hPjSiPrvLqlkJGtVW7V3YVLayfSOXYGLtQjW7tVtUk/fS8hy5Z1GZmpmfELuz7HEKeLelK5
|
||||
SeQUCHjnPdmYV9r/2rmNZnWAtV2532ll2xbnHsRA5EaKHnYyFueDZ9p4VqsPTFzxcNpmIPT4D/bc
|
||||
L3KXa3hAeZ1bbb4DznBCqCpxEd8ugQHqhhKRT9AY7YSkSDC5uXtWPu+N4R/9kLJEhVhvpzB0fPGu
|
||||
jJk/8U1XxZVowjay7MJoesCBqVUF58+vUKw=
|
||||
-----END CERTIFICATE-----
|
||||
9
samples/cert-root-ec.pem
Normal file
9
samples/cert-root-ec.pem
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBijCCATCgAwIBAgIBCTAKBggqhkjOPQQDAjAcMQswCQYDVQQGEwJDQTENMAsGA1UEAxMEUm9v
|
||||
dDAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEyMzU5NTlaMBwxCzAJBgNVBAYTAkNBMQ0wCwYDVQQD
|
||||
EwRSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t
|
||||
6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eHwuXYxfN/jaNjMGEwHwYDVR0jBBgwFoAU
|
||||
lUG04meq8X+8j3nzaBRaa5IWokAwHQYDVR0OBBYEFJVBtOJnqvF/vI9582gUWmuSFqJAMA4GA1Ud
|
||||
DwEB/wQEAwIAhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQCz1GCIAoRtqU2h
|
||||
x62hec7E+/XxnUGDORWnkliiGrcmxQIgNPq9NHD7ts0xYjTwZsd0bN62+iY93lM4LHbkNV9q/gA=
|
||||
-----END CERTIFICATE-----
|
||||
16
samples/cert-root-rsa.pem
Normal file
16
samples/cert-root-rsa.pem
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDFjCCAf6gAwIBAgIBCDANBgkqhkiG9w0BAQsFADAcMQswCQYDVQQGEwJDQTENMAsGA1UEAxME
|
||||
Um9vdDAeFw0xMDAxMDEwMDAwMDBaFw0zNzEyMzEyMzU5NTlaMBwxCzAJBgNVBAYTAkNBMQ0wCwYD
|
||||
VQQDEwRSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttk01FD9s696c/HOOL9d
|
||||
b0Xh/U6xmMZggybSF9HFt5qjwd5jOZec8F5cyBwXuYgZbfC2LjBQoVRuk8DbzzDLnx4nefHDmVI1
|
||||
qj2237CtfMtJzcDt52YQKunOKB8hUPp3TC3a7zxY606/zun7Gtqjg6PNo8qTgNza8xfMeqszgJyy
|
||||
1H9GP8U83GGUtycpbiq8Wwk21MY7Deu+ztsdHLwQanFxs/LKKJp38orsQu+xSo7i8hoyKs3ApkYs
|
||||
msKFN5F/RqGTgaF0Zt+6szkgkZP6HaGohefk+Qf2EPaoJwG2fxLDQMPJ4rCrSRg6ZLZZt5W1ljbf
|
||||
ImmqcmpUTicpow6XFQIDAQABo2MwYTAfBgNVHSMEGDAWgBTDCry0kGOWkkW8J6DwWIkq1XgAEjAd
|
||||
BgNVHQ4EFgQUwwq8tJBjlpJFvCeg8FiJKtV4ABIwDgYDVR0PAQH/BAQDAgCGMA8GA1UdEwEB/wQF
|
||||
MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA7SaR2V1Gx71RiL5Cdfr15jkU88snnm+v+0PvIfQrNP
|
||||
4RzKJkaD3j//oZf6Hr2yH6c7Bi3OhCxBFNbXjDXiAXVRoTjOSxNSwVq43utl9Z4IKAZzQlEYW5S5
|
||||
U0oskEq2q6jDEWoj8lUtQW4GAVuZhq7lNs0jJJu84IBsxHJFgZJ/7+LHFLXs+vQkz3hjzMZ7gIt+
|
||||
lwXI/gdY9ld1QB6WLLIzxs7zid+Z0LZTYi851vbmMwUqgL8V5Np0Q0EVHHy1c6LQ0hj1kVLay2ZN
|
||||
d2dsUMCQJI5EF2kWon+xFDpAtv0vUT2xuMkYFhjS/aBxzevWCsXuUQphBYaIGli8P68NNPo=
|
||||
-----END CERTIFICATE-----
|
||||
166
samples/chain-ec+rsa.h
Normal file
166
samples/chain-ec+rsa.h
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* A sample server certificate chain with a single intermediate CA.
|
||||
* Certificate key type: EC
|
||||
* Signing algorithm for both certificates: RSA
|
||||
*/
|
||||
|
||||
static const unsigned char CERT0[] = {
|
||||
0x30, 0x82, 0x02, 0x71, 0x30, 0x82, 0x01, 0x59, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x6E, 0x63, 0xBB, 0x49, 0xCE, 0x41, 0x7E, 0x03, 0x8C,
|
||||
0xF5, 0x46, 0xF2, 0x8A, 0xAE, 0x61, 0x08, 0x35, 0xB0, 0x94, 0xB3, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64,
|
||||
0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31,
|
||||
0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A,
|
||||
0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39,
|
||||
0x35, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
|
||||
0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
|
||||
0x55, 0x04, 0x03, 0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F,
|
||||
0x73, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
|
||||
0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
|
||||
0x07, 0x03, 0x42, 0x00, 0x04, 0x5F, 0x38, 0x9D, 0xA7, 0xFF, 0x4D, 0x8A,
|
||||
0xAF, 0xF6, 0x34, 0x39, 0x46, 0x1A, 0xFC, 0x3A, 0xDF, 0xF4, 0x23, 0xAA,
|
||||
0xA9, 0xEA, 0xFB, 0xC5, 0x08, 0xDE, 0x00, 0x8E, 0xBE, 0x79, 0xA5, 0x37,
|
||||
0x58, 0x4C, 0x6D, 0xDD, 0x01, 0xCA, 0xAB, 0x47, 0xDF, 0x89, 0xB6, 0xC7,
|
||||
0x17, 0x1F, 0x38, 0xFC, 0x1D, 0x20, 0x14, 0xDD, 0x45, 0xC0, 0xE0, 0x8F,
|
||||
0x93, 0x4E, 0x38, 0x0B, 0xFC, 0xE9, 0x99, 0xA1, 0x49, 0xA3, 0x66, 0x30,
|
||||
0x64, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16,
|
||||
0x80, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA, 0x19,
|
||||
0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30, 0x1D,
|
||||
0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC3, 0x0E, 0x86,
|
||||
0xAA, 0x75, 0xB4, 0x15, 0xC0, 0xE5, 0x95, 0x09, 0x32, 0xBE, 0x5E, 0x92,
|
||||
0x75, 0xA9, 0xE4, 0x44, 0x9B, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13,
|
||||
0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x11, 0x04, 0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61,
|
||||
0x6C, 0x68, 0x6F, 0x73, 0x74, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48,
|
||||
0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01,
|
||||
0x00, 0x8E, 0x89, 0x63, 0xA7, 0x9B, 0xA8, 0x10, 0x8E, 0x9E, 0x18, 0xD0,
|
||||
0xA4, 0x7A, 0xDD, 0x2C, 0x82, 0x16, 0x8F, 0x0B, 0x0E, 0xD5, 0xCA, 0x57,
|
||||
0xBB, 0x5F, 0x6F, 0xFC, 0x57, 0x28, 0xC0, 0x21, 0xBA, 0xAD, 0x94, 0xA8,
|
||||
0x17, 0x42, 0x45, 0xD7, 0x31, 0xF7, 0x84, 0x57, 0x19, 0x46, 0x24, 0x3C,
|
||||
0xC7, 0x49, 0x38, 0x3F, 0x48, 0x7A, 0x09, 0x1A, 0xEB, 0x51, 0xBA, 0xC5,
|
||||
0x75, 0x8E, 0x4C, 0xB2, 0x25, 0xB0, 0xC7, 0x22, 0x3E, 0xE7, 0xE5, 0x46,
|
||||
0xDB, 0xB1, 0x36, 0xFC, 0x1B, 0x85, 0x51, 0xB0, 0xED, 0x83, 0x16, 0xF0,
|
||||
0x3A, 0x79, 0xDA, 0x5D, 0x28, 0x6A, 0xEE, 0x6A, 0x20, 0x4C, 0xB0, 0x70,
|
||||
0x5E, 0xB0, 0xED, 0x7A, 0x6D, 0x2D, 0x1A, 0xC9, 0xB4, 0x71, 0xC2, 0xC4,
|
||||
0xA3, 0x1D, 0x25, 0x86, 0x30, 0x54, 0xB1, 0x98, 0x26, 0xC1, 0x51, 0xE0,
|
||||
0xF8, 0x31, 0xAD, 0x67, 0x48, 0x9D, 0xE6, 0xA1, 0x52, 0x3B, 0x20, 0x47,
|
||||
0xC9, 0x70, 0xDA, 0x80, 0xB5, 0xA4, 0xF4, 0x3F, 0x72, 0x6B, 0x37, 0x30,
|
||||
0x57, 0x39, 0x2C, 0x46, 0x9B, 0x44, 0xF1, 0xD9, 0x4E, 0xBB, 0xA6, 0x5F,
|
||||
0xE3, 0x9A, 0xC5, 0x7F, 0x6C, 0xB6, 0x65, 0xCB, 0xBF, 0x40, 0x72, 0x92,
|
||||
0xD0, 0x68, 0xF6, 0xAE, 0x79, 0x7E, 0x24, 0xC1, 0x5B, 0x68, 0x30, 0x28,
|
||||
0x53, 0x71, 0x61, 0x7A, 0xF4, 0x36, 0x7B, 0x3B, 0xC2, 0xB6, 0xEC, 0x1F,
|
||||
0xDC, 0x30, 0x40, 0x04, 0x0D, 0xEA, 0xB3, 0x0A, 0xCF, 0x75, 0xD3, 0xBD,
|
||||
0x9E, 0xAB, 0x71, 0x71, 0x68, 0x7F, 0xA5, 0x41, 0x52, 0x00, 0xE9, 0xB3,
|
||||
0xAE, 0xE4, 0x1E, 0xF1, 0xBB, 0x69, 0xC6, 0x3B, 0xD5, 0xDE, 0xD2, 0xC2,
|
||||
0x25, 0x69, 0x08, 0x3C, 0x37, 0xCC, 0xF7, 0x82, 0x6A, 0xE5, 0xA8, 0x7B,
|
||||
0x6A, 0x02, 0xDA, 0xBD, 0xA4, 0x01, 0x33, 0x33, 0xF3, 0xDE, 0x46, 0x00,
|
||||
0xEC, 0x75, 0xCF, 0xE0, 0x7D
|
||||
};
|
||||
|
||||
static const unsigned char CERT1[] = {
|
||||
0x30, 0x82, 0x03, 0x34, 0x30, 0x82, 0x02, 0x1C, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x70, 0x0F, 0x60, 0xEE, 0xF0, 0x07, 0x9A, 0x9C, 0x69,
|
||||
0xAC, 0x97, 0x62, 0x26, 0x4F, 0x5D, 0x05, 0xB6, 0xF9, 0x8F, 0x48, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D,
|
||||
0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35,
|
||||
0x39, 0x35, 0x39, 0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
|
||||
0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D,
|
||||
0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01,
|
||||
0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01,
|
||||
0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB3, 0xE8, 0x6B, 0xAF, 0x9C, 0x16,
|
||||
0x52, 0xE3, 0x81, 0x0C, 0x50, 0xAB, 0x25, 0xCE, 0xCC, 0x0D, 0xC7, 0xF2,
|
||||
0x1F, 0x7F, 0x50, 0xDF, 0x2C, 0x5C, 0x35, 0xD6, 0x62, 0x2E, 0x63, 0x27,
|
||||
0x41, 0xA7, 0xE4, 0x53, 0xA8, 0x4B, 0x27, 0xFA, 0x13, 0x91, 0xA3, 0xFA,
|
||||
0x09, 0x4A, 0x2F, 0x3B, 0x5E, 0xCF, 0x77, 0xB3, 0x8A, 0xC1, 0xCD, 0x49,
|
||||
0x95, 0x9C, 0x75, 0x0D, 0x64, 0x74, 0xEF, 0xE4, 0xD7, 0x4B, 0xB9, 0xA1,
|
||||
0x9B, 0x68, 0xD2, 0x30, 0x71, 0x48, 0xEA, 0xF7, 0x4B, 0x14, 0xDF, 0x3F,
|
||||
0x47, 0xA9, 0xD8, 0xBB, 0xEC, 0x8F, 0x28, 0xCC, 0xFA, 0xDF, 0xB4, 0x1F,
|
||||
0x94, 0x7C, 0x96, 0xFC, 0x08, 0x05, 0x28, 0xF9, 0xE8, 0xF4, 0x2F, 0x2F,
|
||||
0xEE, 0x62, 0x9C, 0x8A, 0x3A, 0xE0, 0x85, 0x58, 0x60, 0xB6, 0x0F, 0x2D,
|
||||
0x30, 0xB4, 0xC0, 0x41, 0x54, 0x91, 0x4C, 0x1F, 0x5F, 0xAD, 0xF1, 0x19,
|
||||
0xF0, 0xC0, 0x22, 0xA6, 0x7D, 0xD8, 0x3F, 0x79, 0x34, 0x59, 0x42, 0x7B,
|
||||
0x5B, 0xB5, 0x41, 0xC4, 0x64, 0x7F, 0x52, 0xCF, 0x3C, 0x37, 0x22, 0xA1,
|
||||
0x2F, 0x79, 0x25, 0x94, 0x24, 0x41, 0xC2, 0x3F, 0xFA, 0xC7, 0x75, 0xFB,
|
||||
0x48, 0xB5, 0x0D, 0x18, 0xA7, 0xF4, 0x54, 0xF3, 0x2E, 0x6E, 0xD8, 0x43,
|
||||
0x58, 0xC4, 0xAB, 0x50, 0xE8, 0x05, 0xAD, 0x91, 0xB6, 0x1E, 0x01, 0x75,
|
||||
0xB3, 0x54, 0x9C, 0xDE, 0xA0, 0x99, 0x15, 0xFB, 0xAC, 0xF1, 0x5C, 0x97,
|
||||
0x49, 0x51, 0xCC, 0xEF, 0x58, 0x12, 0x6F, 0x73, 0x6B, 0xB3, 0x34, 0x14,
|
||||
0x01, 0x0F, 0x5A, 0x9D, 0xFA, 0xAA, 0xD6, 0x93, 0xD3, 0xE2, 0xEA, 0xC3,
|
||||
0xAB, 0xBC, 0x4E, 0xED, 0xCC, 0x51, 0xA1, 0xB8, 0xF8, 0x94, 0xB6, 0xB4,
|
||||
0x2C, 0xA8, 0x86, 0x2B, 0x1F, 0xF6, 0x51, 0x43, 0x29, 0x52, 0x5E, 0x13,
|
||||
0x89, 0xB3, 0x6A, 0x78, 0x60, 0x4E, 0x4E, 0xC0, 0x1B, 0xA5, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC3, 0x0A, 0xBC, 0xB4,
|
||||
0x90, 0x63, 0x96, 0x92, 0x45, 0xBC, 0x27, 0xA0, 0xF0, 0x58, 0x89, 0x2A,
|
||||
0xD5, 0x78, 0x00, 0x12, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04,
|
||||
0x16, 0x04, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA,
|
||||
0x19, 0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30,
|
||||
0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03,
|
||||
0x02, 0x00, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
|
||||
0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09,
|
||||
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03,
|
||||
0x82, 0x01, 0x01, 0x00, 0x54, 0x3B, 0xF4, 0xEA, 0xC6, 0xE4, 0xE8, 0xC0,
|
||||
0x5B, 0x12, 0xB2, 0xAD, 0xFA, 0xBD, 0xA9, 0xF4, 0x62, 0x03, 0xAD, 0x57,
|
||||
0x4C, 0x6F, 0x07, 0xA7, 0x47, 0x35, 0x75, 0x3E, 0x48, 0xA2, 0x5B, 0x71,
|
||||
0x10, 0x01, 0x8F, 0x93, 0x99, 0x9D, 0xA7, 0x47, 0xE3, 0x8E, 0x3E, 0xAF,
|
||||
0x2D, 0xBA, 0x06, 0xFE, 0xD4, 0xE4, 0x97, 0xBC, 0x10, 0x8D, 0xA6, 0xA5,
|
||||
0x3A, 0x3C, 0xE6, 0x21, 0xCB, 0x3B, 0xDA, 0x13, 0xE3, 0x4A, 0x23, 0xEB,
|
||||
0xBC, 0xBA, 0xA5, 0x90, 0x91, 0xAD, 0x55, 0x6E, 0xD5, 0xDD, 0x85, 0x4B,
|
||||
0x6B, 0x27, 0xD2, 0x39, 0x76, 0x06, 0x2E, 0xD4, 0x23, 0x5B, 0xBB, 0x55,
|
||||
0xB5, 0x49, 0x3F, 0x7D, 0x2F, 0x21, 0xCB, 0x96, 0x75, 0x19, 0x99, 0xA9,
|
||||
0x99, 0xF1, 0x0B, 0xBB, 0x3E, 0xC7, 0x10, 0xA7, 0x8B, 0x7A, 0x52, 0xB9,
|
||||
0x49, 0xE4, 0x14, 0x08, 0x78, 0xE7, 0x3D, 0xD9, 0x98, 0x57, 0xDA, 0xFF,
|
||||
0xDA, 0xB9, 0x8D, 0x66, 0x75, 0x80, 0xB5, 0x5D, 0xB9, 0xDF, 0x69, 0x65,
|
||||
0xDB, 0x16, 0xE7, 0x1E, 0xC4, 0x40, 0xE4, 0x46, 0x8A, 0x1E, 0x76, 0x32,
|
||||
0x16, 0xE7, 0x83, 0x67, 0xDA, 0x78, 0x56, 0xAB, 0x0F, 0x4C, 0x5C, 0xF1,
|
||||
0x70, 0xDA, 0x66, 0x20, 0xF4, 0xF8, 0x0F, 0xF6, 0xDC, 0x2F, 0x72, 0x97,
|
||||
0x6B, 0x78, 0x40, 0x79, 0x9D, 0x5B, 0x6D, 0xBE, 0x03, 0xCE, 0x70, 0x42,
|
||||
0xA8, 0x2A, 0x71, 0x11, 0xDF, 0x2E, 0x81, 0x01, 0xEA, 0x86, 0x12, 0x91,
|
||||
0x4F, 0xD0, 0x18, 0xED, 0x84, 0xA4, 0x48, 0x30, 0xB9, 0xB9, 0x7B, 0x56,
|
||||
0x3E, 0xEF, 0x8D, 0xE1, 0x1F, 0xFD, 0x90, 0xB2, 0x44, 0x85, 0x58, 0x6F,
|
||||
0xA7, 0x30, 0x74, 0x7C, 0xF1, 0xAE, 0x8C, 0x99, 0x3F, 0xF1, 0x4D, 0x57,
|
||||
0xC5, 0x95, 0x68, 0xC2, 0x36, 0xB2, 0xEC, 0xC2, 0x68, 0x7A, 0xC0, 0x81,
|
||||
0xA9, 0x55, 0x05, 0xE7, 0xCF, 0xAF, 0x50, 0xAC
|
||||
};
|
||||
|
||||
static const br_x509_certificate CHAIN[] = {
|
||||
{ (unsigned char *)CERT0, sizeof CERT0 },
|
||||
{ (unsigned char *)CERT1, sizeof CERT1 }
|
||||
};
|
||||
|
||||
#define CHAIN_LEN 2
|
||||
117
samples/chain-ec.h
Normal file
117
samples/chain-ec.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* A sample server certificate chain with a single intermediate CA.
|
||||
* Certificate key type: EC
|
||||
* Signing algorithm for both certificates: ECDSA
|
||||
*/
|
||||
|
||||
static const unsigned char CERT0[] = {
|
||||
0x30, 0x82, 0x01, 0xB0, 0x30, 0x82, 0x01, 0x56, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x1C, 0x4D, 0x00, 0x91, 0x69, 0xE2, 0x46, 0xAC, 0x90,
|
||||
0x7C, 0x64, 0x5C, 0x53, 0xF1, 0xFF, 0xB7, 0xC1, 0xCB, 0x6E, 0x7A, 0x30,
|
||||
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30,
|
||||
0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
|
||||
0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x74,
|
||||
0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x30, 0x30, 0x31,
|
||||
0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33,
|
||||
0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A,
|
||||
0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
|
||||
0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F, 0x73, 0x74, 0x30,
|
||||
0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
|
||||
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42,
|
||||
0x00, 0x04, 0x5F, 0x38, 0x9D, 0xA7, 0xFF, 0x4D, 0x8A, 0xAF, 0xF6, 0x34,
|
||||
0x39, 0x46, 0x1A, 0xFC, 0x3A, 0xDF, 0xF4, 0x23, 0xAA, 0xA9, 0xEA, 0xFB,
|
||||
0xC5, 0x08, 0xDE, 0x00, 0x8E, 0xBE, 0x79, 0xA5, 0x37, 0x58, 0x4C, 0x6D,
|
||||
0xDD, 0x01, 0xCA, 0xAB, 0x47, 0xDF, 0x89, 0xB6, 0xC7, 0x17, 0x1F, 0x38,
|
||||
0xFC, 0x1D, 0x20, 0x14, 0xDD, 0x45, 0xC0, 0xE0, 0x8F, 0x93, 0x4E, 0x38,
|
||||
0x0B, 0xFC, 0xE9, 0x99, 0xA1, 0x49, 0xA3, 0x66, 0x30, 0x64, 0x30, 0x1F,
|
||||
0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xF0,
|
||||
0xD0, 0xF1, 0x22, 0xF9, 0x7A, 0x48, 0x17, 0x06, 0x7B, 0x3D, 0xBD, 0xB8,
|
||||
0xF5, 0xCD, 0x55, 0x9C, 0x5C, 0x3E, 0x70, 0x30, 0x1D, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC3, 0x0E, 0x86, 0xAA, 0x75, 0xB4,
|
||||
0x15, 0xC0, 0xE5, 0x95, 0x09, 0x32, 0xBE, 0x5E, 0x92, 0x75, 0xA9, 0xE4,
|
||||
0x44, 0x9B, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF,
|
||||
0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04,
|
||||
0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F,
|
||||
0x73, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04,
|
||||
0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x91, 0xFB,
|
||||
0xF4, 0x04, 0xD0, 0xE5, 0x2E, 0x01, 0xD4, 0x8C, 0xF0, 0x17, 0x62, 0x0F,
|
||||
0xDC, 0xCC, 0x80, 0xCA, 0x18, 0xC4, 0x40, 0x7C, 0x27, 0x03, 0xCB, 0x34,
|
||||
0x03, 0x0D, 0x9B, 0xC8, 0x59, 0x4D, 0x02, 0x20, 0x05, 0x55, 0x69, 0xE2,
|
||||
0xD8, 0xA1, 0x40, 0x33, 0x34, 0x0E, 0x7E, 0x49, 0x32, 0x64, 0x1D, 0x3F,
|
||||
0x6B, 0x1F, 0xD0, 0x2D, 0xB7, 0x2F, 0x52, 0x04, 0x56, 0xAF, 0xD3, 0x37,
|
||||
0x8F, 0x87, 0x99, 0xA2
|
||||
};
|
||||
|
||||
static const unsigned char CERT1[] = {
|
||||
0x30, 0x82, 0x01, 0xA9, 0x30, 0x82, 0x01, 0x4E, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x20, 0xD3, 0xEB, 0xE2, 0x8C, 0xFE, 0xDA, 0xE6, 0xA3,
|
||||
0x2C, 0x5E, 0x3B, 0xF2, 0x66, 0x3A, 0x2B, 0x36, 0x7B, 0xB0, 0xCA, 0x30,
|
||||
0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30,
|
||||
0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
|
||||
0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x30, 0x30,
|
||||
0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D,
|
||||
0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39,
|
||||
0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
|
||||
0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
|
||||
0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64, 0x69,
|
||||
0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
|
||||
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48,
|
||||
0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x70, 0x2E, 0x92,
|
||||
0x82, 0x01, 0x17, 0x6C, 0x6D, 0xAB, 0xE1, 0xD1, 0x63, 0x09, 0x48, 0x49,
|
||||
0xD2, 0xA6, 0x35, 0x52, 0xD3, 0x3C, 0x73, 0xBB, 0xB2, 0x88, 0x37, 0x98,
|
||||
0x87, 0xF1, 0x8D, 0xE0, 0xEC, 0x65, 0x9A, 0x0E, 0x13, 0xF5, 0xED, 0x91,
|
||||
0x61, 0xC8, 0xB6, 0x6D, 0x33, 0x84, 0x6E, 0xAE, 0x8E, 0x55, 0x80, 0xCD,
|
||||
0x49, 0x9E, 0x07, 0xBF, 0xD0, 0xAE, 0x9D, 0xE6, 0xD0, 0xB3, 0x27, 0x16,
|
||||
0xA1, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23,
|
||||
0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x95, 0x41, 0xB4, 0xE2, 0x67, 0xAA,
|
||||
0xF1, 0x7F, 0xBC, 0x8F, 0x79, 0xF3, 0x68, 0x14, 0x5A, 0x6B, 0x92, 0x16,
|
||||
0xA2, 0x40, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04,
|
||||
0x14, 0xF0, 0xD0, 0xF1, 0x22, 0xF9, 0x7A, 0x48, 0x17, 0x06, 0x7B, 0x3D,
|
||||
0xBD, 0xB8, 0xF5, 0xCD, 0x55, 0x9C, 0x5C, 0x3E, 0x70, 0x30, 0x0E, 0x06,
|
||||
0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x00,
|
||||
0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04,
|
||||
0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86,
|
||||
0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02,
|
||||
0x21, 0x00, 0x85, 0xE3, 0x46, 0x68, 0x99, 0xD6, 0x02, 0x7A, 0x59, 0x66,
|
||||
0x1C, 0xB7, 0x4F, 0x35, 0x2D, 0x08, 0x36, 0x38, 0x61, 0x7E, 0x05, 0x48,
|
||||
0xD8, 0x69, 0x43, 0x1F, 0xEB, 0x56, 0xE9, 0xAD, 0x06, 0x0E, 0x02, 0x21,
|
||||
0x00, 0x82, 0x70, 0xB4, 0x62, 0x03, 0x49, 0x46, 0xC8, 0x54, 0x59, 0x05,
|
||||
0xD9, 0x78, 0xDB, 0x53, 0x1C, 0xE0, 0x6E, 0x66, 0xF5, 0x0F, 0x14, 0x3B,
|
||||
0xC9, 0x2D, 0x38, 0x12, 0x70, 0x91, 0x56, 0xF9, 0xA9
|
||||
};
|
||||
|
||||
static const br_x509_certificate CHAIN[] = {
|
||||
{ (unsigned char *)CERT0, sizeof CERT0 },
|
||||
{ (unsigned char *)CERT1, sizeof CERT1 }
|
||||
};
|
||||
|
||||
#define CHAIN_LEN 2
|
||||
183
samples/chain-rsa.h
Normal file
183
samples/chain-rsa.h
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* A sample server certificate chain with a single intermediate CA.
|
||||
* Certificate key type: RSA
|
||||
* Signing algorithm for both certificates: RSA
|
||||
*/
|
||||
|
||||
static const unsigned char CERT0[] = {
|
||||
0x30, 0x82, 0x03, 0x3C, 0x30, 0x82, 0x02, 0x24, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x58, 0xDA, 0xBA, 0x36, 0xCD, 0xED, 0xA0, 0xDA, 0x5C,
|
||||
0x10, 0x33, 0x73, 0x8E, 0x0C, 0x64, 0x92, 0x79, 0x92, 0xAF, 0x03, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D, 0x65, 0x64,
|
||||
0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31,
|
||||
0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A,
|
||||
0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39,
|
||||
0x35, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
|
||||
0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
|
||||
0x55, 0x04, 0x03, 0x13, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x68, 0x6F,
|
||||
0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86,
|
||||
0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
|
||||
0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xD4,
|
||||
0x7A, 0x1D, 0x27, 0xBA, 0x2B, 0x3A, 0x67, 0xB2, 0x91, 0x6A, 0xFB, 0xE7,
|
||||
0x83, 0x44, 0xCA, 0xED, 0x1C, 0x75, 0xAD, 0xDD, 0x4D, 0x83, 0x62, 0xD6,
|
||||
0xAA, 0x68, 0x95, 0xB2, 0x24, 0x21, 0x7B, 0x15, 0xAE, 0x2A, 0x99, 0x68,
|
||||
0x15, 0xED, 0x66, 0xF0, 0xB8, 0x58, 0xE7, 0xD3, 0xF5, 0x2E, 0xC6, 0xD9,
|
||||
0x2A, 0x5E, 0xE7, 0x0E, 0x2E, 0xE7, 0xFC, 0x67, 0x59, 0xC0, 0xC8, 0x61,
|
||||
0x7D, 0x4B, 0xA4, 0x6F, 0xDD, 0x9F, 0xD9, 0xC8, 0x85, 0x87, 0x64, 0xC7,
|
||||
0xBA, 0x1A, 0x0F, 0x29, 0xD4, 0x96, 0xA8, 0x78, 0x9A, 0x6B, 0x62, 0x20,
|
||||
0xA9, 0x32, 0xD0, 0xEE, 0xA9, 0x8C, 0x28, 0x61, 0x47, 0xA2, 0x50, 0x2A,
|
||||
0x63, 0xF6, 0x21, 0xDE, 0xDA, 0xD8, 0xD5, 0xF0, 0x7F, 0xC5, 0x00, 0x82,
|
||||
0x70, 0xE6, 0xA3, 0xBF, 0x5C, 0x89, 0x27, 0x4F, 0x51, 0x92, 0x77, 0x03,
|
||||
0xC3, 0xB0, 0xCC, 0x2E, 0x3B, 0xEC, 0x23, 0xF2, 0x2F, 0x53, 0x41, 0xAF,
|
||||
0x89, 0x93, 0xFF, 0xD2, 0x80, 0xB1, 0x43, 0x97, 0xDE, 0xD6, 0x19, 0xA0,
|
||||
0x92, 0x12, 0x7A, 0x3D, 0x66, 0x79, 0xE1, 0xC1, 0xBC, 0xE1, 0x77, 0x70,
|
||||
0xA2, 0x8B, 0x3D, 0x46, 0x84, 0x53, 0x3F, 0xE4, 0x4E, 0x42, 0x41, 0x37,
|
||||
0x92, 0x1E, 0x1F, 0xFD, 0x38, 0xB3, 0xF7, 0xEF, 0x87, 0x39, 0x80, 0xD3,
|
||||
0x56, 0xCF, 0xF4, 0xE0, 0x13, 0xDE, 0x64, 0xB0, 0x72, 0xA4, 0x03, 0x84,
|
||||
0xC4, 0x41, 0xED, 0x6F, 0xFA, 0x3E, 0xE2, 0xCA, 0x04, 0x20, 0xD2, 0xD7,
|
||||
0xDC, 0x2C, 0x82, 0x2B, 0x7A, 0xE2, 0x6D, 0xA1, 0x1C, 0x48, 0xDB, 0xCF,
|
||||
0x89, 0x4F, 0x34, 0x97, 0x3D, 0x28, 0xA8, 0x53, 0xDA, 0xE7, 0xC1, 0xE1,
|
||||
0x73, 0x15, 0xA3, 0x30, 0x76, 0x7F, 0x8F, 0x23, 0x42, 0x14, 0x3D, 0x51,
|
||||
0x34, 0xD2, 0x5A, 0xAD, 0x3C, 0x9B, 0xCB, 0xC8, 0xFE, 0x7F, 0x6E, 0x8E,
|
||||
0x40, 0xF3, 0xBD, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x66, 0x30, 0x64,
|
||||
0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
|
||||
0x14, 0xC5, 0x01, 0xAD, 0x7C, 0xE6, 0x63, 0xC9, 0x9C, 0x17, 0x5F, 0xC5,
|
||||
0xA2, 0xA7, 0xE1, 0x50, 0x5F, 0xE8, 0xF5, 0xA8, 0xC6, 0x30, 0x1D, 0x06,
|
||||
0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC5, 0x01, 0xAD, 0x7C,
|
||||
0xE6, 0x63, 0xC9, 0x9C, 0x17, 0x5F, 0xC5, 0xA2, 0xA7, 0xE1, 0x50, 0x5F,
|
||||
0xE8, 0xF5, 0xA8, 0xC6, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01,
|
||||
0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x14, 0x06, 0x03, 0x55, 0x1D,
|
||||
0x11, 0x04, 0x0D, 0x30, 0x0B, 0x82, 0x09, 0x6C, 0x6F, 0x63, 0x61, 0x6C,
|
||||
0x68, 0x6F, 0x73, 0x74, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
|
||||
0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
|
||||
0x71, 0xB3, 0x5D, 0x21, 0xC2, 0x0E, 0xD7, 0xD0, 0xC6, 0xF8, 0x4A, 0x73,
|
||||
0x87, 0x4D, 0x22, 0x02, 0x27, 0xD0, 0xC7, 0xF8, 0xFD, 0x1A, 0x6D, 0x62,
|
||||
0x58, 0x82, 0x08, 0x76, 0x20, 0x07, 0xC0, 0x48, 0x92, 0xF3, 0xE9, 0x98,
|
||||
0x5A, 0xEB, 0x0D, 0x4E, 0x56, 0x95, 0x63, 0x68, 0x4D, 0xAB, 0xD4, 0x00,
|
||||
0x76, 0xE0, 0x37, 0xCF, 0x0B, 0x11, 0x61, 0x59, 0x5C, 0xDE, 0xF6, 0xA5,
|
||||
0x14, 0x59, 0xD9, 0x25, 0x9F, 0x59, 0xD9, 0xD3, 0x5E, 0x86, 0xAC, 0x1D,
|
||||
0xA6, 0x2C, 0x32, 0x42, 0x19, 0x32, 0x13, 0x40, 0x0B, 0x54, 0xCD, 0x67,
|
||||
0x26, 0xB6, 0xBD, 0xB4, 0x96, 0xA4, 0xCA, 0x1F, 0x7F, 0x37, 0xD6, 0xA8,
|
||||
0x75, 0xEB, 0x3A, 0x81, 0x51, 0x30, 0xB9, 0xF9, 0x4A, 0x01, 0x6F, 0xD1,
|
||||
0xD6, 0xED, 0x4F, 0xDF, 0x3F, 0x30, 0x60, 0x06, 0x67, 0x92, 0x8E, 0x61,
|
||||
0x85, 0x5F, 0x1A, 0xB5, 0x8C, 0xB3, 0x0F, 0x61, 0xA9, 0xFA, 0xDF, 0x5D,
|
||||
0xC4, 0x64, 0x00, 0xEA, 0x87, 0xB1, 0x33, 0x5F, 0x7D, 0xCB, 0xA3, 0x85,
|
||||
0x24, 0x6E, 0x2C, 0x65, 0x3B, 0xEA, 0x73, 0x3F, 0x86, 0xD3, 0xFD, 0xE8,
|
||||
0xE4, 0x02, 0xC6, 0x61, 0x6A, 0x26, 0x17, 0x52, 0x01, 0x25, 0x5C, 0x7F,
|
||||
0xA8, 0xCE, 0x69, 0x1F, 0xAC, 0x61, 0x2C, 0xB7, 0x04, 0xAF, 0xFD, 0xA4,
|
||||
0x7A, 0x99, 0xCB, 0x26, 0x15, 0x4C, 0xFF, 0x74, 0xD4, 0x73, 0x0C, 0x57,
|
||||
0x0C, 0x26, 0xEB, 0xD7, 0x2A, 0xDC, 0x5C, 0xC3, 0x41, 0xBB, 0xC2, 0xF3,
|
||||
0xCE, 0x16, 0xBD, 0x8E, 0x7B, 0xFB, 0xE9, 0xDF, 0xAB, 0x21, 0x0D, 0x91,
|
||||
0xB3, 0x8D, 0xD8, 0xCF, 0xC8, 0xF4, 0x49, 0xB9, 0xD0, 0xE3, 0x16, 0x70,
|
||||
0x3F, 0xB3, 0xDE, 0xD4, 0x07, 0x25, 0xFA, 0x46, 0x44, 0x52, 0x89, 0x4D,
|
||||
0x89, 0xC8, 0xE2, 0xCA, 0xB5, 0x33, 0x7F, 0xC7, 0x21, 0xBD, 0x28, 0xEF,
|
||||
0xFE, 0x66, 0x74, 0x03
|
||||
};
|
||||
|
||||
static const unsigned char CERT1[] = {
|
||||
0x30, 0x82, 0x03, 0x34, 0x30, 0x82, 0x02, 0x1C, 0xA0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x14, 0x70, 0x0F, 0x60, 0xEE, 0xF0, 0x07, 0x9A, 0x9C, 0x69,
|
||||
0xAC, 0x97, 0x62, 0x26, 0x4F, 0x5D, 0x05, 0xB6, 0xF9, 0x8F, 0x48, 0x30,
|
||||
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
|
||||
0x05, 0x00, 0x30, 0x1C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D,
|
||||
0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x5A, 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35,
|
||||
0x39, 0x35, 0x39, 0x5A, 0x30, 0x27, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
|
||||
0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x41, 0x31, 0x18, 0x30, 0x16, 0x06,
|
||||
0x03, 0x55, 0x04, 0x03, 0x13, 0x0F, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6D,
|
||||
0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01,
|
||||
0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01,
|
||||
0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB3, 0xE8, 0x6B, 0xAF, 0x9C, 0x16,
|
||||
0x52, 0xE3, 0x81, 0x0C, 0x50, 0xAB, 0x25, 0xCE, 0xCC, 0x0D, 0xC7, 0xF2,
|
||||
0x1F, 0x7F, 0x50, 0xDF, 0x2C, 0x5C, 0x35, 0xD6, 0x62, 0x2E, 0x63, 0x27,
|
||||
0x41, 0xA7, 0xE4, 0x53, 0xA8, 0x4B, 0x27, 0xFA, 0x13, 0x91, 0xA3, 0xFA,
|
||||
0x09, 0x4A, 0x2F, 0x3B, 0x5E, 0xCF, 0x77, 0xB3, 0x8A, 0xC1, 0xCD, 0x49,
|
||||
0x95, 0x9C, 0x75, 0x0D, 0x64, 0x74, 0xEF, 0xE4, 0xD7, 0x4B, 0xB9, 0xA1,
|
||||
0x9B, 0x68, 0xD2, 0x30, 0x71, 0x48, 0xEA, 0xF7, 0x4B, 0x14, 0xDF, 0x3F,
|
||||
0x47, 0xA9, 0xD8, 0xBB, 0xEC, 0x8F, 0x28, 0xCC, 0xFA, 0xDF, 0xB4, 0x1F,
|
||||
0x94, 0x7C, 0x96, 0xFC, 0x08, 0x05, 0x28, 0xF9, 0xE8, 0xF4, 0x2F, 0x2F,
|
||||
0xEE, 0x62, 0x9C, 0x8A, 0x3A, 0xE0, 0x85, 0x58, 0x60, 0xB6, 0x0F, 0x2D,
|
||||
0x30, 0xB4, 0xC0, 0x41, 0x54, 0x91, 0x4C, 0x1F, 0x5F, 0xAD, 0xF1, 0x19,
|
||||
0xF0, 0xC0, 0x22, 0xA6, 0x7D, 0xD8, 0x3F, 0x79, 0x34, 0x59, 0x42, 0x7B,
|
||||
0x5B, 0xB5, 0x41, 0xC4, 0x64, 0x7F, 0x52, 0xCF, 0x3C, 0x37, 0x22, 0xA1,
|
||||
0x2F, 0x79, 0x25, 0x94, 0x24, 0x41, 0xC2, 0x3F, 0xFA, 0xC7, 0x75, 0xFB,
|
||||
0x48, 0xB5, 0x0D, 0x18, 0xA7, 0xF4, 0x54, 0xF3, 0x2E, 0x6E, 0xD8, 0x43,
|
||||
0x58, 0xC4, 0xAB, 0x50, 0xE8, 0x05, 0xAD, 0x91, 0xB6, 0x1E, 0x01, 0x75,
|
||||
0xB3, 0x54, 0x9C, 0xDE, 0xA0, 0x99, 0x15, 0xFB, 0xAC, 0xF1, 0x5C, 0x97,
|
||||
0x49, 0x51, 0xCC, 0xEF, 0x58, 0x12, 0x6F, 0x73, 0x6B, 0xB3, 0x34, 0x14,
|
||||
0x01, 0x0F, 0x5A, 0x9D, 0xFA, 0xAA, 0xD6, 0x93, 0xD3, 0xE2, 0xEA, 0xC3,
|
||||
0xAB, 0xBC, 0x4E, 0xED, 0xCC, 0x51, 0xA1, 0xB8, 0xF8, 0x94, 0xB6, 0xB4,
|
||||
0x2C, 0xA8, 0x86, 0x2B, 0x1F, 0xF6, 0x51, 0x43, 0x29, 0x52, 0x5E, 0x13,
|
||||
0x89, 0xB3, 0x6A, 0x78, 0x60, 0x4E, 0x4E, 0xC0, 0x1B, 0xA5, 0x02, 0x03,
|
||||
0x01, 0x00, 0x01, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x1F, 0x06, 0x03, 0x55,
|
||||
0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC3, 0x0A, 0xBC, 0xB4,
|
||||
0x90, 0x63, 0x96, 0x92, 0x45, 0xBC, 0x27, 0xA0, 0xF0, 0x58, 0x89, 0x2A,
|
||||
0xD5, 0x78, 0x00, 0x12, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04,
|
||||
0x16, 0x04, 0x14, 0x7C, 0xCF, 0xA3, 0xC6, 0x29, 0xF7, 0xF3, 0xC5, 0xAA,
|
||||
0x19, 0xD0, 0xC0, 0x16, 0xEB, 0xE0, 0x40, 0x0F, 0xCE, 0x44, 0xA7, 0x30,
|
||||
0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03,
|
||||
0x02, 0x00, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
|
||||
0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09,
|
||||
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03,
|
||||
0x82, 0x01, 0x01, 0x00, 0x54, 0x3B, 0xF4, 0xEA, 0xC6, 0xE4, 0xE8, 0xC0,
|
||||
0x5B, 0x12, 0xB2, 0xAD, 0xFA, 0xBD, 0xA9, 0xF4, 0x62, 0x03, 0xAD, 0x57,
|
||||
0x4C, 0x6F, 0x07, 0xA7, 0x47, 0x35, 0x75, 0x3E, 0x48, 0xA2, 0x5B, 0x71,
|
||||
0x10, 0x01, 0x8F, 0x93, 0x99, 0x9D, 0xA7, 0x47, 0xE3, 0x8E, 0x3E, 0xAF,
|
||||
0x2D, 0xBA, 0x06, 0xFE, 0xD4, 0xE4, 0x97, 0xBC, 0x10, 0x8D, 0xA6, 0xA5,
|
||||
0x3A, 0x3C, 0xE6, 0x21, 0xCB, 0x3B, 0xDA, 0x13, 0xE3, 0x4A, 0x23, 0xEB,
|
||||
0xBC, 0xBA, 0xA5, 0x90, 0x91, 0xAD, 0x55, 0x6E, 0xD5, 0xDD, 0x85, 0x4B,
|
||||
0x6B, 0x27, 0xD2, 0x39, 0x76, 0x06, 0x2E, 0xD4, 0x23, 0x5B, 0xBB, 0x55,
|
||||
0xB5, 0x49, 0x3F, 0x7D, 0x2F, 0x21, 0xCB, 0x96, 0x75, 0x19, 0x99, 0xA9,
|
||||
0x99, 0xF1, 0x0B, 0xBB, 0x3E, 0xC7, 0x10, 0xA7, 0x8B, 0x7A, 0x52, 0xB9,
|
||||
0x49, 0xE4, 0x14, 0x08, 0x78, 0xE7, 0x3D, 0xD9, 0x98, 0x57, 0xDA, 0xFF,
|
||||
0xDA, 0xB9, 0x8D, 0x66, 0x75, 0x80, 0xB5, 0x5D, 0xB9, 0xDF, 0x69, 0x65,
|
||||
0xDB, 0x16, 0xE7, 0x1E, 0xC4, 0x40, 0xE4, 0x46, 0x8A, 0x1E, 0x76, 0x32,
|
||||
0x16, 0xE7, 0x83, 0x67, 0xDA, 0x78, 0x56, 0xAB, 0x0F, 0x4C, 0x5C, 0xF1,
|
||||
0x70, 0xDA, 0x66, 0x20, 0xF4, 0xF8, 0x0F, 0xF6, 0xDC, 0x2F, 0x72, 0x97,
|
||||
0x6B, 0x78, 0x40, 0x79, 0x9D, 0x5B, 0x6D, 0xBE, 0x03, 0xCE, 0x70, 0x42,
|
||||
0xA8, 0x2A, 0x71, 0x11, 0xDF, 0x2E, 0x81, 0x01, 0xEA, 0x86, 0x12, 0x91,
|
||||
0x4F, 0xD0, 0x18, 0xED, 0x84, 0xA4, 0x48, 0x30, 0xB9, 0xB9, 0x7B, 0x56,
|
||||
0x3E, 0xEF, 0x8D, 0xE1, 0x1F, 0xFD, 0x90, 0xB2, 0x44, 0x85, 0x58, 0x6F,
|
||||
0xA7, 0x30, 0x74, 0x7C, 0xF1, 0xAE, 0x8C, 0x99, 0x3F, 0xF1, 0x4D, 0x57,
|
||||
0xC5, 0x95, 0x68, 0xC2, 0x36, 0xB2, 0xEC, 0xC2, 0x68, 0x7A, 0xC0, 0x81,
|
||||
0xA9, 0x55, 0x05, 0xE7, 0xCF, 0xAF, 0x50, 0xAC
|
||||
};
|
||||
|
||||
static const br_x509_certificate CHAIN[] = {
|
||||
{ (unsigned char *)CERT0, sizeof CERT0 },
|
||||
{ (unsigned char *)CERT1, sizeof CERT1 }
|
||||
};
|
||||
|
||||
#define CHAIN_LEN 2
|
||||
374
samples/client_basic.c
Normal file
374
samples/client_basic.c
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF 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 <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 = "/";
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
529
samples/custom_profile.c
Normal file
529
samples/custom_profile.c
Normal file
|
|
@ -0,0 +1,529 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF 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_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.
|
||||
*
|
||||
* 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 imeplementations.
|
||||
*
|
||||
* -- 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 ECDH_ECDSA or ECDH_RSA).
|
||||
*
|
||||
* The RSA code comes in two variants, called "i31" and "i32".
|
||||
* Right now, the "i31" is somewhat faster.
|
||||
*/
|
||||
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_prime_i31);
|
||||
br_ssl_client_set_ecdsa(cc, &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").
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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 prefered. The
|
||||
* ctmul32 implementation is meant to be used for the specific
|
||||
* 32-bit systems that do not have a 32x32->64 multiplier (i.e.
|
||||
* the ARM Cortex-M0 and Cortex-M0+).
|
||||
*
|
||||
* These implementations are all constant-time as long as the
|
||||
* underlying multiplication opcode is constant-time (which is
|
||||
* true for all modern systems, but not for older architectures
|
||||
* such that ARM9 or 80486).
|
||||
*/
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul);
|
||||
/* Alternate: ghash_ctmul32
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul32);
|
||||
*/
|
||||
/* Alternate: ghash_ctmul64
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul64);
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* For a client, the normal case is to validate the server
|
||||
* certificate with regards to a set of trust anchors. This
|
||||
* entails using a br_x509_minimal_context structure, configured
|
||||
* with the relevant algorithms, as shown below.
|
||||
*
|
||||
* Alternatively, the client could "know" the intended server
|
||||
* public key through an out-of-band mechanism, in which case
|
||||
* a br_x509_knownkey_context is appropriate, for a much reduced
|
||||
* code footprint.
|
||||
*
|
||||
* We assume here that the following extra parameters have been
|
||||
* provided:
|
||||
*
|
||||
* xc engine context (br_x509_minimal_context *)
|
||||
* trust_anchors trust anchors (br_x509_trust_anchor *)
|
||||
* trust_anchors_num number of trust anchors (size_t)
|
||||
*/
|
||||
|
||||
/*
|
||||
* The X.509 engine needs a hash function for processing the
|
||||
* subject and issuer DN of certificates and trust anchors. Any
|
||||
* supported hash function is appropriate; here we use SHA-256.
|
||||
* The trust an
|
||||
*/
|
||||
br_x509_minimal_init(xc, &br_sha256_vtable,
|
||||
trust_anchors, trust_anchors_num);
|
||||
|
||||
/*
|
||||
* Set suites and asymmetric crypto implementations. We use the
|
||||
* "i31" code for RSA (it is somewhat faster than the "i32"
|
||||
* implementation). These implementations are used for
|
||||
* signature verification on certificates, but not for the
|
||||
* SSL-specific usage of the server's public key. For instance,
|
||||
* if the server has an EC public key but the rest of the chain
|
||||
* (intermediate CA, root...) use RSA, then you would need only
|
||||
* the RSA verification function below.
|
||||
*/
|
||||
br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy);
|
||||
br_x509_minimal_set_ecdsa(xc,
|
||||
&br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
|
||||
|
||||
/*
|
||||
* Set supported hash functions. These are for signatures on
|
||||
* certificates. There again, you only need the hash functions
|
||||
* that are actually used in certificates, but if a given
|
||||
* function was included for the SSL engine, you may as well
|
||||
* add it here.
|
||||
*
|
||||
* Note: the engine explicitly rejects signatures that use MD5.
|
||||
* Thus, there is no need for MD5 here.
|
||||
*/
|
||||
br_ssl_engine_set_hash(xc, br_sha1_ID, &br_sha1_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha224_ID, &br_sha224_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha256_ID, &br_sha256_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha384_ID, &br_sha384_vtable);
|
||||
br_ssl_engine_set_hash(xc, br_sha512_ID, &br_sha512_vtable);
|
||||
|
||||
/*
|
||||
* Link the X.509 engine in the SSL engine.
|
||||
*/
|
||||
br_ssl_engine_set_x509(&cc->eng, &xc->vtable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Example server profile. Most of it is shared with the client
|
||||
* profile, so see the comments in the client function for details.
|
||||
*
|
||||
* This example function assumes a server with a (unique) RSA private
|
||||
* key, so the list of cipher suites is trimmed down for RSA.
|
||||
*/
|
||||
void
|
||||
example_server_profile(br_ssl_server_context *cc,
|
||||
const br_x509_certificate *chain, size_t chain_len,
|
||||
const br_rsa_private_key *sk)
|
||||
{
|
||||
static const uint16_t suites[] = {
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
||||
BR_TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||
BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||
BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||
};
|
||||
|
||||
br_ssl_server_zero(cc);
|
||||
br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12);
|
||||
|
||||
br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf);
|
||||
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
|
||||
br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf);
|
||||
|
||||
/*
|
||||
* Apart from the requirements listed in the client side, these
|
||||
* hash functions are also used by the server to compute its
|
||||
* signature on ECDHE parameters. Which functions are needed
|
||||
* depends on what the client may support; furthermore, the
|
||||
* client may fail to send the relevant extension, in which
|
||||
* case the server will default to whatever it can (as per the
|
||||
* standard, it should be SHA-1 in that case).
|
||||
*/
|
||||
br_ssl_engine_set_hash(&cc->eng, br_md5_ID, &br_md5_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha1_ID, &br_sha1_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha224_ID, &br_sha224_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha384_ID, &br_sha384_vtable);
|
||||
br_ssl_engine_set_hash(&cc->eng, br_sha512_ID, &br_sha512_vtable);
|
||||
|
||||
br_ssl_engine_set_suites(&cc->eng, suites,
|
||||
(sizeof suites) / (sizeof suites[0]));
|
||||
|
||||
/*
|
||||
* Elliptic curve implementation is used for ECDHE suites (but
|
||||
* not for ECDH).
|
||||
*/
|
||||
br_ssl_engine_set_ec(&cc->eng, &br_ec_prime_i31);
|
||||
|
||||
/*
|
||||
* Set the "server policy": handler for the certificate chain
|
||||
* and private key operations. Here, we indicate that the RSA
|
||||
* private key is fit for both signing and decrypting, and we
|
||||
* provide the two relevant implementations.
|
||||
|
||||
* BR_KEYTYPE_KEYX allows TLS_RSA_*, BR_KEYTYPE_SIGN allows
|
||||
* TLS_ECDHE_RSA_*.
|
||||
*/
|
||||
br_ssl_server_set_single_rsa(cc, chain, chain_len, sk,
|
||||
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||
br_rsa_i31_private, br_rsa_i31_pkcs1_sign);
|
||||
/*
|
||||
* If the server used an EC private key, this call would look
|
||||
* like this:
|
||||
|
||||
br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
|
||||
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
|
||||
cert_issuer_key_type,
|
||||
&br_ec_prime_i31, br_ecdsa_i31_sign_asn1);
|
||||
|
||||
* Note the tricky points:
|
||||
*
|
||||
* -- "ECDH" cipher suites use only the EC code (&br_ec_prime_i31);
|
||||
* the ECDHE_ECDSA cipher suites need both the EC code and
|
||||
* the ECDSA signature implementation.
|
||||
*
|
||||
* -- For "ECDH" (not "ECDHE") cipher suites, the engine must
|
||||
* know the key type (RSA or EC) for the intermediate CA that
|
||||
* issued the server's certificate; this is an artefact of
|
||||
* how the protocol is defined. BearSSL won't try to decode
|
||||
* the server's certificate to obtain that information (it
|
||||
* could do that, the code is there, but it would increase the
|
||||
* footprint). So this must be provided by the caller.
|
||||
*
|
||||
* -- BR_KEYTYPE_KEYX allows ECDH, BR_KEYTYPE_SIGN allows
|
||||
* ECDHE_ECDSA.
|
||||
*/
|
||||
|
||||
br_ssl_engine_set_cbc(&cc->eng,
|
||||
&br_sslrec_in_cbc_vtable,
|
||||
&br_sslrec_out_cbc_vtable);
|
||||
br_ssl_engine_set_gcm(&cc->eng,
|
||||
&br_sslrec_in_gcm_vtable,
|
||||
&br_sslrec_out_gcm_vtable);
|
||||
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct_cbcenc_vtable,
|
||||
&br_aes_ct_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct_ctr_vtable);
|
||||
/* Alternate: aes_ct64
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_ct64_cbcenc_vtable,
|
||||
&br_aes_ct64_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_ct64_ctr_vtable);
|
||||
*/
|
||||
/* Alternate: aes_small
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_small_cbcenc_vtable,
|
||||
&br_aes_small_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_small_ctr_vtable);
|
||||
*/
|
||||
/* Alternate: aes_big
|
||||
br_ssl_engine_set_aes_cbc(&cc->eng,
|
||||
&br_aes_big_cbcenc_vtable,
|
||||
&br_aes_big_cbcdec_vtable);
|
||||
br_ssl_engine_set_aes_ctr(&cc->eng,
|
||||
&br_aes_big_ctr_vtable);
|
||||
*/
|
||||
br_ssl_engine_set_des_cbc(&cc->eng,
|
||||
&br_des_ct_cbcenc_vtable,
|
||||
&br_des_ct_cbcdec_vtable);
|
||||
/* Alternate: des_tab
|
||||
br_ssl_engine_set_des_cbc(&cc->eng,
|
||||
&br_des_tab_cbcenc_vtable,
|
||||
&br_des_tab_cbcdec_vtable);
|
||||
*/
|
||||
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul);
|
||||
/* Alternate: ghash_ctmul32
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul32);
|
||||
*/
|
||||
/* Alternate: ghash_ctmul64
|
||||
br_ssl_engine_set_ghash(&cc->eng,
|
||||
&br_ghash_ctmul64);
|
||||
*/
|
||||
}
|
||||
40
samples/key-ec.h
Normal file
40
samples/key-ec.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* The private key for the server certificate (EC).
|
||||
*/
|
||||
|
||||
static const unsigned char EC_X[] = {
|
||||
0x03, 0x91, 0x5B, 0x42, 0x06, 0x90, 0x73, 0x91, 0x1B, 0x48, 0xEF, 0x08,
|
||||
0xFB, 0xB5, 0xAD, 0x75, 0x65, 0xF9, 0xE6, 0xF7, 0x21, 0x47, 0x62, 0x48,
|
||||
0xFA, 0x3F, 0x97, 0x7B, 0x70, 0x9D, 0x86, 0xA5
|
||||
};
|
||||
|
||||
static const br_ec_private_key EC = {
|
||||
23,
|
||||
(unsigned char *)EC_X, sizeof EC_X
|
||||
};
|
||||
5
samples/key-ee-ec.pem
Normal file
5
samples/key-ee-ec.pem
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIAORW0IGkHORG0jvCPu1rXVl+eb3IUdiSPo/l3twnYaloAoGCCqGSM49AwEHoUQDQgAE
|
||||
Xzidp/9Niq/2NDlGGvw63/Qjqqnq+8UI3gCOvnmlN1hMbd0ByqtH34m2xxcfOPwdIBTdRcDgj5NO
|
||||
OAv86ZmhSQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
23
samples/key-ee-rsa.pem
Normal file
23
samples/key-ee-rsa.pem
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA1HodJ7orOmeykWr754NEyu0cda3dTYNi1qpolbIkIXsVriqZaBXtZvC4WOfT
|
||||
9S7G2Spe5w4u5/xnWcDIYX1LpG/dn9nIhYdkx7oaDynUlqh4mmtiIKky0O6pjChhR6JQKmP2Id7a
|
||||
2NXwf8UAgnDmo79ciSdPUZJ3A8OwzC477CPyL1NBr4mT/9KAsUOX3tYZoJISej1meeHBvOF3cKKL
|
||||
PUaEUz/kTkJBN5IeH/04s/fvhzmA01bP9OAT3mSwcqQDhMRB7W/6PuLKBCDS19wsgit64m2hHEjb
|
||||
z4lPNJc9KKhT2ufB4XMVozB2f48jQhQ9UTTSWq08m8vI/n9ujkDzvQIDAQABAoIBADzb40jzQpl+
|
||||
hT+wsIl96HDlXI76Z1Zh6SgKdF1YQpASdMHHstwE19Rx46OXd3cVWGBwifFNdzL8cU/cb6i43jcx
|
||||
0X2NQCm6/6tTi05HkXw7shus4VTwkb0VdxvNnxuJCsQxkJjf/7g3AyVdtIkoNG+3ipZAW7BGLu+1
|
||||
mAjLv18h4LniI8JGWQK75z8xNQzEdOFVyqC1PujjC5emesxlRW8Ks+MzQ+20WTpHGkLAoLJZJ1XE
|
||||
bDQqFbkRXu4imKLtA4iyBrEpXEKZR85tVO+NQOGdPyH/ugK23nSDcJlI2PTHSlGABTpZZUmigO4O
|
||||
b8lppU7cFa2JemKG3kEj0BWDOWMCgYEA+fYynFHXcbJi7YEk2vapLMMtVZSVUeU2Ep4uH47YIiJk
|
||||
XqP8YPAU3BBIb08afcw3Iyd2tjGq3nDJ7KsKUPHqeXl0vjurLmOXom8KRXvXbNJtG3AxA68miyjF
|
||||
+ElnRUHx0zUFJyp5IdoGtj2i6DxA+m/E/PXEBeuaMapAfl7uIlsCgYEA2Zwa3JRR9sGW2g4RPzco
|
||||
ejOwxL7faCvTHGVnejyvWVCrKTYXORVxl2LdzSXujf8mj3Ehvo+chU464STH4Urf0GCzxEQurHMW
|
||||
XwfJOnNe2pvu4rSpPTMUe+6n1Kz3U+Y+8IVXTIuWG93XNvyJN1l1lnWLLvcELSmJ2befcTvi7ccC
|
||||
gYEA5PwCLyvWRwTZFaRaI/EU17nRHPYpuEVXPMUFkclk/BgvhHeLay5knZiZEscPiLB8zkqHuK5V
|
||||
TsNaZ+HkaHTFjRSTuvWkgrGfpqE8cpzZo4o9g4ZKkIpyr8bhXOu5nDumEgsfNlr1bupxfZ+HTmJs
|
||||
UD/14JowQhAsSFUkEeBbHMMCgYEAjazgoDPAmVK4kAcQm4Ohys3UjINomD3QGHC8ygywbQnkJdSd
|
||||
kgCwD8vCdEn54mD4DfOt8I83bGLeWq7Do55H0TbkUyfA622SZxR+optyagmToe3VMY8MCxP6GLDz
|
||||
5Z/F4notuBw5ArOP5rDL9Uk9EVQ95bnU8kJVCXZPTD2dJQkCgYByDKfPBpVp9HUgNAPgz5pRk/VC
|
||||
LvKFvs5POLWMoplC871lOOI0PyGd9b2zv3M8GN728H+hwlXyOOkOHjHn21HFcY1ncTqfVVJg7kX2
|
||||
CJiBt3sv8pZ9c9Cmq6qDSUE1qZBnztO5c1SqhACIiJAdhpvluM6JChtHYjHCP8OMhgk8hg==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
5
samples/key-ica-ec.pem
Normal file
5
samples/key-ica-ec.pem
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIEJOkvo4MZ9N+wlTodEzmWor1RauybudPe92K15viDbzoAoGCCqGSM49AwEHoUQDQgAE
|
||||
cC6SggEXbG2r4dFjCUhJ0qY1UtM8c7uyiDeYh/GN4Oxlmg4T9e2RYci2bTOEbq6OVYDNSZ4Hv9Cu
|
||||
nebQsycWoQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
23
samples/key-ica-rsa.pem
Normal file
23
samples/key-ica-rsa.pem
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAs+hrr5wWUuOBDFCrJc7MDcfyH39Q3yxcNdZiLmMnQafkU6hLJ/oTkaP6CUov
|
||||
O17Pd7OKwc1JlZx1DWR07+TXS7mhm2jSMHFI6vdLFN8/R6nYu+yPKMz637QflHyW/AgFKPno9C8v
|
||||
7mKcijrghVhgtg8tMLTAQVSRTB9frfEZ8MAipn3YP3k0WUJ7W7VBxGR/Us88NyKhL3kllCRBwj/6
|
||||
x3X7SLUNGKf0VPMubthDWMSrUOgFrZG2HgF1s1Sc3qCZFfus8VyXSVHM71gSb3NrszQUAQ9anfqq
|
||||
1pPT4urDq7xO7cxRobj4lLa0LKiGKx/2UUMpUl4TibNqeGBOTsAbpQIDAQABAoIBAAtBpQ85SGpK
|
||||
QsZG+9ZjQIAyPPN8j05PY7uYnM8DNC8W9qHHW2B2dKf9pwTSx+7CiV+Xc7yZgBukzOwYF3r1CgV6
|
||||
aWKkZdZTGDlfXKrDJx3wQhfL/s8SODYr+nfbbcT6KXx9WnaAx1J2iA3cDjU5qN9rRqwP+yF7TZYC
|
||||
NoXXGoTmHb7gj1H1IJNdiUgG0netXpM2HydRLzwHDweKav6sm4V4TTeHPYokVp8W7lL7xRhwQXVD
|
||||
lcE1noY5NczXV88k9n0EbqGDwX3pJoDC/xWzBFh/+oupxotM4KY2dKJGmtKTmiIef3u43CPv5SYh
|
||||
V2OcEXn+joV5qHGhg6yN+ri0/ucCgYEA4x2NBFNtbpx3lmc2r2hwfbawcTVKKlxqJWdoG2bd7HQz
|
||||
bO+uqtxhLOxEou4S9uPUVylvpNlDs3xQ+DF9p8oTo5XlHvA6DT/cAjWSQ+MRHqCV30T0lDSd0McZ
|
||||
4PaV1nq94bGuPVrGe/Dex5dL+VVhn2tpoqwudsyx5hHA8hFE1zcCgYEAysnhrQa1HZQ0hOaA2c/e
|
||||
A8I47dEIyGi4N6uJVBUMM1ecKifs4FKybOtI+XM3mwuAXUyVQGi2SZBBpE4bN3oUDWGwYF7SAJV0
|
||||
JJHpBxlZBvYRC7Vfh8HFPYIQCynP0Q4BeQVDaCPW3puJsTWnn2lNhT/PsSm3v76JwTRrBoqaGgMC
|
||||
gYAwyyiAxWu9V+BZb9NP3CBO4fEGYWyNrU0gvBahzHfhVRW3Ucc07iPygtA8MOniIRB9qWlTAVqK
|
||||
NSswJ3HXmpKdkpanDvVp405hKyFBdIc5DUclsKrbLHK7aAsnSdLnQXeKBaJpjBcYiadTOi4YYz+W
|
||||
AH2xdUyGOXP++dF6MDuaAQKBgQCtWyHygW5pR94R0t9J1FpuCiYSn4ULlgINjTXLzGZuqbGVlCX6
|
||||
qpdfZ1At92IMyCtHFwXsVtemUYzcAe1gYpsryVw3Njf+ScVM0fNMn02tFsQBp15wNqT/7OT8NhUz
|
||||
GO8HXwl9yE2SZZKzDDQsoZ+kjqVlRU2QvDkVElN/9xK/swKBgDz6m4XHvhvITo2bd8/i4FxTN1gr
|
||||
napgAc2DHOzCmeyYCjKvZAJDLeNleni1kj1UfrzVrH2BFM38asRJu8xPI4WjfH1fFktNjXVu6Ctk
|
||||
YFu0/0TlWkzowZHmE/K0M0tuJLt42m/DLW8deMyl38x+PUPUZb4OdVAKAua/voOMZtQw
|
||||
-----END RSA PRIVATE KEY-----
|
||||
5
samples/key-root-ec.pem
Normal file
5
samples/key-root-ec.pem
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEINx41f6h/utlj52XNFbIGJdkF3qZy1/g9hH2/yV4t/tnoAoGCCqGSM49AwEHoUQDQgAE
|
||||
cXS6q7kwLoHV5Vf58yBoDJz5ZNu0IA1t6kDQSm5C/baaaCVE9t97xPze3Xu7xdt8dj9BZkBu26eH
|
||||
wuXYxfN/jQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
23
samples/key-root-rsa.pem
Normal file
23
samples/key-root-rsa.pem
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAttk01FD9s696c/HOOL9db0Xh/U6xmMZggybSF9HFt5qjwd5jOZec8F5cyBwX
|
||||
uYgZbfC2LjBQoVRuk8DbzzDLnx4nefHDmVI1qj2237CtfMtJzcDt52YQKunOKB8hUPp3TC3a7zxY
|
||||
606/zun7Gtqjg6PNo8qTgNza8xfMeqszgJyy1H9GP8U83GGUtycpbiq8Wwk21MY7Deu+ztsdHLwQ
|
||||
anFxs/LKKJp38orsQu+xSo7i8hoyKs3ApkYsmsKFN5F/RqGTgaF0Zt+6szkgkZP6HaGohefk+Qf2
|
||||
EPaoJwG2fxLDQMPJ4rCrSRg6ZLZZt5W1ljbfImmqcmpUTicpow6XFQIDAQABAoIBAENjavKDBPWn
|
||||
yygXKqtEb/GWHlNmoNKO7jv33z9TGxzvW8IULZqos3jtNiG0JNRGgiTALcx5FwZWYUiIMBq8v5bd
|
||||
nKv3O+DyaP/crdzkNxRCsekoXSXGuleugsHLs1IudTA4yDMamSTkCZH/LwH3KYNXJ+9hNhqsiu9D
|
||||
yqM9HIad2k/hmVFv4NDdH3VWqsQJFfrGEXgKRJKNpuzKeST3oo4iLcwH9NGiKXfjW23ekOiLYFwZ
|
||||
q8Yd6tOgNLpGuDWk9rlXPJALyXFZ/3UXZaKU5f0ZRfPfMQgM8toeWeWJS0FW7g6aLCJATsfOu/II
|
||||
j3nTVCPryvGF4mwe/y+Rgbd67xMCgYEA3Wpiac27hvbLzwbSTWYsKql5uKV0HTim3haNDuzMHJVY
|
||||
ZRJSuTY+rZBoaiuDRKMCMI3dQM8AZUJfHQclyTxjtn17Ig8cTKMN6Wr2MRTBplCq3wNLVjbOPAE2
|
||||
cv74gUfgpRLdlyueYO7j6PcTS+l41+wB1A/zAEm346Eoxoztt5cCgYEA02ipYQFX4T+8BSkcEyzP
|
||||
qeMT9d3BLPm4tTeq2sXRgcfEbF/ENcAX9OfPSEx4kVtzsfJXma5/dg0fuVgl1hO5WLBT+L6MJ/A2
|
||||
sGX3Y7x+doXI0xcNd/Epr7oWqZuCO7477vzJcNtud/KQJj2EmRNaHKKtaohqO5dnNhsM540lnDMC
|
||||
gYBU40KT2eJ5ngkJeE4Mio2IVa1rE1PvGBcxsmemPzcKBl/7cAjzJU7mcCT3/3K2T+C5CMq43CQE
|
||||
rmuUz3a3LkX0YytgJXbuEt10jiORMaoEv4yjL7okdaKf8r8TW5mexxXjc9Ys7PYtp6kNWhy1z+8a
|
||||
qUsSKIM7qwerZ9AgP0usRQKBgQDEHy4y/coG/tdweii/aSzlT/Huf2B8VtaR1yi7eBTaLvb8CwO9
|
||||
UY1n970GN1sKjiqQhF/cBFPesmIh0bKYHQgvTLU555uiWWiC0LVmYzF2xrn9ij9GbAXeLeZkRg3V
|
||||
Wq/DD+PYvNiIkhBESYG/eIJ6WjhCwna6/cQUH5gjH4AqnQKBgQCsKyjLtx+FeFu7PZ8AgCGWRVvs
|
||||
suxB74pxlMqMgBbBHyAGQOTTuaaTr/gwNXAAErAXS1X9VsAcAkM/yFv19mdZmJQG9vUMOe48AZDB
|
||||
c7xt3t3Ul71eAlbAYkrQGtq64yO3w7ny4C7GUVqMX03XwKToCrXqeKfGwrZGNP+lgZYrbw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
108
samples/key-rsa.h
Normal file
108
samples/key-rsa.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "bearssl.h"
|
||||
|
||||
/*
|
||||
* The private key for the server certificate (RSA).
|
||||
*/
|
||||
|
||||
static const unsigned char RSA_P[] = {
|
||||
0xF9, 0xF6, 0x32, 0x9C, 0x51, 0xD7, 0x71, 0xB2, 0x62, 0xED, 0x81, 0x24,
|
||||
0xDA, 0xF6, 0xA9, 0x2C, 0xC3, 0x2D, 0x55, 0x94, 0x95, 0x51, 0xE5, 0x36,
|
||||
0x12, 0x9E, 0x2E, 0x1F, 0x8E, 0xD8, 0x22, 0x22, 0x64, 0x5E, 0xA3, 0xFC,
|
||||
0x60, 0xF0, 0x14, 0xDC, 0x10, 0x48, 0x6F, 0x4F, 0x1A, 0x7D, 0xCC, 0x37,
|
||||
0x23, 0x27, 0x76, 0xB6, 0x31, 0xAA, 0xDE, 0x70, 0xC9, 0xEC, 0xAB, 0x0A,
|
||||
0x50, 0xF1, 0xEA, 0x79, 0x79, 0x74, 0xBE, 0x3B, 0xAB, 0x2E, 0x63, 0x97,
|
||||
0xA2, 0x6F, 0x0A, 0x45, 0x7B, 0xD7, 0x6C, 0xD2, 0x6D, 0x1B, 0x70, 0x31,
|
||||
0x03, 0xAF, 0x26, 0x8B, 0x28, 0xC5, 0xF8, 0x49, 0x67, 0x45, 0x41, 0xF1,
|
||||
0xD3, 0x35, 0x05, 0x27, 0x2A, 0x79, 0x21, 0xDA, 0x06, 0xB6, 0x3D, 0xA2,
|
||||
0xE8, 0x3C, 0x40, 0xFA, 0x6F, 0xC4, 0xFC, 0xF5, 0xC4, 0x05, 0xEB, 0x9A,
|
||||
0x31, 0xAA, 0x40, 0x7E, 0x5E, 0xEE, 0x22, 0x5B
|
||||
};
|
||||
|
||||
static const unsigned char RSA_Q[] = {
|
||||
0xD9, 0x9C, 0x1A, 0xDC, 0x94, 0x51, 0xF6, 0xC1, 0x96, 0xDA, 0x0E, 0x11,
|
||||
0x3F, 0x37, 0x28, 0x7A, 0x33, 0xB0, 0xC4, 0xBE, 0xDF, 0x68, 0x2B, 0xD3,
|
||||
0x1C, 0x65, 0x67, 0x7A, 0x3C, 0xAF, 0x59, 0x50, 0xAB, 0x29, 0x36, 0x17,
|
||||
0x39, 0x15, 0x71, 0x97, 0x62, 0xDD, 0xCD, 0x25, 0xEE, 0x8D, 0xFF, 0x26,
|
||||
0x8F, 0x71, 0x21, 0xBE, 0x8F, 0x9C, 0x85, 0x4E, 0x3A, 0xE1, 0x24, 0xC7,
|
||||
0xE1, 0x4A, 0xDF, 0xD0, 0x60, 0xB3, 0xC4, 0x44, 0x2E, 0xAC, 0x73, 0x16,
|
||||
0x5F, 0x07, 0xC9, 0x3A, 0x73, 0x5E, 0xDA, 0x9B, 0xEE, 0xE2, 0xB4, 0xA9,
|
||||
0x3D, 0x33, 0x14, 0x7B, 0xEE, 0xA7, 0xD4, 0xAC, 0xF7, 0x53, 0xE6, 0x3E,
|
||||
0xF0, 0x85, 0x57, 0x4C, 0x8B, 0x96, 0x1B, 0xDD, 0xD7, 0x36, 0xFC, 0x89,
|
||||
0x37, 0x59, 0x75, 0x96, 0x75, 0x8B, 0x2E, 0xF7, 0x04, 0x2D, 0x29, 0x89,
|
||||
0xD9, 0xB7, 0x9F, 0x71, 0x3B, 0xE2, 0xED, 0xC7
|
||||
};
|
||||
|
||||
static const unsigned char RSA_DP[] = {
|
||||
0xE4, 0xFC, 0x02, 0x2F, 0x2B, 0xD6, 0x47, 0x04, 0xD9, 0x15, 0xA4, 0x5A,
|
||||
0x23, 0xF1, 0x14, 0xD7, 0xB9, 0xD1, 0x1C, 0xF6, 0x29, 0xB8, 0x45, 0x57,
|
||||
0x3C, 0xC5, 0x05, 0x91, 0xC9, 0x64, 0xFC, 0x18, 0x2F, 0x84, 0x77, 0x8B,
|
||||
0x6B, 0x2E, 0x64, 0x9D, 0x98, 0x99, 0x12, 0xC7, 0x0F, 0x88, 0xB0, 0x7C,
|
||||
0xCE, 0x4A, 0x87, 0xB8, 0xAE, 0x55, 0x4E, 0xC3, 0x5A, 0x67, 0xE1, 0xE4,
|
||||
0x68, 0x74, 0xC5, 0x8D, 0x14, 0x93, 0xBA, 0xF5, 0xA4, 0x82, 0xB1, 0x9F,
|
||||
0xA6, 0xA1, 0x3C, 0x72, 0x9C, 0xD9, 0xA3, 0x8A, 0x3D, 0x83, 0x86, 0x4A,
|
||||
0x90, 0x8A, 0x72, 0xAF, 0xC6, 0xE1, 0x5C, 0xEB, 0xB9, 0x9C, 0x3B, 0xA6,
|
||||
0x12, 0x0B, 0x1F, 0x36, 0x5A, 0xF5, 0x6E, 0xEA, 0x71, 0x7D, 0x9F, 0x87,
|
||||
0x4E, 0x62, 0x6C, 0x50, 0x3F, 0xF5, 0xE0, 0x9A, 0x30, 0x42, 0x10, 0x2C,
|
||||
0x48, 0x55, 0x24, 0x11, 0xE0, 0x5B, 0x1C, 0xC3
|
||||
};
|
||||
|
||||
static const unsigned char RSA_DQ[] = {
|
||||
0x8D, 0xAC, 0xE0, 0xA0, 0x33, 0xC0, 0x99, 0x52, 0xB8, 0x90, 0x07, 0x10,
|
||||
0x9B, 0x83, 0xA1, 0xCA, 0xCD, 0xD4, 0x8C, 0x83, 0x68, 0x98, 0x3D, 0xD0,
|
||||
0x18, 0x70, 0xBC, 0xCA, 0x0C, 0xB0, 0x6D, 0x09, 0xE4, 0x25, 0xD4, 0x9D,
|
||||
0x92, 0x00, 0xB0, 0x0F, 0xCB, 0xC2, 0x74, 0x49, 0xF9, 0xE2, 0x60, 0xF8,
|
||||
0x0D, 0xF3, 0xAD, 0xF0, 0x8F, 0x37, 0x6C, 0x62, 0xDE, 0x5A, 0xAE, 0xC3,
|
||||
0xA3, 0x9E, 0x47, 0xD1, 0x36, 0xE4, 0x53, 0x27, 0xC0, 0xEB, 0x6D, 0x92,
|
||||
0x67, 0x14, 0x7E, 0xA2, 0x9B, 0x72, 0x6A, 0x09, 0x93, 0xA1, 0xED, 0xD5,
|
||||
0x31, 0x8F, 0x0C, 0x0B, 0x13, 0xFA, 0x18, 0xB0, 0xF3, 0xE5, 0x9F, 0xC5,
|
||||
0xE2, 0x7A, 0x2D, 0xB8, 0x1C, 0x39, 0x02, 0xB3, 0x8F, 0xE6, 0xB0, 0xCB,
|
||||
0xF5, 0x49, 0x3D, 0x11, 0x54, 0x3D, 0xE5, 0xB9, 0xD4, 0xF2, 0x42, 0x55,
|
||||
0x09, 0x76, 0x4F, 0x4C, 0x3D, 0x9D, 0x25, 0x09
|
||||
};
|
||||
|
||||
static const unsigned char RSA_IQ[] = {
|
||||
0x72, 0x0C, 0xA7, 0xCF, 0x06, 0x95, 0x69, 0xF4, 0x75, 0x20, 0x34, 0x03,
|
||||
0xE0, 0xCF, 0x9A, 0x51, 0x93, 0xF5, 0x42, 0x2E, 0xF2, 0x85, 0xBE, 0xCE,
|
||||
0x4F, 0x38, 0xB5, 0x8C, 0xA2, 0x99, 0x42, 0xF3, 0xBD, 0x65, 0x38, 0xE2,
|
||||
0x34, 0x3F, 0x21, 0x9D, 0xF5, 0xBD, 0xB3, 0xBF, 0x73, 0x3C, 0x18, 0xDE,
|
||||
0xF6, 0xF0, 0x7F, 0xA1, 0xC2, 0x55, 0xF2, 0x38, 0xE9, 0x0E, 0x1E, 0x31,
|
||||
0xE7, 0xDB, 0x51, 0xC5, 0x71, 0x8D, 0x67, 0x71, 0x3A, 0x9F, 0x55, 0x52,
|
||||
0x60, 0xEE, 0x45, 0xF6, 0x08, 0x98, 0x81, 0xB7, 0x7B, 0x2F, 0xF2, 0x96,
|
||||
0x7D, 0x73, 0xD0, 0xA6, 0xAB, 0xAA, 0x83, 0x49, 0x41, 0x35, 0xA9, 0x90,
|
||||
0x67, 0xCE, 0xD3, 0xB9, 0x73, 0x54, 0xAA, 0x84, 0x00, 0x88, 0x88, 0x90,
|
||||
0x1D, 0x86, 0x9B, 0xE5, 0xB8, 0xCE, 0x89, 0x0A, 0x1B, 0x47, 0x62, 0x31,
|
||||
0xC2, 0x3F, 0xC3, 0x8C, 0x86, 0x09, 0x3C, 0x86
|
||||
};
|
||||
|
||||
static const br_rsa_private_key RSA = {
|
||||
2048,
|
||||
(unsigned char *)RSA_P, sizeof RSA_P,
|
||||
(unsigned char *)RSA_Q, sizeof RSA_Q,
|
||||
(unsigned char *)RSA_DP, sizeof RSA_DP,
|
||||
(unsigned char *)RSA_DQ, sizeof RSA_DQ,
|
||||
(unsigned char *)RSA_IQ, sizeof RSA_IQ
|
||||
};
|
||||
402
samples/server_basic.c
Normal file
402
samples/server_basic.c
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF 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 <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.
|
||||
*/
|
||||
|
||||
#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_INET,
|
||||
&((struct sockaddr_in *)&sa)->sin_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];
|
||||
|
||||
/*
|
||||
* 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
|
||||
br_ssl_server_init_mine2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#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
|
||||
br_ssl_server_init_minf2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#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
|
||||
br_ssl_server_init_minf2g(&sc, CHAIN, CHAIN_LEN, &SKEY);
|
||||
#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);
|
||||
}
|
||||
}
|
||||
44
src/codec/ccopy.c
Normal file
44
src/codec/ccopy.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len)
|
||||
{
|
||||
unsigned char *d;
|
||||
const unsigned char *s;
|
||||
|
||||
d = dst;
|
||||
s = src;
|
||||
while (len -- > 0) {
|
||||
uint32_t x, y;
|
||||
|
||||
x = *s ++;
|
||||
y = *d;
|
||||
*d = MUX(ctl, x, y);
|
||||
d ++;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec16be.c
Normal file
38
src/codec/dec16be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec16be(uint16_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec16be(buf);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec16le.c
Normal file
38
src/codec/dec16le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_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;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec32be.c
Normal file
38
src/codec/dec32be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_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;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec32le.c
Normal file
38
src/codec/dec32le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_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;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec64be.c
Normal file
38
src/codec/dec64be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_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;
|
||||
}
|
||||
}
|
||||
38
src/codec/dec64le.c
Normal file
38
src/codec/dec64le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_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;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc16be.c
Normal file
38
src/codec/enc16be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc16be(void *dst, const uint16_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc16be(buf, *v ++);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc16le.c
Normal file
38
src/codec/enc16le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc16le(void *dst, const uint16_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc16le(buf, *v ++);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc32be.c
Normal file
38
src/codec/enc32be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc32be(void *dst, const uint32_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc32be(buf, *v ++);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc32le.c
Normal file
38
src/codec/enc32le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc32le(void *dst, const uint32_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc32le(buf, *v ++);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc64be.c
Normal file
38
src/codec/enc64be.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc64be(void *dst, const uint64_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc64be(buf, *v ++);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
38
src/codec/enc64le.c
Normal file
38
src/codec/enc64le.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc64le(void *dst, const uint64_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc64le(buf, *v ++);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
508
src/codec/pemdec.c
Normal file
508
src/codec/pemdec.c
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
/* 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 uint8_t 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 *)((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 uint8_t 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 uint8_t 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, 0x24, 0x01, 0x00, 0x17, 0x0D, 0x06, 0x03,
|
||||
0x13, 0x04, 0x3C, 0x01, 0x7F, 0x17, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00,
|
||||
0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x22, 0x01,
|
||||
0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x17, 0x0D, 0x06, 0x09, 0x13, 0x01,
|
||||
0x00, 0x22, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x17, 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, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00,
|
||||
0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03,
|
||||
0x00, 0x25, 0x14, 0x1C, 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, 0x1B, 0x01, 0x01, 0x00, 0x25, 0x14,
|
||||
0x1C, 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, 0x1B, 0x02, 0x00, 0x01, 0x02,
|
||||
0x0F, 0x1B, 0x01, 0x01, 0x00, 0x25, 0x14, 0x1C, 0x06, 0x05, 0x13, 0x2E,
|
||||
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02,
|
||||
0x00, 0x01, 0x10, 0x0F, 0x1B, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1B, 0x02,
|
||||
0x00, 0x1B, 0x01, 0x00, 0x00, 0x00, 0x14, 0x14, 0x01, 0x80, 0x41, 0x0E,
|
||||
0x1A, 0x01, 0x80, 0x5A, 0x0B, 0x10, 0x06, 0x05, 0x01, 0x80, 0x41, 0x08,
|
||||
0x00, 0x14, 0x14, 0x01, 0x80, 0x61, 0x0E, 0x1A, 0x01, 0x80, 0x7A, 0x0B,
|
||||
0x10, 0x06, 0x05, 0x01, 0x80, 0x47, 0x08, 0x00, 0x14, 0x14, 0x01, 0x30,
|
||||
0x0E, 0x1A, 0x01, 0x39, 0x0B, 0x10, 0x06, 0x04, 0x01, 0x04, 0x07, 0x00,
|
||||
0x14, 0x01, 0x2B, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x3E, 0x00, 0x14, 0x01,
|
||||
0x2F, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x3F, 0x00, 0x01, 0x3D, 0x0C, 0x1E,
|
||||
0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x23, 0x06, 0x02, 0x04, 0x7B, 0x04,
|
||||
0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04, 0x1F, 0x01, 0x7F, 0x00,
|
||||
0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05, 0x13, 0x1F, 0x01, 0x00,
|
||||
0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00, 0x00, 0x1D, 0x04, 0x5E,
|
||||
0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x21, 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,
|
||||
0x1A, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03, 0x01, 0x20, 0x08, 0x00,
|
||||
0x01, 0x14, 0x03, 0x00, 0x1A, 0x17, 0x05, 0x05, 0x1F, 0x2E, 0x01, 0x00,
|
||||
0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06, 0x1F, 0x02, 0x00, 0x1A,
|
||||
0x08, 0x00, 0x2A, 0x17, 0x19, 0x1D, 0x1A, 0x1E, 0x1A, 0x04, 0x62, 0x00,
|
||||
0x18, 0x14, 0x1C, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00, 0x20,
|
||||
0x19, 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, 0x1E, 0x14, 0x21, 0x07, 0x16, 0x01,
|
||||
0x2D, 0x0C, 0x06, 0x08, 0x21, 0x07, 0x1D, 0x01, 0x00, 0x1A, 0x19, 0x00,
|
||||
0x04, 0x69, 0x21, 0x19, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1A, 0x01,
|
||||
0x20, 0x0B, 0x10, 0x00
|
||||
};
|
||||
|
||||
static const uint16_t t0_caddr[] = {
|
||||
0,
|
||||
5,
|
||||
10,
|
||||
15,
|
||||
19,
|
||||
24,
|
||||
29,
|
||||
67,
|
||||
149,
|
||||
384,
|
||||
464,
|
||||
476,
|
||||
511,
|
||||
530,
|
||||
540,
|
||||
559,
|
||||
594,
|
||||
605,
|
||||
610,
|
||||
620,
|
||||
645,
|
||||
672
|
||||
};
|
||||
|
||||
#define T0_INTERPRETED 28
|
||||
|
||||
#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)
|
||||
|
||||
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() break
|
||||
|
||||
dp = ((t0_context *)t0ctx)->dp;
|
||||
rp = ((t0_context *)t0ctx)->rp;
|
||||
ip = ((t0_context *)t0ctx)->ip;
|
||||
for (;;) {
|
||||
uint32_t t0x;
|
||||
|
||||
t0x = t0_parse7E_unsigned(&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) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 22: {
|
||||
/* get8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(*((unsigned char *)CTX + addr));
|
||||
|
||||
}
|
||||
break;
|
||||
case 23: {
|
||||
/* over */
|
||||
T0_PUSH(T0_PEEK(1));
|
||||
}
|
||||
break;
|
||||
case 24: {
|
||||
/* read8-native */
|
||||
|
||||
if (CTX->hlen > 0) {
|
||||
T0_PUSH(*CTX->hbuf ++);
|
||||
CTX->hlen --;
|
||||
} else {
|
||||
T0_PUSHi(-1);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 25: {
|
||||
/* set8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
unsigned x = T0_POP();
|
||||
*((unsigned char *)CTX + addr) = x;
|
||||
|
||||
}
|
||||
break;
|
||||
case 26: {
|
||||
/* swap */
|
||||
T0_SWAP();
|
||||
}
|
||||
break;
|
||||
case 27: {
|
||||
/* 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;
|
||||
}
|
||||
303
src/codec/pemdec.t0
Normal file
303
src/codec/pemdec.t0
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
\ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
\
|
||||
\ Permission is hereby granted, free of charge, to any person obtaining
|
||||
\ a copy of this software and associated documentation files (the
|
||||
\ "Software"), to deal in the Software without restriction, including
|
||||
\ without limitation the rights to use, copy, modify, merge, publish,
|
||||
\ distribute, sublicense, and/or sell copies of the Software, and to
|
||||
\ permit persons to whom the Software is furnished to do so, subject to
|
||||
\ the following conditions:
|
||||
\
|
||||
\ The above copyright notice and this permission notice shall be
|
||||
\ included in all copies or substantial portions of the Software.
|
||||
\
|
||||
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
\ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
\ ACTION 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 *)((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
|
||||
norm-upper over set8 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.
|
||||
: from-base64 ( char -- x )
|
||||
dup dup `A >= swap `Z <= and if 65 - ret then
|
||||
dup dup `a >= swap `z <= and if 71 - ret then
|
||||
dup dup `0 >= swap `9 <= and if 4 + ret then
|
||||
dup `+ = if drop 62 ret then
|
||||
dup `/ = if drop 63 ret then
|
||||
`= <> 1- ;
|
||||
|
||||
\ 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) {
|
||||
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 ;
|
||||
102
src/config.h
Normal file
102
src/config.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION 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_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_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_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
|
||||
*/
|
||||
|
||||
#endif
|
||||
791
src/ec/ec_prime_i31.c
Normal file
791
src/ec/ec_prime_i31.c
Normal file
|
|
@ -0,0 +1,791 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT 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 four 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 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 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 independant 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);
|
||||
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_mul,
|
||||
&api_muladd
|
||||
};
|
||||
46
src/ec/ec_prime_i31_secp256r1.c
Normal file
46
src/ec/ec_prime_i31_secp256r1.c
Normal file
|
|
@ -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"
|
||||
|
||||
static const uint32_t P256_P[] = {
|
||||
0x00000108,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
|
||||
0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
|
||||
0x000000FF
|
||||
};
|
||||
|
||||
static const uint32_t P256_B[] = {
|
||||
0x00000108,
|
||||
0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
|
||||
0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
|
||||
0x0000000E
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp256r1 = {
|
||||
P256_P,
|
||||
P256_B,
|
||||
0x00000001
|
||||
};
|
||||
48
src/ec/ec_prime_i31_secp384r1.c
Normal file
48
src/ec/ec_prime_i31_secp384r1.c
Normal file
|
|
@ -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"
|
||||
|
||||
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_B[] = {
|
||||
0x0000018C,
|
||||
0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
|
||||
0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
|
||||
0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
|
||||
0x000008A5
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp384r1 = {
|
||||
P384_P,
|
||||
P384_B,
|
||||
0x00000001
|
||||
};
|
||||
50
src/ec/ec_prime_i31_secp521r1.c
Normal file
50
src/ec/ec_prime_i31_secp521r1.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
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_B[] = {
|
||||
0x00000219,
|
||||
0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
|
||||
0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
|
||||
0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
|
||||
0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
|
||||
0x00654FAE
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp521r1 = {
|
||||
P521_P,
|
||||
P521_B,
|
||||
0x00000001
|
||||
};
|
||||
51
src/ec/ec_secp256r1.c
Normal file
51
src/ec/ec_secp256r1.c
Normal file
|
|
@ -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
|
||||
};
|
||||
57
src/ec/ec_secp384r1.c
Normal file
57
src/ec/ec_secp384r1.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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
|
||||
};
|
||||
64
src/ec/ec_secp521r1.c
Normal file
64
src/ec/ec_secp521r1.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#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
|
||||
};
|
||||
102
src/ec/ecdsa_atr.c
Normal file
102
src/ec/ecdsa_atr.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT 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.
|
||||
*/
|
||||
|
||||
unsigned char *buf, *r, *s;
|
||||
size_t zlen, rlen, slen, off;
|
||||
unsigned char tmp[254];
|
||||
|
||||
buf = sig;
|
||||
if (sig_len < 8) {
|
||||
return 0;
|
||||
}
|
||||
if (buf[0] != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (buf[off ++] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
rlen = buf[off ++];
|
||||
if (rlen >= 0x80) {
|
||||
return 0;
|
||||
}
|
||||
r = buf + off;
|
||||
off += rlen;
|
||||
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;
|
||||
|
||||
while (rlen > 0 && *r == 0) {
|
||||
rlen --;
|
||||
r ++;
|
||||
}
|
||||
while (slen > 0 && *s == 0) {
|
||||
slen --;
|
||||
s ++;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
47
src/ec/ecdsa_i31_bits.c
Normal file
47
src/ec/ecdsa_i31_bits.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
45
src/ec/ecdsa_i31_sign_asn1.c
Normal file
45
src/ec/ecdsa_i31_sign_asn1.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
176
src/ec/ecdsa_i31_sign_raw.c
Normal file
176
src/ec/ecdsa_i31_sign_raw.c
Normal file
|
|
@ -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"
|
||||
|
||||
#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;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, cd->generator, ulen);
|
||||
br_i31_encode(tt, nlen, k);
|
||||
if (!impl->mul(eU, ulen, tt, nlen, sk->curve)) {
|
||||
/*
|
||||
* Point multiplication may fail here only if the
|
||||
* EC implementation does not support the curve, or the
|
||||
* private key is incorrect (x is a multiple of the curve
|
||||
* order).
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
44
src/ec/ecdsa_i31_vrfy_asn1.c
Normal file
44
src/ec/ecdsa_i31_vrfy_asn1.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#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)
|
||||
{
|
||||
unsigned char rsig[(FIELD_LEN << 1) + 12];
|
||||
|
||||
if (sig_len > sizeof rsig) {
|
||||
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);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue