mirror of https://github.com/vacp2p/nim-libp2p.git
Initial commit, not ready yet.
This commit is contained in:
parent
f37c6b1fe1
commit
52f88dbd1e
|
@ -0,0 +1,754 @@
|
|||
import strutils
|
||||
import hexdump
|
||||
from os import DirSep
|
||||
|
||||
when defined(vcc):
|
||||
{.passC: "/Zi /FS".}
|
||||
|
||||
const
|
||||
bearPath = currentSourcePath.rsplit(DirSep, 1)[0] & DirSep &
|
||||
".." & DirSep & "BearSSL" & DirSep
|
||||
bearSrcPath = bearPath & "src"
|
||||
bearIncPath = bearPath & "inc"
|
||||
bearIntPath = bearSrcPath & DirSep & "int" & DirSep
|
||||
bearCodecPath = bearSrcPath & DirSep & "codec" & DirSep
|
||||
bearRandPath = bearSrcPath & DirSep & "rand" & DirSep
|
||||
bearRsaPath = bearSrcPath & DirSep & "rsa" & DirSep
|
||||
bearEcPath = bearSrcPath & DirSep & "ec" & DirSep
|
||||
bearX509Path = bearSrcPath & DirSep & "x509" & DirSep
|
||||
bearMacPath = bearSrcPath & DirSep & "mac" & DirSep
|
||||
bearHashPath = bearSrcPath & DirSep & "hash" & DirSep
|
||||
|
||||
{.passC: "-I" & bearSrcPath}
|
||||
{.passC: "-I" & bearIncPath}
|
||||
|
||||
when defined(windows):
|
||||
{.passC: "-DBR_USE_WIN32_TIME=1".}
|
||||
{.passC: "-DBR_USE_WIN32_RAND=1".}
|
||||
else:
|
||||
{.passC: "-DBR_USE_UNIX_TIME=1".}
|
||||
{.passC: "-DBR_USE_URANDOM=1".}
|
||||
|
||||
when system.cpuEndian == bigEndian:
|
||||
{.passC: "-DBR_BE_UNALIGNED=1".}
|
||||
else:
|
||||
{.passC: "-DBR_LE_UNALIGNED=1".}
|
||||
|
||||
{.pragma: bearssl_func, importc, cdecl.}
|
||||
|
||||
when sizeof(int) == 8:
|
||||
{.passC: "-DBR_64=1".}
|
||||
{.passC:" -DBR_amd64=1".}
|
||||
when defined(vcc):
|
||||
{.passC: "-DBR_UMUL128=1".}
|
||||
else:
|
||||
{.passC: "-DBR_INT128=1".}
|
||||
|
||||
## Codec sources
|
||||
{.compile: bearCodecPath & "ccopy.c".}
|
||||
{.compile: bearCodecPath & "enc64be.c".}
|
||||
{.compile: bearCodecPath & "dec64be.c".}
|
||||
{.compile: bearCodecPath & "enc32be.c".}
|
||||
{.compile: bearCodecPath & "dec32be.c".}
|
||||
{.compile: bearCodecPath & "pemenc.c".}
|
||||
{.compile: bearCodecPath & "pemdec.c".}
|
||||
|
||||
## Big integer sources
|
||||
{.compile: bearIntPath & "i31_add.c".}
|
||||
{.compile: bearIntPath & "i31_bitlen.c".}
|
||||
{.compile: bearIntPath & "i31_decmod.c".}
|
||||
{.compile: bearIntPath & "i31_decode.c".}
|
||||
{.compile: bearIntPath & "i31_decred.c".}
|
||||
{.compile: bearIntPath & "i31_encode.c".}
|
||||
{.compile: bearIntPath & "i31_fmont.c".}
|
||||
{.compile: bearIntPath & "i31_iszero.c".}
|
||||
{.compile: bearIntPath & "i31_moddiv.c".}
|
||||
{.compile: bearIntPath & "i31_modpow.c".}
|
||||
{.compile: bearIntPath & "i31_modpow2.c".}
|
||||
{.compile: bearIntPath & "i31_montmul.c".}
|
||||
{.compile: bearIntPath & "i31_mulacc.c".}
|
||||
{.compile: bearIntPath & "i31_muladd.c".}
|
||||
{.compile: bearIntPath & "i31_ninv31.c".}
|
||||
{.compile: bearIntPath & "i31_reduce.c".}
|
||||
{.compile: bearIntPath & "i31_rshift.c".}
|
||||
{.compile: bearIntPath & "i31_sub.c".}
|
||||
{.compile: bearIntPath & "i31_tmont.c".}
|
||||
|
||||
## Additional integer sources
|
||||
{.compile: bearIntPath & "i32_div32.c".}
|
||||
{.compile: bearIntPath & "i62_modpow2.c".}
|
||||
|
||||
## Random generator sources
|
||||
{.compile: bearRandPath & "sysrng.c".}
|
||||
{.compile: bearRandPath & "hmac_drbg.c".}
|
||||
{.compile: bearRandPath & "aesctr_drbg.c".}
|
||||
|
||||
## HMAC sources
|
||||
{.compile: bearMacPath & "hmac.c".}
|
||||
{.compile: bearMacPath & "hmac_ct.c".}
|
||||
|
||||
## HASH sources
|
||||
{.compile: bearHashPath & "mgf1.c".}
|
||||
{.compile: bearHashPath & "ghash_ctmul64.c".}
|
||||
{.compile: bearHashPath & "sha2small.c".} # SHA2-224/256
|
||||
{.compile: bearHashPath & "sha2big.c".} # SHA2-384/512
|
||||
|
||||
## RSA sources
|
||||
{.compile: bearRsaPath & "rsa_i31_keygen_inner.c".}
|
||||
{.compile: bearRsaPath & "rsa_i62_keygen.c".}
|
||||
{.compile: bearRsaPath & "rsa_i62_oaep_decrypt.c".}
|
||||
{.compile: bearRsaPath & "rsa_i62_oaep_encrypt.c".}
|
||||
{.compile: bearRsaPath & "rsa_i62_pkcs1_sign.c".}
|
||||
{.compile: bearRsaPath & "rsa_i62_pkcs1_vrfy.c".}
|
||||
{.compile: bearRsaPath & "rsa_i62_priv.c".}
|
||||
{.compile: bearRsaPath & "rsa_i62_pub.c".}
|
||||
{.compile: bearRsaPath & "rsa_oaep_pad.c".}
|
||||
{.compile: bearRsaPath & "rsa_oaep_unpad.c".}
|
||||
{.compile: bearRsaPath & "rsa_pkcs1_sig_pad.c".}
|
||||
{.compile: bearRsaPath & "rsa_pkcs1_sig_unpad.c".}
|
||||
{.compile: bearRsaPath & "rsa_ssl_decrypt.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_keygen.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_modulus.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_privexp.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_pubexp.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_modulus.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_privexp.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_pubexp.c".}
|
||||
|
||||
## Elliptic Curve sources
|
||||
{.compile: bearEcPath & "ec_all_m31.c".}
|
||||
{.compile: bearEcPath & "ec_default.c".}
|
||||
{.compile: bearEcPath & "ec_keygen.c".}
|
||||
{.compile: bearEcPath & "ec_c25519_m31.c".}
|
||||
{.compile: bearEcPath & "ec_c25519_m64.c".}
|
||||
{.compile: bearEcPath & "ec_p256_m31.c".}
|
||||
{.compile: bearEcPath & "ec_p256_m64.c".}
|
||||
{.compile: bearEcPath & "ec_curve25519.c".}
|
||||
{.compile: bearEcPath & "ec_prime_i31.c".}
|
||||
{.compile: bearEcPath & "ec_pubkey.c".}
|
||||
{.compile: bearEcPath & "ec_secp256r1.c".}
|
||||
{.compile: bearEcPath & "ec_secp384r1.c".}
|
||||
{.compile: bearEcPath & "ec_secp521r1.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_bits.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_sign_raw.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_sign_asn1.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_vrfy_asn1.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_vrfy_raw.c".}
|
||||
{.compile: bearEcPath & "ecdsa_rta.c".}
|
||||
{.compile: bearEcPath & "ecdsa_atr.c".}
|
||||
|
||||
elif sizeof(int) == 4:
|
||||
|
||||
## Codec sources
|
||||
{.compile: bearCodecPath & "ccopy.c".}
|
||||
{.compile: bearCodecPath & "enc64be.c".}
|
||||
{.compile: bearCodecPath & "dec64be.c".}
|
||||
{.compile: bearCodecPath & "enc32be.c".}
|
||||
{.compile: bearCodecPath & "dec32be.c".}
|
||||
{.compile: bearCodecPath & "pemenc.c".}
|
||||
{.compile: bearCodecPath & "pemdec.c".}
|
||||
|
||||
## Big integer sources
|
||||
{.compile: bearIntPath & "i31_add.c".}
|
||||
{.compile: bearIntPath & "i31_bitlen.c".}
|
||||
{.compile: bearIntPath & "i31_decmod.c".}
|
||||
{.compile: bearIntPath & "i31_decode.c".}
|
||||
{.compile: bearIntPath & "i31_decred.c".}
|
||||
{.compile: bearIntPath & "i31_encode.c".}
|
||||
{.compile: bearIntPath & "i31_fmont.c".}
|
||||
{.compile: bearIntPath & "i31_iszero.c".}
|
||||
{.compile: bearIntPath & "i31_moddiv.c".}
|
||||
{.compile: bearIntPath & "i31_modpow.c".}
|
||||
{.compile: bearIntPath & "i31_modpow2.c".}
|
||||
{.compile: bearIntPath & "i31_montmul.c".}
|
||||
{.compile: bearIntPath & "i31_mulacc.c".}
|
||||
{.compile: bearIntPath & "i31_muladd.c".}
|
||||
{.compile: bearIntPath & "i31_ninv31.c".}
|
||||
{.compile: bearIntPath & "i31_reduce.c".}
|
||||
{.compile: bearIntPath & "i31_rshift.c".}
|
||||
{.compile: bearIntPath & "i31_sub.c".}
|
||||
{.compile: bearIntPath & "i31_tmont.c".}
|
||||
|
||||
## Additional integer sources
|
||||
{.compile: bearIntPath & "i32_div32.c".}
|
||||
|
||||
## Random generator sources
|
||||
{.compile: bearRandPath & "sysrng.c".}
|
||||
{.compile: bearRandPath & "hmac_drbg.c".}
|
||||
{.compile: bearRandPath & "aesctr_drbg.c".}
|
||||
|
||||
## HMAC sources
|
||||
{.compile: bearMacPath & "hmac.c".}
|
||||
{.compile: bearMacPath & "hmac_ct.c".}
|
||||
|
||||
## HASH sources
|
||||
{.compile: bearHashPath & "mgf1.c".}
|
||||
{.compile: bearHashPath & "ghash_ctmul.c".}
|
||||
{.compile: bearHashPath & "sha2small.c".} # SHA2-224/256
|
||||
{.compile: bearHashPath & "sha2big.c".} # SHA2-384/512
|
||||
|
||||
## RSA sources
|
||||
{.compile: bearRsaPath & "rsa_i31_keygen_inner.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_keygen.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_oaep_decrypt.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_oaep_encrypt.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_pkcs1_sign.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_pkcs1_vrfy.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_priv.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_pub.c".}
|
||||
{.compile: bearRsaPath & "rsa_oaep_pad.c".}
|
||||
{.compile: bearRsaPath & "rsa_oaep_unpad.c".}
|
||||
{.compile: bearRsaPath & "rsa_pkcs1_sig_pad.c".}
|
||||
{.compile: bearRsaPath & "rsa_pkcs1_sig_unpad.c".}
|
||||
{.compile: bearRsaPath & "rsa_ssl_decrypt.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_keygen.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_modulus.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_privexp.c".}
|
||||
{.compile: bearRsaPath & "rsa_i31_pubexp.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_modulus.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_privexp.c".}
|
||||
{.compile: bearRsaPath & "rsa_default_pubexp.c".}
|
||||
|
||||
## Elliptic Curve sources
|
||||
{.compile: bearEcPath & "ec_all_m31.c".}
|
||||
{.compile: bearEcPath & "ec_default.c".}
|
||||
{.compile: bearEcPath & "ec_keygen.c".}
|
||||
{.compile: bearEcPath & "ec_p256_m31.c".}
|
||||
{.compile: bearEcPath & "ec_prime_i31.c".}
|
||||
{.compile: bearEcPath & "ec_pubkey.c".}
|
||||
{.compile: bearEcPath & "ec_secp256r1.c".}
|
||||
{.compile: bearEcPath & "ec_secp384r1.c".}
|
||||
{.compile: bearEcPath & "ec_secp521r1.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_bits.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_sign_raw.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_sign_asn1.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_vrfy_asn1.c".}
|
||||
{.compile: bearEcPath & "ecdsa_i31_vrfy_raw.c".}
|
||||
{.compile: bearEcPath & "ecdsa_rta.c".}
|
||||
{.compile: bearEcPath & "ecdsa_atr.c".}
|
||||
|
||||
else:
|
||||
error("Sorry, your target architecture is not supported!")
|
||||
|
||||
## X509 sources
|
||||
{.compile: bearX509Path & "asn1enc.c".}
|
||||
{.compile: bearX509Path & "encode_rsa_pk8der.c".}
|
||||
{.compile: bearX509Path & "encode_rsa_rawder.c".}
|
||||
{.compile: bearX509Path & "skey_decoder.c".}
|
||||
|
||||
const
|
||||
X509_BUFSIZE_KEY* = 520
|
||||
X509_BUFSIZE_SIG* = 512
|
||||
|
||||
ERR_X509_OK* = 32
|
||||
ERR_X509_INVALID_VALUE* = 33
|
||||
ERR_X509_TRUNCATED* = 34
|
||||
ERR_X509_EMPTY_CHAIN* = 35
|
||||
ERR_X509_INNER_TRUNC* = 36
|
||||
ERR_X509_BAD_TAG_CLASS* = 37
|
||||
ERR_X509_BAD_TAG_VALUE* = 38
|
||||
ERR_X509_INDEFINITE_LENGTH* = 39
|
||||
ERR_X509_EXTRA_ELEMENT* = 40
|
||||
ERR_X509_UNEXPECTED* = 41
|
||||
ERR_X509_NOT_CONSTRUCTED* = 42
|
||||
ERR_X509_NOT_PRIMITIVE* = 43
|
||||
ERR_X509_PARTIAL_BYTE* = 44
|
||||
ERR_X509_BAD_BOOLEAN* = 45
|
||||
ERR_X509_OVERFLOW* = 46
|
||||
ERR_X509_BAD_DN* = 47
|
||||
ERR_X509_BAD_TIME* = 48
|
||||
ERR_X509_UNSUPPORTED* = 49
|
||||
ERR_X509_LIMIT_EXCEEDED* = 50
|
||||
ERR_X509_WRONG_KEY_TYPE* = 51
|
||||
ERR_X509_BAD_SIGNATURE* = 52
|
||||
ERR_X509_TIME_UNKNOWN* = 53
|
||||
ERR_X509_EXPIRED* = 54
|
||||
ERR_X509_DN_MISMATCH* = 55
|
||||
ERR_X509_BAD_SERVER_NAME* = 56
|
||||
ERR_X509_CRITICAL_EXTENSION* = 57
|
||||
ERR_X509_NOT_CA* = 58
|
||||
ERR_X509_FORBIDDEN_KEY_USAGE* = 59
|
||||
ERR_X509_WEAK_PUBLIC_KEY* = 60
|
||||
ERR_X509_NOT_TRUSTED* = 62
|
||||
|
||||
BR_PEM_LINE64* = 1
|
||||
BR_PEM_CRLF* = 2
|
||||
|
||||
BR_X509_TA_CA* = 0x00000001
|
||||
BR_KEYTYPE_RSA* = 1
|
||||
BR_KEYTYPE_EC* = 2
|
||||
BR_KEYTYPE_KEYX* = 0x00000010
|
||||
BR_KEYTYPE_SIGN* = 0x00000020
|
||||
|
||||
BR_PEM_BEGIN_OBJ* = 1
|
||||
BR_PEM_END_OBJ* = 2
|
||||
BR_PEM_ERROR* = 3
|
||||
|
||||
BR_EC_SECP256R1* = 23
|
||||
BR_EC_SECP384R1* = 24
|
||||
BR_EC_SECP521R1* = 25
|
||||
|
||||
BR_EC_KBUF_PRIV_MAX_SIZE* = 72
|
||||
BR_EC_KBUF_PUB_MAX_SIZE* = 145
|
||||
|
||||
type
|
||||
MarshalKind* = enum
|
||||
RAW, PKCS8
|
||||
|
||||
X509Status* {.pure.} = enum
|
||||
OK = ERR_X509_OK,
|
||||
INVALID_VALUE = ERR_X509_INVALID_VALUE,
|
||||
TRUNCATED = ERR_X509_TRUNCATED,
|
||||
EMPTY_CHAIN = ERR_X509_EMPTY_CHAIN,
|
||||
INNER_TRUNC = ERR_X509_INNER_TRUNC,
|
||||
BAD_TAG_CLASS = ERR_X509_BAD_TAG_CLASS,
|
||||
BAD_TAG_VALUE = ERR_X509_BAD_TAG_VALUE,
|
||||
INDEFINITE_LENGTH = ERR_X509_INDEFINITE_LENGTH,
|
||||
EXTRA_ELEMENT = ERR_X509_EXTRA_ELEMENT,
|
||||
UNEXPECTED = ERR_X509_UNEXPECTED,
|
||||
NOT_CONSTRUCTED = ERR_X509_NOT_CONSTRUCTED,
|
||||
NOT_PRIMITIVE = ERR_X509_NOT_PRIMITIVE,
|
||||
PARTIAL_BYTE = ERR_X509_PARTIAL_BYTE,
|
||||
BAD_BOOLEAN = ERR_X509_BAD_BOOLEAN,
|
||||
OVERFLOW = ERR_X509_OVERFLOW,
|
||||
BAD_DN = ERR_X509_BAD_DN,
|
||||
BAD_TIME = ERR_X509_BAD_TIME,
|
||||
UNSUPPORTED = ERR_X509_UNSUPPORTED,
|
||||
LIMIT_EXCEEDED = ERR_X509_LIMIT_EXCEEDED,
|
||||
WRONG_KEY_TYPE = ERR_X509_WRONG_KEY_TYPE,
|
||||
BAD_SIGNATURE = ERR_X509_BAD_SIGNATURE,
|
||||
TIME_UNKNOWN = ERR_X509_TIME_UNKNOWN,
|
||||
EXPIRED = ERR_X509_EXPIRED,
|
||||
DN_MISMATCH = ERR_X509_DN_MISMATCH,
|
||||
BAD_SERVER_NAME = ERR_X509_BAD_SERVER_NAME,
|
||||
CRITICAL_EXTENSION = ERR_X509_CRITICAL_EXTENSION,
|
||||
NOT_CA = ERR_X509_NOT_CA,
|
||||
FORBIDDEN_KEY_USAGE = ERR_X509_FORBIDDEN_KEY_USAGE,
|
||||
WEAK_PUBLIC_KEY = ERR_X509_WEAK_PUBLIC_KEY,
|
||||
NOT_TRUSTED = ERR_X509_NOT_TRUSTED,
|
||||
INCORRECT_VALUE = 100
|
||||
MISSING_KEY = 101
|
||||
|
||||
BrHashClass* {.importc: "br_hash_class",
|
||||
header: "bearssl_hash.h", bycopy.} = object
|
||||
contextSize* {.importc: "context_size".}: int
|
||||
desc* {.importc: "desc".}: uint32
|
||||
init* {.importc: "init".}: proc (ctx: ptr ptr BrHashClass) {.cdecl.}
|
||||
update* {.importc: "update".}: proc (ctx: ptr ptr BrHashClass,
|
||||
data: pointer, len: int) {.cdecl.}
|
||||
output* {.importc: "out".}: proc (ctx: ptr ptr BrHashClass,
|
||||
dst: pointer) {.cdecl.}
|
||||
state* {.importc: "state".}: proc (ctx: ptr ptr BrHashClass,
|
||||
dst: pointer): uint64 {.cdecl.}
|
||||
setState* {.importc: "set_state".}: proc (ctx: ptr ptr BrHashClass,
|
||||
stb: pointer,
|
||||
count: uint64) {.cdecl.}
|
||||
|
||||
BrMd5Context* {.importc: "br_md5_context",
|
||||
header: "bearssl_hash.h", bycopy.} = object
|
||||
vtable* {.importc: "vtable".}: ptr BrHashClass
|
||||
buf* {.importc: "buf".}: array[64, cuchar]
|
||||
count* {.importc: "count".}: uint64
|
||||
val* {.importc: "val".}: array[4, uint32]
|
||||
|
||||
BrMd5sha1Context* {.importc: "br_md5sha1_context",
|
||||
header: "bearssl_hash.h", bycopy.} = object
|
||||
vtable* {.importc: "vtable".}: ptr BrHashClass
|
||||
buf* {.importc: "buf".}: array[64, cuchar]
|
||||
count* {.importc: "count".}: uint64
|
||||
valMd5* {.importc: "val_md5".}: array[4, uint32]
|
||||
valSha1* {.importc: "val_sha1".}: array[5, uint32]
|
||||
|
||||
Sha1Context* {.importc: "br_sha1_context",
|
||||
header: "bearssl_hash.h", bycopy.} = object
|
||||
vtable* {.importc: "vtable".}: ptr BrHashClass
|
||||
buf* {.importc: "buf".}: array[64, cuchar]
|
||||
count* {.importc: "count".}: uint64
|
||||
val* {.importc: "val".}: array[5, uint32]
|
||||
|
||||
BrSha512Context* = BrSha384Context
|
||||
BrSha384Context* {.importc: "br_sha384_context",
|
||||
header: "bearssl_hash.h", bycopy.} = object
|
||||
vtable* {.importc: "vtable".}: ptr BrHashClass
|
||||
buf* {.importc: "buf".}: array[128, cuchar]
|
||||
count* {.importc: "count".}: uint64
|
||||
val* {.importc: "val".}: array[8, uint64]
|
||||
|
||||
BrSha256Context* = BrSha224Context
|
||||
BrSha224Context* {.importc: "br_sha224_context",
|
||||
header: "bearssl_hash.h", bycopy.} = object
|
||||
vtable* {.importc: "vtable".}: ptr BrHashClass
|
||||
buf* {.importc: "buf".}: array[64, cuchar]
|
||||
count* {.importc: "count".}: uint64
|
||||
val* {.importc: "val".}: array[8, uint32]
|
||||
|
||||
BrHashCompatContext* {.importc: "br_hash_compat_context",
|
||||
header: "bearssl_hash.h", bycopy.} = object {.union.}
|
||||
vtable* {.importc: "vtable".}: ptr BrHashClass
|
||||
md5* {.importc: "md5".}: BrMd5Context
|
||||
sha1* {.importc: "sha1".}: Sha1Context
|
||||
sha224* {.importc: "sha224".}: BrSha224Context
|
||||
sha256* {.importc: "sha256".}: BrSha256Context
|
||||
sha384* {.importc: "sha384".}: BrSha384Context
|
||||
sha512* {.importc: "sha512".}: BrSha512Context
|
||||
md5sha1* {.importc: "md5sha1".}: BrMd5sha1Context
|
||||
|
||||
BrPrngClass* {.importc: "br_prng_class",
|
||||
header: "bearssl_rand.h", bycopy.} = object
|
||||
contextSize* {.importc: "context_size".}: int
|
||||
init* {.importc: "init".}: proc (ctx: ptr ptr BrPrngClass, params: pointer,
|
||||
seed: pointer, seedLen: int) {.cdecl.}
|
||||
generate* {.importc: "generate".}: proc (ctx: ptr ptr BrPrngClass,
|
||||
output: pointer,
|
||||
length: int) {.cdecl.}
|
||||
update* {.importc: "update".}: proc (ctx: ptr ptr BrPrngClass,
|
||||
seed: pointer, seedLen: int) {.cdecl.}
|
||||
|
||||
BrHmacDrbgContext* {.importc: "br_hmac_drbg_context",
|
||||
header: "bearssl_rand.h", bycopy.} = object
|
||||
vtable* {.importc: "vtable".}: ptr BrPrngClass
|
||||
k* {.importc: "K".}: array[64, cuchar]
|
||||
v* {.importc: "V".}: array[64, cuchar]
|
||||
digestClass* {.importc: "digest_class".}: ptr BrHashClass
|
||||
|
||||
BrRsaPublicKey* {.importc: "br_rsa_public_key",
|
||||
header: "bearssl_rsa.h", bycopy.} = object
|
||||
n* {.importc: "n".}: ptr cuchar
|
||||
nlen* {.importc: "nlen".}: int
|
||||
e* {.importc: "e".}: ptr cuchar
|
||||
elen* {.importc: "elen".}: int
|
||||
|
||||
BrRsaPrivateKey* {.importc: "br_rsa_private_key",
|
||||
header: "bearssl_rsa.h", bycopy.} = object
|
||||
nBitlen* {.importc: "n_bitlen".}: uint32
|
||||
p* {.importc: "p".}: ptr cuchar
|
||||
plen* {.importc: "plen".}: int
|
||||
q* {.importc: "q".}: ptr cuchar
|
||||
qlen* {.importc: "qlen".}: int
|
||||
dp* {.importc: "dp".}: ptr cuchar
|
||||
dplen* {.importc: "dplen".}: int
|
||||
dq* {.importc: "dq".}: ptr cuchar
|
||||
dqlen* {.importc: "dqlen".}: int
|
||||
iq* {.importc: "iq".}: ptr cuchar
|
||||
iqlen* {.importc: "iqlen".}: int
|
||||
|
||||
BrEcPublicKey* {.importc: "br_ec_public_key", header: "bearssl_ec.h",
|
||||
bycopy.} = object
|
||||
curve* {.importc: "curve".}: cint
|
||||
q* {.importc: "q".}: ptr cuchar
|
||||
qlen* {.importc: "qlen".}: int
|
||||
|
||||
BrEcPrivateKey* {.importc: "br_ec_private_key", header: "bearssl_ec.h",
|
||||
bycopy.} = object
|
||||
curve* {.importc: "curve".}: cint
|
||||
x* {.importc: "x".}: ptr cuchar
|
||||
xlen* {.importc: "xlen".}: int
|
||||
|
||||
BrPublicKeyUnion* {.importc: "no_name", header: "bearssl_x509.h",
|
||||
bycopy.} = object {.union.}
|
||||
rsa* {.importc: "rsa".}: BrRsaPublicKey
|
||||
ec* {.importc: "ec".}: BrEcPublicKey
|
||||
|
||||
BrPrivateKeyUnion* {.importc: "no_name", header: "bearssl_x509.h",
|
||||
bycopy.} = object {.union.}
|
||||
rsa* {.importc: "rsa".}: BrRsaPrivateKey
|
||||
ec* {.importc: "ec".}: BrEcPrivateKey
|
||||
|
||||
X509Pkey* {.importc: "br_x509_pkey", header: "bearssl_x509.h",
|
||||
bycopy.} = object
|
||||
keyType* {.importc: "key_type".}: cuchar
|
||||
key* {.importc: "key".}: BrPublicKeyUnion
|
||||
|
||||
BrX509CpuStruct* {.importc: "no_name", header: "bearssl_x509.h",
|
||||
bycopy.} = object
|
||||
dp* {.importc: "dp".}: ptr uint32
|
||||
rp* {.importc: "rp".}: ptr uint32
|
||||
ip* {.importc: "ip".}: ptr cuchar
|
||||
|
||||
BrX509DecoderContext* {.importc: "br_x509_decoder_context",
|
||||
header: "bearssl_x509.h", bycopy.} = object
|
||||
pkey* {.importc: "pkey".}: X509Pkey
|
||||
cpu* {.importc: "cpu".}: BrX509CpuStruct
|
||||
dpStack* {.importc: "dp_stack".}: array[32, uint32]
|
||||
rpStack* {.importc: "rp_stack".}: array[32, uint32]
|
||||
err* {.importc: "err".}: cint
|
||||
pad* {.importc: "pad".}: array[256, cuchar]
|
||||
decoded* {.importc: "decoded".}: bool
|
||||
notbeforeDays* {.importc: "notbefore_days".}: uint32
|
||||
notbeforeSeconds* {.importc: "notbefore_seconds".}: uint32
|
||||
notafterDays* {.importc: "notafter_days".}: uint32
|
||||
notafterSeconds* {.importc: "notafter_seconds".}: uint32
|
||||
isCA* {.importc: "isCA".}: bool
|
||||
copyDn* {.importc: "copy_dn".}: cuchar
|
||||
appendDnCtx* {.importc: "append_dn_ctx".}: pointer
|
||||
appendDn* {.importc: "append_dn".}: proc (ctx: pointer, buf: pointer,
|
||||
length: int) {.cdecl.}
|
||||
hbuf* {.importc: "hbuf".}: ptr cuchar
|
||||
hlen* {.importc: "hlen".}: int
|
||||
pkeyData* {.importc: "pkey_data".}: array[X509_BUFSIZE_KEY, cuchar]
|
||||
signerKeyType* {.importc: "signer_key_type".}: cuchar
|
||||
signerHashId* {.importc: "signer_hash_id".}: cuchar
|
||||
|
||||
BrSkeyDecoderContext* {.importc: "br_skey_decoder_context",
|
||||
header: "bearssl_x509.h", bycopy.} = object
|
||||
pkey* {.importc: "key".}: BrPrivateKeyUnion
|
||||
cpu* {.importc: "cpu".}: BrX509CpuStruct
|
||||
dpStack* {.importc: "dp_stack".}: array[32, uint32]
|
||||
rpStack* {.importc: "rp_stack".}: array[32, uint32]
|
||||
err* {.importc: "err".}: cint
|
||||
hbuf* {.importc: "hbuf".}: ptr cuchar
|
||||
hlen* {.importc: "hlen".}: int
|
||||
pad* {.importc: "pad".}: array[256, cuchar]
|
||||
keyType* {.importc: "key_type".}: cuchar
|
||||
keyData* {.importc: "key_data".}: array[3 * X509_BUFSIZE_SIG, cuchar]
|
||||
|
||||
BrPemCpuStruct* {.importc: "no_name", header: "bearssl_pem.h",
|
||||
bycopy.} = object
|
||||
dp* {.importc: "dp".}: ptr uint32
|
||||
rp* {.importc: "rp".}: ptr uint32
|
||||
ip* {.importc: "ip".}: ptr cuchar
|
||||
|
||||
BrPemDecoderContext* {.importc: "br_pem_decoder_context",
|
||||
header: "bearssl_pem.h", bycopy.} = object
|
||||
cpu* {.importc: "cpu".}: BrPemCpuStruct
|
||||
dpStack* {.importc: "dp_stack".}: array[32, uint32]
|
||||
rpStack* {.importc: "rp_stack".}: array[32, uint32]
|
||||
err* {.importc: "err".}: cint
|
||||
hbuf* {.importc: "hbuf".}: ptr cuchar
|
||||
hlen* {.importc: "hlen".}: int
|
||||
dest* {.importc: "dest".}: proc (destCtx: pointer; src: pointer,
|
||||
length: int) {.cdecl.}
|
||||
destCtx* {.importc: "dest_ctx".}: pointer
|
||||
event* {.importc: "event".}: cuchar
|
||||
name* {.importc: "name".}: array[128, char]
|
||||
buf* {.importc: "buf".}: array[255, cuchar]
|
||||
pptr* {.importc: "ptr".}: int
|
||||
|
||||
BrAsn1Uint* {.importc: "br_asn1_uint", header: "inner.h", bycopy.} = object
|
||||
data* {.importc: "data".}: ptr cuchar
|
||||
length* {.importc: "len".}: int
|
||||
asn1len* {.importc: "asn1len".}: int
|
||||
|
||||
BrEcImplementation* {.importc: "br_ec_impl", header: "bearssl_ec.h",
|
||||
bycopy.} = object
|
||||
supportedCurves* {.importc: "supported_curves".}: uint32
|
||||
generator* {.importc: "generator".}: proc (curve: cint,
|
||||
length: ptr int): ptr cuchar {.cdecl.}
|
||||
order* {.importc: "order".}: proc (curve: cint,
|
||||
length: ptr int): ptr cuchar {.cdecl.}
|
||||
xoff* {.importc: "xoff".}: proc (curve: cint,
|
||||
length: ptr int): int {.cdecl.}
|
||||
mul* {.importc: "mul".}: proc (g: ptr cuchar, glen: int,
|
||||
x: ptr cuchar, xlen: int,
|
||||
curve: cint): uint32 {.cdecl.}
|
||||
mulgen* {.importc: "mulgen".}: proc (r: ptr cuchar,
|
||||
x: ptr cuchar, xlen: int,
|
||||
curve: cint): int {.cdecl.}
|
||||
muladd* {.importc: "muladd".}: proc (a: ptr cuchar, b: ptr cuchar,
|
||||
length: int, x: ptr cuchar, xlen: int,
|
||||
y: ptr cuchar, ylen: int,
|
||||
curve: cint): uint32 {.cdecl.}
|
||||
|
||||
BrPrngSeeder* = proc (ctx: ptr ptr BrPrngClass): cint {.cdecl.}
|
||||
BrRsaKeygen* = proc (ctx: ptr ptr BrPrngClass,
|
||||
sk: ptr BrRsaPrivateKey, bufsec: ptr byte,
|
||||
pk: ptr BrRsaPublicKey, bufpub: ptr byte,
|
||||
size: cuint, pubexp: uint32): uint32 {.cdecl.}
|
||||
BrRsaComputeModulus* = proc (n: pointer,
|
||||
sk: ptr BrRsaPrivateKey): int {.cdecl.}
|
||||
BrRsaComputePubexp* = proc (sk: ptr BrRsaPrivateKey): uint32 {.cdecl.}
|
||||
BrRsaComputePrivexp* = proc (d: pointer,
|
||||
sk: ptr BrRsaPrivateKey,
|
||||
pubexp: uint32): int {.cdecl.}
|
||||
BrRsaPkcs1Verify* = proc (x: ptr cuchar, xlen: int,
|
||||
hash_oid: ptr cuchar, hash_len: int,
|
||||
pk: ptr BrRsaPublicKey,
|
||||
hash_out: ptr cuchar): uint32 {.cdecl.}
|
||||
BrPemDecoderProc* = proc (destctx: pointer, src: pointer,
|
||||
length: int) {.cdecl.}
|
||||
|
||||
type
|
||||
PemObject* = object
|
||||
name*: string
|
||||
data*: seq[byte]
|
||||
|
||||
PemList* = seq[PemObject]
|
||||
|
||||
proc brRsaPkcs1SigPad*(hashoid: ptr cuchar, hash: ptr cuchar, hashlen: int,
|
||||
nbitlen: uint32, x: ptr cchar): uint32 {.cdecl,
|
||||
importc: "br_rsa_pkcs1_sig_pad", header: "inner.h".}
|
||||
|
||||
proc brRsaPkcs1SigUnpad*(sig: ptr cuchar, siglen: int, hashoid: ptr cuchar,
|
||||
hashlen: int, hashout: ptr cuchar): uint32 {.cdecl,
|
||||
importc: "br_rsa_pkcs1_sig_unpad", header: "inner.h".}
|
||||
|
||||
proc brPrngSeederSystem*(name: cstringArray): BrPrngSeeder {.cdecl,
|
||||
importc: "br_prng_seeder_system", header: "bearssl_rand.h".}
|
||||
|
||||
proc brHmacDrbgInit*(ctx: ptr BrHmacDrbgContext, digestClass: ptr BrHashClass,
|
||||
seed: pointer, seedLen: int) {.
|
||||
cdecl, importc: "br_hmac_drbg_init", header: "bearssl_rand.h".}
|
||||
|
||||
proc brRsaKeygenGetDefault*(): BrRsaKeygen {.
|
||||
cdecl, importc: "br_rsa_keygen_get_default", header: "bearssl_rsa.h".}
|
||||
|
||||
proc brRsaComputeModulusGetDefault*(): BrRsaComputeModulus {.
|
||||
cdecl, importc: "br_rsa_compute_modulus_get_default",
|
||||
header: "bearssl_rsa.h".}
|
||||
|
||||
proc brRsaComputePubexpGetDefault*(): BrRsaComputePubexp {.
|
||||
cdecl, importc: "br_rsa_compute_pubexp_get_default",
|
||||
header: "bearssl_rsa.h".}
|
||||
|
||||
proc brRsaComputePrivexpGetDefault*(): BrRsaComputePrivexp {.
|
||||
cdecl, importc: "br_rsa_compute_privexp_get_default",
|
||||
header: "bearssl_rsa.h".}
|
||||
|
||||
proc brEcGetDefault*(): ptr BrEcImplementation {.
|
||||
cdecl, importc: "br_ec_get_default", header: "bearssl_ec.h".}
|
||||
|
||||
proc brEcKeygen*(ctx: ptr ptr BrPrngClass, impl: ptr BrEcImplementation,
|
||||
sk: ptr BrEcPrivateKey, keybuf: ptr byte,
|
||||
curve: cint): int {.cdecl,
|
||||
importc: "br_ec_keygen", header: "bearssl_ec.h".}
|
||||
|
||||
proc brEcComputePublicKey*(impl: ptr BrEcImplementation, pk: ptr BrEcPublicKey,
|
||||
kbuf: ptr byte, sk: ptr BrEcPrivateKey): int {.
|
||||
cdecl, importc: "br_ec_compute_pub", header: "bearssl_ec.h".}
|
||||
|
||||
proc brEcdsaSignRaw*(impl: ptr BrEcImplementation, hf: ptr BrHashClass,
|
||||
value: pointer, sk: ptr BrEcPrivateKey,
|
||||
sig: pointer): int {.
|
||||
cdecl, importc: "br_ecdsa_i31_sign_raw", header: "bearssl_ec.h".}
|
||||
|
||||
proc brEcdsaVerifyRaw*(impl: ptr BrEcImplementation, hash: pointer,
|
||||
hashlen: int, pk: ptr BrEcPublicKey, sig: pointer,
|
||||
siglen: int): uint32 {.
|
||||
cdecl, importc: "br_ecdsa_i31_vrfy_raw", header: "bearssl_ec.h".}
|
||||
|
||||
proc brAsn1UintPrepare*(xdata: pointer, xlen: int): BrAsn1Uint {.
|
||||
cdecl, importc: "br_asn1_uint_prepare", header: "inner.h".}
|
||||
|
||||
proc brAsn1EncodeLength*(dest: pointer, length: int): int {.
|
||||
cdecl, importc: "br_asn1_encode_length", header: "inner.h".}
|
||||
|
||||
proc brAsn1EncodeUint*(dest: pointer, pp: BrAsn1Uint): int {.
|
||||
cdecl, importc: "br_asn1_encode_uint", header: "inner.h".}
|
||||
|
||||
proc brEncodeRsaRawDer*(dest: ptr byte, sk: ptr BrRsaPrivateKey,
|
||||
pk: ptr BrRsaPublicKey, d: ptr byte,
|
||||
dlength: int): int {.
|
||||
cdecl, importc: "br_encode_rsa_raw_der", header: "bearssl_x509.h".}
|
||||
|
||||
proc brEncodeRsaPkcs8Der*(dest: ptr byte, sk: ptr BrRsaPrivateKey,
|
||||
pk: ptr BrRsaPublicKey, d: ptr byte,
|
||||
dlength: int): int {.
|
||||
cdecl, importc: "br_encode_rsa_pkcs8_der", header: "bearssl_x509.h".}
|
||||
|
||||
proc brPemEncode*(dest: ptr byte, data: ptr byte, length: int, banner: cstring,
|
||||
flags: cuint): int {.
|
||||
cdecl, importc: "br_pem_encode", header: "bearssl_pem.h".}
|
||||
|
||||
proc brPemDecoderInit*(ctx: ptr BrPemDecoderContext) {.
|
||||
cdecl, importc: "br_pem_decoder_init", header: "bearssl_pem.h".}
|
||||
|
||||
proc brPemDecoderPush*(ctx: ptr BrPemDecoderContext,
|
||||
data: pointer, length: int): int {.
|
||||
cdecl, importc: "br_pem_decoder_push", header: "bearssl_pem.h".}
|
||||
|
||||
proc brPemDecoderSetdest*(ctx: ptr BrPemDecoderContext, dest: BrPemDecoderProc,
|
||||
destctx: pointer) {.inline.} =
|
||||
ctx.dest = dest
|
||||
ctx.destCtx = destctx
|
||||
|
||||
proc brPemDecoderEvent*(ctx: ptr BrPemDecoderContext): cint {.
|
||||
cdecl, importc: "br_pem_decoder_event", header: "bearssl_pem.h".}
|
||||
|
||||
proc brPemDecoderName*(ctx: ptr BrPemDecoderContext): cstring =
|
||||
result = addr ctx.name[0]
|
||||
|
||||
proc brSkeyDecoderInit*(ctx: ptr BrSkeyDecoderContext) {.cdecl,
|
||||
importc: "br_skey_decoder_init", header: "bearssl_x509.h".}
|
||||
|
||||
proc brSkeyDecoderPush*(ctx: ptr BrSkeyDecoderContext,
|
||||
data: pointer, length: int) {.cdecl,
|
||||
importc: "br_skey_decoder_push", header: "bearssl_x509.h".}
|
||||
|
||||
proc brSkeyDecoderLastError*(ctx: ptr BrSkeyDecoderContext): int {.inline.} =
|
||||
if ctx.err != 0:
|
||||
result = ctx.err
|
||||
else:
|
||||
if ctx.keyType == '\0':
|
||||
result = ERR_X509_TRUNCATED
|
||||
|
||||
proc brSkeyDecoderKeyType*(ctx: ptr BrSkeyDecoderContext): int {.inline.} =
|
||||
if ctx.err == 0:
|
||||
result = cast[int](ctx.keyType)
|
||||
|
||||
var sha256Vtable* {.importc: "br_sha256_vtable",
|
||||
header: "bearssl_hash.h".}: BrHashClass
|
||||
var sha384Vtable* {.importc: "br_sha384_vtable",
|
||||
header: "bearssl_hash.h".}: BrHashClass
|
||||
var sha512Vtable* {.importc: "br_sha512_vtable",
|
||||
header: "bearssl_hash.h".}: BrHashClass
|
||||
|
||||
template brRsaPrivateKeyBufferSize*(size: int): int =
|
||||
# BR_RSA_KBUF_PRIV_SIZE(size)
|
||||
(5 * ((size + 15) shr 4))
|
||||
|
||||
template brRsaPublicKeyBufferSize*(size: int): int =
|
||||
# BR_RSA_KBUF_PUB_SIZE(size)
|
||||
(4 + ((size + 7) shr 3))
|
||||
|
||||
proc blobAppend(pseq: pointer, data: pointer, length: int) {.cdecl.} =
|
||||
var cseq = cast[ptr seq[byte]](pseq)
|
||||
let offset = len(cseq[])
|
||||
cseq[].setLen(offset + length)
|
||||
copyMem(addr cseq[][offset], data, length)
|
||||
|
||||
proc unmarshalPem*(data: string): PemList =
|
||||
## Decode PEM encoded string.
|
||||
var ctx: BrPemDecoderContext
|
||||
result = newSeq[PemObject]()
|
||||
if len(data) > 0:
|
||||
var nlstring = "\n"
|
||||
var extranl = true
|
||||
|
||||
brPemDecoderInit(addr ctx)
|
||||
var pbuf = cast[pointer](unsafeAddr data[0])
|
||||
var plen = len(data)
|
||||
var item = newSeq[byte]()
|
||||
|
||||
GC_ref(item)
|
||||
var inobj: bool
|
||||
while plen > 0:
|
||||
var tlen = brPemDecoderPush(addr ctx, pbuf, plen)
|
||||
pbuf = cast[pointer](cast[uint](pbuf) + cast[uint](tlen))
|
||||
plen = plen - tlen
|
||||
let event = brPemDecoderEvent(addr ctx)
|
||||
if event == BR_PEM_BEGIN_OBJ:
|
||||
item.setLen(0)
|
||||
brPemDecoderSetdest(addr ctx, blobAppend, cast[pointer](addr item))
|
||||
inobj = true
|
||||
elif event == BR_PEM_END_OBJ:
|
||||
if inobj:
|
||||
result.add(PemObject(name: $brPemDecoderName(addr ctx), data: item))
|
||||
inobj = false
|
||||
else:
|
||||
break
|
||||
elif event == BR_PEM_ERROR:
|
||||
result.setLen(0)
|
||||
break
|
||||
if plen == 0 and extranl:
|
||||
# We add an extra newline at the end, in order to
|
||||
# support PEM files that lack the newline on their last
|
||||
# line (this is somwehat invalid, but PEM format is not
|
||||
# standardised and such files do exist in the wild, so
|
||||
# we'd better accept them).
|
||||
extranl = false
|
||||
pbuf = cast[pointer](addr nlstring[0])
|
||||
plen = 1
|
||||
if inobj:
|
||||
# PEM object was not properly finished
|
||||
result.setLen(0)
|
||||
GC_unref(item)
|
|
@ -0,0 +1,587 @@
|
|||
## Nim-Libp2p
|
||||
## Copyright (c) 2018 Status Research & Development GmbH
|
||||
## Licensed under either of
|
||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
## at your option.
|
||||
## This file may not be copied, modified, or distributed except according to
|
||||
## those terms.
|
||||
import common
|
||||
import nimcrypto/utils
|
||||
|
||||
const
|
||||
PubKey256Length* = 65
|
||||
PubKey384Length* = 97
|
||||
PubKey521Length* = 133
|
||||
SecKey256Length* = 32
|
||||
SecKey384Length* = 48
|
||||
SecKey521Length* = 66
|
||||
Sig256Length* = 64
|
||||
Sig384Length* = 96
|
||||
Sig521Length* = 132
|
||||
|
||||
type
|
||||
EcPrivateKey* = ref object
|
||||
buffer*: seq[byte]
|
||||
key*: BrEcPrivateKey
|
||||
|
||||
EcPublicKey* = ref object
|
||||
buffer*: seq[byte]
|
||||
key*: BrEcPublicKey
|
||||
|
||||
EcKeyPair* = object
|
||||
seckey*: EcPrivateKey
|
||||
pubkey*: EcPublicKey
|
||||
|
||||
EcSignature* = ref object
|
||||
buffer*: seq[byte]
|
||||
curve*: cint
|
||||
|
||||
EcCurveKind* = enum
|
||||
Secp256r1 = BR_EC_SECP256R1,
|
||||
Secp384r1 = BR_EC_SECP384R1,
|
||||
Secp521r1 = BR_EC_SECP521R1
|
||||
|
||||
EcPKI* = EcPrivateKey | EcPublicKey | EcSignature
|
||||
|
||||
EcError* = object of Exception
|
||||
EcKeyIncorrectError* = object of EcError
|
||||
EcRngError* = object of EcError
|
||||
EcPublicKeyError* = object of EcError
|
||||
EcSignatureError = object of EcError
|
||||
|
||||
const
|
||||
EcSupportedCurvesCint* = {cint(Secp256r1), cint(Secp384r1), cint(Secp521r1)}
|
||||
|
||||
proc `-`(x: uint32): uint32 {.inline.} =
|
||||
result = (0xFFFF_FFFF'u32 - x) + 1'u32
|
||||
|
||||
proc GT(x, y: uint32): uint32 {.inline.} =
|
||||
var z = cast[uint32](y - x)
|
||||
result = (z xor ((x xor y) and (x xor z))) shr 31
|
||||
|
||||
proc CMP(x, y: uint32): int32 {.inline.} =
|
||||
cast[int32](GT(x, y)) or -(cast[int32](GT(y, x)))
|
||||
|
||||
proc EQ0(x: int32): uint32 {.inline.} =
|
||||
var q = cast[uint32](x)
|
||||
result = not(q or -q) shr 31
|
||||
|
||||
proc NEQ(x, y: uint32): uint32 {.inline.} =
|
||||
var q = cast[uint32](x xor y)
|
||||
result = ((q or -q) shr 31)
|
||||
|
||||
proc LT0(x: int32): uint32 {.inline.} =
|
||||
result = cast[uint32](x) shr 31
|
||||
|
||||
proc checkScalar(scalar: openarray[byte], curve: cint): uint32 =
|
||||
## Return ``1`` if all of the following hold:
|
||||
## - len(``scalar``) <= ``orderlen``
|
||||
## - ``scalar`` != 0
|
||||
## - ``scalar`` is lower than the curve ``order``.
|
||||
##
|
||||
## Otherwise, return ``0``.
|
||||
var impl = brEcGetDefault()
|
||||
var orderlen = 0
|
||||
var order = cast[ptr UncheckedArray[byte]](impl.order(curve, addr orderlen))
|
||||
|
||||
var z = 0'u32
|
||||
var c = 0'i32
|
||||
for u in scalar:
|
||||
z = z or u
|
||||
if len(scalar) == orderlen:
|
||||
for i in 0..<len(scalar):
|
||||
c = c or -(cast[int32](EQ0(c)) and CMP(scalar[i], order[i]))
|
||||
else:
|
||||
c = -1
|
||||
result = NEQ(z, 0'u32) and LT0(c)
|
||||
|
||||
proc checkPublic(key: openarray[byte], curve: cint): uint32 =
|
||||
## Return ``1`` if public key ``key`` is on curve.
|
||||
var ckey = @key
|
||||
var x = [0x00'u8, 0x01'u8]
|
||||
var impl = brEcGetDefault()
|
||||
var orderlen = 0
|
||||
var order = impl.order(curve, addr orderlen)
|
||||
result = impl.mul(cast[ptr cuchar](unsafeAddr ckey[0]), len(ckey),
|
||||
cast[ptr cuchar](addr x[0]), len(x), curve)
|
||||
|
||||
proc getOffset(pubkey: EcPublicKey): int {.inline.} =
|
||||
let o = cast[uint](pubkey.key.q) - cast[uint](unsafeAddr pubkey.buffer[0])
|
||||
if o + cast[uint](pubkey.key.qlen) > uint(len(pubkey.buffer)):
|
||||
result = -1
|
||||
else:
|
||||
result = cast[int](o)
|
||||
|
||||
proc getOffset(seckey: EcPrivateKey): int {.inline.} =
|
||||
let o = cast[uint](seckey.key.x) - cast[uint](unsafeAddr seckey.buffer[0])
|
||||
if o + cast[uint](seckey.key.xlen) > uint(len(seckey.buffer)):
|
||||
result = -1
|
||||
else:
|
||||
result = cast[int](o)
|
||||
|
||||
proc copyKey(dest: var openarray[byte], seckey: EcPrivateKey): bool {.inline.} =
|
||||
let length = seckey.key.xlen
|
||||
if length > 0:
|
||||
if len(dest) >= length:
|
||||
let offset = getOffset(seckey)
|
||||
if offset >= 0:
|
||||
copyMem(addr dest[0], unsafeAddr seckey.buffer[offset], length - offset)
|
||||
result = true
|
||||
|
||||
proc copyKey(dest: var openarray[byte], pubkey: EcPublicKey): bool {.inline.} =
|
||||
let length = pubkey.key.qlen
|
||||
if length > 0:
|
||||
if len(dest) >= length:
|
||||
let offset = getOffset(pubkey)
|
||||
if offset >= 0:
|
||||
copyMem(addr dest[0], unsafeAddr pubkey.buffer[offset], length - offset)
|
||||
result = true
|
||||
|
||||
template getSignatureLength*(curve: EcCurveKind): int =
|
||||
case curve
|
||||
of Secp256r1:
|
||||
Sig256Length
|
||||
of Secp384r1:
|
||||
Sig384Length
|
||||
of Secp521r1:
|
||||
Sig521Length
|
||||
|
||||
template getPublicKeyLength*(curve: EcCurveKind): int =
|
||||
case curve
|
||||
of Secp256r1:
|
||||
PubKey256Length
|
||||
of Secp384r1:
|
||||
PubKey384Length
|
||||
of Secp521r1:
|
||||
PubKey521Length
|
||||
|
||||
template getPrivateKeyLength*(curve: EcCurveKind): int =
|
||||
case curve
|
||||
of Secp256r1:
|
||||
SecKey256Length
|
||||
of Secp384r1:
|
||||
SecKey384Length
|
||||
of Secp521r1:
|
||||
SecKey521Length
|
||||
|
||||
proc copy*[T: EcPKI](dst: var T, src: T): bool =
|
||||
## Copy EC private key, public key or scalar ``src`` to ``dst``.
|
||||
##
|
||||
## Returns ``true`` on success, ``false`` otherwise.
|
||||
dst = new T
|
||||
when T is EcPrivateKey:
|
||||
let length = src.key.xlen
|
||||
if length > 0 and len(src.buffer) > 0:
|
||||
let offset = getOffset(src)
|
||||
if offset >= 0:
|
||||
dst.buffer = src.buffer
|
||||
dst.key.curve = src.key.curve
|
||||
dst.key.xlen = length
|
||||
dst.key.x = cast[ptr cuchar](addr dst.buffer[offset])
|
||||
result = true
|
||||
elif T is EcPublicKey:
|
||||
let length = src.key.qlen
|
||||
if length > 0 and len(src.buffer) > 0:
|
||||
let offset = getOffset(src)
|
||||
if offset >= 0:
|
||||
dst.buffer = src.buffer
|
||||
dst.key.curve = src.key.curve
|
||||
dst.key.qlen = length
|
||||
dst.key.q = cast[ptr cuchar](addr dst.buffer[offset])
|
||||
result = true
|
||||
else:
|
||||
let length = len(src.buffer)
|
||||
if length > 0:
|
||||
dst.buffer = src.buffer
|
||||
dst.curve = src.curve
|
||||
result = true
|
||||
|
||||
proc copy*[T: EcPKI](src: T): T {.inline.} =
|
||||
## Returns copy of EC private key, public key or scalar ``src``.
|
||||
if not copy(result, src):
|
||||
raise newException(EcKeyIncorrectError, "Incorrect key or signature")
|
||||
|
||||
proc clear*[T: EcPKI|EcKeyPair](pki: var T) =
|
||||
## Wipe and clear EC private key, public key or scalar object.
|
||||
when T is EcPrivateKey:
|
||||
burnMem(pki.buffer)
|
||||
pki.buffer.setLen(0)
|
||||
pki.key.x = nil
|
||||
pki.key.xlen = 0
|
||||
pki.key.curve = 0
|
||||
elif T is EcPublicKey:
|
||||
burnMem(pki.buffer)
|
||||
pki.buffer.setLen(0)
|
||||
pki.key.q = nil
|
||||
pki.key.qlen = 0
|
||||
pki.key.curve = 0
|
||||
elif T is EcSignature:
|
||||
burnMem(pki.buffer)
|
||||
pki.buffer.setLen(0)
|
||||
pki.curve = 0
|
||||
else:
|
||||
burnMem(pki.seckey.buffer)
|
||||
burnMem(pki.pubkey.buffer)
|
||||
pki.seckey.buffer.setLen(0)
|
||||
pki.pubkey.buffer.setLen(0)
|
||||
pki.seckey.key.x = nil
|
||||
pki.seckey.key.xlen = 0
|
||||
pki.seckey.key.curve = 0
|
||||
pki.pubkey.key.q = nil
|
||||
pki.pubkey.key.qlen = 0
|
||||
pki.pubkey.key.curve = 0
|
||||
|
||||
proc random*(t: typedesc[EcPrivateKey], kind: EcCurveKind): EcPrivateKey =
|
||||
## Generate new random EC private key using BearSSL's HMAC-SHA256-DRBG
|
||||
## algorithm.
|
||||
##
|
||||
## ``kind`` elliptic curve kind of your choice (secp256r1, secp384r1 or
|
||||
## secp521r1).
|
||||
var rng: BrHmacDrbgContext
|
||||
var seeder = brPrngSeederSystem(nil)
|
||||
brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0)
|
||||
if seeder(addr rng.vtable) == 0:
|
||||
raise newException(ValueError, "Could not seed RNG")
|
||||
var ecimp = brEcGetDefault()
|
||||
result = new EcPrivateKey
|
||||
result.buffer = newSeq[byte](BR_EC_KBUF_PRIV_MAX_SIZE)
|
||||
if brEcKeygen(addr rng.vtable, ecimp,
|
||||
addr result.key, addr result.buffer[0],
|
||||
cast[cint](kind)) == 0:
|
||||
raise newException(ValueError, "Could not generate private key")
|
||||
|
||||
proc getKey*(seckey: EcPrivateKey): EcPublicKey =
|
||||
## Calculate and return EC public key from private key ``seckey``.
|
||||
var ecimp = brEcGetDefault()
|
||||
if seckey.key.curve in EcSupportedCurvesCint:
|
||||
var length = getPublicKeyLength(cast[EcCurveKind](seckey.key.curve))
|
||||
result = new EcPublicKey
|
||||
result.buffer = newSeq[byte](length)
|
||||
if brEcComputePublicKey(ecimp, addr result.key,
|
||||
addr result.buffer[0], unsafeAddr seckey.key) == 0:
|
||||
raise newException(EcKeyIncorrectError, "Could not calculate public key")
|
||||
else:
|
||||
raise newException(EcKeyIncorrectError, "Incorrect private key")
|
||||
|
||||
proc random*(t: typedesc[EcKeyPair], kind: EcCurveKind): EcKeyPair {.inline.} =
|
||||
## Generate new random EC private and public keypair using BearSSL's
|
||||
## HMAC-SHA256-DRBG algorithm.
|
||||
##
|
||||
## ``kind`` elliptic curve kind of your choice (secp256r1, secp384r1 or
|
||||
## secp521r1).
|
||||
result.seckey = EcPrivateKey.random(kind)
|
||||
result.pubkey = result.seckey.getKey()
|
||||
|
||||
proc `$`*(seckey: EcPrivateKey): string =
|
||||
## Return string representation of EC private key.
|
||||
if seckey.key.curve == 0 or seckey.key.xlen == 0 or len(seckey.buffer) == 0:
|
||||
result = "Empty key"
|
||||
else:
|
||||
if seckey.key.curve notin EcSupportedCurvesCint:
|
||||
result = "Unknown key"
|
||||
else:
|
||||
let offset = seckey.getOffset()
|
||||
if offset < 0:
|
||||
result = "Corrupted key"
|
||||
else:
|
||||
let e = offset + cast[int](seckey.key.xlen) - 1
|
||||
result = toHex(seckey.buffer.toOpenArray(offset, e))
|
||||
|
||||
proc `$`*(pubkey: EcPublicKey): string =
|
||||
## Return string representation of EC public key.
|
||||
if pubkey.key.curve == 0 or pubkey.key.qlen == 0 or len(pubkey.buffer) == 0:
|
||||
result = "Empty key"
|
||||
else:
|
||||
if pubkey.key.curve notin EcSupportedCurvesCint:
|
||||
result = "Unknown key"
|
||||
else:
|
||||
let offset = pubkey.getOffset()
|
||||
if offset < 0:
|
||||
result = "Corrupted key"
|
||||
else:
|
||||
let e = offset + cast[int](pubkey.key.qlen) - 1
|
||||
result = toHex(pubkey.buffer.toOpenArray(offset, e))
|
||||
|
||||
proc `$`*(sig: EcSignature): string =
|
||||
## Return hexadecimal string representation of EC signature.
|
||||
if sig.curve == 0 or len(sig.buffer) == 0:
|
||||
result = "Empty signature"
|
||||
else:
|
||||
if sig.curve notin EcSupportedCurvesCint:
|
||||
result = "Unknown signature"
|
||||
else:
|
||||
result = toHex(sig.buffer)
|
||||
|
||||
proc toBytes*(seckey: EcPrivateKey, data: var openarray[byte]): bool =
|
||||
## Serialize EC private key ``seckey`` to raw binary form and store it to
|
||||
## ``data``.
|
||||
##
|
||||
## If ``seckey`` curve is ``Secp256r1`` length of ``data`` array must be at
|
||||
## least ``SecKey256Length``.
|
||||
##
|
||||
## If ``seckey`` curve is ``Secp384r1`` length of ``data`` array must be at
|
||||
## least ``SecKey384Length``.
|
||||
##
|
||||
## If ``seckey`` curve is ``Secp521r1`` length of ``data`` array must be at
|
||||
## least ``SecKey521Length``.
|
||||
##
|
||||
## Procedure returns ``true`` if serialization successfull, ``false``
|
||||
## otherwise.
|
||||
if seckey.key.curve in EcSupportedCurvesCint:
|
||||
if copyKey(data, seckey):
|
||||
result = true
|
||||
|
||||
proc toBytes*(pubkey: EcPublicKey, data: var openarray[byte]): bool =
|
||||
## Serialize EC public key ``pubkey`` to raw binary form and store it to
|
||||
## ``data``.
|
||||
##
|
||||
## If ``pubkey`` curve is ``Secp256r1`` length of ``data`` array must be at
|
||||
## least ``PubKey256Length``.
|
||||
##
|
||||
## If ``pubkey`` curve is ``Secp384r1`` length of ``data`` array must be at
|
||||
## least ``PubKey384Length``.
|
||||
##
|
||||
## If ``pubkey`` curve is ``Secp521r1`` length of ``data`` array must be at
|
||||
## least ``PubKey521Length``.
|
||||
##
|
||||
## Procedure returns ``true`` if serialization successfull, ``false``
|
||||
## otherwise.
|
||||
if pubkey.key.curve in EcSupportedCurvesCint:
|
||||
if copyKey(data, pubkey):
|
||||
result = true
|
||||
|
||||
proc getBytes*(seckey: EcPrivateKey): seq[byte] =
|
||||
## Serialize EC private key ``seckey`` to raw binary form and return it.
|
||||
if seckey.key.curve in EcSupportedCurvesCint:
|
||||
result = newSeq[byte](seckey.key.xlen)
|
||||
discard toBytes(seckey, result)
|
||||
else:
|
||||
raise newException(EcKeyIncorrectError, "Incorrect private key")
|
||||
|
||||
proc getBytes*(pubkey: EcPublicKey): seq[byte] =
|
||||
## Serialize EC public key ``pubkey`` to raw binary form and return it.
|
||||
if pubkey.key.curve in EcSupportedCurvesCint:
|
||||
result = newSeq[byte](pubkey.key.qlen)
|
||||
discard toBytes(pubkey, result)
|
||||
else:
|
||||
raise newException(EcKeyIncorrectError, "Incorrect public key")
|
||||
|
||||
proc `==`*(pubkey1, pubkey2: EcPublicKey): bool =
|
||||
## Returns ``true`` if both keys ``pubkey1`` and ``pubkey2`` are equal.
|
||||
if pubkey1.key.curve != pubkey2.key.curve:
|
||||
return false
|
||||
if pubkey1.key.qlen != pubkey2.key.qlen:
|
||||
return false
|
||||
let op1 = pubkey1.getOffset()
|
||||
let op2 = pubkey2.getOffset()
|
||||
if op1 == -1 or op2 == -1:
|
||||
return false
|
||||
result = equalMem(unsafeAddr pubkey1.buffer[op1],
|
||||
unsafeAddr pubkey2.buffer[op2], pubkey1.key.qlen)
|
||||
|
||||
proc `==`*(seckey1, seckey2: EcPrivateKey): bool =
|
||||
## Returns ``true`` if both keys ``seckey1`` and ``seckey2`` are equal.
|
||||
if seckey1.key.curve != seckey2.key.curve:
|
||||
return false
|
||||
if seckey1.key.xlen != seckey2.key.xlen:
|
||||
return false
|
||||
let op1 = seckey1.getOffset()
|
||||
let op2 = seckey2.getOffset()
|
||||
if op1 == -1 or op2 == -1:
|
||||
return false
|
||||
result = equalMem(unsafeAddr seckey1.buffer[op1],
|
||||
unsafeAddr seckey2.buffer[op2], seckey1.key.xlen)
|
||||
|
||||
proc `==`*(sig1, sig2: EcSignature): bool =
|
||||
## Return ``true`` if both signatures ``sig1`` and ``sig2`` are equal.
|
||||
if sig1.curve != sig2.curve:
|
||||
return false
|
||||
result = (sig1.buffer == sig2.buffer)
|
||||
|
||||
proc init*(key: var EcPrivateKey, data: openarray[byte]): bool =
|
||||
## Initialize EC `private key` or `scalar` ``key`` from raw binary
|
||||
## representation ``data``.
|
||||
##
|
||||
## Length of ``data`` array must be ``SecKey256Length``, ``SecKey384Length``
|
||||
## or ``SecKey521Length``.
|
||||
##
|
||||
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||
var curve: cint
|
||||
if len(data) == SecKey256Length:
|
||||
curve = cast[cint](Secp256r1)
|
||||
result = true
|
||||
elif len(data) == SecKey384Length:
|
||||
curve = cast[cint](Secp384r1)
|
||||
result = true
|
||||
elif len(data) == SecKey521Length:
|
||||
curve = cast[cint](Secp521r1)
|
||||
result = true
|
||||
if result:
|
||||
result = false
|
||||
if checkScalar(data, curve) == 1'u32:
|
||||
let length = len(data)
|
||||
key = new EcPrivateKey
|
||||
key.buffer = newSeq[byte](length)
|
||||
copyMem(addr key.buffer[0], unsafeAddr data[0], length)
|
||||
key.key.x = cast[ptr cuchar](addr key.buffer[0])
|
||||
key.key.xlen = length
|
||||
key.key.curve = curve
|
||||
result = true
|
||||
|
||||
proc init*(pubkey: var EcPublicKey, data: openarray[byte]): bool =
|
||||
## Initialize EC public key ``pubkey`` from raw binary representation
|
||||
## ``data``.
|
||||
##
|
||||
## Length of ``data`` array must be ``PubKey256Length``, ``PubKey384Length``
|
||||
## or ``PubKey521Length``.
|
||||
##
|
||||
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||
var curve: cint
|
||||
if len(data) > 0:
|
||||
if data[0] == 0x04'u8:
|
||||
if len(data) == PubKey256Length:
|
||||
curve = cast[cint](Secp256r1)
|
||||
result = true
|
||||
elif len(data) == PubKey384Length:
|
||||
curve = cast[cint](Secp384r1)
|
||||
result = true
|
||||
elif len(data) == PubKey521Length:
|
||||
curve = cast[cint](Secp521r1)
|
||||
result = true
|
||||
if result:
|
||||
result = false
|
||||
if checkPublic(data, curve) != 0:
|
||||
let length = len(data)
|
||||
pubkey = new EcPublicKey
|
||||
pubkey.buffer = newSeq[byte](length)
|
||||
copyMem(addr pubkey.buffer[0], unsafeAddr data[0], length)
|
||||
pubkey.key.q = cast[ptr cuchar](addr pubkey.buffer[0])
|
||||
pubkey.key.qlen = length
|
||||
pubkey.key.curve = curve
|
||||
result = true
|
||||
|
||||
proc init*(sig: var EcSignature, data: openarray[byte]): bool =
|
||||
## Initialize EC signature ``sig`` from raw binary representation ``data``.
|
||||
##
|
||||
## Length of ``data`` array must be ``Sig256Length``, ``Sig384Length``
|
||||
## or ``Sig521Length``.
|
||||
##
|
||||
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||
var curve: cint
|
||||
if len(data) > 0:
|
||||
if len(data) == Sig256Length:
|
||||
curve = cast[cint](Secp256r1)
|
||||
result = true
|
||||
elif len(data) == Sig384Length:
|
||||
curve = cast[cint](Secp384r1)
|
||||
result = true
|
||||
elif len(data) == Sig521Length:
|
||||
curve = cast[cint](Secp521r1)
|
||||
result = true
|
||||
if result:
|
||||
sig = new EcSignature
|
||||
sig.curve = curve
|
||||
sig.buffer = @data
|
||||
result = true
|
||||
|
||||
proc init*[T: EcPKI](sospk: var T, data: string): bool {.inline.} =
|
||||
## Initialize EC `private key`, `public key` or `scalar` ``sospk`` from
|
||||
## hexadecimal string representation ``data``.
|
||||
##
|
||||
## Procedure returns ``true`` on success, ``false`` otherwise.
|
||||
result = sospk.init(fromHex(data))
|
||||
|
||||
proc init*(t: typedesc[EcPrivateKey], data: openarray[byte]): EcPrivateKey =
|
||||
## Initialize EC private key from raw binary representation ``data`` and
|
||||
## return constructed object.
|
||||
if not result.init(data):
|
||||
raise newException(EcKeyIncorrectError, "Incorrect private key")
|
||||
|
||||
proc init*(t: typedesc[EcPublicKey], data: openarray[byte]): EcPublicKey =
|
||||
## Initialize EC public key from raw binary representation ``data`` and
|
||||
## return constructed object.
|
||||
if not result.init(data):
|
||||
raise newException(EcKeyIncorrectError, "Incorrect public key")
|
||||
|
||||
proc init*(t: typedesc[EcSignature], data: openarray[byte]): EcSignature =
|
||||
## Initialize EC signature from raw binary representation ``data`` and
|
||||
## return constructed object.
|
||||
if not result.init(data):
|
||||
raise newException(EcKeyIncorrectError, "Incorrect signature")
|
||||
|
||||
proc init*[T: EcPKI](t: typedesc[T], data: string): T {.inline.} =
|
||||
## Initialize EC `private key`, `public key` or `scalar` from hexadecimal
|
||||
## string representation ``data`` and return constructed object.
|
||||
result = t.init(fromHex(data))
|
||||
|
||||
proc scalarMul*(pub: EcPublicKey, sec: EcPrivateKey): EcPublicKey =
|
||||
## Return scalar multiplication of ``pub`` and ``sec``.
|
||||
##
|
||||
## Returns point in curve as ``pub * sec`` or ``nil`` otherwise.
|
||||
var impl = brEcGetDefault()
|
||||
if sec.key.curve in EcSupportedCurvesCint:
|
||||
if pub.key.curve == sec.key.curve:
|
||||
var key = new EcPublicKey
|
||||
if key.copy(pub):
|
||||
var slength = cint(0)
|
||||
let poffset = key.getOffset()
|
||||
let soffset = sec.getOffset()
|
||||
if poffset >= 0 and soffset >= 0:
|
||||
let res = impl.mul(cast[ptr cuchar](addr key.buffer[poffset]),
|
||||
key.key.qlen,
|
||||
cast[ptr cuchar](unsafeAddr sec.buffer[soffset]),
|
||||
sec.key.xlen,
|
||||
key.key.curve)
|
||||
if res != 0:
|
||||
result = key
|
||||
|
||||
proc sign*[T: byte|char](seckey: EcPrivateKey,
|
||||
message: openarray[T]): EcSignature =
|
||||
## Get ECDSA signature of data ``message`` using private key ``seckey``.
|
||||
var hc: BrHashCompatContext
|
||||
var hash: array[32, byte]
|
||||
var impl = brEcGetDefault()
|
||||
if len(message) > 0:
|
||||
if seckey.key.curve in EcSupportedCurvesCint:
|
||||
let length = getSignatureLength(cast[EcCurveKind](seckey.key.curve))
|
||||
result = new EcSignature
|
||||
result.curve = seckey.key.curve
|
||||
result.buffer = newSeq[byte](length)
|
||||
var kv = addr sha256Vtable
|
||||
kv.init(addr hc.vtable)
|
||||
kv.update(addr hc.vtable, unsafeAddr message[0], len(message))
|
||||
kv.output(addr hc.vtable, addr hash[0])
|
||||
let res = brEcdsaSignRaw(impl, kv, addr hash[0], addr seckey.key,
|
||||
addr result.buffer[0])
|
||||
if res != getSignatureLength(cast[EcCurveKind](result.curve)):
|
||||
raise newException(EcSignatureError, "Could not make signature")
|
||||
# Clear context with initial value
|
||||
kv.init(addr hc.vtable)
|
||||
else:
|
||||
raise newException(EcKeyIncorrectError, "Incorrect private key")
|
||||
else:
|
||||
raise newException(EcSignatureError, "Empty message")
|
||||
|
||||
proc verify*[T: byte|char](sig: EcSignature, message: openarray[T],
|
||||
pubkey: EcPublicKey): bool {.inline.} =
|
||||
## Verify ECDSA signature ``sig`` using public key ``pubkey`` and data
|
||||
## ``message``.
|
||||
##
|
||||
## Return ``true`` if message verification succeeded, ``false`` if
|
||||
## verification failed.
|
||||
var hc: BrHashCompatContext
|
||||
var hash: array[32, byte]
|
||||
var impl = brEcGetDefault()
|
||||
if len(message) > 0:
|
||||
if pubkey.key.curve in EcSupportedCurvesCint and
|
||||
pubkey.key.curve == sig.curve:
|
||||
var kv = addr sha256Vtable
|
||||
kv.init(addr hc.vtable)
|
||||
kv.update(addr hc.vtable, unsafeAddr message[0], len(message))
|
||||
kv.output(addr hc.vtable, addr hash[0])
|
||||
let res = brEcdsaVerifyRaw(impl, addr hash[0], 32, unsafeAddr pubkey.key,
|
||||
addr sig.buffer[0], len(sig.buffer))
|
||||
# Clear context with initial value
|
||||
kv.init(addr hc.vtable)
|
||||
result = (res == 1)
|
|
@ -0,0 +1,342 @@
|
|||
import strutils, hexdump, nimcrypto/utils
|
||||
import common
|
||||
|
||||
const
|
||||
DefaultPublicExponent = 3'u32
|
||||
|
||||
type
|
||||
RsaPrivateKey* = ref object
|
||||
buffer*: seq[byte]
|
||||
key*: BrRsaPrivateKey
|
||||
|
||||
RsaPublicKey* = ref object
|
||||
buffer*: seq[byte]
|
||||
key*: BrRsaPublicKey
|
||||
|
||||
RsaKeyPair* = object
|
||||
seckey*: RsaPrivateKey
|
||||
pubkey*: RsaPublicKey
|
||||
|
||||
RsaModulus* = seq[byte]
|
||||
RsaPublicExponent* = uint32
|
||||
RsaPrivateExponent* = seq[byte]
|
||||
|
||||
RsaError = object of Exception
|
||||
RsaRngError = object of RsaError
|
||||
RsaGenError = object of RsaError
|
||||
RsaIncorrectKeyError = object of RsaError
|
||||
|
||||
proc random*(t: typedesc[RsaKeyPair], bits: int): RsaKeyPair =
|
||||
## Generate new random RSA key pair (private key and public key) using
|
||||
## BearSSL's HMAC-SHA256-DRBG algorithm.
|
||||
##
|
||||
## ``bits`` number of bits in RSA key, must be in range [512, 4096].
|
||||
var rng: BrHmacDrbgContext
|
||||
var keygen: BrRsaKeygen
|
||||
var seeder = brPrngSeederSystem(nil)
|
||||
brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0)
|
||||
if seeder(addr rng.vtable) == 0:
|
||||
raise newException(ValueError, "Could not seed RNG")
|
||||
keygen = brRsaKeygenGetDefault()
|
||||
result.seckey = new RsaPrivateKey
|
||||
result.pubkey = new RsaPublicKey
|
||||
result.seckey.buffer = newSeq[byte](brRsaPrivateKeyBufferSize(bits))
|
||||
result.pubkey.buffer = newSeq[byte](brRsaPublicKeyBufferSize(bits))
|
||||
if keygen(addr rng.vtable,
|
||||
addr result.seckey.key, addr result.seckey.buffer[0],
|
||||
addr result.pubkey.key, addr result.pubkey.buffer[0],
|
||||
cuint(bits), DefaultPublicExponent) == 0:
|
||||
raise newException(RsaGenError, "Could not create keypair")
|
||||
|
||||
proc random*(t: typedesc[RsaPrivateKey], bits: int): RsaPrivateKey =
|
||||
## Generate new random RSA private key using BearSSL's HMAC-SHA256-DRBG
|
||||
## algorithm.
|
||||
##
|
||||
## ``bits`` number of bits in RSA key, must be in range [512, 4096].
|
||||
var rng: BrHmacDrbgContext
|
||||
var keygen: BrRsaKeygen
|
||||
var seeder = brPrngSeederSystem(nil)
|
||||
brHmacDrbgInit(addr rng, addr sha256Vtable, nil, 0)
|
||||
if seeder(addr rng.vtable) == 0:
|
||||
raise newException(RsaRngError, "Could not seed RNG")
|
||||
keygen = brRsaKeygenGetDefault()
|
||||
result = new RsaPrivateKey
|
||||
result.buffer = newSeq[byte](brRsaPrivateKeyBufferSize(bits))
|
||||
if keygen(addr rng.vtable,
|
||||
addr result.seckey.key, addr result.seckey.buffer[0],
|
||||
nil, nil,
|
||||
cuint(bits), DefaultPublicExponent) == 0:
|
||||
raise newException(RsaGenError, "Could not create private key")
|
||||
|
||||
proc modulus*(seckey: RsaPrivateKey): RsaModulus =
|
||||
## Calculate and return RSA modulus.
|
||||
let bytelen = (seckey.key.nBitlen + 7) shr 3
|
||||
let compute = brRsaComputeModulusGetDefault()
|
||||
result = newSeq[byte](bytelen)
|
||||
let length = compute(addr result[0], unsafeAddr seckey.key)
|
||||
assert(length == len(result), $length)
|
||||
|
||||
proc pubexp*(seckey: RsaPrivateKey): RsaPublicExponent =
|
||||
## Calculate and return RSA public exponent.
|
||||
let compute = brRsaComputePubexpGetDefault()
|
||||
result = compute(unsafeAddr seckey.key)
|
||||
|
||||
proc privexp*(seckey: RsaPrivateKey,
|
||||
pubexp: RsaPublicExponent): RsaPrivateExponent =
|
||||
## Calculate and return RSA private exponent.
|
||||
let bytelen = (seckey.key.nBitlen + 7) shr 3
|
||||
let compute = brRsaComputePrivexpGetDefault()
|
||||
result = newSeq[byte](bytelen)
|
||||
let length = compute(addr result[0], unsafeAddr seckey.key, pubexp)
|
||||
assert(length == len(result), $length)
|
||||
|
||||
proc getKey*(seckey: RsaPrivateKey): RsaPublicKey =
|
||||
## Calculate and return RSA public key from RSA private key ``seckey``.
|
||||
var ebuf: array[4, byte]
|
||||
var modulus = seckey.modulus()
|
||||
var pubexp = seckey.pubexp()
|
||||
let modlen = len(modulus)
|
||||
result = new RsaPublicKey
|
||||
result.buffer = newSeq[byte](modlen + sizeof(ebuf))
|
||||
result.key.n = cast[ptr cuchar](addr result.buffer[0])
|
||||
result.key.nlen = modlen
|
||||
result.key.e = cast[ptr cuchar](addr result.buffer[modlen])
|
||||
result.key.elen = sizeof(ebuf)
|
||||
ebuf[0] = cast[byte](pubexp shr 24)
|
||||
ebuf[1] = cast[byte](pubexp shr 16)
|
||||
ebuf[2] = cast[byte](pubexp shr 8)
|
||||
ebuf[3] = cast[byte](pubexp)
|
||||
copyMem(addr result.buffer[0], addr modulus[0], modlen)
|
||||
copyMem(addr result.buffer[modlen], addr ebuf[0], sizeof(ebuf))
|
||||
|
||||
|
||||
|
||||
proc brEncodePublicRsaRawDer(pubkey: RsaPublicKey,
|
||||
dest: var openarray[byte]): int =
|
||||
# RSAPublicKey ::= SEQUENCE {
|
||||
# modulus INTEGER, -- n
|
||||
# publicExponent INTEGER, -- e
|
||||
# }
|
||||
var num: array[2, BrAsn1Uint]
|
||||
num[0] = brAsn1UintPrepare(pubkey.key.n, pubkey.key.nlen)
|
||||
num[1] = brAsn1UintPrepare(pubkey.key.e, pubkey.key.elen)
|
||||
var slen = 0
|
||||
for i in 0..<2:
|
||||
var ilen = num[i].asn1len
|
||||
slen += 1 + brAsn1EncodeLength(nil, ilen) + ilen
|
||||
result = 1 + brAsn1EncodeLength(nil, slen) + slen
|
||||
if len(dest) >= result:
|
||||
var offset = 1
|
||||
dest[0] = 0x30'u8
|
||||
offset += brAsn1EncodeLength(addr dest[offset], slen)
|
||||
for i in 0..<2:
|
||||
offset += brAsn1EncodeUint(addr dest[offset], num[i])
|
||||
|
||||
proc brAsn1EncodeBitString(data: var openarray[byte], bytesize: int): int =
|
||||
result = 1 + brAsn1EncodeLength(nil, bytesize + 1) + 1
|
||||
if len(data) >= result:
|
||||
var offset = 1
|
||||
data[0] = 0x03'u8
|
||||
offset += brAsn1EncodeLength(addr data[offset], bytesize + 1)
|
||||
data[offset] = 0'u8
|
||||
|
||||
proc marshalBin*(pubkey: RsaPublicKey, kind: MarshalKind): seq[byte] =
|
||||
## Serialize RSA public key ``pubkey`` to binary [RAWDER, PKCS8DER] format.
|
||||
var tmp: array[1, byte]
|
||||
if kind == RAW:
|
||||
var res = brEncodePublicRsaRawDer(pubkey, tmp)
|
||||
result = newSeq[byte](res)
|
||||
res = brEncodePublicRsaRawDer(pubkey, result)
|
||||
assert res == len(result)
|
||||
elif kind == PKCS8:
|
||||
var pkcs8head = [
|
||||
0x30'u8, 0x0D'u8, 0x06'u8, 0x09'u8, 0x2A'u8, 0x86'u8, 0x48'u8, 0x86'u8,
|
||||
0xF7'u8, 0x0D'u8, 0x01'u8, 0x01'u8, 0x01'u8, 0x05'u8, 0x00'u8
|
||||
]
|
||||
var lenraw = brEncodePublicRsaRawDer(pubkey, tmp)
|
||||
echo "lenraw = ", lenraw, " hex = 0x", toHex(lenraw)
|
||||
echo "RAWDER"
|
||||
|
||||
var lenseq = sizeof(pkcs8head) + brAsn1EncodeLength(nil, lenraw) + lenraw +
|
||||
brAsn1EncodeBitString(tmp, lenraw)
|
||||
echo "brAsn1EncodeBitString = ", brAsn1EncodeBitString(tmp, lenraw)
|
||||
echo "lenseq = ", lenseq
|
||||
result = newSeq[byte](1 + brAsn1EncodeLength(nil, lenseq) + lenseq)
|
||||
result[0] = 0x30'u8
|
||||
echo dumpHex(result)
|
||||
var offset = 1
|
||||
offset += brAsn1EncodeLength(addr result[offset], lenseq)
|
||||
echo dumpHex(result)
|
||||
copyMem(addr result[offset], addr pkcs8head[0], sizeof(pkcs8head))
|
||||
echo dumpHex(result)
|
||||
offset += sizeof(pkcs8head)
|
||||
offset += brAsn1EncodeBitString(result.toOpenArray(offset, len(result) - 1),
|
||||
lenraw)
|
||||
echo "AFTER BITSTRING"
|
||||
echo dumpHex(result)
|
||||
echo dumpHex(result.toOpenArray(offset, len(result) - 1))
|
||||
offset += brAsn1EncodeLength(addr result[offset], lenraw)
|
||||
|
||||
var res = brEncodePublicRsaRawDer(pubkey, result.toOpenArray(offset,
|
||||
len(result) - 1))
|
||||
echo "AFTER RAWDER"
|
||||
echo dumpHex(result)
|
||||
offset += res
|
||||
|
||||
|
||||
proc marshalBin*(seckey: RsaPrivateKey, kind: MarshalKind): seq[byte] =
|
||||
## Serialize RSA private key ``seckey`` to binary [RAWDER, PKCS8DER] format.
|
||||
var ebuf: array[4, byte]
|
||||
var pubkey: BrRsaPublicKey
|
||||
var modulus = seckey.modulus()
|
||||
var pubexp = seckey.pubexp()
|
||||
var privexp = seckey.privexp(pubexp)
|
||||
pubkey.n = cast[ptr cuchar](addr modulus[0])
|
||||
pubkey.nlen = len(modulus)
|
||||
ebuf[0] = cast[byte](pubexp shr 24)
|
||||
ebuf[1] = cast[byte](pubexp shr 16)
|
||||
ebuf[2] = cast[byte](pubexp shr 8)
|
||||
ebuf[3] = cast[byte](pubexp)
|
||||
pubkey.e = cast[ptr cuchar](addr ebuf[0])
|
||||
pubkey.elen = sizeof(ebuf)
|
||||
if kind == RAW:
|
||||
let length = brEncodeRsaRawDer(nil, unsafeAddr seckey.key, addr pubkey,
|
||||
addr privexp[0], len(privexp))
|
||||
result = newSeq[byte](length)
|
||||
let res = brEncodeRsaRawDer(addr result[0], unsafeAddr seckey.key,
|
||||
addr pubkey, addr privexp[0],
|
||||
len(privexp))
|
||||
assert(res == length)
|
||||
elif kind == PKCS8:
|
||||
let length = brEncodeRsaPkcs8Der(nil, unsafeAddr seckey.key, addr pubkey,
|
||||
addr privexp[0], len(privexp))
|
||||
result = newSeq[byte](length)
|
||||
let res = brEncodeRsaPkcs8Der(addr result[0], unsafeAddr seckey.key,
|
||||
addr pubkey, addr privexp[0],
|
||||
len(privexp))
|
||||
assert(res == length)
|
||||
|
||||
proc marshalPem*[T: RsaPrivateKey | RsaPublicKey](key: T,
|
||||
kind: MarshalKind): string =
|
||||
## Serialize RSA private key ``seckey`` to PEM encoded format string.
|
||||
var banner: string
|
||||
let flags = cast[cuint](BR_PEM_CRLF or BR_PEM_LINE64)
|
||||
if kind == RAW:
|
||||
when T is RsaPrivateKey:
|
||||
banner = "RSA PRIVATE KEY"
|
||||
else:
|
||||
banner = "RSA PUBLIC KEY"
|
||||
elif kind == PKCS8:
|
||||
when T is RsaPrivateKey:
|
||||
banner = "PRIVATE KEY"
|
||||
else:
|
||||
banner = "PUBLIC KEY"
|
||||
var buffer = marshalBin(key, kind)
|
||||
if len(buffer) > 0:
|
||||
let length = brPemEncode(nil, nil, len(buffer), banner, flags)
|
||||
result = newString(length + 1)
|
||||
let res = brPemEncode(cast[ptr byte](addr result[0]), addr buffer[0],
|
||||
len(buffer), banner, flags)
|
||||
result.setLen(res)
|
||||
|
||||
proc copyRsaPrivateKey(brkey: BrRsaPrivateKey,
|
||||
buffer: ptr cuchar): RsaPrivateKey =
|
||||
result.buffer = newSeq[byte](brRsaPrivateKeyBufferSize(int(brkey.nBitlen)))
|
||||
let p = cast[uint](addr result.buffer[0])
|
||||
let o = cast[uint](buffer)
|
||||
let size = brkey.iqlen + cast[int](cast[uint](brkey.iq) - o)
|
||||
if size > 0 and size <= len(result.buffer):
|
||||
copyMem(addr result.buffer[0], buffer, size)
|
||||
result.key.nBitlen = brkey.nBitlen
|
||||
result.key.plen = brkey.plen
|
||||
result.key.qlen = brkey.qlen
|
||||
result.key.dplen = brkey.dplen
|
||||
result.key.dqlen = brkey.dqlen
|
||||
result.key.iqlen = brkey.iqlen
|
||||
result.key.p = cast[ptr cuchar](p + cast[uint](brkey.p) - o)
|
||||
result.key.q = cast[ptr cuchar](p + cast[uint](brkey.q) - o)
|
||||
result.key.dp = cast[ptr cuchar](p + cast[uint](brkey.dp) - o)
|
||||
result.key.dq = cast[ptr cuchar](p + cast[uint](brkey.dq) - o)
|
||||
result.key.iq = cast[ptr cuchar](p + cast[uint](brkey.iq) - o)
|
||||
|
||||
proc tryUnmarshalBin*(key: var RsaPrivateKey,
|
||||
data: openarray[byte]): X509Status =
|
||||
## Unserialize RSA private key ``key`` from binary blob ``data``. Binary blob
|
||||
## must be RAWDER or PKCS8DER format.
|
||||
var ctx: BrSkeyDecoderContext
|
||||
result = X509Status.INCORRECT_VALUE
|
||||
if len(data) > 0:
|
||||
brSkeyDecoderInit(addr ctx)
|
||||
brSkeyDecoderPush(addr ctx, unsafeAddr data[0], len(data))
|
||||
let err = brSkeyDecoderLastError(addr ctx)
|
||||
if err == 0:
|
||||
let kt = brSkeyDecoderKeyType(addr ctx)
|
||||
if kt == BR_KEYTYPE_RSA:
|
||||
key = copyRsaPrivateKey(ctx.pkey.rsa, addr ctx.keyData[0])
|
||||
if key.key.nBitlen == ctx.pkey.rsa.nBitlen:
|
||||
result = X509Status.OK
|
||||
else:
|
||||
result = X509Status.INCORRECT_VALUE
|
||||
else:
|
||||
result = X509Status.WRONG_KEY_TYPE
|
||||
else:
|
||||
result = cast[X509Status](err)
|
||||
|
||||
proc unmarshalBin*(rt: typedesc[RsaPrivateKey],
|
||||
data: openarray[byte]): RsaPrivateKey {.inline.} =
|
||||
let res = tryUnmarshalBin(result, data)
|
||||
if res != X509Status.OK:
|
||||
raise newException(ValueError, $res)
|
||||
|
||||
proc getPrivateKey*(key: var RsaPrivateKey, pemlist: PemList): X509Status =
|
||||
## Get first
|
||||
result = X509Status.MISSING_KEY
|
||||
for item in pemlist:
|
||||
if "RSA PRIVATE KEY" in item.name:
|
||||
result = key.tryUnmarshalBin(item.data)
|
||||
return
|
||||
elif "PRIVATE KEY" in item.name:
|
||||
result = key.tryUnmarshalBin(item.data)
|
||||
return
|
||||
|
||||
proc cmp(a: ptr cuchar, alen: int, b: ptr cuchar, blen: int): bool =
|
||||
var arr = cast[ptr UncheckedArray[byte]](a)
|
||||
var brr = cast[ptr UncheckedArray[byte]](b)
|
||||
if alen == blen:
|
||||
var n = len(a)
|
||||
var res, diff: int
|
||||
while n > 0:
|
||||
dec(n)
|
||||
diff = int(arr[n]) - int(brr[n])
|
||||
res = (res and -not(diff)) or diff
|
||||
result = (res == 0)
|
||||
|
||||
proc `==`*(a, b: RsaPrivateKey): bool =
|
||||
## Compare two RSA private keys for equality.
|
||||
if a.key.nBitlen == b.key.nBitlen:
|
||||
if cast[int](a.key.nBitlen) > 0:
|
||||
let r1 = cmp(a.key.p, a.key.plen, b.key.p, b.key.plen)
|
||||
let r2 = cmp(a.key.q, a.key.qlen, b.key.q, b.key.qlen)
|
||||
let r3 = cmp(a.key.dp, a.key.dplen, b.key.dp, b.key.dplen)
|
||||
let r4 = cmp(a.key.dq, a.key.dqlen, b.key.dq, b.key.dqlen)
|
||||
let r5 = cmp(a.key.iq, a.key.iqlen, b.key.iq, b.key.iqlen)
|
||||
result = r1 and r2 and r3 and r4 and r5
|
||||
else:
|
||||
result = true
|
||||
|
||||
proc `$`*(a: RsaPrivateKey): string =
|
||||
## Return hexadecimal string representation of RSA private key.
|
||||
result = "P: "
|
||||
result.add("\n")
|
||||
result.add("Q: ")
|
||||
result.add("\n")
|
||||
result.add("DP: ")
|
||||
result.add("\n")
|
||||
result.add("DQ: ")
|
||||
result.add("\n")
|
||||
result.add("IQ: ")
|
||||
result.add("\n")
|
||||
|
||||
when isMainModule:
|
||||
var pk = RsaKeyPair.random()
|
||||
|
Loading…
Reference in New Issue