/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
package stdx.crypto.keys
import stdx.crypto.digest.*
import stdx.crypto.common.*
const RSA_id: Int32 = 6
const EC_id: Int32 = 408
// curve id
const NID_secp224r1: Int32 = 713
const NID_X9_62_prime256v1: Int32 = 415
const NID_secp384r1: Int32 = 715
const NID_secp521r1: Int32 = 716
const NID_brainpoolP256r1: Int32 = 927
const NID_brainpoolP320r1: Int32 = 929
const NID_brainpoolP384r1: Int32 = 931
const NID_brainpoolP512r1: Int32 = 933
const NID_sm2: Int32 = 1172
const PKCS1_PADDING_SIZE: Int32 = 11
const RSA_PKCS1_PADDING: Int32 = 1
const RSA_PKCS1_OAEP_PADDING: Int32 = 4
const RSA_PKCS1_PSS_PADDING: Int32 = 6
const CJ_FAIL: Int32 = -1
const CJ_NEED_READ: Int32 = -2
const CJ_NEED_WRITE: Int32 = -3
const CJ_OK: Int32 = 1
// sm2
foreign func DYN_EVP_PKEY_CTX_set1_id(ctx: CPointer<UInt64>, id: CPointer<Byte>, len: Int64, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_DigestVerifyInit(ctx: CPointer<UInt64>, pctx: CPointer<UInt64>, md: CPointer<UInt64>,
e: CPointer<UInt64>, pkey: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_DigestVerifyUpdate(ctx: CPointer<UInt64>, data: CPointer<Byte>, len: UIntNative, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_DigestVerifyFinal(ctx: CPointer<UInt64>, sig: CPointer<Byte>, len: UIntNative, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_MD_CTX_new(msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_MD_CTX_free(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Unit
foreign func DYN_EVP_MD_CTX_set_pkey_ctx(ctx: CPointer<UInt64>, pctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Unit
foreign func DYN_EVP_DigestSignInit(ctx: CPointer<UInt64>, pctx: CPointer<UInt64>, md: CPointer<UInt64>,
e: CPointer<UInt64>, pkey: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_DigestSignUpdate(ctx: CPointer<UInt64>, data: CPointer<Byte>, len: UIntNative, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_DigestSignFinal(ctx: CPointer<UInt64>, sig: CPointer<Byte>, len: CPointer<Int64>,
msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_keygen(ctx: CPointer<UInt64>, ppkey: CPointer<CPointer<UInt64>>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_paramgen_init(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
// context new & free
foreign func DYN_EVP_PKEY_CTX_new(pkey: CPointer<UInt64>, e: CPointer<UInt64>, msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_PKEY_CTX_new_id(id: Int32, e: CPointer<UInt64>, msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_PKEY_free(c: CPointer<UInt64>, msg: CPointer<DynMsg>): Unit
foreign func DYN_EVP_PKEY_CTX_free(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Unit
foreign func DYN_EVP_PKEY_keygen_init(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_generate(ctx: CPointer<UInt64>, ppkey: CPointer<CPointer<UInt64>>, msg: CPointer<DynMsg>): Int32
// keys type setting
foreign func DYN_BN_free(bn: CPointer<BIGNUM>, msg: CPointer<DynMsg>): Unit
foreign func DYN_BN_bin2bn(bn: CPointer<Byte>, len: Int32, ret: CPointer<BIGNUM>, msg: CPointer<DynMsg>): CPointer<BIGNUM>
foreign func DYN_EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx: CPointer<UInt64>, exp: CPointer<BIGNUM>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_CTX_set_rsa_keygen_bits(ctx: CPointer<UInt64>, bit: Int32, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx: CPointer<UInt64>, nid: Int32, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_get_id(pkey: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_is_a(pkey: CPointer<UInt64>, type_name: CString, msg: CPointer<DynMsg>): Int32
// encrypt & decrypt
foreign func DYN_EVP_PKEY_encrypt_init(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_encrypt(
ctx: CPointer<UInt64>,
out: CPointer<Byte>,
outlen: CPointer<UIntNative>,
indata: CPointer<Byte>,
inlen: UIntNative,
msg: CPointer<DynMsg>
): Int32
foreign func DYN_EVP_PKEY_decrypt_init(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_decrypt(
ctx: CPointer<UInt64>,
out: CPointer<Byte>,
outlen: CPointer<UIntNative>,
indata: CPointer<Byte>,
inlen: UIntNative,
msg: CPointer<DynMsg>
): Int32
// sign & verify
foreign func DYN_EVP_PKEY_sign_init(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_sign(
ctx: CPointer<UInt64>,
sig: CPointer<Byte>,
siglen: CPointer<UIntNative>,
tbs: CPointer<Byte>,
tbslen: UIntNative,
msg: CPointer<DynMsg>
): Int32
foreign func DYN_EVP_PKEY_verify_init(ctx: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_verify(
ctx: CPointer<UInt64>,
sig: CPointer<Byte>,
siglen: UIntNative,
tbs: CPointer<Byte>,
tbslen: UIntNative,
msg: CPointer<DynMsg>
): Int32
foreign func DYN_EVP_PKEY_get_size(pkey: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
// DER format
foreign func DYN_i2d_PrivateKey(pkey: CPointer<UInt64>, c: CPointer<CPointer<Byte>>, msg: CPointer<DynMsg>): Int32
foreign func DYN_d2i_PrivateKey(id: Int32, ppkey: CPointer<CPointer<UInt64>>, c: CPointer<CPointer<Byte>>,
length: Int64, msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_d2i_PUBKEY(ppkey: CPointer<CPointer<UInt64>>, c: CPointer<CPointer<Byte>>, length: Int64,
msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_i2d_PUBKEY(pkey: CPointer<UInt64>, c: CPointer<CPointer<Byte>>, msg: CPointer<DynMsg>): Int32
// digest setting
foreign func DYN_EVP_md5(msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_sha1(msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_sha224(msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_sha256(msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_sha384(msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_sha512(msg: CPointer<DynMsg>): CPointer<UInt64>
foreign func DYN_EVP_sm3(msg: CPointer<DynMsg>): CPointer<UInt64>
// PSS option setting
foreign func DYN_EVP_PKEY_CTX_set_rsa_padding(ctx: CPointer<UInt64>, pad: Int32, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_CTX_set_signature_md(ctx: CPointer<UInt64>, md: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func DYN_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx: CPointer<UInt64>, saltlen: Int32, msg: CPointer<DynMsg>): Int32
// OAEP option setting
foreign func DYN_CJ_KEYS_OAEPSetting(ctx: CPointer<UInt64>, label: CString, md: CPointer<UInt64>,
mgf1: CPointer<UInt64>, msg: CPointer<DynMsg>): Int32
foreign func MallocDynMsg(): CPointer<DynMsg>
foreign func FreeDynMsg(dynMsgPtr: CPointer<DynMsg>): Unit
class EVPKEYCTX {
var ptr: CPointer<UInt64>
let e = CPointer<UInt64>()
init(pkey: CPointer<UInt64>) {
unsafe {
this.ptr = keyCtxNew(pkey, e)
if (this.ptr.isNull()) {
throw CryptoException("create key ctx error.")
}
}
}
~init() {
if (!ptr.isNull()) {
keyCtxFree(ptr)
}
}
}
// map struct bignum_st in openssl
@C
struct BIGNUM {
var d: CPointer<IntNative> = CPointer()
var top: Int32 = 0
var dmax: Int32 = 0
var neg: Int32 = 0
var flags: Int32 = 0
}
func keysOAEPSetting(ctx: CPointer<UInt64>, label: CString, md: CPointer<UInt64>, mgf1: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_CJ_KEYS_OAEPSetting(ctx, label, md, mgf1, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func keyCtxNew(pkey: CPointer<UInt64>, e: CPointer<UInt64>): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_new(pkey, e, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func keyCtxNewId(id: Int32, e: CPointer<UInt64>): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_new_id(id, e, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func keyFree(c: CPointer<UInt64>): Unit {
let dynMsgPtr = generateDynMsg()
unsafe { DYN_EVP_PKEY_free(c, dynMsgPtr) }
checkError(dynMsgPtr)
}
func keyCtxFree(ctx: CPointer<UInt64>): Unit {
let dynMsgPtr = generateDynMsg()
unsafe { DYN_EVP_PKEY_CTX_free(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
}
func keygenInit(ctx: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_keygen_init(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func keyGenerate(ctx: CPointer<UInt64>, ppkey: CPointer<CPointer<UInt64>>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_generate(ctx, ppkey, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func bnFree(bn: CPointer<BIGNUM>): Unit {
let dynMsgPtr = generateDynMsg()
unsafe { DYN_BN_free(bn, dynMsgPtr) }
checkError(dynMsgPtr)
}
func bin2bn(bn: CPointer<Byte>, len: Int32, ret: CPointer<BIGNUM>): CPointer<BIGNUM> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_BN_bin2bn(bn, len, ret, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func setRSAPubExp(ctx: CPointer<UInt64>, exp: CPointer<BIGNUM>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, exp, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func setRSABits(ctx: CPointer<UInt64>, bit: Int32): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bit, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func setCurveNid(ctx: CPointer<UInt64>, nid: Int32): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func getPkeyId(pkey: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_get_id(pkey, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func pkeyIs(pkey: CPointer<UInt64>, name: String): Bool {
let dynMsgPtr = generateDynMsg()
var code: Int32 = 0
try (cstr = unsafe { LibC.mallocCString(name) }.asResource()) {
code = unsafe { DYN_EVP_PKEY_is_a(pkey, cstr.value, dynMsgPtr) }
}
checkError(dynMsgPtr)
return code == 1
}
func encryInit(ctx: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_encrypt_init(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func encrypt(
ctx: CPointer<UInt64>,
out: CPointer<Byte>,
outlen: CPointer<UIntNative>,
indata: CPointer<Byte>,
inlen: UIntNative
): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_encrypt(ctx, out, outlen, indata, inlen, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func decryptInit(ctx: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_decrypt_init(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func decrypt(
ctx: CPointer<UInt64>,
out: CPointer<Byte>,
outlen: CPointer<UIntNative>,
indata: CPointer<Byte>,
inlen: UIntNative
): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_decrypt(ctx, out, outlen, indata, inlen, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func signInit(ctx: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_sign_init(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func sign(
ctx: CPointer<UInt64>,
sig: CPointer<Byte>,
siglen: CPointer<UIntNative>,
tbs: CPointer<Byte>,
tbslen: UIntNative
): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_sign(ctx, sig, siglen, tbs, tbslen, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func verifyInit(ctx: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_verify_init(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func verify(
ctx: CPointer<UInt64>,
sig: CPointer<Byte>,
siglen: UIntNative,
tbs: CPointer<Byte>,
tbslen: UIntNative
): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_verify(ctx, sig, siglen, tbs, tbslen, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func getSize(pkey: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_get_size(pkey, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func privateKey2d(pkey: CPointer<UInt64>, c: CPointer<CPointer<Byte>>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_i2d_PrivateKey(pkey, c, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func d2PrivateKey(id: Int32, ppkey: CPointer<CPointer<UInt64>>, c: CPointer<CPointer<Byte>>, length: Int64): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_d2i_PrivateKey(id, ppkey, c, length, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func d2Pubkey(ppkey: CPointer<CPointer<UInt64>>, c: CPointer<CPointer<Byte>>, length: Int64): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_d2i_PUBKEY(ppkey, c, length, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func pubKey2d(pkey: CPointer<UInt64>, c: CPointer<CPointer<Byte>>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_i2d_PUBKEY(pkey, c, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func md5(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_md5(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func sha1(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_sha1(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func sha224(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_sha224(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func sha256(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_sha256(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func sha384(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_sha384(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func sha512(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_sha512(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func setRSAPadding(ctx: CPointer<UInt64>, pad: Int32): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_set_rsa_padding(ctx, pad, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func setSignatureMD(ctx: CPointer<UInt64>, md: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_set_signature_md(ctx, md, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func setRSAPssSaltLen(ctx: CPointer<UInt64>, saltlen: Int32): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func sm3(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_sm3(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func keyCtxSetId(ctx: CPointer<UInt64>, id: CPointer<Byte>, len: Int64): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_CTX_set1_id(ctx, id, len, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func digestVerifyInit(ctx: CPointer<UInt64>, pctx: CPointer<UInt64>, md: CPointer<UInt64>, e: CPointer<UInt64>,
pkey: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_DigestVerifyInit(ctx, pctx, md, e, pkey, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func digestVerifyUpdate(ctx: CPointer<UInt64>, data: CPointer<Byte>, len: UIntNative): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_DigestVerifyUpdate(ctx, data, len, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func digestVerifyFinal(ctx: CPointer<UInt64>, sig: CPointer<Byte>, len: UIntNative): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_DigestVerifyFinal(ctx, sig, len, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func mdCtxNew(): CPointer<UInt64> {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_MD_CTX_new(dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func mdCtxFree(ctx: CPointer<UInt64>): Unit {
let dynMsgPtr = generateDynMsg()
unsafe { DYN_EVP_MD_CTX_free(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
}
func setKeyCtx(ctx: CPointer<UInt64>, pctx: CPointer<UInt64>): Unit {
let dynMsgPtr = generateDynMsg()
unsafe { DYN_EVP_MD_CTX_set_pkey_ctx(ctx, pctx, dynMsgPtr) }
checkError(dynMsgPtr)
}
func digestSignInit(ctx: CPointer<UInt64>, pctx: CPointer<UInt64>, md: CPointer<UInt64>, e: CPointer<UInt64>,
pkey: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_DigestSignInit(ctx, pctx, md, e, pkey, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func digestSignUpdate(ctx: CPointer<UInt64>, data: CPointer<Byte>, len: UIntNative): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_DigestSignUpdate(ctx, data, len, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func digestSignFinal(ctx: CPointer<UInt64>, sig: CPointer<Byte>, len: CPointer<Int64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_DigestSignFinal(ctx, sig, len, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func keygen(ctx: CPointer<UInt64>, ppkey: CPointer<CPointer<UInt64>>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_keygen(ctx, ppkey, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func paramgenInit(ctx: CPointer<UInt64>): Int32 {
let dynMsgPtr = generateDynMsg()
let res = unsafe { DYN_EVP_PKEY_paramgen_init(ctx, dynMsgPtr) }
checkError(dynMsgPtr)
return res
}
func generateDynMsg(): CPointer<DynMsg> {
unsafe {
let dynMsgPtr = MallocDynMsg()
if (dynMsgPtr.isNull()) {
throw CryptoException("Malloc failed.")
}
return dynMsgPtr
}
}
func checkError(dynMsgPtr: CPointer<DynMsg>): Unit {
unsafe {
if (dynMsgPtr.isNull()) {
throw CryptoException("Null pointer check failed.")
}
try {
if (!dynMsgPtr.read().found) {
let funcName = CString(dynMsgPtr.read().funcName).toString()
throw CryptoException("Can not load openssl library or function ${funcName}.")
}
} finally {
FreeDynMsg(dynMsgPtr)
}
}
}
@C
protected struct DynMsg {
var found = true
var funcName = CPointer<UInt8>()
}
@C
protected struct ExceptionData {
var message: CPointer<Byte> = CPointer() // this is always allocated using malloc
var constMessage: CPointer<Byte> = CPointer() // this is never allocated
protected prop hasException: Bool {
get() {
!message.isNull() || !constMessage.isNull()
}
}
protected func throwException(fallback!: String): Nothing {
if (!message.isNull()) {
throw CryptoException(CString(message).toString())
}
if (!constMessage.isNull()) {
throw CryptoException(CString(constMessage).toString())
}
throw CryptoException(fallback)
}
protected mut func clear(): Unit {
if (!message.isNull()) {
unsafe { CRYPTO_free(message) }
message = CPointer()
}
}
protected static func create(): CPointer<ExceptionData> {
unsafe {
let ptr = LibC.malloc<ExceptionData>(count: 1)
if (ptr.isNull()) {
throw CryptoException("malloc failed")
}
ptr.write(ExceptionData())
return ptr
}
}
protected static func free(exception: CPointer<ExceptionData>): Unit {
unsafe {
if (exception.isNull()) {
return
}
var data = exception.read()
data.clear()
LibC.free(exception)
}
}
protected static func withException<R>(block: (CPointer<ExceptionData>) -> R): R {
let exception = ExceptionData.create()
try {
block(exception)
} finally {
ExceptionData.free(exception)
}
}
}