// D. J. Bernstein // 20240313 // SPDX-License-Identifier: LicenseRef-PD-hp OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT #define provider_name "openssl_ed25519_lib25519" #define provider_version "20240313" /* Basic requirements on the underlying signature library: - Must follow a SUPERCOP-style interface. - The secret key must end with the public key. - The signed message must be a signature followed by the message. - Signatures must be constant length. Overall structure of this file: siglib glue code at the top, then the painful part. The siglib glue code wraps the signature library: - Sizes: - SIGLIB_PKBYTES is the number of public-key bytes. - SIGLIB_SKBYTES is the number of secret-key bytes. - SIGLIB_SIGBYTES is the number of signature bytes. - Data structure: - struct siglib_key stores data[SIGLIB_SKBYTES] and state. - state SIGLIB_KEY_EMPTY: data is all 0. - state SIGLIB_KEY_PK: data is zeros followed by public key. - state SIGLIB_KEY_SK: data is secret key. - SIGLIB_KEY_EMPTY is guaranteed to be 0. - Functions: - siglib_key_generate(&K): stores a new secret key in K. - siglib_key_sign(sig,m,mlen,&K): signs a message using K. - siglib_key_verify(sig,m,mlen,&K): verifies a signature using K. - OpenSSL-style return values: 1 for success, 0 for failure. - Constants to interface with OpenSSL: - siglib_pubkey_asn1_prefix is DER prefix for public keys - siglib_privkey_asn1_prefix is DER prefix for secret keys - siglib_algorithm_asn1 is DER encoding of just the system name - siglib_algorithm_name is main command-line name for the system - siglib_algorithm_names is name:altname1:altname2:... (see openssl/providers/implementations/include/prov/names.h) */ #include // to use OPENSSL_zalloc in the siglib code #include // for SIZE_MAX, LLONG_MAX #include // for memset #include // the wrapped library #define siglib_algorithm_name "ED25519" #define siglib_algorithm_names "ED25519:1.3.101.112" // XXX: must be correct DER; otherwise triggers double-free in openssl req static const unsigned char siglib_algorithm_asn1[7] = { 0x30,0x05,0x06,0x03,0x2b,0x65,0x70, } ; static const unsigned char siglib_pubkey_asn1_prefix[12] = { 0x30,0x2a, 0x30,0x05,0x06,0x03,0x2b,0x65,0x70, 0x03,0x21,0x00 } ; static const unsigned char siglib_privkey_asn1_prefix[16] = { 0x30,0x4e, 0x02,0x01,0x00, 0x30,0x05,0x06,0x03,0x2b,0x65,0x70, 0x04,0x42,0x04,0x40 } ; #define SIGLIB_PKBYTES lib25519_sign_PUBLICKEYBYTES #define SIGLIB_SKBYTES lib25519_sign_SECRETKEYBYTES #define SIGLIB_SIGBYTES lib25519_sign_BYTES #if SIGLIB_PKBYTES > SIGLIB_SKBYTES #error SIGLIB_PKBYTES has to be at most SIGLIB_SKBYTES #endif struct siglib_key { unsigned char data[SIGLIB_SKBYTES]; unsigned char state; } ; #define SIGLIB_KEY_EMPTY 0 #define SIGLIB_KEY_PK 1 #define SIGLIB_KEY_SK 2 static int siglib_key_generate(struct siglib_key *K) { unsigned char pk[SIGLIB_PKBYTES]; if (!K) return 0; lib25519_sign_keypair(pk,K->data); if (CRYPTO_memcmp(K->data+SIGLIB_SKBYTES-SIGLIB_PKBYTES,pk,SIGLIB_PKBYTES)) { memset(K,0,sizeof(struct siglib_key)); return 0; } K->state = SIGLIB_KEY_SK; return 1; } static int siglib_key_sign(unsigned char *sig,const unsigned char *m,size_t mlen,const struct siglib_key *K) { int ok = 0; void *sm = 0; long long smlen = 0; long long smlenused = 0; if (!sig) return 0; memset(sig,0,SIGLIB_SIGBYTES); if (!K) return 0; if (K->state != SIGLIB_KEY_SK) return 0; if (!m) return 0; if (mlen > SIZE_MAX-SIGLIB_SIGBYTES) return 0; if (mlen > LLONG_MAX-SIGLIB_SIGBYTES) return 0; smlen = mlen+SIGLIB_SIGBYTES; sm = OPENSSL_secure_zalloc(smlen); if (!sm) return 0; do { lib25519_sign(sm,&smlenused,m,mlen,K->data); if (smlenused != smlen) break; if (CRYPTO_memcmp(m,sm+SIGLIB_SIGBYTES,mlen)) break; memcpy(sig,sm,SIGLIB_SIGBYTES); ok = 1; } while(0); OPENSSL_secure_clear_free(sm,smlen); return ok; } static int siglib_key_verify(const unsigned char *sig,const unsigned char *m,size_t mlen,const struct siglib_key *K) { int ok = 0; void *sm = 0; long long smlen = 0; long long tlen = 0; if (!K) return 0; if (!K->state) return 0; if (!m) return 0; if (!sig) return 0; if (mlen > SIZE_MAX-SIGLIB_SIGBYTES) return 0; if (mlen > LLONG_MAX-SIGLIB_SIGBYTES) return 0; smlen = mlen+SIGLIB_SIGBYTES; sm = OPENSSL_zalloc(smlen); if (!sm) return 0; do { memcpy(sm,sig,SIGLIB_SIGBYTES); memcpy(sm+SIGLIB_SIGBYTES,m,mlen); if (lib25519_sign_open(sm,&tlen,sm,smlen,K->data+SIGLIB_SKBYTES-SIGLIB_PKBYTES) != 0) break; if ((unsigned long long) tlen != mlen) break; if (CRYPTO_memcmp(sm,m,mlen)) break; ok = 1; } while(0); OPENSSL_clear_free(sm,smlen); return ok; } // ----- and now the painful part begins #include #include #include #include #include #include #include #include #include // various objects below have no parameters static const OSSL_PARAM no_params[] = { OSSL_PARAM_END } ; #define PROVIDER "provider=" provider_name // ----- encoder and decoder // no reason to allocate an extra layer // so pointer to encoder/decoder context is just provider-context pointer static void *coder_newctx(void *provctx) { return provctx; } static void coder_freectx(void *ctx) { ; // nothing to do } static int encode(void *ctx,OSSL_CORE_BIO *out,const void *obj_raw,const OSSL_PARAM obj_abstract[],int selection,OSSL_PASSPHRASE_CALLBACK *cb,void *cbarg,int flagpem) { // XXX: is it possible to skip the PEM part of the encoder? OSSL_LIB_CTX *provider_context = ctx; const struct siglib_key *K = obj_raw; BIO *bio = 0; int ok = 0; if (obj_abstract) return 0; if (!K) return 0; bio = BIO_new_from_core_bio(provider_context,out); if (!bio) return 0; do { if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { long derlen = (sizeof siglib_privkey_asn1_prefix)+SIGLIB_SKBYTES; unsigned char *der = OPENSSL_secure_zalloc(derlen); if (!der) break; do { if (K->state != SIGLIB_KEY_SK) break; memcpy(der,siglib_privkey_asn1_prefix,sizeof siglib_privkey_asn1_prefix); memcpy(der+sizeof siglib_privkey_asn1_prefix,K->data,SIGLIB_SKBYTES); if (flagpem) { if (PEM_write_bio(bio,"PRIVATE KEY",0,der,derlen) <= 0) break; } else { if (BIO_write(bio,der,derlen) < derlen) break; } ok = 1; } while(0); OPENSSL_secure_clear_free(der,derlen); break; } if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) { long derlen = (sizeof siglib_pubkey_asn1_prefix)+SIGLIB_PKBYTES; unsigned char *der = OPENSSL_zalloc(derlen); if (!der) break; do { if (!K->state) break; memcpy(der,siglib_pubkey_asn1_prefix,sizeof siglib_pubkey_asn1_prefix); memcpy(der+sizeof siglib_pubkey_asn1_prefix,K->data+SIGLIB_SKBYTES-SIGLIB_PKBYTES,SIGLIB_PKBYTES); if (flagpem) { if (PEM_write_bio(bio,"PUBLIC KEY",0,der,derlen) <= 0) break; } else { if (BIO_write(bio,der,derlen) < derlen) break; } ok = 1; } while(0); OPENSSL_clear_free(der,derlen); break; } } while(0); BIO_free(bio); return ok; } static int encode_DER(void *ctx,OSSL_CORE_BIO *out,const void *obj_raw,const OSSL_PARAM obj_abstract[],int selection,OSSL_PASSPHRASE_CALLBACK *cb,void *cbarg) { return encode(ctx,out,obj_raw,obj_abstract,selection,cb,cbarg,0); } static int encode_PEM(void *ctx,OSSL_CORE_BIO *out,const void *obj_raw,const OSSL_PARAM obj_abstract[],int selection,OSSL_PASSPHRASE_CALLBACK *cb,void *cbarg) { return encode(ctx,out,obj_raw,obj_abstract,selection,cb,cbarg,1); } static int decode_DER(void *ctx,OSSL_CORE_BIO *in,int selection,OSSL_CALLBACK *data_cb,void *data_cbarg,OSSL_PASSPHRASE_CALLBACK *cb,void *cbarg) { OSSL_LIB_CTX *provider_context = ctx; BIO *bio = 0; int ok = 1; if (!in) return 1; bio = BIO_new_from_core_bio(provider_context,in); if (!bio) return 1; do { int flagpub; for (flagpub = 0;flagpub < 2;++flagpub) { struct siglib_key *K = 0; const unsigned char *prefix = 0; long prefixlen = 0; long pos = 0; if (!data_cb) break; if (flagpub) { if (!(selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) continue; prefix = siglib_pubkey_asn1_prefix; prefixlen = sizeof siglib_pubkey_asn1_prefix; } else { if (!(selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) continue; prefix = siglib_privkey_asn1_prefix; prefixlen = sizeof siglib_privkey_asn1_prefix; } for (pos = 0;pos < prefixlen;++pos) { unsigned char ch; if (BIO_read(bio,&ch,1) < 1) break; if (ch != prefix[pos]) break; } if (pos < prefixlen) continue; K = OPENSSL_secure_zalloc(sizeof(struct siglib_key)); if (!K) continue; do { int pkey = OSSL_OBJECT_PKEY; OSSL_PARAM params[4]; K->state = flagpub ? SIGLIB_KEY_PK : SIGLIB_KEY_SK; pos = flagpub ? SIGLIB_SKBYTES-SIGLIB_PKBYTES : 0; for (;pos < SIGLIB_SKBYTES;++pos) if (BIO_read(bio,&K->data[pos],1) < 1) break; if (pos < SIGLIB_SKBYTES) break; params[0] = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE,&pkey); params[1] = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,siglib_algorithm_name,0); params[2] = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_REFERENCE,&K,sizeof(K)); params[3] = OSSL_PARAM_construct_end(); if (data_cb) ok = data_cb(params,data_cbarg); data_cb = 0; // make sure we do not call it twice } while(0); // K should be 0 if and only if callback took control of key if (K) OPENSSL_secure_clear_free(K,sizeof(struct siglib_key)); } } while(0); BIO_free(bio); return ok; } static const OSSL_DISPATCH encode_DER_functions[] = { { OSSL_FUNC_ENCODER_NEWCTX, (void(*)(void)) coder_newctx }, { OSSL_FUNC_ENCODER_FREECTX, (void(*)(void)) coder_freectx }, { OSSL_FUNC_ENCODER_ENCODE, (void(*)(void)) encode_DER }, { 0, 0 }, } ; static const OSSL_DISPATCH encode_PEM_functions[] = { { OSSL_FUNC_ENCODER_NEWCTX, (void(*)(void)) coder_newctx }, { OSSL_FUNC_ENCODER_FREECTX, (void(*)(void)) coder_freectx }, { OSSL_FUNC_ENCODER_ENCODE, (void(*)(void)) encode_PEM }, { 0, 0 }, } ; static const OSSL_DISPATCH decode_DER_functions[] = { { OSSL_FUNC_DECODER_NEWCTX, (void(*)(void)) coder_newctx }, { OSSL_FUNC_DECODER_FREECTX, (void(*)(void)) coder_freectx }, { OSSL_FUNC_DECODER_DECODE, (void(*)(void)) decode_DER }, { 0, 0 }, } ; static const OSSL_ALGORITHM provider_encoder[] = { { siglib_algorithm_names,PROVIDER ",output=der,structure=PrivateKeyInfo",encode_DER_functions }, { siglib_algorithm_names,PROVIDER ",output=pem,structure=PrivateKeyInfo",encode_PEM_functions }, { siglib_algorithm_names,PROVIDER ",output=der,structure=SubjectPublicKeyInfo",encode_DER_functions }, { siglib_algorithm_names,PROVIDER ",output=pem,structure=SubjectPublicKeyInfo",encode_PEM_functions }, { 0, 0, 0 }, }; static const OSSL_ALGORITHM provider_decoder[] = { { siglib_algorithm_names,PROVIDER ",input=der,structure=PrivateKeyInfo",decode_DER_functions }, { siglib_algorithm_names,PROVIDER ",input=der,structure=SubjectPublicKeyInfo",decode_DER_functions }, { 0, 0, 0 }, }; // ----- keygen // as in encoder/decoder, no reason to allocate an extra layer // so pointer to key-generator context is just provider-context pointer static void *key_gen_init(void *provctx,int selection,const OSSL_PARAM params[]) { return provctx; } static void key_gen_cleanup(void *genctx) { ; // nothing to do } static void *key_new(void *provctx) { return OPENSSL_secure_zalloc(sizeof(struct siglib_key)); } static void key_free(void *keydata) { OPENSSL_secure_clear_free(keydata,sizeof(struct siglib_key)); } static int key_gen_set_params(void *genctx,const OSSL_PARAM params[]) { return 1; } static const OSSL_PARAM *key_gen_settable_params(void *genctx,void *provctx) { return no_params; } static void *key_gen(void *genctx,OSSL_CALLBACK *cb,void *cbarg) { struct siglib_key *K = key_new(genctx); if (!K) return 0; if (!siglib_key_generate(K)) { key_free(K); return 0; } return K; } static void *key_load(const void *reference,size_t reference_sz) { struct siglib_key *K = 0; if (!reference) return 0; if (reference_sz != sizeof(K)) return 0; K = *(struct siglib_key **) reference; *(struct siglib_key **) reference = 0; return K; } static const OSSL_PARAM keygen_params[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_MAX_SIZE,0,0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST,0,0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST,0,0), OSSL_PARAM_END } ; static const OSSL_PARAM *key_gettable_params(void *provctx) { return keygen_params; } static int key_get_params(void *keydata,OSSL_PARAM params[]) { OSSL_PARAM *p = 0; // need MAX_SIZE for openssl pkeyutl -verify p = OSSL_PARAM_locate(params,OSSL_PKEY_PARAM_MAX_SIZE); if (p && !OSSL_PARAM_set_int(p,SIGLIB_SIGBYTES)) return 0; p = OSSL_PARAM_locate(params,OSSL_PKEY_PARAM_DEFAULT_DIGEST); if (p && !OSSL_PARAM_set_utf8_string(p,SN_undef)) return 0; p = OSSL_PARAM_locate(params,OSSL_PKEY_PARAM_MANDATORY_DIGEST); if (p && !OSSL_PARAM_set_utf8_string(p,SN_undef)) return 0; return 1; } static const OSSL_PARAM *key_settable_params(void *provctx) { return no_params; } static int key_set_params(void *keydata, const OSSL_PARAM params[]) { return 1; } static int key_has(const void *keydata,int selection) { const struct siglib_key *K = keydata; int result = 1; if (!K) return 0; if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) result &= (K->state != 0); if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) result &= (K->state == SIGLIB_KEY_SK); return result; } static int key_match(const void *keydata1,const void *keydata2,int selection) { const struct siglib_key *K1 = keydata1; const struct siglib_key *K2 = keydata2; if (!K1) return 0; if (!K2) return 0; if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) if (K1->state && K2->state) if (!CRYPTO_memcmp(K1->data+SIGLIB_SKBYTES-SIGLIB_PKBYTES,K2->data+SIGLIB_SKBYTES-SIGLIB_PKBYTES,SIGLIB_PKBYTES)) return 1; if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) if ((K1->state == SIGLIB_KEY_SK) && (K2->state == SIGLIB_KEY_SK)) if (!CRYPTO_memcmp(K1->data,K2->data,SIGLIB_SKBYTES)) return 1; return 0; } static int key_import(void *keydata,int selection,const OSSL_PARAM params[]) { struct siglib_key *K = keydata; if (!K) return 0; if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) { const OSSL_PARAM *p = OSSL_PARAM_locate_const(params,OSSL_PKEY_PARAM_PUB_KEY); if (p) { size_t len = 0; void *ptr = K->data+SIGLIB_SKBYTES-SIGLIB_PKBYTES; memset(K,0,sizeof(struct siglib_key)); if (!OSSL_PARAM_get_octet_string(p,&ptr,SIGLIB_PKBYTES,&len)) return 0; if (len != SIGLIB_PKBYTES) return 0; K->state = SIGLIB_KEY_PK; } } if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { const OSSL_PARAM *p = OSSL_PARAM_locate_const(params,OSSL_PKEY_PARAM_PRIV_KEY); if (p) { size_t len = 0; void *ptr = K->data; memset(K,0,sizeof(struct siglib_key)); if (!OSSL_PARAM_get_octet_string(p,&ptr,SIGLIB_SKBYTES,&len)) return 0; if (len != SIGLIB_SKBYTES) return 0; K->state = SIGLIB_KEY_SK; } } return 1; } static int key_export(void *keydata,int selection,OSSL_CALLBACK *param_cb,void *cbarg) { struct siglib_key *K = keydata; #define KEY_EXPORT_PARAMS_MAX 3 OSSL_PARAM params[KEY_EXPORT_PARAMS_MAX]; int paramspos = 0; if (!K) return 0; if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) if (K->state) { if (paramspos >= KEY_EXPORT_PARAMS_MAX) return 0; params[paramspos++] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,K->data+SIGLIB_SKBYTES-SIGLIB_PKBYTES,SIGLIB_PKBYTES); } if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) if (K->state == SIGLIB_KEY_SK) { if (paramspos >= KEY_EXPORT_PARAMS_MAX) return 0; params[paramspos++] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,K->data,SIGLIB_SKBYTES); } if (paramspos >= KEY_EXPORT_PARAMS_MAX) return 0; params[paramspos++] = OSSL_PARAM_construct_end(); return param_cb(params,cbarg); } static const OSSL_PARAM params_pub_and_priv[] = { OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY,0,0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,0,0), OSSL_PARAM_END } ; static const OSSL_PARAM *key_import_export_types(int selection) { if (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) return params_pub_and_priv; // maybe in principle should narrow further by pub-vs-priv selection // but examples in openssl do not do that return 0; } static const OSSL_DISPATCH key_functions[] = { { OSSL_FUNC_KEYMGMT_NEW, (void(*)(void)) key_new }, { OSSL_FUNC_KEYMGMT_FREE, (void(*)(void)) key_free }, { OSSL_FUNC_KEYMGMT_GEN_INIT, (void(*)(void)) key_gen_init }, { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void(*)(void)) key_gen_set_params }, { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (void(*)(void)) key_gen_settable_params }, { OSSL_FUNC_KEYMGMT_GEN, (void(*)(void)) key_gen }, { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void(*)(void)) key_gen_cleanup }, { OSSL_FUNC_KEYMGMT_LOAD, (void(*)(void)) key_load }, { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void(*)(void)) key_gettable_params }, { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void(*)(void)) key_get_params }, { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void(*)(void)) key_settable_params }, { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void(*)(void)) key_set_params }, { OSSL_FUNC_KEYMGMT_HAS, (void(*)(void)) key_has }, { OSSL_FUNC_KEYMGMT_MATCH, (void(*)(void)) key_match }, { OSSL_FUNC_KEYMGMT_IMPORT, (void(*)(void)) key_import }, { OSSL_FUNC_KEYMGMT_EXPORT, (void(*)(void)) key_export }, { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void(*)(void)) key_import_export_types }, { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void(*)(void)) key_import_export_types }, { 0, 0 }, } ; static const OSSL_ALGORITHM provider_keygen[] = { { siglib_algorithm_names,PROVIDER,key_functions }, { 0, 0, 0 }, }; // ----- signing and verification static void *signver_new(void *provctx,const char *propq) { return OPENSSL_secure_zalloc(sizeof(struct siglib_key)); } static void signver_free(void *ctx) { OPENSSL_secure_clear_free(ctx,sizeof(struct siglib_key)); } static int signver_copykey(void *ctx,const char *mdname,void *provkey,const OSSL_PARAM params[]) { if (!ctx) return 0; if (!provkey) return 1; // XXX: where is it documented that provkey can legitimately be 0? // this occurs in "reinit" during, e.g., openssl speed memcpy(ctx,provkey,sizeof(struct siglib_key)); return 1; } static int sign(void *ctx,unsigned char *sigret,size_t *siglen,size_t sigsize,const unsigned char *tbs,size_t tbslen) { struct siglib_key *K = ctx; if (!K) return 0; if (!sigret) { *siglen = SIGLIB_SIGBYTES; return 1; } if (sigsize < SIGLIB_SIGBYTES) return 0; if (!siglib_key_sign(sigret,tbs,tbslen,K)) return 0; *siglen = SIGLIB_SIGBYTES; return 1; } static int verify(void *ctx,const unsigned char *sig,size_t siglen,const unsigned char *tbs,size_t tbslen) { struct siglib_key *K = ctx; if (siglen != SIGLIB_SIGBYTES) return 0; if (!siglib_key_verify(sig,tbs,tbslen,K)) return 0; return 1; } static const OSSL_PARAM signver_params[] = { OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_DIGEST,0,0), OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID,0,0), OSSL_PARAM_END } ; static const OSSL_PARAM *signver_gettable_params(void *provctx) { return signver_params; } static int signver_get_params(void *ctx,OSSL_PARAM params[]) { OSSL_PARAM *p = 0; p = OSSL_PARAM_locate(params,OSSL_SIGNATURE_PARAM_DIGEST); if (p && !OSSL_PARAM_set_utf8_string(p,"")) return 0; p = OSSL_PARAM_locate(params,OSSL_SIGNATURE_PARAM_ALGORITHM_ID); if (p && !OSSL_PARAM_set_octet_string(p,siglib_algorithm_asn1,sizeof siglib_algorithm_asn1)) return 0; return 1; } static const OSSL_DISPATCH signver_functions[] = { { OSSL_FUNC_SIGNATURE_NEWCTX, (void(*)(void)) signver_new }, { OSSL_FUNC_SIGNATURE_FREECTX, (void(*)(void)) signver_free }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, (void(*)(void)) signver_copykey }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, (void(*)(void)) sign }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, (void(*)(void)) signver_copykey }, { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, (void(*)(void)) verify }, { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void(*)(void)) signver_gettable_params }, { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void(*)(void)) signver_get_params }, { 0, 0 }, }; static const OSSL_ALGORITHM provider_signatures[] = { { siglib_algorithm_names,PROVIDER,signver_functions }, { 0, 0, 0 }, }; // ----- top-level provider functions static const OSSL_ALGORITHM *provider_get_algorithms(void *provctx,int operation_id,int *no_store) { *no_store = 0; // ok for openssl to store results if (operation_id == OSSL_OP_ENCODER) return provider_encoder; if (operation_id == OSSL_OP_DECODER) return provider_decoder; if (operation_id == OSSL_OP_KEYMGMT) return provider_keygen; if (operation_id == OSSL_OP_SIGNATURE) return provider_signatures; return 0; } static const OSSL_PARAM provider_params_list[] = { OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME,OSSL_PARAM_UTF8_PTR,0,0), OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION,OSSL_PARAM_UTF8_PTR,0,0), OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS,OSSL_PARAM_INTEGER,0,0), OSSL_PARAM_END, } ; static const OSSL_PARAM *provider_gettable_params(void) { return provider_params_list; } // used by, e.g., openssl list -providers static int provider_get_params(void *provctx,OSSL_PARAM params[]) { OSSL_PARAM *p = 0; p = OSSL_PARAM_locate(params,OSSL_PROV_PARAM_NAME); if (p && !OSSL_PARAM_set_utf8_ptr(p,provider_name)) return 0; p = OSSL_PARAM_locate(params,OSSL_PROV_PARAM_VERSION); if (p && !OSSL_PARAM_set_utf8_ptr(p,provider_version)) return 0; p = OSSL_PARAM_locate(params,OSSL_PROV_PARAM_STATUS); if (p && !OSSL_PARAM_set_int(p,1)) return 0; // 1 means provider is running return 1; } static void provider_teardown(void *provctx) { OSSL_LIB_CTX_free(provctx); } static const OSSL_DISPATCH provider_functions[] = { { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void(*)(void)) provider_get_algorithms }, { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void(*)(void)) provider_gettable_params }, { OSSL_FUNC_PROVIDER_GET_PARAMS, (void(*)(void)) provider_get_params }, { OSSL_FUNC_PROVIDER_TEARDOWN, (void(*)(void)) provider_teardown }, { 0, 0 }, }; int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,const OSSL_DISPATCH *in,const OSSL_DISPATCH **out,void **provctx) { OSSL_LIB_CTX *provider_context = OSSL_LIB_CTX_new_child(handle,in); if (!provider_context) return 0; *out = provider_functions; *provctx = provider_context; return 1; }